LCOV - code coverage report
Current view: top level - common - membuf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 41 82 50.0 %
Date: 2015-11-05 17:10:59 Functions: 6 9 66.7 %

          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 <http://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        1027 : init_membuf (membuf_t *mb, int initiallen)
      48             : {
      49        1027 :   mb->len = 0;
      50        1027 :   mb->size = initiallen;
      51        1027 :   mb->out_of_core = 0;
      52        1027 :   mb->buf = xtrymalloc (initiallen);
      53        1027 :   if (!mb->buf)
      54           0 :     mb->out_of_core = errno;
      55        1027 : }
      56             : 
      57             : /* Same as init_membuf but allocates the buffer in secure memory.  */
      58             : void
      59         259 : init_membuf_secure (membuf_t *mb, int initiallen)
      60             : {
      61         259 :   mb->len = 0;
      62         259 :   mb->size = initiallen;
      63         259 :   mb->out_of_core = 0;
      64         259 :   mb->buf = xtrymalloc_secure (initiallen);
      65         259 :   if (!mb->buf)
      66           0 :     mb->out_of_core = errno;
      67         259 : }
      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        3336 : put_membuf (membuf_t *mb, const void *buf, size_t len)
      92             : {
      93        3336 :   if (mb->out_of_core || !len)
      94          33 :     return;
      95             : 
      96        3303 :   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        3303 :   memcpy (mb->buf + mb->len, buf, len);
     115        3303 :   mb->len += len;
     116             : }
     117             : 
     118             : 
     119             : void
     120        1672 : put_membuf_str (membuf_t *mb, const char *string)
     121             : {
     122        1672 :   put_membuf (mb, string, strlen (string));
     123        1672 : }
     124             : 
     125             : 
     126             : void
     127           0 : put_membuf_printf (membuf_t *mb, const char *format, ...)
     128             : {
     129             :   int rc;
     130             :   va_list arg_ptr;
     131             :   char *buf;
     132             : 
     133           0 :   va_start (arg_ptr, format);
     134           0 :   rc = gpgrt_vasprintf (&buf, format, arg_ptr);
     135           0 :   if (rc < 0)
     136           0 :     mb->out_of_core = errno ? errno : ENOMEM;
     137           0 :   va_end (arg_ptr);
     138           0 :   if (rc >= 0)
     139             :     {
     140           0 :       put_membuf (mb, buf, strlen (buf));
     141           0 :       xfree (buf);
     142             :     }
     143           0 : }
     144             : 
     145             : 
     146             : void *
     147        1286 : get_membuf (membuf_t *mb, size_t *len)
     148             : {
     149             :   char *p;
     150             : 
     151        1286 :   if (mb->out_of_core)
     152             :     {
     153           0 :       if (mb->buf)
     154             :         {
     155           0 :           wipememory (mb->buf, mb->len);
     156           0 :           xfree (mb->buf);
     157           0 :           mb->buf = NULL;
     158             :         }
     159           0 :       gpg_err_set_errno (mb->out_of_core);
     160           0 :       return NULL;
     161             :     }
     162             : 
     163        1286 :   p = mb->buf;
     164        1286 :   if (len)
     165         789 :     *len = mb->len;
     166        1286 :   mb->buf = NULL;
     167        1286 :   mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */
     168        1286 :   return p;
     169             : }
     170             : 
     171             : 
     172             : /* Same as get_membuf but shrinks the reallocated space to the
     173             :    required size.  */
     174             : void *
     175          32 : get_membuf_shrink (membuf_t *mb, size_t *len)
     176             : {
     177             :   void *p, *pp;
     178             :   size_t dummylen;
     179             : 
     180          32 :   if (!len)
     181          32 :     len = &dummylen;
     182             : 
     183          32 :   p = get_membuf (mb, len);
     184          32 :   if (!p)
     185           0 :     return NULL;
     186          32 :   if (*len)
     187             :     {
     188          32 :       pp = xtryrealloc (p, *len);
     189          32 :       if (pp)
     190          32 :         p = pp;
     191             :     }
     192             : 
     193          32 :   return p;
     194             : }
     195             : 
     196             : 
     197             : /* Peek at the membuf MB.  On success a pointer to the buffer is
     198             :    returned which is valid until the next operation on MB.  If LEN is
     199             :    not NULL the current LEN of the buffer is stored there.  On error
     200             :    NULL is returned and ERRNO is set.  */
     201             : const void *
     202           0 : peek_membuf (membuf_t *mb, size_t *len)
     203             : {
     204             :   const char *p;
     205             : 
     206           0 :   if (mb->out_of_core)
     207             :     {
     208           0 :       gpg_err_set_errno (mb->out_of_core);
     209           0 :       return NULL;
     210             :     }
     211             : 
     212           0 :   p = mb->buf;
     213           0 :   if (len)
     214           0 :     *len = mb->len;
     215           0 :   return p;
     216             : }

Generated by: LCOV version 1.11