From feb40e2c6ec1eb008960fbcbbb683c96110bf8aa Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 14 Jun 2004 08:32:07 +0000 Subject: [PATCH] * xreadline.c: New. Based on the iobuf_read_line function. * no-libgcrypt.c (gcry_realloc, gcry_xmalloc, gcry_xcalloc): New. * gpgconf-comp.c (retrieve_options_from_program) (retrieve_options_from_file, change_options_file) (change_options_program, gc_component_change_options): Replaced getline by read_line and test for allocation failure. --- common/ChangeLog | 4 ++ common/Makefile.am | 1 + common/util.h | 5 ++ common/xreadline.c | 116 +++++++++++++++++++++++++++++++++++++++++++ tools/ChangeLog | 9 ++++ tools/gpgconf-comp.c | 62 ++++++++++------------- tools/no-libgcrypt.c | 22 ++++++++ 7 files changed, 183 insertions(+), 36 deletions(-) create mode 100644 common/xreadline.c diff --git a/common/ChangeLog b/common/ChangeLog index 2e523618b..a848b8c78 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2004-06-14 Werner Koch + + * xreadline.c: New. Based on the iobuf_read_line function. + 2004-05-12 Werner Koch * util.h (xtrycalloc_secure,xtrymalloc_secure): New. diff --git a/common/Makefile.am b/common/Makefile.am index 4e7fd504c..64b565cd2 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -36,6 +36,7 @@ libcommon_a_SOURCES = \ b64enc.c \ miscellaneous.c \ xasprintf.c \ + xreadline.c \ membuf.c membuf.h \ iobuf.c iobuf.h \ ttyio.c ttyio.h \ diff --git a/common/util.h b/common/util.h index 461e744ad..b9ffe6562 100644 --- a/common/util.h +++ b/common/util.h @@ -99,6 +99,11 @@ int answer_is_yes (const char *s); int answer_is_yes_no_default (const char *s, int def_answer); int answer_is_yes_no_quit (const char *s); +/*-- xreadline.c --*/ +ssize_t read_line (FILE *fp, + char **addr_of_buffer, size_t *length_of_buffer, + size_t *max_length); + /*-- b64enc.c --*/ struct b64state diff --git a/common/xreadline.c b/common/xreadline.c new file mode 100644 index 000000000..85f0af02e --- /dev/null +++ b/common/xreadline.c @@ -0,0 +1,116 @@ +/* xreadline.c - fgets replacement function + * Copyright (C) 1999, 2004 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include + +#include "util.h" + + +/* Same as fgets() but if the provided buffer is too short a larger + one will be allocated. This is similar to getline. A line is + considered a byte stream ending in a LF. + + If MAX_LENGTH is not NULL, it shall point to a value with the + maximum allowed allocation. + + Returns the length of the line. EOF is indicated by a line of + length zero. A truncated line is indicated my setting the value at + MAX_LENGTH to 0. If the returned value is less then 0 not enough + memory was enable and ERRNO is set accordingly. + + If a line has been truncated, the file pointer is moved forward to + the end of the line so that the next read start with tghe next + line. Note that MAX_LENGTH must be re-initialzied in this case.. + + Note: The returned buffer is allocated with enough extra space to + append a CR,LF,Nul + */ +ssize_t +read_line (FILE *fp, + char **addr_of_buffer, size_t *length_of_buffer, + size_t *max_length) +{ + int c; + char *buffer = *addr_of_buffer; + size_t length = *length_of_buffer; + size_t nbytes = 0; + size_t maxlen = max_length? *max_length : 0; + char *p; + + if (!buffer) + { /* No buffer given - allocate a new one. */ + length = 256; + buffer = xtrymalloc (length); + *addr_of_buffer = buffer; + if (!buffer) + { + *length_of_buffer = 0; + if (max_length) + *max_length = 0; + return -1; + } + *length_of_buffer = length; + } + + length -= 3; /* Reserve 3 bytes for CR,LF,EOL. */ + p = buffer; + while ((c = getc (fp)) != EOF) + { + if (nbytes == length) + { /* Enlarge the buffer. */ + if (maxlen && length > maxlen) /* But not beyond our limit. */ + { + /* Skip the rest of the line. */ + while (c != '\n' && (c=getc (fp)) != EOF) + ; + *p++ = '\n'; /* Always append a LF (we reserved some space). */ + nbytes++; + if (max_length) + *max_length = 0; /* Indicate truncation. */ + break; /* the while loop. */ + } + length += 3; /* Adjust for the reserved bytes. */ + length += length < 1024? 256 : 1024; + *addr_of_buffer = xtryrealloc (buffer, length); + if (!*addr_of_buffer) + { + int save_errno = errno; + xfree (buffer); + *length_of_buffer = *max_length = 0; + errno = save_errno; + return -1; + } + buffer = *addr_of_buffer; + *length_of_buffer = length; + length -= 3; + p = buffer + nbytes; + } + *p++ = c; + nbytes++; + if (c == '\n') + break; + } + *p = 0; /* Make sure the line is a string. */ + + return nbytes; +} diff --git a/tools/ChangeLog b/tools/ChangeLog index d8e293bc5..a81a2d301 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,12 @@ +2004-06-14 Werner Koch + + * no-libgcrypt.c (gcry_realloc, gcry_xmalloc, gcry_xcalloc): New. + + * gpgconf-comp.c (retrieve_options_from_program) + (retrieve_options_from_file, change_options_file) + (change_options_program, gc_component_change_options): Replaced + getline by read_line and test for allocation failure. + 2004-05-21 Marcus Brinkmann * gpgconf-comp.c (gc_options_dirmngr): Remove CRL group, put its diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index f51be1762..cc0751d0c 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -42,13 +42,6 @@ /* TODO: - Portability - Add gnulib replacements for getline, etc. - -XXX Marcus: Please use the read_line code from dirmngr/src/http.c - it -has been in use for may years and provides the ability to limit the -length of the line and thus thwart DoS (not a issue here but at many -other places). - Components: Add more components and their options. Robustness: Do more validation. Call programs to do validation for us. Don't use popen, as this will not tell us if the program had a @@ -1252,7 +1245,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) if (!config) gc_error (1, errno, "could not gather active options from %s", cmd_line); - while ((length = getline (&line, &line_len, config)) > 0) + while ((length = read_line (config, &line, &line_len, NULL)) > 0) { gc_option_t *option; char *linep; @@ -1319,7 +1312,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) option->default_value = xstrdup (default_value); } } - if (ferror (config)) + if (length < 0 || ferror (config)) gc_error (1, errno, "error reading from %s", cmd_line); if (fclose (config) && ferror (config)) gc_error (1, errno, "error closing %s", cmd_line); @@ -1334,7 +1327,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) config_pathname); else { - while ((length = getline (&line, &line_len, config)) > 0) + while ((length = read_line (config, &line, &line_len, NULL)) > 0) { char *name; char *value; @@ -1415,14 +1408,13 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) } } - if (ferror (config)) + if (length < 0 || ferror (config)) gc_error (1, errno, "error reading from %s", config_pathname); if (fclose (config) && ferror (config)) gc_error (1, errno, "error closing %s", config_pathname); } - if (line) - free (line); + xfree (line); } @@ -1451,7 +1443,7 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend) else { - while ((length = getline (&line, &line_len, list_file)) > 0) + while ((length = read_line (list_file, &line, &line_len, NULL)) > 0) { char *start; char *end; @@ -1484,15 +1476,14 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend) else list = xasprintf ("\"%s", percent_escape (start)); } - if (ferror (list_file)) + if (length < 0 || ferror (list_file)) gc_error (1, errno, "can not read list file %s", list_pathname); } list_option->active = 1; list_option->value = list; - if (line) - free (line); + xfree (line); } @@ -1735,7 +1726,7 @@ change_options_file (gc_component_t component, gc_backend_t backend, if (!dest_file) goto change_file_one_err; - while ((length = getline (&line, &line_len, dest_file)) > 0) + while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0) { int disable = 0; char *start; @@ -1823,7 +1814,7 @@ change_options_file (gc_component_t component, gc_backend_t backend, goto change_file_one_err; } } - if (ferror (dest_file)) + if (length < 0 || ferror (dest_file)) goto change_file_one_err; } @@ -1889,17 +1880,18 @@ change_options_file (gc_component_t component, gc_backend_t backend, } if (dest_file) { - while ((length = getline (&line, &line_len, dest_file)) > 0) + while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0) { fprintf (src_file, "%s", line); if (ferror (src_file)) goto change_file_one_err; } - if (ferror (dest_file)) + if (length < 0 || ferror (dest_file)) goto change_file_one_err; } - if (line) - free (line); + xfree (line); + line = NULL; + res = fclose (src_file); if (res) { @@ -1920,8 +1912,7 @@ change_options_file (gc_component_t component, gc_backend_t backend, return 0; change_file_one_err: - if (line) - free (line); + xfree (line); res = errno; if (src_file) { @@ -1999,7 +1990,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, if (!dest_file) goto change_one_err; - while ((length = getline (&line, &line_len, dest_file)) > 0) + while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0) { int disable = 0; char *start; @@ -2054,7 +2045,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, goto change_one_err; } } - if (ferror (dest_file)) + if (length < 0 || ferror (dest_file)) goto change_one_err; } @@ -2172,17 +2163,18 @@ change_options_program (gc_component_t component, gc_backend_t backend, } if (dest_file) { - while ((length = getline (&line, &line_len, dest_file)) > 0) + while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0) { fprintf (src_file, "%s", line); if (ferror (src_file)) goto change_one_err; } - if (ferror (dest_file)) + if (length < 0 || ferror (dest_file)) goto change_one_err; } - if (line) - free (line); + xfree (line); + line = NULL; + res = fclose (src_file); if (res) { @@ -2203,8 +2195,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, return 0; change_one_err: - if (line) - free (line); + xfree (line); res = errno; if (src_file) { @@ -2241,7 +2232,7 @@ gc_component_change_options (int component, FILE *in) orig_pathname[backend] = NULL; } - while ((length = getline (&line, &line_len, in)) > 0) + while ((length = read_line (in, &line, &line_len, NULL)) > 0) { char *linep; unsigned long flags = 0; @@ -2439,6 +2430,5 @@ gc_component_change_options (int component, FILE *in) rename (orig_pathname[backend], backup_pathname); } - if (line) - free (line); + xfree (line); } diff --git a/tools/no-libgcrypt.c b/tools/no-libgcrypt.c index b5342732d..0fabec90d 100644 --- a/tools/no-libgcrypt.c +++ b/tools/no-libgcrypt.c @@ -38,6 +38,12 @@ out_of_core (void) } +void * +gcry_malloc (size_t n) +{ + return malloc (n); +} + void * gcry_xmalloc (size_t n) { @@ -47,6 +53,13 @@ gcry_xmalloc (size_t n) return p; } + +void * +gcry_realloc (void *a, size_t n) +{ + return realloc (a, n); +} + void * gcry_xrealloc (void *a, size_t n) { @@ -56,6 +69,14 @@ gcry_xrealloc (void *a, size_t n) return p; } + + +void * +gcry_calloc (size_t n, size_t m) +{ + return calloc (n, m); +} + void * gcry_xcalloc (size_t n, size_t m) { @@ -65,6 +86,7 @@ gcry_xcalloc (size_t n, size_t m) return p; } + char * gcry_xstrdup (const char *string) {