LCOV - code coverage report
Current view: top level - common - membuf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 49 87 56.3 %
Date: 2016-11-29 15:00:56 Functions: 7 10 70.0 %

          Line data    Source code
       1             : /* membuf.c - A simple implementation of a dynamic buffer.
       2             :  * Copyright (C) 2001, 2003, 2009, 2011 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2013 Werner Koch
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * This file is free software; you can redistribute it and/or modify
       8             :  * it under the terms of either
       9             :  *
      10             :  *   - the GNU Lesser General Public License as published by the Free
      11             :  *     Software Foundation; either version 3 of the License, or (at
      12             :  *     your option) any later version.
      13             :  *
      14             :  * or
      15             :  *
      16             :  *   - the GNU General Public License as published by the Free
      17             :  *     Software Foundation; either version 2 of the License, or (at
      18             :  *     your option) any later version.
      19             :  *
      20             :  * or both in parallel, as here.
      21             :  *
      22             :  * This file is distributed in the hope that it will be useful,
      23             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      24             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      25             :  * GNU General Public License for more details.
      26             :  *
      27             :  * You should have received a copy of the GNU General Public License
      28             :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      29             :  */
      30             : 
      31             : #include <config.h>
      32             : #include <stdlib.h>
      33             : #include <errno.h>
      34             : #include <stdarg.h>
      35             : 
      36             : #include "util.h"
      37             : #include "membuf.h"
      38             : 
      39             : 
      40             : /* A simple implementation of a dynamic buffer.  Use init_membuf() to
      41             :    create a buffer, put_membuf to append bytes and get_membuf to
      42             :    release and return the buffer.  Allocation errors are detected but
      43             :    only returned at the final get_membuf(), this helps not to clutter
      44             :    the code with out of core checks.  */
      45             : 
      46             : void
      47        1212 : init_membuf (membuf_t *mb, int initiallen)
      48             : {
      49        1212 :   mb->len = 0;
      50        1212 :   mb->size = initiallen;
      51        1212 :   mb->out_of_core = 0;
      52        1212 :   mb->buf = xtrymalloc (initiallen);
      53        1212 :   if (!mb->buf)
      54           0 :     mb->out_of_core = errno;
      55        1212 : }
      56             : 
      57             : /* Same as init_membuf but allocates the buffer in secure memory.  */
      58             : void
      59         288 : init_membuf_secure (membuf_t *mb, int initiallen)
      60             : {
      61         288 :   mb->len = 0;
      62         288 :   mb->size = initiallen;
      63         288 :   mb->out_of_core = 0;
      64         288 :   mb->buf = xtrymalloc_secure (initiallen);
      65         288 :   if (!mb->buf)
      66           0 :     mb->out_of_core = errno;
      67         288 : }
      68             : 
      69             : 
      70             : /* Shift the the content of the membuf MB by AMOUNT bytes.  The next
      71             :    operation will then behave as if AMOUNT bytes had not been put into
      72             :    the buffer.  If AMOUNT is greater than the actual accumulated
      73             :    bytes, the membuf is basically reset to its initial state.  */
      74             : void
      75           0 : clear_membuf (membuf_t *mb, size_t amount)
      76             : {
      77             :   /* No need to clear if we are already out of core.  */
      78           0 :   if (mb->out_of_core)
      79           0 :     return;
      80           0 :   if (amount >= mb->len)
      81           0 :     mb->len = 0;
      82             :   else
      83             :     {
      84           0 :       mb->len -= amount;
      85           0 :       memmove (mb->buf, mb->buf+amount, mb->len);
      86             :     }
      87             : }
      88             : 
      89             : 
      90             : void
      91        3372 : put_membuf (membuf_t *mb, const void *buf, size_t len)
      92             : {
      93        3372 :   if (mb->out_of_core || !len)
      94          64 :     return;
      95             : 
      96        3308 :   if (mb->len + len >= mb->size)
      97             :     {
      98             :       char *p;
      99             : 
     100           0 :       mb->size += len + 1024;
     101           0 :       p = xtryrealloc (mb->buf, mb->size);
     102           0 :       if (!p)
     103             :         {
     104           0 :           mb->out_of_core = errno ? errno : ENOMEM;
     105             :           /* Wipe out what we already accumulated.  This is required
     106             :              in case we are storing sensitive data here.  The membuf
     107             :              API does not provide another way to cleanup after an
     108             :              error. */
     109           0 :           wipememory (mb->buf, mb->len);
     110           0 :           return;
     111             :         }
     112           0 :       mb->buf = p;
     113             :     }
     114        3308 :   memcpy (mb->buf + mb->len, buf, len);
     115        3308 :   mb->len += len;
     116             : }
     117             : 
     118             : 
     119             : /* A variant of put_membuf accepting a void * and returning a
     120             :    gpg_error_t (which will always return 0) to be used as a generic
     121             :    callback handler.  This function also allows buffer to be NULL.  */
     122             : gpg_error_t
     123         972 : put_membuf_cb (void *opaque, const void *buf, size_t len)
     124             : {
     125         972 :   membuf_t *data = opaque;
     126             : 
     127         972 :   if (buf)
     128         972 :     put_membuf (data, buf, len);
     129         972 :   return 0;
     130             : }
     131             : 
     132             : 
     133             : void
     134         467 : put_membuf_str (membuf_t *mb, const char *string)
     135             : {
     136         467 :   put_membuf (mb, string, strlen (string));
     137         467 : }
     138             : 
     139             : 
     140             : void
     141           0 : put_membuf_printf (membuf_t *mb, const char *format, ...)
     142             : {
     143             :   int rc;
     144             :   va_list arg_ptr;
     145             :   char *buf;
     146             : 
     147           0 :   va_start (arg_ptr, format);
     148           0 :   rc = gpgrt_vasprintf (&buf, format, arg_ptr);
     149           0 :   if (rc < 0)
     150           0 :     mb->out_of_core = errno ? errno : ENOMEM;
     151           0 :   va_end (arg_ptr);
     152           0 :   if (rc >= 0)
     153             :     {
     154           0 :       put_membuf (mb, buf, strlen (buf));
     155           0 :       xfree (buf);
     156             :     }
     157           0 : }
     158             : 
     159             : 
     160             : void *
     161        1501 : get_membuf (membuf_t *mb, size_t *len)
     162             : {
     163             :   char *p;
     164             : 
     165        1501 :   if (mb->out_of_core)
     166             :     {
     167           1 :       if (mb->buf)
     168             :         {
     169           0 :           wipememory (mb->buf, mb->len);
     170           0 :           xfree (mb->buf);
     171           0 :           mb->buf = NULL;
     172             :         }
     173           1 :       gpg_err_set_errno (mb->out_of_core);
     174           1 :       return NULL;
     175             :     }
     176             : 
     177        1500 :   p = mb->buf;
     178        1500 :   if (len)
     179         910 :     *len = mb->len;
     180        1500 :   mb->buf = NULL;
     181        1500 :   mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */
     182        1500 :   return p;
     183             : }
     184             : 
     185             : 
     186             : /* Same as get_membuf but shrinks the reallocated space to the
     187             :    required size.  */
     188             : void *
     189          67 : get_membuf_shrink (membuf_t *mb, size_t *len)
     190             : {
     191             :   void *p, *pp;
     192             :   size_t dummylen;
     193             : 
     194          67 :   if (!len)
     195          67 :     len = &dummylen;
     196             : 
     197          67 :   p = get_membuf (mb, len);
     198          67 :   if (!p)
     199           0 :     return NULL;
     200          67 :   if (*len)
     201             :     {
     202          67 :       pp = xtryrealloc (p, *len);
     203          67 :       if (pp)
     204          67 :         p = pp;
     205             :     }
     206             : 
     207          67 :   return p;
     208             : }
     209             : 
     210             : 
     211             : /* Peek at the membuf MB.  On success a pointer to the buffer is
     212             :    returned which is valid until the next operation on MB.  If LEN is
     213             :    not NULL the current LEN of the buffer is stored there.  On error
     214             :    NULL is returned and ERRNO is set.  */
     215             : const void *
     216           0 : peek_membuf (membuf_t *mb, size_t *len)
     217             : {
     218             :   const char *p;
     219             : 
     220           0 :   if (mb->out_of_core)
     221             :     {
     222           0 :       gpg_err_set_errno (mb->out_of_core);
     223           0 :       return NULL;
     224             :     }
     225             : 
     226           0 :   p = mb->buf;
     227           0 :   if (len)
     228           0 :     *len = mb->len;
     229           0 :   return p;
     230             : }

Generated by: LCOV version 1.11