From d8eea25b8b7becbfa3f059be6f5966a2f1aa7112 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 28 Jan 2015 20:12:21 +0100 Subject: [PATCH] gpg: Fix buffering problem in --list-config. * g10/gpg.c (list_config): Replace print_sanitized_string2 by es_write_sanitized. * common/stringhelp.c (print_sanitized_buffer2): Remove. (print_sanitized_buffer, print_sanitized_utf8_buffer): Remove. (print_sanitized_utf8_buffer, print_sanitized_utf8_string): Remove. (print_sanitized_string): Remove. * sm/certdump.c (print_dn_part, print_dn_parts): Remove arg FP. (pretty_print_sexp, gpgsm_print_name2, gpgsm_print_name): Remove. -- Mixing stdio and estream is never a good idea. This fix also allows us to remove a lot of garbage. Reported-by: Jason A. Donenfeld GnuPG-bug-id: 1822 Signed-off-by: Werner Koch --- common/stringhelp.c | 123 --------------------------------------- common/stringhelp.h | 10 ---- g10/gpg.c | 3 +- sm/certdump.c | 137 ++++---------------------------------------- 4 files changed, 14 insertions(+), 259 deletions(-) diff --git a/common/stringhelp.c b/common/stringhelp.c index 7ce041d01..7128de5fc 100644 --- a/common/stringhelp.c +++ b/common/stringhelp.c @@ -671,129 +671,6 @@ hextobyte (const char *s) } -/* Print a BUFFER to stream FP while replacing all control characters - and the characters DELIM and DELIM2 with standard C escape - sequences. Returns the number of characters printed. */ -size_t -print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length, - int delim, int delim2) -{ - const unsigned char *p = buffer; - size_t count = 0; - - for (; length; length--, p++, count++) - { - if (*p < 0x20 - || *p == 0x7f - || *p == delim - || *p == delim2 - || ((delim || delim2) && *p=='\\')) - { - putc ('\\', fp); - count++; - if (*p == '\n') - { - putc ('n', fp); - count++; - } - else if (*p == '\r') - { - putc ('r', fp); - count++; - } - else if (*p == '\f') - { - putc ('f', fp); - count++; - } - else if (*p == '\v') - { - putc ('v', fp); - count++; - } - else if (*p == '\b') - { - putc ('b', fp); - count++; - } - else if (!*p) - { - putc('0', fp); - count++; - } - else - { - fprintf (fp, "x%02x", *p); - count += 3; - } - } - else - { - putc (*p, fp); - count++; - } - } - - return count; -} - -/* Same as print_sanitized_buffer2 but with just one delimiter. */ -size_t -print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, - int delim) -{ - return print_sanitized_buffer2 (fp, buffer, length, delim, 0); -} - - -size_t -print_sanitized_utf8_buffer (FILE *fp, const void *buffer, - size_t length, int delim) -{ - const char *p = buffer; - size_t i; - - /* We can handle plain ascii simpler, so check for it first. */ - for (i=0; i < length; i++ ) - { - if ( (p[i] & 0x80) ) - break; - } - if (i < length) - { - char *buf = utf8_to_native (p, length, delim); - /*(utf8 conversion already does the control character quoting)*/ - i = strlen (buf); - fputs (buf, fp); - jnlib_free (buf); - return i; - } - else - return print_sanitized_buffer (fp, p, length, delim); -} - - -size_t -print_sanitized_string2 (FILE *fp, const char *string, int delim, int delim2) -{ - return string? print_sanitized_buffer2 (fp, string, strlen (string), - delim, delim2):0; -} - -size_t -print_sanitized_string (FILE *fp, const char *string, int delim) -{ - return string? print_sanitized_buffer (fp, string, strlen (string), delim):0; -} - -size_t -print_sanitized_utf8_string (FILE *fp, const char *string, int delim) -{ - return string? print_sanitized_utf8_buffer (fp, - string, strlen (string), - delim) : 0; -} - /* Create a string from the buffer P_ARG of length N which is suitable for printing. Caller must release the created string using xfree. This function terminates the process on memory shortage. */ diff --git a/common/stringhelp.h b/common/stringhelp.h index 1d3ee7237..d4fe169a7 100644 --- a/common/stringhelp.h +++ b/common/stringhelp.h @@ -60,16 +60,6 @@ int compare_filenames( const char *a, const char *b ); int hextobyte (const char *s); -size_t print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, - int delim); -size_t print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length, - int delim, int delim2); -size_t print_sanitized_utf8_buffer (FILE *fp, const void *buffer, - size_t length, int delim); -size_t print_sanitized_string (FILE *fp, const char *string, int delim); -size_t print_sanitized_string2 (FILE *fp, const char *string, - int delim, int delim2); -size_t print_sanitized_utf8_string (FILE *fp, const char *string, int delim); char *sanitize_buffer (const void *p, size_t n, int delim); diff --git a/g10/gpg.c b/g10/gpg.c index 5e929d985..9a6b104c2 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -1599,7 +1599,8 @@ list_config(char *items) for(sl=iter->values;sl;sl=sl->next) { - print_sanitized_string2 (stdout, sl->d, ':',';'); + es_write_sanitized (es_stdout, sl->d, strlen (sl->d), + ":;", NULL); if(sl->next) es_printf(";"); } diff --git a/sm/certdump.c b/sm/certdump.c index 23cca7385..f32a27cc5 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -479,9 +479,9 @@ parse_dn (const unsigned char *string) } -/* Print a DN part to STREAM or if STREAM is NULL to FP. */ +/* Print a DN part to STREAM. */ static void -print_dn_part (FILE *fp, estream_t stream, +print_dn_part (estream_t stream, struct dn_array_s *dn, const char *key, int translate) { struct dn_array_s *first_dn = dn; @@ -500,24 +500,13 @@ print_dn_part (FILE *fp, estream_t stream, next: if (!dn->done && dn->value && *dn->value) { - if (stream) - { - es_fprintf (stream, "/%s=", dn->key); - if (translate) - print_utf8_buffer3 (stream, dn->value, strlen (dn->value), - "/"); - else - es_write_sanitized (stream, dn->value, strlen (dn->value), - "/", NULL); - } + es_fprintf (stream, "/%s=", dn->key); + if (translate) + print_utf8_buffer3 (stream, dn->value, strlen (dn->value), + "/"); else - { - fprintf (fp, "/%s=", dn->key); - if (translate) - print_sanitized_utf8_string (fp, dn->value, '/'); - else - print_sanitized_string (fp, dn->value, '/'); - } + es_write_sanitized (stream, dn->value, strlen (dn->value), + "/", NULL); } dn->done = 1; if (dn > first_dn && dn[-1].multivalued) @@ -532,7 +521,7 @@ print_dn_part (FILE *fp, estream_t stream, /* Print all parts of a DN in a "standard" sequence. We first print all the known parts, followed by the uncommon ones */ static void -print_dn_parts (FILE *fp, estream_t stream, +print_dn_parts (estream_t stream, struct dn_array_s *dn, int translate) { const char *stdpart[] = { @@ -541,59 +530,14 @@ print_dn_parts (FILE *fp, estream_t stream, int i; for (i=0; stdpart[i]; i++) - print_dn_part (fp, stream, dn, stdpart[i], translate); + print_dn_part (stream, dn, stdpart[i], translate); /* Now print the rest without any specific ordering */ for (; dn->key; dn++) - print_dn_part (fp, stream, dn, dn->key, translate); + print_dn_part (stream, dn, dn->key, translate); } -/* Print the S-Expression in BUF, which has a valid length of BUFLEN, - as a human readable string in one line to FP. */ -static void -pretty_print_sexp (FILE *fp, const unsigned char *buf, size_t buflen) -{ - size_t len; - gcry_sexp_t sexp; - char *result, *p; - - if ( gcry_sexp_sscan (&sexp, NULL, (const char*)buf, buflen) ) - { - fputs (_("[Error - invalid encoding]"), fp); - return; - } - len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0); - assert (len); - result = xtrymalloc (len); - if (!result) - { - fputs (_("[Error - out of core]"), fp); - gcry_sexp_release (sexp); - return; - } - len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len); - assert (len); - for (p = result; len; len--, p++) - { - if (*p == '\n') - { - if (len > 1) /* Avoid printing the trailing LF. */ - fputs ("\\n", fp); - } - else if (*p == '\r') - fputs ("\\r", fp); - else if (*p == '\v') - fputs ("\\v", fp); - else if (*p == '\t') - fputs ("\\t", fp); - else - putc (*p, fp); - } - xfree (result); - gcry_sexp_release (sexp); -} - /* Print the S-Expression in BUF to extended STREAM, which has a valid length of BUFLEN, as a human readable string in one line to FP. */ static void @@ -640,63 +584,6 @@ pretty_es_print_sexp (estream_t fp, const unsigned char *buf, size_t buflen) } - - -void -gpgsm_print_name2 (FILE *fp, const char *name, int translate) -{ - const unsigned char *s = (const unsigned char *)name; - int i; - - if (!s) - { - fputs (_("[Error - No name]"), fp); - } - else if (*s == '<') - { - const char *s2 = strchr ( (char*)s+1, '>'); - if (s2) - { - if (translate) - print_sanitized_utf8_buffer (fp, s + 1, s2 - (char*)s - 1, 0); - else - print_sanitized_buffer (fp, s + 1, s2 - (char*)s - 1, 0); - } - } - else if (*s == '(') - { - pretty_print_sexp (fp, s, gcry_sexp_canon_len (s, 0, NULL, NULL)); - } - else if (!((*s >= '0' && *s < '9') - || (*s >= 'A' && *s <= 'Z') - || (*s >= 'a' && *s <= 'z'))) - fputs (_("[Error - invalid encoding]"), fp); - else - { - struct dn_array_s *dn = parse_dn (s); - if (!dn) - fputs (_("[Error - invalid DN]"), fp); - else - { - print_dn_parts (fp, NULL, dn, translate); - for (i=0; dn[i].key; i++) - { - xfree (dn[i].key); - xfree (dn[i].value); - } - xfree (dn); - } - } -} - - -void -gpgsm_print_name (FILE *fp, const char *name) -{ - gpgsm_print_name2 (fp, name, 1); -} - - /* This is a variant of gpgsm_print_name sending it output to an estream. */ void gpgsm_es_print_name2 (estream_t fp, const char *name, int translate) @@ -736,7 +623,7 @@ gpgsm_es_print_name2 (estream_t fp, const char *name, int translate) es_fputs (_("[Error - invalid DN]"), fp); else { - print_dn_parts (NULL, fp, dn, translate); + print_dn_parts (fp, dn, translate); for (i=0; dn[i].key; i++) { xfree (dn[i].key);