Add parameter checks and extend documentation of estream.
authorWerner Koch <wk@gnupg.org>
Tue, 29 Nov 2011 17:02:05 +0000 (18:02 +0100)
committerWerner Koch <wk@gnupg.org>
Wed, 30 Nov 2011 16:34:49 +0000 (17:34 +0100)
* estream.c (func_mem_create): Don't set FUNC_REALLOC if GROW is not
set.  Require FUNC_REALLOC if DATA is NULL and FUNC_FREE is given.

common/ChangeLog
common/estream.c

index 943862a..d5682fc 100644 (file)
@@ -1,5 +1,9 @@
 2011-11-29  Werner Koch  <wk@g10code.com>
 
+       * estream.c (func_mem_create): Don't set FUNC_REALLOC if GROW is
+       not set.  Require FUNC_REALLOC if DATA is NULL and FUNC_FREE is
+       given.
+
        * dns-cert.c: Use new CERTTYPE_ constants for better readability.
 
 2011-11-28  Werner Koch  <wk@g10code.com>
index 8087a62..20d365a 100644 (file)
@@ -539,7 +539,9 @@ typedef struct estream_cookie_mem
    supplied buffer with the initial conetnt of the memory buffer.  If
    DATA is NULL, DATA_N and DATA_LEN need to be 0 as well.  If DATA is
    not NULL, DATA_N gives the allocated size of DATA and DATA_LEN the
-   used length in DATA.  */
+   used length in DATA.  If this fucntion succeeds DATA is now owned
+   by this function.  If GROW is false FUNC_REALLOC is not
+   required. */
 static int
 func_mem_create (void *ES__RESTRICT *ES__RESTRICT cookie,
                  unsigned char *ES__RESTRICT data, size_t data_n,
@@ -557,6 +559,11 @@ func_mem_create (void *ES__RESTRICT *ES__RESTRICT cookie,
       _set_errno (EINVAL);
       return -1;
     }
+  if (grow && func_free && !func_realloc)
+    {
+      _set_errno (EINVAL);
+      return -1;
+    }
 
   mem_cookie = mem_alloc (sizeof (*mem_cookie));
   if (!mem_cookie)
@@ -571,7 +578,8 @@ func_mem_create (void *ES__RESTRICT *ES__RESTRICT cookie,
       mem_cookie->data_len = data_len;
       mem_cookie->block_size = block_size;
       mem_cookie->flags.grow = !!grow;
-      mem_cookie->func_realloc = func_realloc ? func_realloc : mem_realloc;
+      mem_cookie->func_realloc
+        = grow? (func_realloc ? func_realloc : mem_realloc) : NULL;
       mem_cookie->func_free = func_free ? func_free : mem_free;
       *cookie = mem_cookie;
       err = 0;
@@ -622,7 +630,8 @@ es_func_mem_write (void *cookie, const void *buffer, size_t size)
   assert (mem_cookie->memory_size >= mem_cookie->offset);
   nleft = mem_cookie->memory_size - mem_cookie->offset;
 
-  /* If we are not allowed to grow limit the size to the left space.  */
+  /* If we are not allowed to grow the buffer, limit the size to the
+     left space.  */
   if (!mem_cookie->flags.grow && size > nleft)
     size = nleft;
 
@@ -663,6 +672,7 @@ es_func_mem_write (void *cookie, const void *buffer, size_t size)
           return -1;
         }
 
+      assert (mem_cookie->func_realloc);
       newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize);
       if (!newbuf)
         return -1;
@@ -738,6 +748,7 @@ es_func_mem_seek (void *cookie, off_t *offset, int whence)
           return -1;
         }
 
+      assert (mem_cookie->func_realloc);
       newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize);
       if (!newbuf)
         return -1;
@@ -2580,23 +2591,33 @@ es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
 
 
 \f
+/* Create a new estream object in memory.  If DATA is not NULL this
+   buffer will be used as the memory buffer; thus after this functions
+   returns with the success the the memory at DATA belongs to the new
+   estream.  The allocated length of DATA is given by DATA_LEN and its
+   used length by DATA_N.  Usually this is malloced buffer; if a
+   static buffer is provided, the caller must pass false for GROW and
+   provide a dummy function for FUNC_FREE.  FUNC_FREE and FUNC_REALLOC
+   allow the caller to provide custom functions for realloc and free
+   to be used by the new estream object.  Note that the realloc
+   function is also used for initial allocation.  If DATA is NULL a
+   buffer is internally allocated; either using internal function or
+   those provide by the caller.  It is an error to provide a realloc
+   function but no free function.  Providing only a free function is
+   allowed as long as GROW is false.  */
 estream_t
 es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
          unsigned int grow,
          func_realloc_t func_realloc, func_free_t func_free,
          const char *ES__RESTRICT mode)
 {
+  int create_called = 0;
+  estream_t stream = NULL;
+  void *cookie = NULL;
   unsigned int modeflags;
-  int create_called;
-  estream_t stream;
-  void *cookie;
   int err;
   es_syshd_t syshd;
 
-  cookie = 0;
-  stream = NULL;
-  create_called = 0;
-
   err = parse_mode (mode, &modeflags, NULL);
   if (err)
     goto out;