From e33e74e3a4b2b4a0341f933410ddd5db7a12515e Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Sat, 15 Dec 2012 11:28:00 +0100 Subject: [PATCH] Fix potential heap corruption in "gpg -v --version" * g10/gpg.c (build_list): Rewrite to cope with buffer overflow in certain locales. * util/membuf.c (put_membuf_str): New. (get_membuf): Make LEN optional. -- This fixes an obvious bug in locales where the translated string is longer than the original. The bug could be exhibited by using LANG=ru_RU.utf8 gpg -v --version. En passant we also removed the trailing white space on continued lines. Reported-by: Dmitry V. Levin" --- THANKS | 9 +++--- g10/gpg.c | 84 ++++++++++++++++++++++++-------------------------- include/util.h | 1 + util/membuf.c | 12 ++++++-- 4 files changed, 56 insertions(+), 50 deletions(-) diff --git a/THANKS b/THANKS index ae64d9fa9..791516ef5 100644 --- a/THANKS +++ b/THANKS @@ -49,6 +49,7 @@ David R. Bergstein dbergstein@home.com David Shaw dshaw@jabberwocky.com Detlef Lannert lannert@lannert.rz.uni-duesseldorf.de Dimitri dmitri@advantrix.com +Dmitry V. Levin ldv at altlinux dot org Dirk Lattermann dlatt@t-online.de Dirk Meyer dirk.meyer@dinoex.sub.org Disastry Disastry@saiknes.lv @@ -90,7 +91,7 @@ Ian McKellar imckellar@harvestroad.com.au Ingo Klöcker kloecker@kde.org Ivo Timmermans itimmermans@bigfoot.com Jan Krueger max@physics.otago.ac.nz -Jan Niehusmann jan@gondor.com +Jan Niehusmann jan@gondor.com Janusz A. Urbanowicz alex@bofh.torun.pl James Troup james@nocrew.org Jason Woodward jason dot woodward at timesys dot com @@ -120,18 +121,18 @@ Karl Fogel kfogel@guanabana.onshore.com Karsten Thygesen karthy@kom.auc.dk Katsuhiro Kondou kondou@nec.co.jp Kazu Yamamoto kazu@iijlab.net -Kazuyoshi Kakihara +Kazuyoshi Kakihara Keith Clayton keith@claytons.org Kevin Ryde user42@zip.com.au Klaus Singvogel ks@caldera.de Kurt Garloff garloff@suse.de Lars Kellogg-Stedman lars@bu.edu L. Sassaman rabbi@quickie.net -M Taylor mctaylor@privacy.nb.ca +M Taylor mctaylor@privacy.nb.ca Marcel Waldvogel mwa@arl.wustl.edu Marco d'Itri md@linux.it Marco Parrone marc0@autistici.org -Marcus Brinkmann Marcus.Brinkmann@ruhr-uni-bochum.de +Marcus Brinkmann Marcus.Brinkmann@ruhr-uni-bochum.de Mark Adler madler@alumni.caltech.edu Mark Elbrecht snowball3@bigfoot.com Mark Pettit pettit@yahoo-inc.com diff --git a/g10/gpg.c b/g10/gpg.c index 573bb907b..96f908603 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -835,57 +835,53 @@ strusage( int level ) static char * -build_list( const char *text, char letter, - const char * (*mapf)(int), int (*chkf)(int) ) +build_list (const char *text, char letter, + const char * (*mapf)(int), int (*chkf)(int)) { - int i; - const char *s; - size_t n=strlen(text)+2; - char *list, *p, *line=NULL; + membuf_t mb; + int indent; + int i, j, len; + const char *s; + char *string; - if( maybe_setuid ) - secmem_init( 0 ); /* drop setuid */ + if (maybe_setuid) + secmem_init (0); /* Drop setuid */ - for(i=0; i <= 110; i++ ) - if( !chkf(i) && (s=mapf(i)) ) - n += strlen(s) + 7 + 2; - list = xmalloc( 21 + n ); *list = 0; - for(p=NULL, i=0; i <= 110; i++ ) { - if( !chkf(i) && (s=mapf(i)) ) { - if( !p ) { - p = stpcpy( list, text ); - line=p; + indent = strlen (text); + len = 0; + init_membuf (&mb, 512); + + for (i=0; i <= 110; i++ ) + { + if (!chkf (i) && (s = mapf (i))) + { + if (mb.len - len > 60) + { + put_membuf_str (&mb, ",\n"); + len = mb.len; + for (j=0; j < indent; j++) + put_membuf_str (&mb, " "); } - else - p = stpcpy( p, ", "); + else if (mb.len) + put_membuf_str (&mb, ", "); + else + put_membuf_str (&mb, text); - if(strlen(line)>60) { - int spaces=strlen(text); - - list=xrealloc(list,n+spaces+1); - /* realloc could move the block, so find the end again */ - p=list; - while(*p) - p++; - - p=stpcpy(p, "\n"); - line=p; - for(;spaces;spaces--) - p=stpcpy(p, " "); - } - - p = stpcpy(p, s ); - if(opt.verbose && letter) - { - char num[8]; - sprintf(num," (%c%d)",letter,i); - p = stpcpy(p,num); - } + put_membuf_str (&mb, s); + if (opt.verbose && letter) + { + char num[20]; + snprintf (num, sizeof num, " (%c%d)", letter, i); + put_membuf_str (&mb, num); + } } } - if( p ) - p = stpcpy(p, "\n" ); - return list; + if (mb.len) + put_membuf_str (&mb, "\n"); + put_membuf (&mb, "", 1); + + string = get_membuf (&mb, NULL); + return xrealloc (string, strlen (string)+1); } diff --git a/include/util.h b/include/util.h index 9303a50b1..3057b25e0 100644 --- a/include/util.h +++ b/include/util.h @@ -219,6 +219,7 @@ typedef struct private_membuf_s membuf_t; void init_membuf (membuf_t *mb, int initiallen); void put_membuf (membuf_t *mb, const void *buf, size_t len); +void put_membuf_str (membuf_t *mb, const char *buf); void *get_membuf (membuf_t *mb, size_t *len); diff --git a/util/membuf.c b/util/membuf.c index db3f5ac37..3f7a61ddd 100644 --- a/util/membuf.c +++ b/util/membuf.c @@ -52,7 +52,7 @@ put_membuf (membuf_t *mb, const void *buf, size_t len) if (mb->len + len >= mb->size) { char *p; - + mb->size += len + 1024; p = xrealloc (mb->buf, mb->size); mb->buf = p; @@ -62,6 +62,13 @@ put_membuf (membuf_t *mb, const void *buf, size_t len) } +void +put_membuf_str (membuf_t *mb, const char *buf) +{ + put_membuf (mb, buf, strlen (buf)); +} + + void * get_membuf (membuf_t *mb, size_t *len) { @@ -75,7 +82,8 @@ get_membuf (membuf_t *mb, size_t *len) } p = mb->buf; - *len = mb->len; + if (len) + *len = mb->len; mb->buf = NULL; mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */ return p;