diff options
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | doc/m4.texinfo | 2 | ||||
-rw-r--r-- | m4/m4module.h | 4 | ||||
-rw-r--r-- | m4/utility.c | 24 | ||||
-rw-r--r-- | modules/evalparse.c | 7 | ||||
-rw-r--r-- | modules/gnu.c | 7 | ||||
-rw-r--r-- | modules/m4.c | 29 | ||||
-rw-r--r-- | modules/stdlib.c | 13 | ||||
-rw-r--r-- | modules/time.c | 31 | ||||
-rw-r--r-- | tests/null.err | bin | 1318 -> 2045 bytes | |||
-rw-r--r-- | tests/null.m4 | bin | 7559 -> 7735 bytes | |||
-rw-r--r-- | tests/null.out | bin | 607 -> 613 bytes | |||
-rw-r--r-- | tests/others.at | 8 |
13 files changed, 99 insertions, 48 deletions
@@ -1,5 +1,27 @@ 2009-02-11 Eric Blake <ebb9@byu.net> + Stage 28a: Warn on embedded NUL in numeric arguments. + Quote warning messages related to numeric parsing in order to + handle embedded NUL. + Memory impact: none. + Speed impact: none noticed. + * m4/m4module.h (m4_numeric_arg): Adjust prototype. + * m4/utility.c (m4_numeric_arg): Add parameter. + * modules/gnu.c (debuglen): Adjust callers. + * modules/m4.c (incr, decr, divert, undivert, m4exit, substr) + (index): Likewise. + * modules/evalparse.c (m4_evaluate): Likewise. + * modules/stdlib.c (setenv, getpwuid, srand): Likewise. + * modules/time.c (ctime, gmtime, localtime, mktime, strftime): + Likewise. + * doc/m4.texinfo (Changesyntax): Fix typo. + * tests/others.at (nul character): Adjust test. + * tests/null.m4: Likewise. + * tests/null.out: Likewise. + * tests/null.err: Likewise. + +2009-02-11 Eric Blake <ebb9@byu.net> + Avoid regression in popdef(undef). * doc/m4.texinfo (Trace): Enhance test, to cover regression recently fixed on the branch. diff --git a/doc/m4.texinfo b/doc/m4.texinfo index f972b48b..62fed45f 100644 --- a/doc/m4.texinfo +++ b/doc/m4.texinfo @@ -5751,7 +5751,7 @@ parenthesis will match any close parenthesis, etc. @example changesyntax(`(@{<', `)@}>', `,;:', `O(,)') @result{} -eval@{2**4-1; 2 : 8> +eval@{2**4-1; 2: 8> @result{}00001111 @end example diff --git a/m4/m4module.h b/m4/m4module.h index d5ad5135..84c203e5 100644 --- a/m4/m4module.h +++ b/m4/m4module.h @@ -1,6 +1,6 @@ /* GNU m4 -- A simple macro processor Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1999, 2000, 2003, - 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU M4. @@ -170,7 +170,7 @@ struct m4_string_pair extern bool m4_bad_argc (m4 *, size_t, const m4_call_info *, size_t, size_t, bool); extern bool m4_numeric_arg (m4 *, const m4_call_info *, const char *, - int *); + size_t, int *); extern bool m4_parse_truth_arg (m4 *, const m4_call_info *, const char *, bool); extern m4_symbol *m4_symbol_value_lookup (m4 *, m4_macro_args *, size_t, bool); diff --git a/m4/utility.c b/m4/utility.c index 31c17051..6d19526f 100644 --- a/m4/utility.c +++ b/m4/utility.c @@ -1,6 +1,6 @@ /* GNU m4 -- A simple macro processor Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1998, 1999, 2003, - 2006, 2007, 2008 Free Software Foundation, Inc. + 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU M4. @@ -68,30 +68,36 @@ skip_space (m4 *context, const char *arg) return arg; } -/* The function m4_numeric_arg () converts ARG to an int pointed to by - VALUEP. If the conversion fails, print error message for CALLER. - Return true iff conversion succeeds. */ +/* The function m4_numeric_arg () converts ARG of length LEN to an int + pointed to by VALUEP. If the conversion fails, print error message + for CALLER. Return true iff conversion succeeds. */ /* FIXME: Convert this to use gnulib's xstrtoimax, xstrtoumax. Otherwise, we are arbitrarily limiting integer values. */ bool m4_numeric_arg (m4 *context, const m4_call_info *caller, const char *arg, - int *valuep) + size_t len, int *valuep) { char *endp; - if (*arg == '\0') + if (!len) { *valuep = 0; m4_warn (context, 0, caller, _("empty string treated as 0")); } else { - *valuep = strtol (skip_space (context, arg), &endp, 10); - if (*skip_space (context, endp) != 0) + const char *str = skip_space (context, arg); + *valuep = strtol (str, &endp, 10); + if (endp - arg != len) { - m4_warn (context, 0, caller, _("non-numeric argument `%s'"), arg); + m4_warn (context, 0, caller, _("non-numeric argument %s"), + quotearg_style_mem (locale_quoting_style, arg, len)); return false; } + if (str != arg) + m4_warn (context, 0, caller, _("leading whitespace ignored")); + else if (errno == ERANGE) + m4_warn (context, 0, caller, _("numeric overflow detected")); } return true; } diff --git a/modules/evalparse.c b/modules/evalparse.c index ac30cfe9..87a318e2 100644 --- a/modules/evalparse.c +++ b/modules/evalparse.c @@ -1,6 +1,6 @@ /* GNU m4 -- A simple macro processor Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2001, 2006, 2007, - 2008 Free Software Foundation, Inc. + 2008, 2009 Free Software Foundation, Inc. This file is part of GNU M4. @@ -901,7 +901,7 @@ m4_evaluate (m4 *context, m4_obstack *obs, size_t argc, m4_macro_args *argv) eval_error err = NO_ERROR; if (!m4_arg_empty (argv, 2) - && !m4_numeric_arg (context, me, M4ARG (2), &radix)) + && !m4_numeric_arg (context, me, M4ARG (2), M4ARGLEN (2), &radix)) return; if (radix < 1 || radix > 36) @@ -910,7 +910,8 @@ m4_evaluate (m4 *context, m4_obstack *obs, size_t argc, m4_macro_args *argv) return; } - if (argc >= 4 && !m4_numeric_arg (context, me, M4ARG (3), &min)) + if (argc >= 4 && !m4_numeric_arg (context, me, M4ARG (3), M4ARGLEN (3), + &min)) return; if (min < 0) diff --git a/modules/gnu.c b/modules/gnu.c index 8ad17225..ce14532b 100644 --- a/modules/gnu.c +++ b/modules/gnu.c @@ -1,6 +1,6 @@ /* GNU m4 -- A simple macro processor - Copyright (C) 2000, 2004, 2005, 2006, 2007, 2008 Free Software - Foundation, Inc. + Copyright (C) 2000, 2004, 2005, 2006, 2007, 2008, 2009 Free + Software Foundation, Inc. This file is part of GNU M4. @@ -599,7 +599,8 @@ M4BUILTIN_HANDLER (debuglen) { int i; size_t s; - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &i)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), + &i)) return; /* FIXME - make m4_numeric_arg more powerful - we want to accept suffixes, and limit the result to size_t. */ diff --git a/modules/m4.c b/modules/m4.c index 177590dc..44e8a0ae 100644 --- a/modules/m4.c +++ b/modules/m4.c @@ -536,7 +536,8 @@ M4BUILTIN_HANDLER (incr) { int value; - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &value)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), + &value)) return; m4_shipout_int (obs, value + 1); @@ -546,7 +547,8 @@ M4BUILTIN_HANDLER (decr) { int value; - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &value)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), + &value)) return; m4_shipout_int (obs, value - 1); @@ -563,7 +565,7 @@ M4BUILTIN_HANDLER (divert) int i = 0; if (argc >= 2 && !m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), - &i)) + M4ARGLEN (1), &i)) return; m4_make_diversion (context, i); m4_divert_text (context, NULL, M4ARG (2), M4ARGLEN (2), @@ -592,12 +594,17 @@ M4BUILTIN_HANDLER (undivert) for (i = 1; i < argc; i++) { const char *str = M4ARG (i); + size_t len = M4ARGLEN (i); char *endp; int diversion = strtol (str, &endp, 10); - if (*endp == '\0' && !isspace ((unsigned char) *str)) + if (endp - str == len && !isspace ((unsigned char) *str)) m4_insert_diversion (context, diversion); else if (m4_get_posixly_correct_opt (context)) - m4_numeric_arg (context, me, str, &diversion); + m4_warn (context, 0, me, _("non-numeric argument %s"), + quotearg_style_mem (locale_quoting_style, str, len)); + else if (strlen (str) != len) + m4_warn (context, 0, me, _("invalid file name %s"), + quotearg_style_mem (locale_quoting_style, str, len)); else { FILE *fp = m4_path_search (context, str, NULL); @@ -609,7 +616,7 @@ M4BUILTIN_HANDLER (undivert) quotearg_style (locale_quoting_style, str)); } else - m4_error (context, 0, errno, me, _("cannot undivert `%s'"), + m4_error (context, 0, errno, me, _("cannot undivert %s"), quotearg_style (locale_quoting_style, str)); } } @@ -824,7 +831,8 @@ M4BUILTIN_HANDLER (m4exit) int exit_code = EXIT_SUCCESS; /* Warn on bad arguments, but still exit. */ - if (argc >= 2 && !m4_numeric_arg (context, me, M4ARG (1), &exit_code)) + if (argc >= 2 && !m4_numeric_arg (context, me, M4ARG (1), M4ARGLEN (1), + &exit_code)) exit_code = EXIT_FAILURE; if (exit_code < 0 || exit_code > 255) { @@ -919,7 +927,8 @@ M4BUILTIN_HANDLER (index) int retval = -1; if (!m4_arg_empty (argv, 3) && !m4_numeric_arg (context, m4_arg_info (argv), - M4ARG (3), &offset)) + M4ARG (3), M4ARGLEN (3), + &offset)) return; if (offset < 0) { @@ -967,7 +976,7 @@ M4BUILTIN_HANDLER (substr) length = M4ARGLEN (1); if (!m4_arg_empty (argv, 2) - && !m4_numeric_arg (context, me, M4ARG (2), &start)) + && !m4_numeric_arg (context, me, M4ARG (2), M4ARGLEN (2), &start)) return; if (start < 0) start += length; @@ -976,7 +985,7 @@ M4BUILTIN_HANDLER (substr) end = length; else { - if (!m4_numeric_arg (context, me, M4ARG (3), &end)) + if (!m4_numeric_arg (context, me, M4ARG (3), M4ARGLEN (3), &end)) return; if (end < 0) end += length; diff --git a/modules/stdlib.c b/modules/stdlib.c index b60e977a..3fce71f8 100644 --- a/modules/stdlib.c +++ b/modules/stdlib.c @@ -1,6 +1,6 @@ /* GNU m4 -- A simple macro processor - Copyright (C) 1999, 2000, 2001, 2006, 2007, 2008 Free Software - Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2006, 2007, 2008, 2009 Free + Software Foundation, Inc. This file is part of GNU M4. @@ -108,7 +108,8 @@ M4BUILTIN_HANDLER (setenv) int overwrite = 1; if (argc >= 4) - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (3), &overwrite)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (3), M4ARGLEN (3), + &overwrite)) return; #if HAVE_SETENV @@ -206,7 +207,8 @@ M4BUILTIN_HANDLER (getpwuid) struct passwd *pw; int uid; - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &uid)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), + &uid)) return; pw = getpwuid (uid); @@ -261,7 +263,8 @@ M4BUILTIN_HANDLER (srand) seed = time (0L) * getpid (); else { - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &seed)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), + M4ARGLEN (1), &seed)) return; } diff --git a/modules/time.c b/modules/time.c index a922a677..ee193a7b 100644 --- a/modules/time.c +++ b/modules/time.c @@ -1,6 +1,6 @@ /* GNU m4 -- A simple macro processor - Copyright (C) 1999, 2000, 2001, 2006, 2007, 2008 Free Software - Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2006, 2007, 2008, 2009 Free + Software Foundation, Inc. This file is part of GNU M4. @@ -104,7 +104,8 @@ M4BUILTIN_HANDLER (ctime) if (argc == 2) { - m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &i); + m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), + &i); t = i; } else @@ -152,7 +153,8 @@ M4BUILTIN_HANDLER (gmtime) time_t t; int i; - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &i)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), + &i)) return; t = i; @@ -167,7 +169,8 @@ M4BUILTIN_HANDLER (localtime) time_t t; int i; - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &i)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), + &i)) return; t = i; @@ -184,19 +187,20 @@ M4BUILTIN_HANDLER (mktime) struct tm tm; time_t t; - if (!m4_numeric_arg (context, me, M4ARG (1), &tm.tm_sec)) + if (!m4_numeric_arg (context, me, M4ARG (1), M4ARGLEN (1), &tm.tm_sec)) return; - if (!m4_numeric_arg (context, me, M4ARG (2), &tm.tm_min)) + if (!m4_numeric_arg (context, me, M4ARG (2), M4ARGLEN (2), &tm.tm_min)) return; - if (!m4_numeric_arg (context, me, M4ARG (3), &tm.tm_hour)) + if (!m4_numeric_arg (context, me, M4ARG (3), M4ARGLEN (3), &tm.tm_hour)) return; - if (!m4_numeric_arg (context, me, M4ARG (4), &tm.tm_mday)) + if (!m4_numeric_arg (context, me, M4ARG (4), M4ARGLEN (4), &tm.tm_mday)) return; - if (!m4_numeric_arg (context, me, M4ARG (5), &tm.tm_mon)) + if (!m4_numeric_arg (context, me, M4ARG (5), M4ARGLEN (5), &tm.tm_mon)) return; - if (!m4_numeric_arg (context, me, M4ARG (6), &tm.tm_year)) + if (!m4_numeric_arg (context, me, M4ARG (6), M4ARGLEN (6), &tm.tm_year)) return; - if (M4ARG (7) && !m4_numeric_arg (context, me, M4ARG (7), &tm.tm_isdst)) + if (M4ARG (7) && !m4_numeric_arg (context, me, M4ARG (7), M4ARGLEN (7), + &tm.tm_isdst)) return; t = mktime (&tm); @@ -216,7 +220,8 @@ M4BUILTIN_HANDLER (strftime) char *buf; int l; - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (2), &l)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (2), M4ARGLEN (2), + &l)) return; t = l; diff --git a/tests/null.err b/tests/null.err Binary files differindex 7b9f7981..edad891e 100644 --- a/tests/null.err +++ b/tests/null.err diff --git a/tests/null.m4 b/tests/null.m4 Binary files differindex f7a15875..3d57806e 100644 --- a/tests/null.m4 +++ b/tests/null.m4 diff --git a/tests/null.out b/tests/null.out Binary files differindex 97f80dd5..cfb78c04 100644 --- a/tests/null.out +++ b/tests/null.out diff --git a/tests/others.at b/tests/others.at index 6776ee36..3f123516 100644 --- a/tests/others.at +++ b/tests/others.at @@ -1,5 +1,6 @@ # Hand crafted tests for GNU M4. -*- Autotest -*- -# Copyright (C) 2001, 2006, 2007, 2008 Free Software Foundation, Inc. +# Copyright (C) 2001, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. # This file is part of GNU M4. # @@ -432,8 +433,11 @@ dnl all but m4exit AT_CHECK_M4([-Dm4exit -I "$abs_srcdir" null.m4], [0], [expout], [experr]) dnl just m4exit -AT_CHECK_M4(["$abs_srcdir/null.m4"], [2], +AT_CHECK_M4(["$abs_srcdir/null.m4"], [1], [[# This file tests m4 behavior on NUL bytes. +]], [stderr]) +AT_CHECK([sed "s|$abs_srcdir/||" stderr], [0], +[[m4:null.m4:5: Warning: m4exit: non-numeric argument `2\0002' ]]) AT_CLEANUP |