aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2012-12-15 10:28:00 +0000
committerWerner Koch <[email protected]>2013-04-22 18:43:27 +0000
commit151b78cc26d728e9eb42620e0caf8c6f4bd7f839 (patch)
treecd828d34c6fd5dc27b982f64b0426bec4407ec1f
parentgpgsm: Remove non-implemented commands from --help. (diff)
downloadgnupg-151b78cc26d728e9eb42620e0caf8c6f4bd7f839.tar.gz
gnupg-151b78cc26d728e9eb42620e0caf8c6f4bd7f839.zip
Fix potential heap corruption in "gpg -v --version".
* g10/gpg.c (build_list): Rewrite to cope with buffer overflow in certain locales. -- 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" <ldv at altlinux.org> (cherry picked from commit 3402a84720e7d8c6ad04fc50eacb338a8ca05ca1) Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to '')
-rw-r--r--g10/gpg.c83
1 files changed, 40 insertions, 43 deletions
diff --git a/g10/gpg.c b/g10/gpg.c
index a19c9a76a..a141164f5 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -40,6 +40,7 @@
#include "../common/iobuf.h"
#include "util.h"
#include "packet.h"
+#include "membuf.h"
#include "main.h"
#include "options.h"
#include "keydb.h"
@@ -895,57 +896,53 @@ my_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;
-
- if (maybe_setuid)
- gcry_control (GCRYCTL_INIT_SECMEM, 0, 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;
- }
- else
- p = stpcpy( p, ", ");
+ membuf_t mb;
+ int indent;
+ int i, j, len;
+ const char *s;
+ char *string;
- if(strlen(line)>60) {
- int spaces=strlen(text);
+ if (maybe_setuid)
+ gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* Drop setuid. */
- list=xrealloc(list,n+spaces+1);
- /* realloc could move the block, so find the end again */
- p=list;
- while(*p)
- p++;
+ indent = utf8_charcount (text);
+ len = 0;
+ init_membuf (&mb, 512);
- p=stpcpy(p, "\n");
- line=p;
- for(;spaces;spaces--)
- p=stpcpy(p, " ");
+ 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 if (mb.len)
+ put_membuf_str (&mb, ", ");
+ else
+ put_membuf_str (&mb, text);
- 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);
}