This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "GNU M4 source repository".
http://git.sv.gnu.org/gitweb/?p=m4.git;a=commitdiff;h=9f8edd91d4dcab4e1735f02253c32a55c62f2aac The branch, master has been updated via 9f8edd91d4dcab4e1735f02253c32a55c62f2aac (commit) via 4fab2788576b9e10374138be453620a05c95c7be (commit) from 43173c1ade54a595a488e750dfba700c89b9fdb8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 9f8edd91d4dcab4e1735f02253c32a55c62f2aac Author: Eric Blake <[EMAIL PROTECTED]> Date: Tue May 13 09:30:04 2008 -0600 Fix frozen file regression in diversions from 2007-01-21. * m4/output.c (insert_diversion_helper): Add parameter. (m4_insert_file): Move contents... (insert_file): ...to this new helper, with added parameter. (m4_insert_diversion, m4_undivert_all, m4_freeze_diversions): Update callers. * src/freeze.c (produce_mem_dump): Simplify. (produce_syntax_dump, produce_module_dump): Add parameter. * tests/freeze.at (large diversion): Test for this. Signed-off-by: Eric Blake <[EMAIL PROTECTED]> commit 4fab2788576b9e10374138be453620a05c95c7be Author: Eric Blake <[EMAIL PROTECTED]> Date: Tue May 13 06:25:46 2008 -0600 Improve error message when frozen file is invalid. * src/freeze.c (decode_char): Add parameter. Allow \<newline> 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 <[EMAIL PROTECTED]> ----------------------------------------------------------------------- Summary of changes: ChangeLog | 19 ++++++++++++ m4/output.c | 51 +++++++++++++++++++++---------- src/freeze.c | 89 ++++++++++++++++++++++++++++++++----------------------- tests/freeze.at | 42 +++++++++++++++++++------- 4 files changed, 136 insertions(+), 65 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05234af..18e5d0a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2008-05-13 Eric Blake <[EMAIL PROTECTED]> + + Fix frozen file regression in diversions from 2007-01-21. + * m4/output.c (insert_diversion_helper): Add parameter. + (m4_insert_file): Move contents... + (insert_file): ...to this new helper, with added parameter. + (m4_insert_diversion, m4_undivert_all, m4_freeze_diversions): + Update callers. + * src/freeze.c (produce_mem_dump): Simplify. + (produce_syntax_dump, produce_module_dump): Add parameter. + * tests/freeze.at (large diversion): Test for this. + + Improve error message when frozen file is invalid. + * src/freeze.c (decode_char): Add parameter. Allow \<newline> + 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 <[EMAIL PROTECTED]> Detect integer overflow when loading frozen file. diff --git a/m4/output.c b/m4/output.c index c903d99..d3c5507 100644 --- a/m4/output.c +++ b/m4/output.c @@ -27,6 +27,7 @@ #include "exitfail.h" #include "gl_avltree_oset.h" #include "intprops.h" +#include "quotearg.h" #include "xvasprintf.h" /* Define this to see runtime debug output. Implied by DEBUG. */ @@ -740,19 +741,16 @@ m4_make_diversion (m4 *context, int divnum) } /* Insert a FILE into the current output file, in the same manner - diversions are handled. This allows files to be included, without - having them rescanned by m4. */ -void -m4_insert_file (m4 *context, FILE *file) + diversions are handled. If ESCAPED, ensure the output is all + ASCII. */ +static void +insert_file (m4 *context, FILE *file, bool escaped) { char buffer[COPY_BUFFER_SIZE]; size_t length; + char *str = buffer; - /* Optimize out inserting into a sink. */ - - if (!output_diversion) - return; - + assert (output_diversion); /* Insert output by big chunks. */ for (;;) { @@ -762,16 +760,29 @@ m4_insert_file (m4 *context, FILE *file) _("reading inserted file")); if (length == 0) break; - m4_output_text (context, buffer, length); + if (escaped) + str = quotearg_style_mem (escape_quoting_style, buffer, length); + m4_output_text (context, str, escaped ? strlen (str) : length); } } +/* Insert a FILE into the current output file, in the same manner + diversions are handled. This allows files to be included, without + having them rescanned by m4. */ +void +m4_insert_file (m4 *context, FILE *file) +{ + /* Optimize out inserting into a sink. */ + if (output_diversion) + insert_file (context, file, false); +} + /* Insert DIVERSION living at NODE into the current output file. The diversion is NOT placed on the expansion obstack, because it must - not be rescanned. When the file is closed, it is deleted by the - system. */ + not be rescanned. If ESCAPED, ensure the output is ASCII. When + the file is closed, it is deleted by the system. */ static void -insert_diversion_helper (m4 *context, m4_diversion *diversion) +insert_diversion_helper (m4 *context, m4_diversion *diversion, bool escaped) { assert (diversion->divnum > 0 && diversion->divnum != m4_get_current_diversion (context)); @@ -779,7 +790,13 @@ insert_diversion_helper (m4 *context, m4_diversion *diversion) if (output_diversion) { if (diversion->size) - m4_output_text (context, diversion->u.buffer, diversion->used); + { + char *str = diversion->u.buffer; + size_t len = diversion->used; + if (escaped) + str = quotearg_style_mem (escape_quoting_style, str, len); + m4_output_text (context, str, escaped ? strlen (str) : len); + } else { assert (diversion->used); @@ -836,7 +853,7 @@ m4_insert_diversion (m4 *context, int divnum) { m4_diversion *diversion = (m4_diversion *) elt; if (diversion->divnum == divnum) - insert_diversion_helper (context, diversion); + insert_diversion_helper (context, diversion, false); } } @@ -852,7 +869,7 @@ m4_undivert_all (m4 *context) { m4_diversion *diversion = (m4_diversion *) elt; if (diversion->divnum != divnum) - insert_diversion_helper (context, diversion); + insert_diversion_helper (context, diversion, false); } gl_oset_iterator_free (&iter); } @@ -902,7 +919,7 @@ m4_freeze_diversions (m4 *context, FILE *file) (unsigned long int) file_stat.st_size); } - insert_diversion_helper (context, diversion); + insert_diversion_helper (context, diversion, true); putc ('\n', file); last_inserted = diversion->divnum; diff --git a/src/freeze.c b/src/freeze.c index 186b69b..0b48ac6 100644 --- a/src/freeze.c +++ b/src/freeze.c @@ -25,6 +25,7 @@ #include "m4.h" #include "binary-io.h" +#include "quotearg.h" static void produce_mem_dump (FILE *, const char *, size_t); static void produce_resyntax_dump (m4 *, FILE *); @@ -34,7 +35,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. @@ -42,34 +43,9 @@ static int decode_char (FILE *); static void produce_mem_dump (FILE *file, const char *mem, size_t len) { - while (len--) - { - int ch = to_uchar (*mem++); - switch (ch) - { - case '\a': putc ('\\', file); putc ('a', file); break; - case '\b': putc ('\\', file); putc ('b', file); break; - case '\f': putc ('\\', file); putc ('f', file); break; - case '\n': putc ('\\', file); putc ('n', file); break; - case '\r': putc ('\\', file); putc ('r', file); break; - case '\t': putc ('\\', file); putc ('t', file); break; - case '\v': putc ('\\', file); putc ('v', file); break; - case '\\': putc ('\\', file); putc ('\\', file); break; - default: - if (ch >= 0x7f || ch < 0x20) - { - int digit = ch / 16; - ch %= 16; - digit += digit > 9 ? 'a' - 10 : '0'; - ch += ch > 9 ? 'a' - 10 : '0'; - putc ('\\', file); - putc ('x', file); - putc (digit, file); - } - putc (ch, file); - break; - } - } + char *quoted = quotearg_style_mem (escape_quoting_style, mem, len); + /* Any errors will be detected by ferror later. */ + fwrite (quoted, strlen (quoted), 1, file); } @@ -294,13 +270,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 +296,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 +347,8 @@ decode_char (FILE *in) } } + if (ch == '\n') + *advance_line = true; return ch; } @@ -378,9 +367,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 +406,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 +456,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 +784,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 56933b7..74dc3e9 100644 --- a/tests/freeze.at +++ b/tests/freeze.at @@ -27,9 +27,10 @@ AT_SETUP([large diversion]) AT_KEYWORDS([frozen]) # Check that large diversions are handled across freeze boundaries. - +# Also check for escape character handling. AT_DATA([[frozen.m4]], [M4_ONE_MEG_DEFN[divert(2)f divert(1)hi +a\nb ]]) AT_DATA([[unfrozen.m4]], @@ -138,6 +139,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 +177,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 +207,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 +223,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 +236,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 +251,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], [:]) hooks/post-receive -- GNU M4 source repository
