m4-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU M4 source repository branch, branch-1.6, updated. v1.5.89a-90-


From: Eric Blake
Subject: [SCM] GNU M4 source repository branch, branch-1.6, updated. v1.5.89a-90-g1b5e601
Date: Thu, 12 Feb 2009 03:30:35 +0000

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=1b5e6019b86abfc086af32b79087b8e862ed7a81

The branch, branch-1.6 has been updated
       via  1b5e6019b86abfc086af32b79087b8e862ed7a81 (commit)
      from  f35224878771517f1d7c13568c1b65a59e7908a4 (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 1b5e6019b86abfc086af32b79087b8e862ed7a81
Author: Eric Blake <address@hidden>
Date:   Tue Feb 5 11:41:05 2008 -0700

    Stage 28: Allow embedded NUL in warning messages.
    
    * src/m4.h (debug_decode): Add argument.
    * src/m4.c (main): Adjust caller.
    * src/format.c (arg_int, arg_long, arg_double): Likewise.
    (arg_string): New function.
    (ARG_INT, ARG_LONG, ARG_STR, ARG_DOUBLE): Support embedded NUL.
    * src/freeze.c (reload_frozen_state): Likewise.
    * src/debug.c (debug_decode): Likewise.
    * src/builtin.c (numeric_arg): Add argument.
    (m4_syscmd, m4_esyscmd, m4_eval, m4_incr, m4_decr, m4_divert)
    (m4_undivert, include, mkstemp_helper, m4_m4exit, m4_debugmode)
    (m4_debugfile, m4_index, m4_substr): Detect embedded NUL.
    (m4_defn, m4_maketemp, m4_placeholder): Improve warning message.
    * src/path.c (m4_path_search): Likewise.
    * doc/m4.texinfo (Syntax, Mkstemp, Using frozen files): Adjust
    tests.
    * examples/null.m4: Likewise.
    * examples/null.out: Likewise.
    * examples/null.err: Likewise.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit fd9f6463352aee342c4061b5df9d0f4bf56742c7)

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog         |   28 ++++++++++++
 doc/m4.texinfo    |   20 ++++++++-
 examples/null.err |  Bin 1078 -> 3298 bytes
 examples/null.m4  |  Bin 6667 -> 6776 bytes
 examples/null.out |  Bin 553 -> 578 bytes
 src/builtin.c     |  121 ++++++++++++++++++++++++++++++++++++-----------------
 src/debug.c       |   30 ++++++++-----
 src/format.c      |   55 ++++++++++++++++--------
 src/freeze.c      |   13 ++++--
 src/m4.c          |   14 ++++---
 src/m4.h          |    2 +-
 src/path.c        |   10 +++-
 12 files changed, 210 insertions(+), 83 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2aa09b4..39d40df 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,33 @@
 2009-02-11  Eric Blake  <address@hidden>
 
+       Stage 28: Allow embedded NUL in warning messages.
+       Issue graceful error messages for a variety of places where
+       embedded NUL is otherwise unhandled.  For example, numeric parsing
+       rejects embedded NUL, while file-related commands warn about
+       truncation at NUL, and frozen files detect unexpected NUL.
+       Memory impact: none.
+       Speed impact: none noticed.
+       * src/m4.h (debug_decode): Add argument.
+       * src/m4.c (main): Adjust caller.
+       * src/format.c (arg_int, arg_long, arg_double): Likewise.
+       (arg_string): New function.
+       (ARG_INT, ARG_LONG, ARG_STR, ARG_DOUBLE): Support embedded NUL.
+       * src/freeze.c (reload_frozen_state): Likewise.
+       * src/debug.c (debug_decode): Likewise.
+       * src/builtin.c (numeric_arg): Add argument.
+       (m4_syscmd, m4_esyscmd, m4_eval, m4_incr, m4_decr, m4_divert)
+       (m4_undivert, include, mkstemp_helper, m4_m4exit, m4_debugmode)
+       (m4_debugfile, m4_index, m4_substr): Detect embedded NUL.
+       (m4_defn, m4_maketemp, m4_placeholder): Improve warning message.
+       * src/path.c (m4_path_search): Likewise.
+       * doc/m4.texinfo (Syntax, Mkstemp, Using frozen files): Adjust
+       tests.
+       * examples/null.m4: Likewise.
+       * examples/null.out: Likewise.
+       * examples/null.err: Likewise.
+
+2009-02-11  Eric Blake  <address@hidden>
+
        Warn when popping traced but undefined macro.
        * src/symtab.c (lookup_symbol): Recognize traced placeholder when
        delete is requested.  Bug introduced 2008-07-18.
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index b337e5e..fd48e80 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -1081,14 +1081,16 @@ exception of the @sc{nul} character (the zero byte 
@samp{'\0'}).
 
 @comment xout: null.out
 @comment xerr: null.err
