diff options
author | Werner Koch <wk@gnupg.org> | 2006-06-21 09:19:13 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2006-06-21 09:19:13 +0000 |
commit | eb9ebf3b7f1bceec03fa8785aa1138be29a73ff2 (patch) | |
tree | 9b1c180778f8e8c4cd9d7ee27406edc7a8c0beef | |
parent | 54c8861ff110789261ee546cc76e19c3199c2120 (diff) | |
download | libgcrypt-eb9ebf3b7f1bceec03fa8785aa1138be29a73ff2.tar.gz |
Changed xmalloc style calls to proper malloc calls with error returns at
many (but not all) places.
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | TODO | 11 | ||||
-rw-r--r-- | cipher/ChangeLog | 8 | ||||
-rw-r--r-- | cipher/md.c | 63 | ||||
-rw-r--r-- | cipher/pubkey.c | 84 | ||||
-rw-r--r-- | cipher/rsa.c | 21 | ||||
-rw-r--r-- | src/ChangeLog | 14 | ||||
-rw-r--r-- | src/global.c | 35 | ||||
-rw-r--r-- | src/sexp.c | 226 |
9 files changed, 342 insertions, 123 deletions
@@ -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. @@ -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 * @@ -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. */ |