summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2006-06-21 09:19:13 +0000
committerWerner Koch <wk@gnupg.org>2006-06-21 09:19:13 +0000
commiteb9ebf3b7f1bceec03fa8785aa1138be29a73ff2 (patch)
tree9b1c180778f8e8c4cd9d7ee27406edc7a8c0beef
parent54c8861ff110789261ee546cc76e19c3199c2120 (diff)
downloadlibgcrypt-eb9ebf3b7f1bceec03fa8785aa1138be29a73ff2.tar.gz
Changed xmalloc style calls to proper malloc calls with error returns at
many (but not all) places.
-rw-r--r--NEWS3
-rw-r--r--TODO11
-rw-r--r--cipher/ChangeLog8
-rw-r--r--cipher/md.c63
-rw-r--r--cipher/pubkey.c84
-rw-r--r--cipher/rsa.c21
-rw-r--r--src/ChangeLog14
-rw-r--r--src/global.c35
-rw-r--r--src/sexp.c226
9 files changed, 342 insertions, 123 deletions
diff --git a/NEWS b/NEWS
index bd68be28..1d30c1cd 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,9 @@ gcry_fast_random_poll NEW
gcry_pk_algo_name CHANGED (minor change in respect to return value)
gcry_cipher_algo_name CHANGED (minor change in respect to return value)
GCRY_MD_SHA224 NEW
+GCRY_PK_USAGE_CERT NEW
+GCRY_PK_USAGE_AUTH NEW
+GCRY_PK_USAGE_UNKN NEW
FIXME: Please add API changes immediatley so that we don't
forget about them.
diff --git a/TODO b/TODO
index 5986ddcd..365d8f7c 100644
--- a/TODO
+++ b/TODO
@@ -48,3 +48,14 @@ What's left to do -*- outline -*-
initialization of the pool and in case the entropy collectros need
to run that bunch of Unix utilities we don't waste their precious
results.
+
+* Out of memory handler for secure memory shopuld do proper logging
+
+ There is no shortage of standard memory, so logging is most likely
+ possible.
+
+* signed vs. unsigned.
+ Sync the code with 1.2 where we have fixed all these issues.
+
+
+
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 70f1cf8b..0907b887 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,11 @@
+2006-06-21 Werner Koch <wk@g10code.com>
+
+ * rsa.c (_gcry_rsa_generate): Replace xcalloc by calloc.
+ * pubkey.c (gcry_pk_encrypt, gcry_pk_sign): Ditto.
+ (sexp_to_key, sexp_to_sig, sexp_to_enc, gcry_pk_encrypt)
+ (gcry_pk_sign, gcry_pk_genkey, gcry_pk_get_keygrip): Ditto.
+ * md.c (md_copy): Ditto.
+
2006-04-22 Moritz Schulte <moritz@g10code.com>
* random-daemon.c (_gcry_daemon_initialize_basics): New argument:
diff --git a/cipher/md.c b/cipher/md.c
index b5cd9401..7942e70d 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -440,8 +440,8 @@ md_open (gcry_md_hd_t *h, int algo, int secure, int hmac)
}
if (! ctx->macpads)
{
- md_close (hd);
err = gpg_err_code_from_errno (errno);
+ md_close (hd);
}
}
}
@@ -602,8 +602,8 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
b->macpads = gcry_malloc_secure (2*(a->macpads_Bsize));
if (! b->macpads)
{
- md_close (bhd);
err = gpg_err_code_from_errno (errno);
+ md_close (bhd);
}
else
memcpy (b->macpads, a->macpads, (2*(a->macpads_Bsize)));
@@ -612,32 +612,41 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
/* Copy the complete list of algorithms. The copied list is
reversed, but that doesn't matter. */
- if (! err)
- for (ar = a->list; ar; ar = ar->next)
- {
- if (a->secure)
- br = gcry_xmalloc_secure (sizeof *br
- + ar->digest->contextsize
- - sizeof(ar->context));
- else
- br = gcry_xmalloc (sizeof *br
- + ar->digest->contextsize
- - sizeof (ar->context));
- memcpy (br, ar,
- sizeof (*br) + ar->digest->contextsize - sizeof (ar->context));
- br->next = b->list;
- b->list = br;
-
- /* Add a reference to the module. */
- ath_mutex_lock (&digests_registered_lock);
- _gcry_module_use (br->module);
- ath_mutex_unlock (&digests_registered_lock);
- }
-
- if (a->debug)
+ if (!err)
+ {
+ for (ar = a->list; ar; ar = ar->next)
+ {
+ if (a->secure)
+ br = gcry_malloc_secure (sizeof *br
+ + ar->digest->contextsize
+ - sizeof(ar->context));
+ else
+ br = gcry_malloc (sizeof *br
+ + ar->digest->contextsize
+ - sizeof (ar->context));
+ if (!br)
+ {
+ err = gpg_err_code_from_errno (errno);
+ md_close (bhd);
+ break;
+ }
+
+ memcpy (br, ar, (sizeof (*br) + ar->digest->contextsize
+ - sizeof (ar->context)));
+ br->next = b->list;
+ b->list = br;
+
+ /* Add a reference to the module. */
+ ath_mutex_lock (&digests_registered_lock);
+ _gcry_module_use (br->module);
+ ath_mutex_unlock (&digests_registered_lock);
+ }
+ }
+
+ if (a->debug && !err)
md_start_debug (bhd, "unknown");
- if (! err)
+ if (!err)
*b_hd = bhd;
return err;
@@ -822,7 +831,7 @@ gcry_md_ctl (gcry_md_hd_t hd, int cmd, byte *buffer, size_t buflen)
rc = gcry_err_code (gcry_md_setkey (hd, buffer, buflen));
break;
case GCRYCTL_START_DUMP:
- md_start_debug (hd, buffer);
+ md_start_debug (hd, (char*)buffer);
break;
case GCRYCTL_STOP_DUMP:
md_stop_debug( hd );
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 8aa13c2e..c2efdfc4 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -786,7 +786,15 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray,
}
{
- char *name_terminated = gcry_xmalloc (n + 1);
+ char *name_terminated;
+
+ name_terminated = gcry_malloc (n + 1);
+ if (!name_terminated)
+ {
+ err = gpg_err_code_from_errno (errno);
+ gcry_sexp_release (list);
+ return err;
+ }
memcpy (name_terminated, name, n);
name_terminated[n] = 0;
@@ -876,7 +884,17 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray,
}
{
- char *name_terminated = gcry_xmalloc (n + 1);
+ char *name_terminated;
+
+ name_terminated = gcry_malloc (n + 1);
+ if (!name_terminated)
+ {
+ err = gcry_err_code_from_errno (errno);
+ gcry_sexp_release (l2);
+ gcry_sexp_release (list);
+ return err;
+ }
+
memcpy (name_terminated, name, n);
name_terminated[n] = 0;
@@ -1026,7 +1044,14 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo,
}
{
- char *name_terminated = gcry_xmalloc (n + 1);
+ char *name_terminated;
+
+ name_terminated = gcry_malloc (n + 1);
+ if (!name_terminated)
+ {
+ err = gcry_err_code_from_errno (errno);
+ goto leave;
+ }
memcpy (name_terminated, name, n);
name_terminated[n] = 0;
@@ -1391,7 +1416,12 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
goto leave;
/* Now we can encrypt DATA to CIPH. */
- ciph = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*ciph));
+ ciph = gcry_calloc (strlen (algo_elems) + 1, sizeof (*ciph));
+ if (!ciph)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
rc = pubkey_encrypt (module->mod_id, ciph, data, pkey, flags);
mpi_free (data);
data = NULL;
@@ -1407,7 +1437,12 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
void **arg_list;
/* Build the string. */
- string = p = gcry_xmalloc (needed);
+ string = p = gcry_malloc (needed);
+ if (!string)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
p = stpcpy ( p, "(enc-val(" );
p = stpcpy ( p, algo_name );
for (i=0; algo_elems[i]; i++ )
@@ -1609,7 +1644,12 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
if (rc)
goto leave;
- result = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*result));
+ result = gcry_calloc (strlen (algo_elems) + 1, sizeof (*result));
+ if (!result)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
rc = pubkey_sign (module->mod_id, result, hash, skey);
if (rc)
goto leave;
@@ -1625,7 +1665,12 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
needed += 10 * nelem;
/* Build the string. */
- string = p = gcry_xmalloc (needed);
+ string = p = gcry_malloc (needed);
+ if (!string)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
p = stpcpy (p, "(sig-val(");
p = stpcpy (p, algo_name);
for (i = 0; algo_elems[i]; i++)
@@ -1847,7 +1892,12 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
goto leave;
}
- name_terminated = gcry_xmalloc (n + 1);
+ name_terminated = gcry_malloc (n + 1);
+ if (!name_terminated)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
memcpy (name_terminated, name, n);
name_terminated[n] = 0;
ath_mutex_lock (&pubkeys_registered_lock);
@@ -1908,7 +1958,12 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
goto leave;
}
- name_terminated = gcry_xmalloc (n + 1);
+ name_terminated = gcry_malloc (n + 1);
+ if (!name_terminated)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
memcpy (name_terminated, name, n);
name_terminated[n] = 0;
nbits = (unsigned int) strtoul (name_terminated, NULL, 0);
@@ -1935,7 +1990,12 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
/* Build the string. */
nelem = 0;
- string = p = gcry_xmalloc (needed);
+ string = p = gcry_malloc (needed);
+ if (!string)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
p = stpcpy (p, "(key-data");
p = stpcpy (p, "(public-key(");
p = stpcpy (p, algo_name);
@@ -2103,7 +2163,9 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
goto fail; /* Invalid structure of object. */
{
- char *name_terminated = gcry_xmalloc (n + 1);
+ char *name_terminated = gcry_malloc (n + 1);
+ if (!name_terminated)
+ goto fail;
memcpy (name_terminated, name, n);
name_terminated[n] = 0;
ath_mutex_lock (&pubkeys_registered_lock);
diff --git a/cipher/rsa.c b/cipher/rsa.c
index 9cceba21..18fda93e 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -28,6 +28,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
+
#include "g10lib.h"
#include "mpi.h"
#include "cipher.h"
@@ -440,6 +442,8 @@ _gcry_rsa_generate (int algo, unsigned int nbits, unsigned long use_e,
gcry_mpi_t *skey, gcry_mpi_t **retfactors)
{
RSA_secret_key sk;
+ gpg_err_code_t rc;
+ int i;
generate (&sk, nbits, use_e);
skey[0] = sk.n;
@@ -449,10 +453,21 @@ _gcry_rsa_generate (int algo, unsigned int nbits, unsigned long use_e,
skey[4] = sk.q;
skey[5] = sk.u;
- /* make an empty list of factors */
- *retfactors = gcry_xcalloc( 1, sizeof **retfactors );
+ /* Make an empty list of factors. */
+ *retfactors = gcry_calloc ( 1, sizeof **retfactors );
+ if (!*retfactors)
+ {
+ rc = gpg_err_code_from_errno (errno);
+ for (i=0; i <= 5; i++)
+ {
+ gcry_mpi_release (skey[i]);
+ skey[i] = NULL;
+ }
+ }
+ else
+ rc = 0;
- return GPG_ERR_NO_ERROR;
+ return rc;
}
diff --git a/src/ChangeLog b/src/ChangeLog
index a751dd3f..e43e58ae 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,17 @@
+2006-06-21 Werner Koch <wk@g10code.com>
+
+ * global.c (gcry_xcalloc, gcry_xcalloc_secure): Made safe against
+ integer overflow.
+
+ * sexp.c (make_space): Return an error on out of core.
+ (sexp_sscan): Remove all xmalloc style calls and return proper
+ error codes on allocation failures.
+ (gcry_sexp_find_token): Ditto.
+ (gcry_sexp_nth):
+
+ * sexp.c (gcry_sexp_find_token): Re-indented and removed a cruft
+ "while(level);" which fortunately had no effect.
+
2006-04-28 Werner Koch <wk@g10code.com>
* gcrypt.h (GCRY_MD_SHA224): Change value from 306 to 11 to match
diff --git a/src/global.c b/src/global.c
index 399fc769..7c52070c 100644
--- a/src/global.c
+++ b/src/global.c
@@ -1,6 +1,6 @@
/* global.c - global control functions
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
- * 2004, 2005 Free Software Foundation, Inc.
+ * 2004, 2005, 2006 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
@@ -659,20 +659,41 @@ gcry_xmalloc_secure( size_t n )
return p;
}
+
void *
gcry_xcalloc( size_t n, size_t m )
{
- void *p = gcry_xmalloc( n*m );
- memset( p, 0, n*m );
- return p;
+ size_t nbytes;
+ void *p;
+
+ nbytes = n * m;
+ if (m && nbytes / m != n)
+ {
+ errno = ENOMEM;
+ _gcry_fatal_error(gpg_err_code_from_errno (errno), NULL );
+ }
+
+ p = gcry_xmalloc ( nbytes );
+ memset ( p, 0, nbytes );
+ return p;
}
void *
gcry_xcalloc_secure( size_t n, size_t m )
{
- void *p = gcry_xmalloc_secure( n* m );
- memset( p, 0, n*m );
- return p;
+ size_t nbytes;
+ void *p;
+
+ nbytes = n * m;
+ if (m && nbytes / m != n)
+ {
+ errno = ENOMEM;
+ _gcry_fatal_error(gpg_err_code_from_errno (errno), NULL );
+ }
+
+ p = gcry_xmalloc_secure ( nbytes );
+ memset ( p, 0, nbytes );
+ return p;
}
char *
diff --git a/src/sexp.c b/src/sexp.c
index 8dc7313a..1d3a9cfe 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
+#include <errno.h>
#define GCRYPT_NO_MPI_MACROS 1
#include "g10lib.h"
@@ -367,61 +368,78 @@ gcry_sexp_prepend( const gcry_sexp_t a, const gcry_sexp_t n )
gcry_sexp_t
gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen )
{
- const byte *p;
- DATALEN n;
+ const byte *p;
+ DATALEN n;
+
+ if ( !list )
+ return NULL;
- if ( !list )
- return NULL;
+ if ( !toklen )
+ toklen = strlen(tok);
- if( !toklen )
- toklen = strlen(tok);
- p = list->d;
- while ( *p != ST_STOP ) {
- if ( *p == ST_OPEN && p[1] == ST_DATA ) {
- const byte *head = p;
-
- p += 2;
- memcpy ( &n, p, sizeof n ); p += sizeof n;
- if ( n == toklen && !memcmp( p, tok, toklen ) ) { /* found it */
- gcry_sexp_t newlist;
- byte *d;
- int level = 1;
-
- /* look for the end of the list */
- for ( p += n; level; p++ ) {
- if ( *p == ST_DATA ) {
+ p = list->d;
+ while ( *p != ST_STOP )
+ {
+ if ( *p == ST_OPEN && p[1] == ST_DATA )
+ {
+ const byte *head = p;
+
+ p += 2;
+ memcpy ( &n, p, sizeof n );
+ p += sizeof n;
+ if ( n == toklen && !memcmp( p, tok, toklen ) )
+ { /* found it */
+ gcry_sexp_t newlist;
+ byte *d;
+ int level = 1;
+
+ /* Look for the end of the list. */
+ for ( p += n; level; p++ )
+ {
+ if ( *p == ST_DATA )
+ {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
- p--; /* compensate for later increment */
+ p--; /* Compensate for later increment. */
}
- else if ( *p == ST_OPEN ) {
- level++;
+ else if ( *p == ST_OPEN )
+ {
+ level++;
}
- else if ( *p == ST_CLOSE ) {
- level--;
+ else if ( *p == ST_CLOSE )
+ {
+ level--;
}
- else if ( *p == ST_STOP ) {
- BUG ();
+ else if ( *p == ST_STOP )
+ {
+ BUG ();
}
- } while ( level );
- n = p - head;
-
- newlist = gcry_xmalloc ( sizeof *newlist + n );
- d = newlist->d;
- memcpy ( d, head, n ); d += n;
- *d++ = ST_STOP;
- return normalize ( newlist );
+ }
+ n = p - head;
+
+ newlist = gcry_malloc ( sizeof *newlist + n );
+ if (!newlist)
+ {
+ /* No way to return an error code, so we can only
+ return Not Found. */
+ return NULL;
+ }
+ d = newlist->d;
+ memcpy ( d, head, n ); d += n;
+ *d++ = ST_STOP;
+ return normalize ( newlist );
}
- p += n;
+ p += n;
}
- else if ( *p == ST_DATA ) {
- memcpy ( &n, ++p, sizeof n ); p += sizeof n;
- p += n;
+ else if ( *p == ST_DATA )
+ {
+ memcpy ( &n, ++p, sizeof n ); p += sizeof n;
+ p += n;
}
- else
- p++;
+ else
+ p++;
}
- return NULL;
+ return NULL;
}
/****************
@@ -462,9 +480,8 @@ gcry_sexp_length( const gcry_sexp_t list )
-/****************
- * Extract the CAR of the given list
- */
+/* Extract the CAR of the given list. May return NULL for bad lists
+ or memory failure. */
gcry_sexp_t
gcry_sexp_nth( const gcry_sexp_t list, int number )
{
@@ -503,7 +520,9 @@ gcry_sexp_nth( const gcry_sexp_t list, int number )
if ( *p == ST_DATA ) {
memcpy ( &n, p, sizeof n ); p += sizeof n;
- newlist = gcry_xmalloc ( sizeof *newlist + n + 1 );
+ newlist = gcry_malloc ( sizeof *newlist + n + 1 );
+ if (!newlist)
+ return NULL;
d = newlist->d;
memcpy ( d, p, n ); d += n;
*d++ = ST_STOP;
@@ -531,7 +550,9 @@ gcry_sexp_nth( const gcry_sexp_t list, int number )
} while ( level );
n = p + 1 - head;
- newlist = gcry_xmalloc ( sizeof *newlist + n );
+ newlist = gcry_malloc ( sizeof *newlist + n );
+ if (!newlist)
+ return NULL;
d = newlist->d;
memcpy ( d, head, n ); d += n;
*d++ = ST_STOP;
@@ -723,7 +744,9 @@ gcry_sexp_cdr( const gcry_sexp_t list )
} while ( level );
n = p - head;
- newlist = gcry_xmalloc ( sizeof *newlist + n + 2 );
+ newlist = gcry_malloc ( sizeof *newlist + n + 2 );
+ if (!newlist)
+ return NULL;
d = newlist->d;
*d++ = ST_OPEN;
memcpy ( d, head, n ); d += n;
@@ -775,21 +798,29 @@ struct make_space_ctx {
byte *pos;
};
-static void
+static gpg_err_code_t
make_space ( struct make_space_ctx *c, size_t n )
{
- size_t used = c->pos - c->sexp->d;
-
- if ( used + n + sizeof(DATALEN) + 1 >= c->allocated ) {
- gcry_sexp_t newsexp;
- byte *newhead;
-
- c->allocated += 2*(n+sizeof(DATALEN)+1);
- newsexp = gcry_xrealloc ( c->sexp, sizeof *newsexp + c->allocated - 1 );
- newhead = newsexp->d;
- c->pos = newhead + used;
- c->sexp = newsexp;
+ size_t used = c->pos - c->sexp->d;
+
+ if ( used + n + sizeof(DATALEN) + 1 >= c->allocated )
+ {
+ gcry_sexp_t newsexp;
+ byte *newhead;
+ size_t newsize;
+
+ newsize = c->allocated + 2*(n+sizeof(DATALEN)+1);
+ if (newsize <= c->allocated)
+ return GPG_ERR_TOO_LARGE;
+ newsexp = gcry_realloc ( c->sexp, sizeof *newsexp + newsize - 1);
+ if (!newsexp)
+ return gpg_err_code_from_errno (errno);
+ c->allocated = newsize;
+ newhead = newsexp->d;
+ c->pos = newhead + used;
+ c->sexp = newsexp;
}
+ return 0;
}
@@ -891,7 +922,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
const char *buffer, size_t length, int argflag,
va_list arg_ptr, void **arg_list)
{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
+ gcry_err_code_t err = 0;
static const char tokenchars[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -913,8 +944,6 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
int arg_counter = 0;
int level = 0;
- /* FIXME: invent better error codes (?). */
-
if (!erroff)
erroff = &dummy_erroff;
@@ -931,21 +960,41 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
} \
while (0)
-#define MAKE_SPACE(n) do { make_space ( &c, (n) ); } while (0)
+ /* The MAKE_SPACE macro is used before each store operation to
+ ensure that the buffer is large enough. It requires a global
+ context named C and jumps out to the label LEAVE on error! It
+ also sets ERROFF using the variables BUFFER and P. */
+#define MAKE_SPACE(n) do { \
+ gpg_err_code_t _ms_err = make_space (&c, (n)); \
+ if (_ms_err) \
+ { \
+ err = _ms_err; \
+ *erroff = p - buffer; \
+ goto leave; \
+ } \
+ } while (0)
+
+ /* The STORE_LEN macro is used to store the length N at buffer P. */
#define STORE_LEN(p,n) do { \
DATALEN ashort = (n); \
memcpy ( (p), &ashort, sizeof(ashort) ); \
(p) += sizeof (ashort); \
} while (0)
- /* We assume that the internal representation takes less memory
- * than the provided one. However, we add space for one extra datalen
- * so that the code which does the ST_CLOSE can use MAKE_SPACE */
+ /* We assume that the internal representation takes less memory than
+ the provided one. However, we add space for one extra datalen so
+ that the code which does the ST_CLOSE can use MAKE_SPACE */
c.allocated = length + sizeof(DATALEN);
if (buffer && length && gcry_is_secure (buffer))
- c.sexp = gcry_xmalloc_secure (sizeof *c.sexp + c.allocated - 1);
+ c.sexp = gcry_malloc_secure (sizeof *c.sexp + c.allocated - 1);
else
- c.sexp = gcry_xmalloc (sizeof *c.sexp + c.allocated - 1);
+ c.sexp = gcry_malloc (sizeof *c.sexp + c.allocated - 1);
+ if (!c.sexp)
+ {
+ err = gpg_err_code_from_errno (errno);
+ *erroff = 0;
+ goto leave;
+ }
c.pos = c.sexp->d;
for (p = buffer, n = length; n; p++, n--)
@@ -986,6 +1035,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
*erroff = p - buffer;
/* Invalid octal value. */
err = GPG_ERR_SEXP_BAD_QUOTATION;
+ goto leave;
}
p += 2;
n -= 2;
@@ -998,6 +1048,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
*erroff = p - buffer;
/* Invalid hex value. */
err = GPG_ERR_SEXP_BAD_QUOTATION;
+ goto leave;
}
p += 2;
n -= 2;
@@ -1028,6 +1079,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
*erroff = p - buffer;
/* Invalid quoted string escape. */
err = GPG_ERR_SEXP_BAD_QUOTATION;
+ goto leave;
}
}
else if (*p == '\\')
@@ -1060,6 +1112,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
{
*erroff = p - buffer;
err = GPG_ERR_SEXP_ODD_HEX_NUMBERS;
+ goto leave;
}
datalen = hexcount / 2;
@@ -1079,6 +1132,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
{
*erroff = p - buffer;
err = GPG_ERR_SEXP_BAD_HEX_CHAR;
+ goto leave;
}
}
else if (base64)
@@ -1099,6 +1153,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
*erroff = p - buffer;
/* Buffer too short. */
err = GPG_ERR_SEXP_STRING_TOO_LONG;
+ goto leave;
}
/* Make a new list entry. */
MAKE_SPACE (datalen);
@@ -1130,6 +1185,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
{
*erroff = p - buffer;
err = GPG_ERR_SEXP_INV_LEN_SPEC;
+ goto leave;
}
}
else if (percent)
@@ -1153,8 +1209,13 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
gcry_sexp_t newsexp;
byte *newhead;
- newsexp = gcry_xmalloc_secure (sizeof *newsexp
- + c.allocated - 1);
+ newsexp = gcry_malloc_secure (sizeof *newsexp
+ + c.allocated - 1);
+ if (!newsexp)
+ {
+ err = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
newhead = newsexp->d;
memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
c.pos = newhead + (c.pos - c.sexp->d);
@@ -1201,8 +1262,13 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
gcry_sexp_t newsexp;
byte *newhead;
- newsexp = gcry_xmalloc_secure (sizeof *newsexp
- + c.allocated - 1);
+ newsexp = gcry_malloc_secure (sizeof *newsexp
+ + c.allocated - 1);
+ if (!newsexp)
+ {
+ err = gpg_err_code_from_errno (errno);
+ goto leave;
+ }
newhead = newsexp->d;
memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
c.pos = newhead + (c.pos - c.sexp->d);
@@ -1236,6 +1302,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
*erroff = p - buffer;
/* Invalid format specifier. */
err = GPG_ERR_SEXP_INV_LEN_SPEC;
+ goto leave;
}
percent = NULL;
}
@@ -1246,6 +1313,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
*erroff = p - buffer;
/* Open display hint. */
err = GPG_ERR_SEXP_UNMATCHED_DH;
+ goto leave;
}
MAKE_SPACE (0);
*c.pos++ = ST_OPEN;
@@ -1259,6 +1327,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
*erroff = p - buffer;
/* Open display hint. */
err = GPG_ERR_SEXP_UNMATCHED_DH;
+ goto leave;
}
MAKE_SPACE (0);
*c.pos++ = ST_CLOSE;
@@ -1283,6 +1352,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
*erroff = p - buffer;
/* Open display hint. */
err = GPG_ERR_SEXP_NESTED_DH;
+ goto leave;
}
disphint = p;
}
@@ -1293,6 +1363,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
*erroff = p - buffer;
/* Open display hint. */
err = GPG_ERR_SEXP_UNMATCHED_DH;
+ goto leave;
}
disphint = NULL;
}
@@ -1303,6 +1374,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
/* A length may not begin with zero. */
*erroff = p - buffer;
err = GPG_ERR_SEXP_ZERO_PREFIX;
+ goto leave;
}
digptr = p;
}
@@ -1318,12 +1390,14 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
need to save it. Great. */
*erroff = p - buffer;
err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
+ goto leave;
}
else if (strchr ("&\\", *p))
{
/* Reserved punctuation. */
*erroff = p - buffer;
err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
+ goto leave;
}
else if (argflag && (*p == '%'))
percent = p;
@@ -1332,14 +1406,16 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
/* Bad or unavailable. */
*erroff = p - buffer;
err = GPG_ERR_SEXP_BAD_CHARACTER;
+ goto leave;
}
}
MAKE_SPACE (0);
*c.pos++ = ST_STOP;
- if (level)
+ if (level && !err)
err = GPG_ERR_SEXP_UNMATCHED_PAREN;
+ leave:
if (err)
{
/* Error -> deallocate. */