LCOV - code coverage report
Current view: top level - contrib/pgcrypto - mbuf.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 207 226 91.6 %
Date: 2020-06-01 09:07:10 Functions: 24 26 92.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13