LCOV - code coverage report
Current view: top level - contrib/pgcrypto - mbuf.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 93.6 % 219 205
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 24 24
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 82.1 % 84 69

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * mbuf.c
       3                 :             :  *      Memory buffer operations.
       4                 :             :  *
       5                 :             :  * Copyright (c) 2005 Marko Kreen
       6                 :             :  * All rights reserved.
       7                 :             :  *
       8                 :             :  * Redistribution and use in source and binary forms, with or without
       9                 :             :  * modification, are permitted provided that the following conditions
      10                 :             :  * are met:
      11                 :             :  * 1. Redistributions of source code must retain the above copyright
      12                 :             :  *    notice, this list of conditions and the following disclaimer.
      13                 :             :  * 2. Redistributions in binary form must reproduce the above copyright
      14                 :             :  *    notice, this list of conditions and the following disclaimer in the
      15                 :             :  *    documentation and/or other materials provided with the distribution.
      16                 :             :  *
      17                 :             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      18                 :             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      19                 :             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20                 :             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      21                 :             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      22                 :             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      23                 :             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      24                 :             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      25                 :             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      26                 :             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      27                 :             :  * SUCH DAMAGE.
      28                 :             :  *
      29                 :             :  * contrib/pgcrypto/mbuf.c
      30                 :             :  */
      31                 :             : 
      32                 :             : #include "postgres.h"
      33                 :             : 
      34                 :             : #include "mbuf.h"
      35                 :             : #include "px.h"
      36                 :             : 
      37                 :             : #define STEP  (16*1024)
      38                 :             : 
      39                 :             : struct MBuf
      40                 :             : {
      41                 :             :     uint8      *data;
      42                 :             :     uint8      *data_end;
      43                 :             :     uint8      *read_pos;
      44                 :             :     uint8      *buf_end;
      45                 :             :     bool        no_write;
      46                 :             :     bool        own_data;
      47                 :             : };
      48                 :             : 
      49                 :             : int
      50                 :        2882 : mbuf_avail(MBuf *mbuf)
      51                 :             : {
      52                 :        2882 :     return mbuf->data_end - mbuf->read_pos;
      53                 :             : }
      54                 :             : 
      55                 :             : int
      56                 :         100 : mbuf_size(MBuf *mbuf)
      57                 :             : {
      58                 :         100 :     return mbuf->data_end - mbuf->data;
      59                 :             : }
      60                 :             : 
      61                 :             : int
      62                 :         278 : mbuf_free(MBuf *mbuf)
      63                 :             : {
      64         [ +  + ]:         278 :     if (mbuf->own_data)
      65                 :             :     {
      66                 :          17 :         px_memset(mbuf->data, 0, mbuf->buf_end - mbuf->data);
      67                 :          17 :         pfree(mbuf->data);
      68                 :             :     }
      69                 :         278 :     pfree(mbuf);
      70                 :         278 :     return 0;
      71                 :             : }
      72                 :             : 
      73                 :             : static void
      74                 :         404 : prepare_room(MBuf *mbuf, int block_len)
      75                 :             : {
      76                 :             :     uint8      *newbuf;
      77                 :             :     unsigned    newlen;
      78                 :             : 
      79         [ +  + ]:         404 :     if (mbuf->data_end + block_len <= mbuf->buf_end)
      80                 :         398 :         return;
      81                 :             : 
      82                 :           6 :     newlen = (mbuf->buf_end - mbuf->data)
      83                 :           6 :         + ((block_len + STEP + STEP - 1) & -STEP);
      84                 :             : 
      85                 :           6 :     newbuf = repalloc(mbuf->data, newlen);
      86                 :             : 
      87                 :           6 :     mbuf->buf_end = newbuf + newlen;
      88                 :           6 :     mbuf->data_end = newbuf + (mbuf->data_end - mbuf->data);
      89                 :           6 :     mbuf->read_pos = newbuf + (mbuf->read_pos - mbuf->data);
      90                 :           6 :     mbuf->data = newbuf;
      91                 :             : }
      92                 :             : 
      93                 :             : int
      94                 :         404 : mbuf_append(MBuf *dst, const uint8 *buf, int len)
      95                 :             : {
      96         [ -  + ]:         404 :     if (dst->no_write)
      97                 :             :     {
      98                 :           0 :         px_debug("mbuf_append: no_write");
      99                 :           0 :         return PXE_BUG;
     100                 :             :     }
     101                 :             : 
     102                 :         404 :     prepare_room(dst, len);
     103                 :             : 
     104                 :         404 :     memcpy(dst->data_end, buf, len);
     105                 :         404 :     dst->data_end += len;
     106                 :             : 
     107                 :         404 :     return 0;
     108                 :             : }
     109                 :             : 
     110                 :             : MBuf *
     111                 :         117 : mbuf_create(int len)
     112                 :             : {
     113                 :             :     MBuf       *mbuf;
     114                 :             : 
     115         [ -  + ]:         117 :     if (!len)
     116                 :           0 :         len = 8192;
     117                 :             : 
     118                 :         117 :     mbuf = palloc_object(MBuf);
     119                 :         117 :     mbuf->data = palloc(len);
     120                 :         117 :     mbuf->buf_end = mbuf->data + len;
     121                 :         117 :     mbuf->data_end = mbuf->data;
     122                 :         117 :     mbuf->read_pos = mbuf->data;
     123                 :             : 
     124                 :         117 :     mbuf->no_write = false;
     125                 :         117 :     mbuf->own_data = true;
     126                 :             : 
     127                 :         117 :     return mbuf;
     128                 :             : }
     129                 :             : 
     130                 :             : MBuf *
     131                 :         161 : mbuf_create_from_data(uint8 *data, int len)
     132                 :             : {
     133                 :             :     MBuf       *mbuf;
     134                 :             : 
     135                 :         161 :     mbuf = palloc_object(MBuf);
     136                 :         161 :     mbuf->data = data;
     137                 :         161 :     mbuf->buf_end = mbuf->data + len;
     138                 :         161 :     mbuf->data_end = mbuf->data + len;
     139                 :         161 :     mbuf->read_pos = mbuf->data;
     140                 :             : 
     141                 :         161 :     mbuf->no_write = true;
     142                 :         161 :     mbuf->own_data = false;
     143                 :             : 
     144                 :         161 :     return mbuf;
     145                 :             : }
     146                 :             : 
     147                 :             : 
     148                 :             : int
     149                 :        2743 : mbuf_grab(MBuf *mbuf, int len, uint8 **data_p)
     150                 :             : {
     151         [ +  + ]:        2743 :     if (len > mbuf_avail(mbuf))
     152                 :         103 :         len = mbuf_avail(mbuf);
     153                 :             : 
     154                 :        2743 :     mbuf->no_write = true;
     155                 :             : 
     156                 :        2743 :     *data_p = mbuf->read_pos;
     157                 :        2743 :     mbuf->read_pos += len;
     158                 :        2743 :     return len;
     159                 :             : }
     160                 :             : 
     161                 :             : int
     162                 :         100 : mbuf_steal_data(MBuf *mbuf, uint8 **data_p)
     163                 :             : {
     164                 :         100 :     int         len = mbuf_size(mbuf);
     165                 :             : 
     166                 :         100 :     mbuf->no_write = true;
     167                 :         100 :     mbuf->own_data = false;
     168                 :             : 
     169                 :         100 :     *data_p = mbuf->data;
     170                 :             : 
     171                 :         100 :     mbuf->data = mbuf->data_end = mbuf->read_pos = mbuf->buf_end = NULL;
     172                 :             : 
     173                 :         100 :     return len;
     174                 :             : }
     175                 :             : 
     176                 :             : /*
     177                 :             :  * PullFilter
     178                 :             :  */
     179                 :             : 
     180                 :             : struct PullFilter
     181                 :             : {
     182                 :             :     PullFilter *src;
     183                 :             :     const PullFilterOps *op;
     184                 :             :     int         buflen;
     185                 :             :     uint8      *buf;
     186                 :             :     int         pos;
     187                 :             :     void       *priv;
     188                 :             : };
     189                 :             : 
     190                 :             : int
     191                 :         821 : pullf_create(PullFilter **pf_p, const PullFilterOps *op, void *init_arg, PullFilter *src)
     192                 :             : {
     193                 :             :     PullFilter *pf;
     194                 :             :     void       *priv;
     195                 :             :     int         res;
     196                 :             : 
     197         [ +  + ]:         821 :     if (op->init != NULL)
     198                 :             :     {
     199                 :         228 :         res = op->init(&priv, init_arg, src);
     200         [ -  + ]:         228 :         if (res < 0)
     201                 :           0 :             return res;
     202                 :             :     }
     203                 :             :     else
     204                 :             :     {
     205                 :         593 :         priv = init_arg;
     206                 :         593 :         res = 0;
     207                 :             :     }
     208                 :             : 
     209                 :         821 :     pf = palloc0_object(PullFilter);
     210                 :         821 :     pf->buflen = res;
     211                 :         821 :     pf->op = op;
     212                 :         821 :     pf->priv = priv;
     213                 :         821 :     pf->src = src;
     214         [ +  + ]:         821 :     if (pf->buflen > 0)
     215                 :             :     {
     216                 :          77 :         pf->buf = palloc(pf->buflen);
     217                 :          77 :         pf->pos = 0;
     218                 :             :     }
     219                 :             :     else
     220                 :             :     {
     221                 :         744 :         pf->buf = NULL;
     222                 :         744 :         pf->pos = 0;
     223                 :             :     }
     224                 :         821 :     *pf_p = pf;
     225                 :         821 :     return 0;
     226                 :             : }
     227                 :             : 
     228                 :             : void
     229                 :         821 : pullf_free(PullFilter *pf)
     230                 :             : {
     231         [ +  + ]:         821 :     if (pf->op->free)
     232                 :         552 :         pf->op->free(pf->priv);
     233                 :             : 
     234         [ +  + ]:         821 :     if (pf->buf)
     235                 :             :     {
     236                 :          77 :         px_memset(pf->buf, 0, pf->buflen);
     237                 :          77 :         pfree(pf->buf);
     238                 :             :     }
     239                 :             : 
     240                 :         821 :     px_memset(pf, 0, sizeof(*pf));
     241                 :         821 :     pfree(pf);
     242                 :         821 : }
     243                 :             : 
     244                 :             : /* may return less data than asked, 0 means eof */
     245                 :             : int
     246                 :        7653 : pullf_read(PullFilter *pf, int len, uint8 **data_p)
     247                 :             : {
     248                 :             :     int         res;
     249                 :             : 
     250         [ +  + ]:        7653 :     if (pf->op->pull)
     251                 :             :     {
     252   [ +  +  +  + ]:        6934 :         if (pf->buflen && len > pf->buflen)
     253                 :          23 :             len = pf->buflen;
     254                 :        6934 :         res = pf->op->pull(pf->priv, pf->src, len, data_p,
     255                 :             :                            pf->buf, pf->buflen);
     256                 :             :     }
     257                 :             :     else
     258                 :         719 :         res = pullf_read(pf->src, len, data_p);
     259                 :        7653 :     return res;
     260                 :             : }
     261                 :             : 
     262                 :             : int
     263                 :        1941 : pullf_read_max(PullFilter *pf, int len, uint8 **data_p, uint8 *tmpbuf)
     264                 :             : {
     265                 :             :     int         res,
     266                 :             :                 total;
     267                 :             :     uint8      *tmp;
     268                 :             : 
     269                 :        1941 :     res = pullf_read(pf, len, data_p);
     270   [ +  +  +  + ]:        1941 :     if (res <= 0 || res == len)
     271                 :        1934 :         return res;
     272                 :             : 
     273                 :             :     /* read was shorter, use tmpbuf */
     274                 :           7 :     memcpy(tmpbuf, *data_p, res);
     275                 :           7 :     *data_p = tmpbuf;
     276                 :           7 :     len -= res;
     277                 :           7 :     total = res;
     278                 :             : 
     279         [ +  + ]:           8 :     while (len > 0)
     280                 :             :     {
     281                 :           7 :         res = pullf_read(pf, len, &tmp);
     282         [ -  + ]:           7 :         if (res < 0)
     283                 :             :         {
     284                 :             :             /* so the caller must clear only on success */
     285                 :           0 :             px_memset(tmpbuf, 0, total);
     286                 :           0 :             return res;
     287                 :             :         }
     288         [ +  + ]:           7 :         if (res == 0)
     289                 :           6 :             break;
     290                 :           1 :         memcpy(tmpbuf + total, tmp, res);
     291                 :           1 :         total += res;
     292                 :           1 :         len -= res;
     293                 :             :     }
     294                 :           7 :     return total;
     295                 :             : }
     296                 :             : 
     297                 :             : /*
     298                 :             :  * caller wants exactly len bytes and don't bother with references
     299                 :             :  */
     300                 :             : int
     301                 :        1675 : pullf_read_fixed(PullFilter *src, int len, uint8 *dst)
     302                 :             : {
     303                 :             :     int         res;
     304                 :             :     uint8      *p;
     305                 :             : 
     306                 :        1675 :     res = pullf_read_max(src, len, &p, dst);
     307         [ -  + ]:        1675 :     if (res < 0)
     308                 :           0 :         return res;
     309         [ +  + ]:        1675 :     if (res != len)
     310                 :             :     {
     311                 :           2 :         px_debug("pullf_read_fixed: need=%d got=%d", len, res);
     312                 :           2 :         return PXE_PGP_CORRUPT_DATA;
     313                 :             :     }
     314         [ +  - ]:        1673 :     if (p != dst)
     315                 :        1673 :         memcpy(dst, p, len);
     316                 :        1673 :     return 0;
     317                 :             : }
     318                 :             : 
     319                 :             : /*
     320                 :             :  * read from MBuf
     321                 :             :  */
     322                 :             : static int
     323                 :        2707 : pull_from_mbuf(void *arg, PullFilter *src, int len,
     324                 :             :                uint8 **data_p, uint8 *buf, int buflen)
     325                 :             : {
     326                 :        2707 :     MBuf       *mbuf = arg;
     327                 :             : 
     328                 :        2707 :     return mbuf_grab(mbuf, len, data_p);
     329                 :             : }
     330                 :             : 
     331                 :             : static const struct PullFilterOps mbuf_reader = {
     332                 :             :     NULL, pull_from_mbuf, NULL
     333                 :             : };
     334                 :             : 
     335                 :             : int
     336                 :         119 : pullf_create_mbuf_reader(PullFilter **mp_p, MBuf *src)
     337                 :             : {
     338                 :         119 :     return pullf_create(mp_p, &mbuf_reader, src, NULL);
     339                 :             : }
     340                 :             : 
     341                 :             : 
     342                 :             : /*
     343                 :             :  * PushFilter
     344                 :             :  */
     345                 :             : 
     346                 :             : struct PushFilter
     347                 :             : {
     348                 :             :     PushFilter *next;
     349                 :             :     const PushFilterOps *op;
     350                 :             :     int         block_size;
     351                 :             :     uint8      *buf;
     352                 :             :     int         pos;
     353                 :             :     void       *priv;
     354                 :             : };
     355                 :             : 
     356                 :             : int
     357                 :         193 : pushf_create(PushFilter **mp_p, const PushFilterOps *op, void *init_arg, PushFilter *next)
     358                 :             : {
     359                 :             :     PushFilter *mp;
     360                 :             :     void       *priv;
     361                 :             :     int         res;
     362                 :             : 
     363         [ +  + ]:         193 :     if (op->init != NULL)
     364                 :             :     {
     365                 :         155 :         res = op->init(next, init_arg, &priv);
     366         [ -  + ]:         155 :         if (res < 0)
     367                 :           0 :             return res;
     368                 :             :     }
     369                 :             :     else
     370                 :             :     {
     371                 :          38 :         priv = init_arg;
     372                 :          38 :         res = 0;
     373                 :             :     }
     374                 :             : 
     375                 :         193 :     mp = palloc0_object(PushFilter);
     376                 :         193 :     mp->block_size = res;
     377                 :         193 :     mp->op = op;
     378                 :         193 :     mp->priv = priv;
     379                 :         193 :     mp->next = next;
     380         [ +  + ]:         193 :     if (mp->block_size > 0)
     381                 :             :     {
     382                 :         120 :         mp->buf = palloc(mp->block_size);
     383                 :         120 :         mp->pos = 0;
     384                 :             :     }
     385                 :             :     else
     386                 :             :     {
     387                 :          73 :         mp->buf = NULL;
     388                 :          73 :         mp->pos = 0;
     389                 :             :     }
     390                 :         193 :     *mp_p = mp;
     391                 :         193 :     return 0;
     392                 :             : }
     393                 :             : 
     394                 :             : void
     395                 :         193 : pushf_free(PushFilter *mp)
     396                 :             : {
     397         [ +  + ]:         193 :     if (mp->op->free)
     398                 :         155 :         mp->op->free(mp->priv);
     399                 :             : 
     400         [ +  + ]:         193 :     if (mp->buf)
     401                 :             :     {
     402                 :         120 :         px_memset(mp->buf, 0, mp->block_size);
     403                 :         120 :         pfree(mp->buf);
     404                 :             :     }
     405                 :             : 
     406                 :         193 :     px_memset(mp, 0, sizeof(*mp));
     407                 :         193 :     pfree(mp);
     408                 :         193 : }
     409                 :             : 
     410                 :             : void
     411                 :          36 : pushf_free_all(PushFilter *mp)
     412                 :             : {
     413                 :             :     PushFilter *tmp;
     414                 :             : 
     415         [ +  + ]:         223 :     while (mp)
     416                 :             :     {
     417                 :         187 :         tmp = mp->next;
     418                 :         187 :         pushf_free(mp);
     419                 :         187 :         mp = tmp;
     420                 :             :     }
     421                 :          36 : }
     422                 :             : 
     423                 :             : static int
     424                 :         487 : wrap_process(PushFilter *mp, const uint8 *data, int len)
     425                 :             : {
     426                 :             :     int         res;
     427                 :             : 
     428         [ +  - ]:         487 :     if (mp->op->push != NULL)
     429                 :         487 :         res = mp->op->push(mp->next, mp->priv, data, len);
     430                 :             :     else
     431                 :           0 :         res = pushf_write(mp->next, data, len);
     432         [ -  + ]:         487 :     if (res > 0)
     433                 :           0 :         return PXE_BUG;
     434                 :         487 :     return res;
     435                 :             : }
     436                 :             : 
     437                 :             : /* consumes all data, returns len on success */
     438                 :             : int
     439                 :         757 : pushf_write(PushFilter *mp, const uint8 *data, int len)
     440                 :             : {
     441                 :             :     int         need,
     442                 :             :                 res;
     443                 :             : 
     444                 :             :     /*
     445                 :             :      * no buffering
     446                 :             :      */
     447         [ +  + ]:         757 :     if (mp->block_size <= 0)
     448                 :         347 :         return wrap_process(mp, data, len);
     449                 :             : 
     450                 :             :     /*
     451                 :             :      * try to empty buffer
     452                 :             :      */
     453                 :         410 :     need = mp->block_size - mp->pos;
     454         [ +  - ]:         410 :     if (need > 0)
     455                 :             :     {
     456         [ +  + ]:         410 :         if (len < need)
     457                 :             :         {
     458                 :         397 :             memcpy(mp->buf + mp->pos, data, len);
     459                 :         397 :             mp->pos += len;
     460                 :         397 :             return 0;
     461                 :             :         }
     462                 :          13 :         memcpy(mp->buf + mp->pos, data, need);
     463                 :          13 :         len -= need;
     464                 :          13 :         data += need;
     465                 :             :     }
     466                 :             : 
     467                 :             :     /*
     468                 :             :      * buffer full, process
     469                 :             :      */
     470                 :          13 :     res = wrap_process(mp, mp->buf, mp->block_size);
     471         [ -  + ]:          13 :     if (res < 0)
     472                 :           0 :         return res;
     473                 :          13 :     mp->pos = 0;
     474                 :             : 
     475                 :             :     /*
     476                 :             :      * now process directly from data
     477                 :             :      */
     478         [ +  + ]:          20 :     while (len > 0)
     479                 :             :     {
     480         [ +  + ]:          19 :         if (len > mp->block_size)
     481                 :             :         {
     482                 :           7 :             res = wrap_process(mp, data, mp->block_size);
     483         [ -  + ]:           7 :             if (res < 0)
     484                 :           0 :                 return res;
     485                 :           7 :             data += mp->block_size;
     486                 :           7 :             len -= mp->block_size;
     487                 :             :         }
     488                 :             :         else
     489                 :             :         {
     490                 :          12 :             memcpy(mp->buf, data, len);
     491                 :          12 :             mp->pos += len;
     492                 :          12 :             break;
     493                 :             :         }
     494                 :             :     }
     495                 :          13 :     return 0;
     496                 :             : }
     497                 :             : 
     498                 :             : int
     499                 :          42 : pushf_flush(PushFilter *mp)
     500                 :             : {
     501                 :             :     int         res;
     502                 :             : 
     503         [ +  + ]:         241 :     while (mp)
     504                 :             :     {
     505         [ +  + ]:         199 :         if (mp->block_size > 0)
     506                 :             :         {
     507                 :         120 :             res = wrap_process(mp, mp->buf, mp->pos);
     508         [ -  + ]:         120 :             if (res < 0)
     509                 :           0 :                 return res;
     510                 :             :         }
     511                 :             : 
     512         [ +  + ]:         199 :         if (mp->op->flush)
     513                 :             :         {
     514                 :         119 :             res = mp->op->flush(mp->next, mp->priv);
     515         [ -  + ]:         119 :             if (res < 0)
     516                 :           0 :                 return res;
     517                 :             :         }
     518                 :             : 
     519                 :         199 :         mp = mp->next;
     520                 :             :     }
     521                 :          42 :     return 0;
     522                 :             : }
     523                 :             : 
     524                 :             : 
     525                 :             : /*
     526                 :             :  * write to MBuf
     527                 :             :  */
     528                 :             : static int
     529                 :         196 : push_into_mbuf(PushFilter *next, void *arg, const uint8 *data, int len)
     530                 :             : {
     531                 :         196 :     int         res = 0;
     532                 :         196 :     MBuf       *mbuf = arg;
     533                 :             : 
     534         [ +  - ]:         196 :     if (len > 0)
     535                 :         196 :         res = mbuf_append(mbuf, data, len);
     536                 :         196 :     return res < 0 ? res : 0;
     537                 :             : }
     538                 :             : 
     539                 :             : static const struct PushFilterOps mbuf_filter = {
     540                 :             :     NULL, push_into_mbuf, NULL, NULL
     541                 :             : };
     542                 :             : 
     543                 :             : int
     544                 :          36 : pushf_create_mbuf_writer(PushFilter **res, MBuf *dst)
     545                 :             : {
     546                 :          36 :     return pushf_create(res, &mbuf_filter, dst, NULL);
     547                 :             : }
        

Generated by: LCOV version 2.0-1