address@hidden status: 1
 @example
 define(`m4exit')include(`null.m4')dnl
 @end example
 
address@hidden status: 2
address@hidden status: 1
 @example
 include(`null.m4')
 @result{}# This file tests m4 behavior on NUL bytes.
address@hidden:examples/null.m4:5: Warning: m4exit: non-numeric argument 
`2\0002'
 @end example
 @end ignore
 
@@ -7485,10 +7487,12 @@ define(`foo', `errprint(`oops')')
 syscmd(`rm -f foo-??????')sysval
 @result{}0
 define(`file1', maketemp(`foo-XXXXXX'))dnl
address@hidden:stdin:3: Warning: maketemp: recommend using mkstemp instead
 ifelse(esyscmd(`echo \` foo-?????? \''), ` foo-?????? ',
        `no file', `created')
 @result{}created
 define(`file2', maketemp(`foo-XX'))dnl
address@hidden:stdin:6: Warning: maketemp: recommend using mkstemp instead
 define(`file3', mkstemp(`foo-XXXXXX'))dnl
 ifelse(len(defn(`file1')), len(defn(`file2')),
        `same length', `different')
@@ -7905,6 +7909,20 @@ divert(1)undivert(null.out)' | ]__program__[ -F in.m4f \
 ])dnl
 @error{}divnum #-- 3 0
 @end example
+
address@hidden Do we reject unexpected NUL bytes?
+
address@hidden
+ifdef(`__unix__', ,
+      `errprint(` skipping: syscmd does not have unix semantics
+')m4exit(`77')')dnl
+changequote(`[', `]')dnl
+syscmd([printf '#bogus\nV1\nF3,4\nlenlen\0\n' > in.m4f \
+     && ]__program__[ -R in.m4f \
+     && rm in.m4f])sysval
address@hidden:in.m4f:4: ill-formed frozen file, invalid builtin `len\0' 
encountered
address@hidden
address@hidden example
 @end ignore
 
 When an @code{m4} run is to be frozen, the automatic undiversion
diff --git a/examples/null.err b/examples/null.err
index 977b3b7..8446d78 100644
Binary files a/examples/null.err and b/examples/null.err differ
diff --git a/examples/null.m4 b/examples/null.m4
index e60aec5..3f901f4 100644
Binary files a/examples/null.m4 and b/examples/null.m4 differ
diff --git a/examples/null.out b/examples/null.out
index c2c1cb9..812df0c 100644
Binary files a/examples/null.out and b/examples/null.out differ
diff --git a/src/builtin.c b/src/builtin.c
index a398fdb..22d156d 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -564,18 +564,18 @@ bad_argc (const call_info *name, int argc, unsigned int 
min, unsigned int max)
   return false;
 }
 
-/*-------------------------------------------------------------------.
-| The function numeric_arg () converts ARG to an int pointed to by   |
-| VALUEP.  If the conversion fails, print error message on behalf of |
-| NAME.  Return true iff conversion succeeds.                        |
-`-------------------------------------------------------------------*/
+/*------------------------------------------------------------------.
+| The function numeric_arg () converts ARG of length LEN to an int  |
+| pointed to by VALUEP.  If the conversion fails, print error       |
+| message on behalf of NAME.  Return true iff conversion succeeds.  |
+`------------------------------------------------------------------*/
 
 static bool
-numeric_arg (const call_info *name, const char *arg, int *valuep)
+numeric_arg (const call_info *name, const char *arg, size_t len, int *valuep)
 {
   char *endp;
 
-  if (*arg == '\0')
+  if (!len)
     {
       *valuep = 0;
       m4_warn (0, name, _("empty string treated as 0"));
@@ -584,9 +584,10 @@ numeric_arg (const call_info *name, const char *arg, int 
*valuep)
     {
       errno = 0;
       *valuep = strtol (arg, &endp, 10);
-      if (*endp != '\0')
+      if (endp - arg != len)
        {
-         m4_warn (0, name, _("non-numeric argument `%s'"), arg);
+         m4_warn (0, name, _("non-numeric argument %s"),
+                  quotearg_style_mem (locale_quoting_style, arg, len));
          return false;
        }
       if (isspace (to_uchar (*arg)))
@@ -1087,8 +1088,9 @@ m4_defn (struct obstack *obs, int argc, macro_arguments 
*argv)
          b = SYMBOL_FUNC (s);
          if (b == m4_placeholder)
            m4_warn (0, me,
-                    _("builtin `%s' requested by frozen file not found"),
-                    ARG (i));
+                    _("builtin %s requested by frozen file not found"),
+                    quotearg_style_mem (locale_quoting_style, ARG (i),
+                                        ARG_LEN (i)));
          else
            push_macro (obs, b);
          break;
@@ -1140,7 +1142,14 @@ static int sysval;
 static void
 m4_syscmd (struct obstack *obs, int argc, macro_arguments *argv)
 {
-  if (bad_argc (arg_info (argv), argc, 1, 1))
+  const call_info *me = arg_info (argv);
+  const char *cmd = ARG (1);
+  size_t len = ARG_LEN (1);
+
+  if (strlen (cmd) != len)
+    m4_warn (0, me, _("argument %s truncated"),
+            quotearg_style_mem (locale_quoting_style, cmd, len));
+  if (bad_argc (me, argc, 1, 1) || !*cmd)
     {
       /* The empty command is successful.  */
       sysval = 0;
@@ -1148,7 +1157,7 @@ m4_syscmd (struct obstack *obs, int argc, macro_arguments 
*argv)
     }
 
   debug_flush_files ();
-  sysval = system (ARG (1));
+  sysval = system (cmd);
 #if FUNC_SYSTEM_BROKEN
   /* OS/2 has a buggy system() that returns exit status in the lowest eight
      bits, although pclose() and WEXITSTATUS are defined to return exit
@@ -1165,10 +1174,15 @@ static void
 m4_esyscmd (struct obstack *obs, int argc, macro_arguments *argv)
 {
   const call_info *me = arg_info (argv);
+  const char *cmd = ARG (1);
+  size_t len = ARG_LEN (1);
   FILE *pin;
   int ch;
 
-  if (bad_argc (me, argc, 1, 1))
+  if (strlen (cmd) != len)
+    m4_warn (0, me, _("argument %s truncated"),
+            quotearg_style_mem (locale_quoting_style, cmd, len));
+  if (bad_argc (me, argc, 1, 1) || !*cmd)
     {
       /* The empty command is successful.  */
       sysval = 0;
@@ -1177,10 +1191,11 @@ m4_esyscmd (struct obstack *obs, int argc, 
macro_arguments *argv)
 
   debug_flush_files ();
   errno = 0;
-  pin = popen (ARG (1), "r");
+  pin = popen (cmd, "r");
   if (pin == NULL)
     {
-      m4_warn (errno, me, _("cannot open pipe to command `%s'"), ARG (1));
+      m4_warn (errno, me, _("cannot open pipe to command %s"),
+              quotearg_style (locale_quoting_style, cmd));
       sysval = -1;
     }
   else
@@ -1217,7 +1232,7 @@ m4_eval (struct obstack *obs, int argc, macro_arguments 
*argv)
   if (bad_argc (me, argc, 1, 3))
     return;
 
-  if (!arg_empty (argv, 2) && !numeric_arg (me, ARG (2), &radix))
+  if (!arg_empty (argv, 2) && !numeric_arg (me, ARG (2), ARG_LEN (2), &radix))
     return;
 
   if (radix < 1 || radix > 36)
@@ -1226,7 +1241,7 @@ m4_eval (struct obstack *obs, int argc, macro_arguments 
*argv)
       return;
     }
 
-  if (argc >= 4 && !numeric_arg (me, ARG (3), &min))
+  if (argc >= 4 && !numeric_arg (me, ARG (3), ARG_LEN (3), &min))
     return;
   if (min < 0)
     {
@@ -1281,7 +1296,7 @@ m4_incr (struct obstack *obs, int argc, macro_arguments 
*argv)
   if (bad_argc (me, argc, 1, 1))
     return;
 
-  if (!numeric_arg (me, ARG (1), &value))
+  if (!numeric_arg (me, ARG (1), ARG_LEN (1), &value))
     return;
 
   shipout_int (obs, value + 1);
@@ -1296,7 +1311,7 @@ m4_decr (struct obstack *obs, int argc, macro_arguments 
*argv)
   if (bad_argc (me, argc, 1, 1))
     return;
 
-  if (!numeric_arg (me, ARG (1), &value))
+  if (!numeric_arg (me, ARG (1), ARG_LEN (1), &value))
     return;
 
   shipout_int (obs, value - 1);
@@ -1317,7 +1332,7 @@ m4_divert (struct obstack *obs, int argc, macro_arguments 
*argv)
   int i = 0;
 
   bad_argc (me, argc, 0, 2);
-  if (argc >= 2 && !numeric_arg (me, ARG (1), &i))
+  if (argc >= 2 && !numeric_arg (me, ARG (1), ARG_LEN (1), &i))
     return;
 
   make_diversion (i);
@@ -1357,11 +1372,16 @@ m4_undivert (struct obstack *obs, int argc, 
macro_arguments *argv)
     for (i = 1; i < argc; i++)
       {
        const char *str = ARG (i);
+       size_t len = ARG_LEN (i);
        file = strtol (str, &endp, 10);
-       if (*endp == '\0' && !isspace (to_uchar (*str)))
+       if (endp - str == len && !isspace (to_uchar (*str)))
          insert_diversion (file);
        else if (no_gnu_extensions)
-         m4_warn (0, me, _("non-numeric argument `%s'"), str);
+         m4_warn (0, me, _("non-numeric argument %s"),
+                  quotearg_style_mem (locale_quoting_style, str, len));
+       else if (strlen (str) != len)
+         m4_warn (0, me, _("invalid file name %s"),
+                  quotearg_style_mem (locale_quoting_style, str, len));
        else
          {
            fp = m4_path_search (str, NULL);
@@ -1473,16 +1493,23 @@ include (int argc, macro_arguments *argv, bool silent)
   const call_info *me = arg_info (argv);
   FILE *fp;
   char *name;
+  const char *arg;
+  size_t len;
 
   if (bad_argc (me, argc, 1, 1))
     return;
 
-  fp = m4_path_search (ARG (1), &name);
+  arg = ARG (1);
+  len = ARG_LEN (1);
+  if (strlen (arg) != len)
+    m4_warn (0, me, _("argument %s truncated"),
+            quotearg_style_mem (locale_quoting_style, arg, len));
+  fp = m4_path_search (arg, &name);
   if (fp == NULL)
     {
       if (!silent)
        m4_error (0, errno, me, _("cannot open %s"),
-                 quotearg_style (locale_quoting_style, ARG (1)));
+                 quotearg_style (locale_quoting_style, arg));
       return;
     }
 
@@ -1532,6 +1559,12 @@ mkstemp_helper (struct obstack *obs, const call_info 
*me, const char *pattern,
      user forgot to supply them.  Output must be quoted if
      successful.  */
   obstack_grow (obs, curr_quote.str1, curr_quote.len1);
+  if (strlen (pattern) < len)
+    {
+      m4_warn (0, me, _("argument %s truncated"),
+              quotearg_style_mem (locale_quoting_style, pattern, len));
+      len = strlen (pattern);
+    }
   obstack_grow (obs, pattern, len);
   for (i = 0; len > 0 && i < 6; i++)
     if (pattern[--len] != 'X')
@@ -1543,7 +1576,8 @@ mkstemp_helper (struct obstack *obs, const call_info *me, 
const char *pattern,
   fd = mkstemp (name);
   if (fd < 0)
     {
-      m4_warn (errno, me, _("cannot create tempfile `%s'"), pattern);
+      m4_warn (errno, me, _("cannot create file from template %s"),
+              quotearg_style (locale_quoting_style, pattern));
       obstack_free (obs, obstack_finish (obs));
     }
   else
@@ -1562,6 +1596,7 @@ m4_maketemp (struct obstack *obs, int argc, 
macro_arguments *argv)
 
   if (bad_argc (me, argc, 1, 1))
     return;
+  m4_warn (0, me, _("recommend using mkstemp instead"));
   if (no_gnu_extensions)
     {
       /* POSIX states "any trailing 'X' characters [are] replaced with
@@ -1583,7 +1618,6 @@ m4_maketemp (struct obstack *obs, int argc, 
macro_arguments *argv)
                                       (unsigned long) getpid ());
       char *pid = (char *) obstack_copy0 (scratch, "", 0);
 
-      m4_warn (0, me, _("recommend using mkstemp instead"));
       for (i = len; i > 1; i--)
        if (str[i - 1] != 'X')
          break;
@@ -1669,7 +1703,7 @@ m4_m4exit (struct obstack *obs, int argc, macro_arguments 
*argv)
 
   /* Warn on bad arguments, but still exit.  */
   bad_argc (me, argc, 0, 1);
-  if (argc >= 2 && !numeric_arg (me, ARG (1), &exit_code))
+  if (argc >= 2 && !numeric_arg (me, ARG (1), ARG_LEN (1), &exit_code))
     exit_code = EXIT_FAILURE;
   if (exit_code < 0 || exit_code > 255)
     {
@@ -1784,13 +1818,15 @@ m4_debugmode (struct obstack *obs, int argc, 
macro_arguments *argv)
 {
   const call_info *me = arg_info (argv);
   const char *str = ARG (1);
+  size_t len = ARG_LEN (1);
 
   bad_argc (me, argc, 0, 1);
 
   if (argc == 1)
     debug_level = 0;
-  else if (debug_decode (str) < 0)
-    m4_warn (0, me, _("bad debug flags: `%s'"), str);
+  else if (debug_decode (str, len) < 0)
+    m4_warn (0, me, _("bad debug flags: %s"),
+            quotearg_style_mem (locale_quoting_style, str, len));
 }
 
 /*-------------------------------------------------------------------------.
@@ -1807,9 +1843,17 @@ m4_debugfile (struct obstack *obs, int argc, 
macro_arguments *argv)
 
   if (argc == 1)
     debug_set_output (me, NULL);
-  else if (!debug_set_output (me, ARG (1)))
-    m4_warn (errno, me, _("cannot set debug file %s"),
-            quotearg_style (locale_quoting_style, ARG (1)));
+  else
+    {
+      const char *str = ARG (1);
+      size_t len = ARG_LEN (1);
+      if (strlen (str) < len)
+       m4_warn (0, me, _("argument %s truncated"),
+                quotearg_style_mem (locale_quoting_style, str, len));
+      if (!debug_set_output (me, str))
+       m4_warn (errno, me, _("cannot set debug file %s"),
+                quotearg_style (locale_quoting_style, str));
+    }
 }
 
 /* This section contains text processing macros: "len", "index",
@@ -1855,7 +1899,8 @@ m4_index (struct obstack *obs, int argc, macro_arguments 
*argv)
   haystack = ARG (1);
   haystack_len = ARG_LEN (1);
   needle = ARG (2);
-  if (!arg_empty (argv, 3) && !numeric_arg (arg_info (argv), ARG (3), &offset))
+  if (!arg_empty (argv, 3)
+      && !numeric_arg (arg_info (argv), ARG (3), ARG_LEN (3), &offset))
     return;
   if (offset < 0)
     {
@@ -1907,7 +1952,7 @@ m4_substr (struct obstack *obs, int argc, macro_arguments 
*argv)
     }
 
   length = ARG_LEN (1);
-  if (!arg_empty (argv, 2) && !numeric_arg (me, ARG (2), &start))
+  if (!arg_empty (argv, 2) && !numeric_arg (me, ARG (2), ARG_LEN (2), &start))
     return;
   if (start < 0)
     start += length;
@@ -1916,7 +1961,7 @@ m4_substr (struct obstack *obs, int argc, macro_arguments 
*argv)
     end = length;
   else
     {
-      if (!numeric_arg (me, ARG (3), &end))
+      if (!numeric_arg (me, ARG (3), ARG_LEN (3), &end))
        return;
       if (end < 0)
        end += length;
@@ -2406,8 +2451,8 @@ m4_patsubst (struct obstack *obs, int argc, 
macro_arguments *argv)
 void
 m4_placeholder (struct obstack *obs, int argc, macro_arguments *argv)
 {
-  m4_warn (0, NULL, _("builtin `%s' requested by frozen file not found"),
-          ARG (0));
+  m4_warn (0, NULL, _("builtin %s requested by frozen file not found"),
+          quotearg_style_mem (locale_quoting_style, ARG (0), ARG_LEN (0)));
 }
 
 /*-------------------------------------------------------------------------.
diff --git a/src/debug.c b/src/debug.c
index b97fca3..8ed2d0d 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -1,7 +1,7 @@
 /* GNU m4 -- A simple macro processor
 
-   Copyright (C) 1991, 1992, 1993, 1994, 2004, 2006, 2007, 2008 Free
-   Software Foundation, Inc.
+   Copyright (C) 1991, 1992, 1993, 1994, 2004, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
 
    This file is part of GNU M4.
 
@@ -43,25 +43,33 @@ debug_init (void)
   obstack_init (&trace);
 }
 
-/*------------------------------------------------------------------.
-| Function to decode the debugging flags OPTS.  Used by main while  |
-| processing option -d, and by the builtin debugmode ().  Return -1 |
-| if the parse failed, otherwise change the debug level.           |
-`------------------------------------------------------------------*/
+/*-------------------------------------------------------------------.
+| Function to decode the debugging flags OPTS of length LEN.  If LEN |
+| is SIZE_MAX, use strlen (OPTS) instead.  Used by main while       |
+| processing option -d, and by the builtin debugmode.  Return -1 if  |
+| the parse failed, otherwise change the debug level.               |
+`-------------------------------------------------------------------*/
 
 int
-debug_decode (const char *opts)
+debug_decode (const char *opts, size_t len)
 {
   int level;
   char mode = '\0';
 
-  if (opts == NULL || *opts == '\0')
+  if (!opts)
+    opts = "";
+  if (len == SIZE_MAX)
+    len = strlen (opts);
+  if (!len)
     level = DEBUG_TRACE_DEFAULT | debug_level;
   else
     {
       if (*opts == '-' || *opts == '+')
-       mode = *opts++;
-      for (level = 0; *opts; opts++)
+       {
+         len--;
+         mode = *opts++;
+       }
+      for (level = 0; len--; opts++)
        {
          switch (*opts)
            {
diff --git a/src/format.c b/src/format.c
index 8b2b11a..09cffa3 100644
--- a/src/format.c
+++ b/src/format.c
@@ -27,24 +27,26 @@
    same size; likewise for long and unsigned long.  We do not yet
    handle long double or long long.  */
 
-/* Parse STR as an integer, reporting warnings on behalf of ME.  */
+/* Parse STR of length LEN as an integer, reporting warnings on behalf
+   of ME.  */
 static int
-arg_int (const call_info *me, const char *str)
+arg_int (const call_info *me, const char *str, size_t len)
 {
   char *endp;
   long value;
 
   /* TODO - also allow parsing `'a' or `"a' which results in the
      numeric value of 'a', as in printf(1).  */
-  if (*str == '\0')
+  if (!len)
     {
       m4_warn (0, me, _("empty string treated as 0"));
       return 0;
     }
   errno = 0;
   value = strtol (str, &endp, 10);
-  if (*endp != '\0')
-    m4_warn (0, me, _("non-numeric argument `%s'"), str);
+  if (endp - str != len)
+    m4_warn (0, me, _("non-numeric argument %s"),
+            quotearg_style_mem (locale_quoting_style, str, len));
   else if (isspace (to_uchar (*str)))
     m4_warn (0, me, _("leading whitespace ignored"));
   else if (errno == ERANGE || (int) value != value)
@@ -52,24 +54,26 @@ arg_int (const call_info *me, const char *str)
   return value;
 }
 
-/* Parse STR as a long, reporting warnings on behalf of ME.  */
+/* Parse STR of length LEN as a long, reporting warnings on behalf of
+   ME.  */
 static long
-arg_long (const call_info *me, const char *str)
+arg_long (const call_info *me, const char *str, size_t len)
 {
   char *endp;
   long value;
 
   /* TODO - also allow parsing `'a' or `"a' which results in the
      numeric value of 'a', as in printf(1).  */
-  if (*str == '\0')
+  if (!len)
     {
       m4_warn (0, me, _("empty string treated as 0"));
       return 0L;
     }
   errno = 0;
   value = strtol (str, &endp, 10);
-  if (*endp != '\0')
-    m4_warn (0, me, _("non-numeric argument `%s'"), str);
+  if (endp - str != len)
+    m4_warn (0, me, _("non-numeric argument %s"),
+            quotearg_style_mem (locale_quoting_style, str, len));
   else if (isspace (to_uchar (*str)))
     m4_warn (0, me, _("leading whitespace ignored"));
   else if (errno == ERANGE)
@@ -77,22 +81,35 @@ arg_long (const call_info *me, const char *str)
   return value;
 }
 
-/* Parse STR as a double, reporting warnings on behalf of ME.  */
+/* Check STR of length LEN for embedded NUL, reporting warnings on
+   behalf of ME.  */
+static const char *
+arg_string (const call_info *me, const char *str, size_t len)
+{
+  if (strlen (str) < len)
+    m4_warn (0, me, _("argument %s truncated"),
+            quotearg_style_mem (locale_quoting_style, str, len));
+  return str;
+}
+
+/* Parse STR of length LEN as a double, reporting warnings on behalf
+   of ME.  */
 static double
-arg_double (const call_info *me, const char *str)
+arg_double (const call_info *me, const char *str, size_t len)
 {
   char *endp;
   double value;
 
-  if (*str == '\0')
+  if (!len)
     {
       m4_warn (0, me, _("empty string treated as 0"));
       return 0.0;
     }
   errno = 0;
   value = strtod (str, &endp);
-  if (*endp != '\0')
-    m4_warn (0, me, _("non-numeric argument `%s'"), str);
+  if (endp - str != len)
+    m4_warn (0, me, _("non-numeric argument %s"),
+            quotearg_style_mem (locale_quoting_style, str, len));
   else if (isspace (to_uchar (*str)))
     m4_warn (0, me, _("leading whitespace ignored"));
   else if (errno == ERANGE)
@@ -101,16 +118,16 @@ arg_double (const call_info *me, const char *str)
 }
 
 #define ARG_INT(i, argc, argv)                                         \
-  ((argc <= ++i) ? 0 : arg_int (me, ARG (i)))
+  ((argc <= ++i) ? 0 : arg_int (me, ARG (i), ARG_LEN (i)))
 
 #define ARG_LONG(i, argc, argv)                                                
\
-  ((argc <= ++i) ? 0L : arg_long (me, ARG (i)))
+  ((argc <= ++i) ? 0L : arg_long (me, ARG (i), ARG_LEN (i)))
 
 #define ARG_STR(i, argc, argv)                                         \
-  ((argc <= ++i) ? "" : ARG (i))
+  ((argc <= ++i) ? "" : arg_string (me, ARG (i), ARG_LEN (i)))
 
 #define ARG_DOUBLE(i, argc, argv)                                      \
-  ((argc <= ++i) ? 0.0 : arg_double (me, ARG (i)))
+  ((argc <= ++i) ? 0.0 : arg_double (me, ARG (i), ARG_LEN (i)))
 
 
 /*------------------------------------------------------------------.
diff --git a/src/freeze.c b/src/freeze.c
index 2648e39..1502532 100644
--- a/src/freeze.c
+++ b/src/freeze.c
@@ -1,7 +1,7 @@
 /* GNU m4 -- A simple macro processor
 
-   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2006, 2007, 2008
-   Free Software Foundation, Inc.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2006, 2007, 2008,
+   2009 Free Software Foundation, Inc.
 
    This file is part of GNU M4.
 
@@ -371,8 +371,13 @@ reload_frozen_state (const char *name)
 
            case 'F':
 
-             /* Enter a macro having a builtin function as a definition.  */
-
+             /* Enter a macro having a builtin function as a
+                definition.  No builtin contains NUL in the name.  */
+             if (strlen (string[1]) < number[1])
+               m4_error (EXIT_FAILURE, 0, NULL, _("\
+ill-formed frozen file, invalid builtin %s encountered"),
+                         quotearg_style_mem (locale_quoting_style, string[1],
+                                             number[1]));
              bp = find_builtin_by_name (string[1]);
              define_builtin (string[0], number[0], bp, SYMBOL_PUSHDEF);
              break;
diff --git a/src/m4.c b/src/m4.c
index 91842e4..ef244e3 100644
--- a/src/m4.c
+++ b/src/m4.c
@@ -480,7 +480,7 @@ main (int argc, char *const *argv, char *const *envp)
        break;
 
       case 'E':
-       debug_decode ("-d");
+       debug_decode ("-d", SIZE_MAX);
        if (!fatal_warnings)
          fatal_warnings = true;
        else
@@ -530,8 +530,9 @@ main (int argc, char *const *argv, char *const *envp)
       case 'd':
        if (seen_file)
          goto defer;
-       if (debug_decode (optarg) < 0)
-         error (0, 0, "bad debug flags: `%s'", optarg);
+       if (debug_decode (optarg, SIZE_MAX) < 0)
+         error (0, 0, "bad debug flags: %s",
+                quotearg_style (locale_quoting_style, optarg));
        break;
 
       case 'e':
@@ -603,7 +604,7 @@ main (int argc, char *const *argv, char *const *envp)
   if (interactive)
     {
       signal (SIGINT, SIG_IGN);
-      setbuf (stdout, (char *) NULL);
+      setbuf (stdout, NULL);
     }
 
   /* Handle deferred command line macro definitions.  Must come after
@@ -631,8 +632,9 @@ main (int argc, char *const *argv, char *const *envp)
          break;
 
        case 'd':
-         if (debug_decode (arg) < 0)
-           error (0, 0, "bad debug flags: `%s'", arg);
+         if (debug_decode (arg, SIZE_MAX) < 0)
+           error (0, 0, "bad debug flags: %s",
+                  quotearg_style (locale_quoting_style, optarg));
          break;
 
        case 't':
diff --git a/src/m4.h b/src/m4.h
index 0611db4..b5521ca 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -205,7 +205,7 @@ extern FILE *debug;
 #define DEBUG_TRACE_DEFAULT 0x407
 
 void debug_init (void);
-int debug_decode (const char *);
+int debug_decode (const char *, size_t);
 void debug_flush_files (void);
 bool debug_set_output (const call_info *, const char *);
 void debug_message (const char *, ...) M4_GNUC_PRINTF (1, 2);
diff --git a/src/path.c b/src/path.c
index d630bad..0ed674c 100644
--- a/src/path.c
+++ b/src/path.c
@@ -1,7 +1,7 @@
 /* GNU m4 -- A simple macro processor
 
-   Copyright (C) 1989, 1990, 1991, 1992, 1993, 2004, 2006, 2007, 2008
-   Free Software Foundation, Inc.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993, 2004, 2006, 2007, 2008,
+   2009 Free Software Foundation, Inc.
 
    This file is part of GNU M4.
 
@@ -176,7 +176,11 @@ m4_path_search (const char *file, char **result)
       if (fp != NULL)
        {
          if (debug_level & DEBUG_TRACE_PATH)
-           debug_message ("path search for `%s' found `%s'", file, name);
+           debug_message ("path search for %s found %s",
+                          quotearg_style (locale_quoting_style, file),
+                          quotearg_n_style (1, locale_quoting_style, name));
+         if (set_cloexec_flag (fileno (fp), true) != 0)
+           m4_warn (errno, NULL, _("cannot protect input file across forks"));
          if (result)
            *result = name;
          else


hooks/post-receive
--
GNU M4 source repository




reply via email to

[Prev in Thread] Current Thread [Next in Thread]