From 88ac9568364b399b896de2d6f2432b1cb73415a8 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 2 Jun 2014 11:47:25 +0200 Subject: [PATCH] gpg: Fix bug parsing a zero length user id. * g10/getkey.c (get_user_id): Do not call xmalloc with 0. * common/xmalloc.c (xmalloc, xcalloc): Take extra precaution not to pass 0 to the arguments. -- The problem did not occur in 1.x because over there the xmalloc makes sure to allocate at least one byte. With 2.x for most calls the xmalloc of Libgcrypt is used and Libgcrypt returns an error insteead of silent allocating a byte. Thus gpg 2.x bailed out with an "Fatal: out of core while allocating 0 bytes". The extra code in xmalloc.c is for more robustness for the other xmalloc calls. (cherry picked from commit 99972bd6e9abea71f270284f49997de5f00208af) Resolved conflicts: g10/getkey.c - ignore whitespace changes. --- g10/getkey.c | 48 ++++++++++++++++++++++++++++-------------------- jnlib/xmalloc.c | 19 +++++++++++++++++-- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/g10/getkey.c b/g10/getkey.c index 5e8c1c9f5..c0184c209 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -3035,27 +3035,35 @@ get_long_user_id_string( u32 *keyid ) char* get_user_id( u32 *keyid, size_t *rn ) { - user_id_db_t r; - char *p; - int pass=0; + user_id_db_t r; + char *p; + int pass = 0; - /* try it two times; second pass reads from key resources */ - do { - for(r=user_id_db; r; r = r->next ) { - keyid_list_t a; - for (a=r->keyids; a; a= a->next ) { - if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { - p = xmalloc( r->len ); - memcpy(p, r->name, r->len ); - *rn = r->len; - return p; - } - } - } - } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); - p = xstrdup( user_id_not_found_utf8 () ); - *rn = strlen(p); - return p; + /* Try it two times; second pass reads from key resources. */ + do + { + for (r = user_id_db; r; r = r->next) + { + keyid_list_t a; + for (a = r->keyids; a; a = a->next) + { + if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1]) + { + /* An empty string as user id is possible. Make + sure that the malloc allocates one byte and does + not bail out. */ + p = xmalloc (r->len? r->len : 1); + memcpy (p, r->name, r->len); + *rn = r->len; + return p; + } + } + } + } + while (++pass < 2 && !get_pubkey (NULL, keyid)); + p = xstrdup (user_id_not_found_utf8 ()); + *rn = strlen (p); + return p; } char* diff --git a/jnlib/xmalloc.c b/jnlib/xmalloc.c index eb6d5ab11..244f7643e 100644 --- a/jnlib/xmalloc.c +++ b/jnlib/xmalloc.c @@ -36,7 +36,15 @@ out_of_core(void) void * xmalloc( size_t n ) { - void *p = malloc( n ); + void *p; + + /* Make sure that xmalloc (0) works. This is the same behaviour + has in gpg 2.x. Note that in contrast to this code, Libgcrypt + (and thus most xmallocs in gpg 2.x) detect the !n and bail out. */ + if (!n) + n = 1; + + p = malloc( n ); if( !p ) out_of_core(); return p; @@ -54,7 +62,14 @@ xrealloc( void *a, size_t n ) void * xcalloc( size_t n, size_t m ) { - void *p = calloc( n, m ); + void *p; + + if (!n) + n = 1; + if (!m) + m = 1; + + p = calloc( n, m ); if( !p ) out_of_core(); return p;