Eric Blake <ebb9 <at> byu.net> writes: > According to Jim Meyering on 5/8/2008 1:10 PM: > | > | However, given too long a string of digits, "Number" overflows. > > Accidental, but not unnoticed, and hopefully not severe. > But now that you mention it, I'll > probably tighten up the check
Like this. >From b5fe50a4ef3e20912ee835888c9effda8a290721 Mon Sep 17 00:00:00 2001 From: Eric Blake <[EMAIL PROTECTED]> Date: Fri, 9 May 2008 07:59:51 -0600 Subject: [PATCH] Detect integer overflow when loading frozen file. * src/freeze.c (reload_frozen_state) [GET_NUMBER]: Rewrite to fail immediately on overflow. Reported by Jim Meyering. Signed-off-by: Eric Blake <[EMAIL PROTECTED]> --- ChangeLog | 5 +++++ src/freeze.c | 31 ++++++++++++++++++------------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0a40526..fc894b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2008-05-09 Eric Blake <[EMAIL PROTECTED]> + Detect integer overflow when loading frozen file. + * src/freeze.c (reload_frozen_state) [GET_NUMBER]: Rewrite to fail + immediately on overflow. + Reported by Jim Meyering. + Stage 23: allow tracing of indirect macro calls. Track all trace information as part of the argv struct, rather than temporarily resetting global state. Teach indir to trace diff --git a/src/freeze.c b/src/freeze.c index 383d008..16ed75e 100644 --- a/src/freeze.c +++ b/src/freeze.c @@ -179,33 +179,38 @@ reload_frozen_state (const char *name) int number[2]; const builtin *bp; -#define GET_CHARACTER \ +#define GET_CHARACTER \ (character = getc (file)) -#define GET_NUMBER(Number) \ +#define GET_NUMBER(Number, AllowNeg) \ do \ { \ - (Number) = 0; \ - while (isdigit (character)) \ + unsigned int n = 0; \ + while (isdigit (character) && n <= INT_MAX / 10) \ { \ - (Number) = 10 * (Number) + character - '0'; \ + n = 10 * n + character - '0'; \ GET_CHARACTER; \ } \ + if (((AllowNeg) ? INT_MIN : INT_MAX) < n \ + || isdigit (character)) \ + m4_error (EXIT_FAILURE, 0, NULL, \ + _("integer overflow in frozen file")); \ + (Number) = n; \ } \ while (0) -#define VALIDATE(Expected) \ +#define VALIDATE(Expected) \ do \ { \ if (character != (Expected)) \ - issue_expect_message ((Expected)); \ + issue_expect_message (Expected); \ } \ while (0) /* Skip comments (`#' at beginning of line) and blank lines, setting character to the next directive or to EOF. */ -#define GET_DIRECTIVE \ +#define GET_DIRECTIVE \ do \ { \ GET_CHARACTER; \ @@ -215,7 +220,7 @@ reload_frozen_state (const char *name) GET_CHARACTER; \ VALIDATE ('\n'); \ } \ - } \ + } \ while (character == '\n') file = m4_path_search (name, NULL); @@ -231,7 +236,7 @@ reload_frozen_state (const char *name) GET_DIRECTIVE; VALIDATE ('V'); GET_CHARACTER; - GET_NUMBER (number[0]); + GET_NUMBER (number[0], false); if (number[0] > 1) m4_error (EXIT_MISMATCH, 0, NULL, _("frozen file version %d greater than max supported of 1"), @@ -262,14 +267,14 @@ reload_frozen_state (const char *name) if (operation == 'D' && character == '-') { GET_CHARACTER; - GET_NUMBER (number[0]); + GET_NUMBER (number[0], true); number[0] = -number[0]; } else - GET_NUMBER (number[0]); + GET_NUMBER (number[0], false); VALIDATE (','); GET_CHARACTER; - GET_NUMBER (number[1]); + GET_NUMBER (number[1], false); VALIDATE ('\n'); if (operation != 'D') -- 1.5.5.1 >From 34985ceaf524a511894776fe446279b5a7c12ced Mon Sep 17 00:00:00 2001 From: Eric Blake <[EMAIL PROTECTED]> Date: Fri, 9 May 2008 09:24:41 -0600 Subject: [PATCH] Improve error message when frozen file is invalid. * src/freeze.c (reload_frozen_state): Track current line. [GET_STRING]: New helper macro. Signed-off-by: Eric Blake <[EMAIL PROTECTED]> --- ChangeLog | 4 +++ src/freeze.c | 79 ++++++++++++++++++++++++++++++++------------------------- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index fc894b1..2abc489 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2008-05-09 Eric Blake <[EMAIL PROTECTED]> + Improve error message when frozen file is invalid. + * src/freeze.c (reload_frozen_state): Track current line. + [GET_STRING]: New helper macro. + Detect integer overflow when loading frozen file. * src/freeze.c (reload_frozen_state) [GET_NUMBER]: Rewrite to fail immediately on overflow. diff --git a/src/freeze.c b/src/freeze.c index 16ed75e..15f06fe 100644 --- a/src/freeze.c +++ b/src/freeze.c @@ -178,9 +178,21 @@ reload_frozen_state (const char *name) int allocated[2]; int number[2]; const builtin *bp; + bool advance_line = true; #define GET_CHARACTER \ - (character = getc (file)) + do \ + { \ + if (advance_line) \ + { \ + current_line++; \ + advance_line = false; \ + } \ + (character = getc (file)); \ + if (character == '\n') \ + advance_line = true; \ + } \ + while (0) #define GET_NUMBER(Number, AllowNeg) \ do \ @@ -223,9 +235,35 @@ reload_frozen_state (const char *name) } \ while (character == '\n') +#define GET_STRING(i) \ + do \ + { \ + void *tmp; \ + char *p; \ + if (number[(i)] + 1 > allocated[(i)]) \ + { \ + free (string[(i)]); \ + allocated[(i)] = number[(i)] + 1; \ + string[(i)] = xcharalloc ((size_t) allocated[(i)]); \ + } \ + if (number[(i)] > 0 \ + && !fread (string[(i)], (size_t) number[(i)], 1, file)) \ + m4_error (EXIT_FAILURE, 0, NULL, \ + _("premature end of frozen file")); \ + string[(i)][number[(i)]] = '\0'; \ + p = string[(i)]; \ + while ((tmp = memchr(p, '\n', number[(i)] - (p - string[(i)])))) \ + { \ + current_line++; \ + p = (char *) tmp + 1; \ + } \ + } \ + while (0) + file = m4_path_search (name, NULL); if (file == NULL) m4_error (EXIT_FAILURE, errno, NULL, _("cannot open %s"), name); + current_file = name; allocated[0] = 100; string[0] = xcharalloc ((size_t) allocated[0]); @@ -278,40 +316,8 @@ reload_frozen_state (const char *name) VALIDATE ('\n'); if (operation != 'D') - { - - /* Get first string contents. */ - - if (number[0] + 1 > allocated[0]) - { - free (string[0]); - allocated[0] = number[0] + 1; - string[0] = xcharalloc ((size_t) allocated[0]); - } - - if (number[0] > 0) - if (!fread (string[0], (size_t) number[0], 1, file)) - m4_error (EXIT_FAILURE, 0, NULL, - _("premature end of frozen file")); - - string[0][number[0]] = '\0'; - } - - /* Get second string contents. */ - - if (number[1] + 1 > allocated[1]) - { - free (string[1]); - allocated[1] = number[1] + 1; - string[1] = xcharalloc ((size_t) allocated[1]); - } - - if (number[1] > 0) - if (!fread (string[1], (size_t) number[1], 1, file)) - m4_error (EXIT_FAILURE, 0, NULL, - _("premature end of frozen file")); - - string[1][number[1]] = '\0'; + GET_STRING (0); + GET_STRING (1); GET_CHARACTER; VALIDATE ('\n'); @@ -375,9 +381,12 @@ reload_frozen_state (const char *name) errno = 0; if (ferror (file) || fclose (file) != 0) m4_error (EXIT_FAILURE, errno, NULL, _("unable to read frozen state")); + current_file = NULL; + current_line = 0; #undef GET_CHARACTER #undef GET_DIRECTIVE #undef GET_NUMBER #undef VALIDATE +#undef GET_STRING } -- 1.5.5.1