LCOV - differential code coverage report
Current view: top level - contrib/pgcrypto - mbuf.c (source / functions) Coverage Total Hit LBC UIC GBC GIC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 93.6 % 219 205 7 7 4 112 89 10 102 7
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 24 24 22 2 21 1
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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 CBC        2829 : mbuf_avail(MBuf *mbuf)
      51                 : {
      52            2829 :     return mbuf->data_end - mbuf->read_pos;
      53                 : }
      54                 : 
      55                 : int
      56              99 : mbuf_size(MBuf *mbuf)
      57                 : {
      58              99 :     return mbuf->data_end - mbuf->data;
      59                 : }
      60                 : 
      61 ECB             : int
      62 GIC         273 : mbuf_free(MBuf *mbuf)
      63 ECB             : {
      64 CBC         273 :     if (mbuf->own_data)
      65                 :     {
      66 GIC          16 :         px_memset(mbuf->data, 0, mbuf->buf_end - mbuf->data);
      67              16 :         pfree(mbuf->data);
      68 ECB             :     }
      69 GIC         273 :     pfree(mbuf);
      70             273 :     return 0;
      71                 : }
      72                 : 
      73 ECB             : static void
      74 CBC         401 : prepare_room(MBuf *mbuf, int block_len)
      75                 : {
      76 ECB             :     uint8      *newbuf;
      77                 :     unsigned    newlen;
      78                 : 
      79 CBC         401 :     if (mbuf->data_end + block_len <= mbuf->buf_end)
      80 GIC         395 :         return;
      81 ECB             : 
      82 CBC           6 :     newlen = (mbuf->buf_end - mbuf->data)
      83               6 :         + ((block_len + STEP + STEP - 1) & -STEP);
      84 ECB             : 
      85 GIC           6 :     newbuf = repalloc(mbuf->data, newlen);
      86                 : 
      87               6 :     mbuf->buf_end = newbuf + newlen;
      88 CBC           6 :     mbuf->data_end = newbuf + (mbuf->data_end - mbuf->data);
      89 GIC           6 :     mbuf->read_pos = newbuf + (mbuf->read_pos - mbuf->data);
      90 CBC           6 :     mbuf->data = newbuf;
      91                 : }
      92 EUB             : 
      93                 : int
      94 GIC         401 : mbuf_append(MBuf *dst, const uint8 *buf, int len)
      95                 : {
      96 CBC         401 :     if (dst->no_write)
      97                 :     {
      98 LBC           0 :         px_debug("mbuf_append: no_write");
      99               0 :         return PXE_BUG;
     100                 :     }
     101 ECB             : 
     102 GIC         401 :     prepare_room(dst, len);
     103                 : 
     104             401 :     memcpy(dst->data_end, buf, len);
     105 CBC         401 :     dst->data_end += len;
     106                 : 
     107 GIC         401 :     return 0;
     108                 : }
     109 ECB             : 
     110 EUB             : MBuf *
     111 GIC         115 : mbuf_create(int len)
     112 ECB             : {
     113                 :     MBuf       *mbuf;
     114                 : 
     115 CBC         115 :     if (!len)
     116 LBC           0 :         len = 8192;
     117                 : 
     118 CBC         115 :     mbuf = palloc(sizeof *mbuf);
     119             115 :     mbuf->data = palloc(len);
     120 GIC         115 :     mbuf->buf_end = mbuf->data + len;
     121 CBC         115 :     mbuf->data_end = mbuf->data;
     122 GIC         115 :     mbuf->read_pos = mbuf->data;
     123                 : 
     124             115 :     mbuf->no_write = false;
     125 CBC         115 :     mbuf->own_data = true;
     126                 : 
     127 GIC         115 :     return mbuf;
     128                 : }
     129 ECB             : 
     130                 : MBuf *
     131 CBC         158 : mbuf_create_from_data(uint8 *data, int len)
     132 ECB             : {
     133                 :     MBuf       *mbuf;
     134                 : 
     135 CBC         158 :     mbuf = palloc(sizeof *mbuf);
     136             158 :     mbuf->data = (uint8 *) data;
     137 GIC         158 :     mbuf->buf_end = mbuf->data + len;
     138 CBC         158 :     mbuf->data_end = mbuf->data + len;
     139 GIC         158 :     mbuf->read_pos = mbuf->data;
     140                 : 
     141             158 :     mbuf->no_write = true;
     142             158 :     mbuf->own_data = false;
     143 ECB             : 
     144 GIC         158 :     return mbuf;
     145 ECB             : }
     146                 : 
     147                 : 
     148                 : int
     149 GIC        2692 : mbuf_grab(MBuf *mbuf, int len, uint8 **data_p)
     150 ECB             : {
     151 CBC        2692 :     if (len > mbuf_avail(mbuf))
     152             101 :         len = mbuf_avail(mbuf);
     153                 : 
     154 GIC        2692 :     mbuf->no_write = true;
     155                 : 
     156 CBC        2692 :     *data_p = mbuf->read_pos;
     157 GIC        2692 :     mbuf->read_pos += len;
     158 CBC        2692 :     return len;
     159                 : }
     160 ECB             : 
     161                 : int
     162 GIC          99 : mbuf_steal_data(MBuf *mbuf, uint8 **data_p)
     163                 : {
     164              99 :     int         len = mbuf_size(mbuf);
     165                 : 
     166              99 :     mbuf->no_write = true;
     167              99 :     mbuf->own_data = false;
     168                 : 
     169              99 :     *data_p = mbuf->data;
     170                 : 
     171              99 :     mbuf->data = mbuf->data_end = mbuf->read_pos = mbuf->buf_end = NULL;
     172                 : 
     173              99 :     return len;
     174                 : }
     175                 : 
     176                 : /*
     177                 :  * PullFilter
     178 ECB             :  */
     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 EUB             : };
     189                 : 
     190                 : int
     191 GIC         809 : pullf_create(PullFilter **pf_p, const PullFilterOps *op, void *init_arg, PullFilter *src)
     192 ECB             : {
     193                 :     PullFilter *pf;
     194                 :     void       *priv;
     195                 :     int         res;
     196                 : 
     197 CBC         809 :     if (op->init != NULL)
     198 ECB             :     {
     199 CBC         225 :         res = op->init(&priv, init_arg, src);
     200             225 :         if (res < 0)
     201 LBC           0 :             return res;
     202                 :     }
     203 ECB             :     else
     204                 :     {
     205 GIC         584 :         priv = init_arg;
     206             584 :         res = 0;
     207                 :     }
     208 ECB             : 
     209 CBC         809 :     pf = palloc0(sizeof(*pf));
     210 GIC         809 :     pf->buflen = res;
     211 CBC         809 :     pf->op = op;
     212             809 :     pf->priv = priv;
     213 GIC         809 :     pf->src = src;
     214             809 :     if (pf->buflen > 0)
     215                 :     {
     216 CBC          76 :         pf->buf = palloc(pf->buflen);
     217 GIC          76 :         pf->pos = 0;
     218 ECB             :     }
     219                 :     else
     220                 :     {
     221 CBC         733 :         pf->buf = NULL;
     222 GIC         733 :         pf->pos = 0;
     223 ECB             :     }
     224 CBC         809 :     *pf_p = pf;
     225 GIC         809 :     return 0;
     226                 : }
     227 ECB             : 
     228                 : void
     229 CBC         809 : pullf_free(PullFilter *pf)
     230                 : {
     231 GIC         809 :     if (pf->op->free)
     232             545 :         pf->op->free(pf->priv);
     233 ECB             : 
     234 GIC         809 :     if (pf->buf)
     235                 :     {
     236              76 :         px_memset(pf->buf, 0, pf->buflen);
     237 CBC          76 :         pfree(pf->buf);
     238                 :     }
     239 ECB             : 
     240 CBC         809 :     px_memset(pf, 0, sizeof(*pf));
     241             809 :     pfree(pf);
     242 GIC         809 : }
     243                 : 
     244                 : /* may return less data than asked, 0 means eof */
     245 ECB             : int
     246 CBC        7522 : pullf_read(PullFilter *pf, int len, uint8 **data_p)
     247                 : {
     248                 :     int         res;
     249                 : 
     250            7522 :     if (pf->op->pull)
     251                 :     {
     252 GIC        6813 :         if (pf->buflen && len > pf->buflen)
     253              23 :             len = pf->buflen;
     254            6813 :         res = pf->op->pull(pf->priv, pf->src, len, data_p,
     255                 :                            pf->buf, pf->buflen);
     256 ECB             :     }
     257                 :     else
     258 CBC         709 :         res = pullf_read(pf->src, len, data_p);
     259 GIC        7522 :     return res;
     260                 : }
     261 ECB             : 
     262                 : int
     263 CBC        1898 : pullf_read_max(PullFilter *pf, int len, uint8 **data_p, uint8 *tmpbuf)
     264 ECB             : {
     265                 :     int         res,
     266                 :                 total;
     267                 :     uint8      *tmp;
     268                 : 
     269 CBC        1898 :     res = pullf_read(pf, len, data_p);
     270 GIC        1898 :     if (res <= 0 || res == len)
     271            1891 :         return res;
     272 EUB             : 
     273                 :     /* read was shorter, use tmpbuf */
     274 GIC           7 :     memcpy(tmpbuf, *data_p, res);
     275 CBC           7 :     *data_p = tmpbuf;
     276               7 :     len -= res;
     277               7 :     total = res;
     278 ECB             : 
     279 CBC           8 :     while (len > 0)
     280                 :     {
     281               7 :         res = pullf_read(pf, len, &tmp);
     282 GIC           7 :         if (res < 0)
     283                 :         {
     284                 :             /* so the caller must clear only on success */
     285 UIC           0 :             px_memset(tmpbuf, 0, total);
     286               0 :             return res;
     287                 :         }
     288 CBC           7 :         if (res == 0)
     289 GIC           6 :             break;
     290               1 :         memcpy(tmpbuf + total, tmp, res);
     291               1 :         total += res;
     292               1 :         len -= res;
     293 ECB             :     }
     294 CBC           7 :     return total;
     295 EUB             : }
     296 ECB             : 
     297                 : /*
     298                 :  * caller wants exactly len bytes and don't bother with references
     299                 :  */
     300                 : int
     301 CBC        1636 : pullf_read_fixed(PullFilter *src, int len, uint8 *dst)
     302 ECB             : {
     303                 :     int         res;
     304                 :     uint8      *p;
     305                 : 
     306 GIC        1636 :     res = pullf_read_max(src, len, &p, dst);
     307            1636 :     if (res < 0)
     308 UIC           0 :         return res;
     309 GIC        1636 :     if (res != len)
     310 ECB             :     {
     311 GIC           2 :         px_debug("pullf_read_fixed: need=%d got=%d", len, res);
     312               2 :         return PXE_PGP_CORRUPT_DATA;
     313 ECB             :     }
     314 GIC        1634 :     if (p != dst)
     315 CBC        1634 :         memcpy(dst, p, len);
     316 GIC        1634 :     return 0;
     317                 : }
     318                 : 
     319                 : /*
     320                 :  * read from MBuf
     321                 :  */
     322                 : static int
     323 CBC        2656 : pull_from_mbuf(void *arg, PullFilter *src, int len,
     324                 :                uint8 **data_p, uint8 *buf, int buflen)
     325 ECB             : {
     326 GIC        2656 :     MBuf       *mbuf = arg;
     327                 : 
     328            2656 :     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             116 : pullf_create_mbuf_reader(PullFilter **mp_p, MBuf *src)
     337                 : {
     338             116 :     return pullf_create(mp_p, &mbuf_reader, src, NULL);
     339                 : }
     340                 : 
     341                 : 
     342                 : /*
     343                 :  * PushFilter
     344 ECB             :  */
     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 EUB             : };
     355                 : 
     356                 : int
     357 GIC         193 : pushf_create(PushFilter **mp_p, const PushFilterOps *op, void *init_arg, PushFilter *next)
     358 ECB             : {
     359                 :     PushFilter *mp;
     360                 :     void       *priv;
     361                 :     int         res;
     362                 : 
     363 CBC         193 :     if (op->init != NULL)
     364 ECB             :     {
     365 CBC         155 :         res = op->init(next, init_arg, &priv);
     366             155 :         if (res < 0)
     367 LBC           0 :             return res;
     368                 :     }
     369 ECB             :     else
     370                 :     {
     371 GIC          38 :         priv = init_arg;
     372              38 :         res = 0;
     373                 :     }
     374 ECB             : 
     375 CBC         193 :     mp = palloc0(sizeof(*mp));
     376 GIC         193 :     mp->block_size = res;
     377 CBC         193 :     mp->op = op;
     378             193 :     mp->priv = priv;
     379 GIC         193 :     mp->next = next;
     380             193 :     if (mp->block_size > 0)
     381                 :     {
     382 CBC         120 :         mp->buf = palloc(mp->block_size);
     383 GIC         120 :         mp->pos = 0;
     384 ECB             :     }
     385                 :     else
     386                 :     {
     387 CBC          73 :         mp->buf = NULL;
     388 GIC          73 :         mp->pos = 0;
     389 ECB             :     }
     390 CBC         193 :     *mp_p = mp;
     391 GIC         193 :     return 0;
     392                 : }
     393 ECB             : 
     394                 : void
     395 CBC         193 : pushf_free(PushFilter *mp)
     396                 : {
     397 GIC         193 :     if (mp->op->free)
     398 CBC         155 :         mp->op->free(mp->priv);
     399                 : 
     400 GIC         193 :     if (mp->buf)
     401                 :     {
     402 CBC         120 :         px_memset(mp->buf, 0, mp->block_size);
     403 GIC         120 :         pfree(mp->buf);
     404 ECB             :     }
     405                 : 
     406 CBC         193 :     px_memset(mp, 0, sizeof(*mp));
     407 GIC         193 :     pfree(mp);
     408 CBC         193 : }
     409                 : 
     410                 : void
     411              36 : pushf_free_all(PushFilter *mp)
     412                 : {
     413                 :     PushFilter *tmp;
     414                 : 
     415             223 :     while (mp)
     416 ECB             :     {
     417 GIC         187 :         tmp = mp->next;
     418 GBC         187 :         pushf_free(mp);
     419 CBC         187 :         mp = tmp;
     420 EUB             :     }
     421 CBC          36 : }
     422                 : 
     423                 : static int
     424 GIC         487 : wrap_process(PushFilter *mp, const uint8 *data, int len)
     425                 : {
     426 ECB             :     int         res;
     427                 : 
     428 GIC         487 :     if (mp->op->push != NULL)
     429             487 :         res = mp->op->push(mp->next, mp->priv, data, len);
     430                 :     else
     431 UIC           0 :         res = pushf_write(mp->next, data, len);
     432 GIC         487 :     if (res > 0)
     433 UIC           0 :         return PXE_BUG;
     434 CBC         487 :     return res;
     435 ECB             : }
     436                 : 
     437                 : /* consumes all data, returns len on success */
     438                 : int
     439 GIC         757 : pushf_write(PushFilter *mp, const uint8 *data, int len)
     440 ECB             : {
     441                 :     int         need,
     442                 :                 res;
     443                 : 
     444                 :     /*
     445                 :      * no buffering
     446                 :      */
     447 CBC         757 :     if (mp->block_size <= 0)
     448 GIC         347 :         return wrap_process(mp, data, len);
     449 ECB             : 
     450                 :     /*
     451                 :      * try to empty buffer
     452                 :      */
     453 GIC         410 :     need = mp->block_size - mp->pos;
     454             410 :     if (need > 0)
     455                 :     {
     456             410 :         if (len < need)
     457 ECB             :         {
     458 CBC         397 :             memcpy(mp->buf + mp->pos, data, len);
     459 GBC         397 :             mp->pos += len;
     460 CBC         397 :             return 0;
     461                 :         }
     462 GIC          13 :         memcpy(mp->buf + mp->pos, data, need);
     463              13 :         len -= need;
     464              13 :         data += need;
     465 ECB             :     }
     466                 : 
     467                 :     /*
     468                 :      * buffer full, process
     469                 :      */
     470 CBC          13 :     res = wrap_process(mp, mp->buf, mp->block_size);
     471 GBC          13 :     if (res < 0)
     472 LBC           0 :         return res;
     473 CBC          13 :     mp->pos = 0;
     474                 : 
     475                 :     /*
     476                 :      * now process directly from data
     477 ECB             :      */
     478 CBC          20 :     while (len > 0)
     479 ECB             :     {
     480 GIC          19 :         if (len > mp->block_size)
     481                 :         {
     482 CBC           7 :             res = wrap_process(mp, data, mp->block_size);
     483 GIC           7 :             if (res < 0)
     484 UIC           0 :                 return res;
     485 GIC           7 :             data += mp->block_size;
     486 CBC           7 :             len -= mp->block_size;
     487                 :         }
     488                 :         else
     489                 :         {
     490              12 :             memcpy(mp->buf, data, len);
     491 GIC          12 :             mp->pos += len;
     492 CBC          12 :             break;
     493                 :         }
     494 ECB             :     }
     495 CBC          13 :     return 0;
     496 EUB             : }
     497                 : 
     498                 : int
     499 CBC          42 : pushf_flush(PushFilter *mp)
     500                 : {
     501 ECB             :     int         res;
     502                 : 
     503 GBC         241 :     while (mp)
     504                 :     {
     505 GIC         199 :         if (mp->block_size > 0)
     506 ECB             :         {
     507 GIC         120 :             res = wrap_process(mp, mp->buf, mp->pos);
     508 CBC         120 :             if (res < 0)
     509 UIC           0 :                 return res;
     510                 :         }
     511                 : 
     512 GIC         199 :         if (mp->op->flush)
     513                 :         {
     514             119 :             res = mp->op->flush(mp->next, mp->priv);
     515             119 :             if (res < 0)
     516 LBC           0 :                 return res;
     517                 :         }
     518 ECB             : 
     519 CBC         199 :         mp = mp->next;
     520                 :     }
     521              42 :     return 0;
     522 ECB             : }
     523                 : 
     524                 : 
     525                 : /*
     526                 :  * write to MBuf
     527                 :  */
     528                 : static int
     529 GIC         196 : push_into_mbuf(PushFilter *next, void *arg, const uint8 *data, int len)
     530                 : {
     531 CBC         196 :     int         res = 0;
     532 GIC         196 :     MBuf       *mbuf = arg;
     533 ECB             : 
     534 GIC         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 v1.16-55-g56c0a2a