From 4fab2788576b9e10374138be453620a05c95c7be Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 13 May 2008 06:25:46 -0600 Subject: Improve error message when frozen file is invalid. * src/freeze.c (decode_char): Add parameter. Allow \ line continuations. (reload_frozen_state): Track current line. * tests/freeze.at (loading format 1, loading format 2): Update to test this. Signed-off-by: Eric Blake --- ChangeLog | 9 +++++++++ src/freeze.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++--------- tests/freeze.at | 39 +++++++++++++++++++++++++++++---------- 3 files changed, 86 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05234af5..4bee8823 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2008-05-13 Eric Blake + + Improve error message when frozen file is invalid. + * src/freeze.c (decode_char): Add parameter. Allow \ + line continuations. + (reload_frozen_state): Track current line. + * tests/freeze.at (loading format 1, loading format 2): Update to + test this. + 2008-05-10 Eric Blake Detect integer overflow when loading frozen file. diff --git a/src/freeze.c b/src/freeze.c index 186b69b0..897a2460 100644 --- a/src/freeze.c +++ b/src/freeze.c @@ -34,7 +34,7 @@ static void produce_symbol_dump (m4 *, FILE *, m4_symbol_table *); static void *dump_symbol_CB (m4_symbol_table *, const char *, m4_symbol *, void *); static void issue_expect_message (m4 *, int); -static int decode_char (FILE *); +static int decode_char (m4 *, FILE *, bool *); /* Dump an ASCII-encoded representation of LEN bytes at MEM to FILE. @@ -294,13 +294,19 @@ issue_expect_message (m4 *context, int expected) unrecognized escape sequence. */ static int -decode_char (FILE *in) +decode_char (m4 *context, FILE *in, bool *advance_line) { int ch = getc (in); int next; int value = 0; - if (ch == '\\') + if (*advance_line) + { + m4_set_current_line (context, m4_get_current_line (context) + 1); + *advance_line = false; + } + + while (ch == '\\') { ch = getc (in); switch (ch) @@ -314,6 +320,11 @@ decode_char (FILE *in) case 'v': return '\v'; case '\\': return '\\'; + case '\n': + ch = getc (in); + m4_set_current_line (context, m4_get_current_line (context) + 1); + continue; + case 'x': case 'X': next = getc (in); if (next >= '0' && next <= '9') @@ -360,6 +371,8 @@ decode_char (FILE *in) } } + if (ch == '\n') + *advance_line = true; return ch; } @@ -378,9 +391,22 @@ reload_frozen_state (m4 *context, const char *name) char *string[3]; size_t allocated[3]; int number[3] = {0}; - -#define GET_CHARACTER \ - (character = getc (file)) + bool advance_line = true; + +#define GET_CHARACTER \ + do \ + { \ + if (advance_line) \ + { \ + m4_set_current_line (context, \ + m4_get_current_line (context) + 1); \ + advance_line = false; \ + } \ + character = getc (file); \ + if (character == '\n') \ + advance_line = true; \ + } \ + while (0) #define GET_NUMBER(Number, AllowNeg) \ do \ @@ -404,12 +430,14 @@ reload_frozen_state (m4 *context, const char *name) { \ size_t len = (StrLen); \ char *p; \ + int ch; \ CHECK_ALLOCATION ((Buf), (BufSize), len); \ p = (Buf); \ while (len-- > 0) \ { \ - int ch = (version > 1 ? decode_char (File) \ - : getc (File)); \ + ch = (version > 1 \ + ? decode_char (context, File, &advance_line) \ + : getc (File)); \ if (ch == EOF) \ m4_error (context, EXIT_FAILURE, 0, NULL, \ _("premature end of frozen file")); \ @@ -452,12 +480,19 @@ reload_frozen_state (m4 *context, const char *name) GET_CHARACTER; \ VALIDATE ('\n'); \ } \ + else if (character == '\\') \ + { \ + GET_CHARACTER; \ + VALIDATE ('\n'); \ + continue; \ + } \ } \ while (character == '\n') file = m4_path_search (context, name, (char **)NULL); if (file == NULL) m4_error (context, EXIT_FAILURE, errno, NULL, _("cannot open `%s'"), name); + m4_set_current_file (context, name); allocated[0] = 100; string[0] = xcharalloc (allocated[0]); @@ -773,7 +808,11 @@ ill-formed frozen file, version 2 directive `%c' encountered"), 'T'); free (string[0]); free (string[1]); free (string[2]); - fclose (file); + if (ferror (file) || fclose (file) != 0) + m4_error (context, EXIT_FAILURE, errno, NULL, + _("unable to read frozen state")); + m4_set_current_file (context, NULL); + m4_set_current_line (context, 0); #undef GET_STRING #undef GET_CHARACTER diff --git a/tests/freeze.at b/tests/freeze.at index 56933b75..e43af6ce 100644 --- a/tests/freeze.at +++ b/tests/freeze.at @@ -138,6 +138,15 @@ bar${1} [[m4:input.m4:5: Warning: popdef: undefined macro `my_define' ]]) +dnl Test rejection of v2 features in a v1 frozen file +AT_DATA([bogus.m4f], [[V1 +M2 +m4 +]]) +AT_CHECK_M4([-R bogus.m4f], [1], [], +[[m4:bogus.m4f:2: ill-formed frozen file, version 2 directive `M' encountered +]]) + AT_CLEANUP @@ -167,6 +176,10 @@ builtinbuiltingnu # introduced 2007-05-28 and fixed 2007-05-31. D-1,5 12345 +# Check line continuations. +D1,3 +a\n\ +b # Zero can be implied D, @@ -193,13 +206,15 @@ AT_CHECK_M4([-R frozen.m4f input.m4], [0], bar '7 \ -]]) +a +b]]) dnl We don't support anything larger than format 2; make sure of that... -AT_DATA([bogus.m4f], [[V3 +AT_DATA([bogus.m4f], [[# comments aren't continued\ +V3 ]]) AT_CHECK_M4([-R bogus.m4f], [63], [], -[[m4: frozen file version 3 greater than max supported of 2 +[[m4:bogus.m4f:2: frozen file version 3 greater than max supported of 2 ]]) dnl Check that V appears. @@ -207,7 +222,7 @@ AT_DATA([bogus.m4f], [[# not really a frozen file oops ]]) AT_CHECK_M4([-R bogus.m4f], [1], [], -[[m4: expecting character `V' in frozen file +[[m4:bogus.m4f:2: expecting character `V' in frozen file ]]) dnl M4_DIVNUM_TEST(number, [out-of-bounds]) @@ -220,8 +235,12 @@ M2 m4 M3 gnu +T1,5 +a\n\n\n\n\n F6,6,2 -divnumdivnumm4 +divnum\ +divnumm4\ + F6,6,2 divertdivertm4 F6,6,2 @@ -231,16 +250,16 @@ hi ]]) AT_CHECK_M4([-R frozen.m4f in.m4], m4_ifval([$2], [1], [0]), -m4_ifval([$2], [], [[$1 -]m4_if(m4_substr([$1], [0], [1]), [-], [], [[hi -]])]), m4_ifval([$2], [[m4: integer overflow in frozen file +m4_ifval([$2], [], [m4_bpatsubst([$1], [^0*]) +m4_if(m4_substr([$1], [0], [1]), [-], [], [[hi +]])]), m4_ifval([$2], [[m4:frozen.m4f:16: integer overflow in frozen file ]])) ]) AT_DATA([in.m4], [[define(d,divnum)divert(0)d ]]) -M4_DIVNUM_TEST([2147483647]) -M4_DIVNUM_TEST([2147483648], [:]) +M4_DIVNUM_TEST([02147483647]) +M4_DIVNUM_TEST([02147483648], [:]) M4_DIVNUM_TEST([-2147483648]) M4_DIVNUM_TEST([-2147483649], [:]) -- cgit v1.2.1