* m4/utility.c (m4_verror_at_line): Properly escape macro names.
* src/main.c (main): Manage quoteargs defaults.
* doc/m4.texinfo (Indir): Document and test this.
Signed-off-by: Eric Blake <ebb9@byu.net>
index edaf4bb983ea8a35c68bb69abef78b4fcf97c60e..53413137134569aeaba1bb4d6c286d5700210b4f 100644 (file)
 2008年02月06日 Eric Blake <ebb9@byu.net>
+    Fix security hole introduced 2007年11月23日.
+    * m4/utility.c (m4_verror_at_line): Properly escape macro names.
+    * src/main.c (main): Manage quoteargs defaults.
+    * doc/m4.texinfo (Indir): Document and test this.
+
    Using raw strtod is not portable.
    * ltdl/m4/gnulib-cache.m4: Import the strtod module.
 
index 9e9dd46c860cec777dba585acb8e15eb52968d67..642c14eb3fad142a4bf1d1ca75ef11d43807cd36 100644 (file)
 @result{}
 @end example
+Warning messages issued on behalf of an indirect macro use an
+unambiguous representation of the macro name, using escape sequences
+similar to C strings, and with colons also quoted.
+
+@example
+define(`%%:\
+odd', defn(`divnum'))
+@result{}
+indir(`%%:\
+odd', `extra')
+@error{}m4:stdin:3: Warning: %%\:\\\nodd: extra arguments ignored: 1 > 0
+@result{}0
+@end example
+
 @node Builtin
 @section Indirect call of builtins
 
index 69349feab3e3661818f13524fcb9b1cff3ffb889..60b76446ac2d08ba3652dc64dd7e7c292a172c79 100644 (file)
 #include "exitfail.h"
 #include "progname.h"
+#include "quotearg.h"
 #include "verror.h"
 #include "xvasprintf.h"
@@ -154,18 +155,37 @@ m4_verror_at_line (m4 *context, bool warn, int status, int errnum, 
          const char *format, va_list args)
 {
  char *full = NULL;
+ char *safe_macro = NULL;
+
+ /* Sanitize MACRO, sinze we are turning around and using it in a
+   format string. The allocation is overly conservative, but
+   problematic macro names only occur via indir or changesyntax. */
+ if (macro && strchr (macro, '%'))
+  {
+   char *p = safe_macro = xcharalloc (2 * strlen (macro) + 1);
+   do
+    {
+     if (*macro == '%')
+      *p++ = '%';
+     *p++ = *macro++;
+    }
+   while (*macro);
+  }
  /* Prepend warning and the macro name, as needed. But if that fails
   for non-memory reasons (unlikely), then still use the original
   format. */
  if (warn && macro)
-  full = xasprintf (_("Warning: %s: %s"), macro, format);
+  full = xasprintf (_("Warning: %s: %s"),
+           quotearg (safe_macro ? safe_macro : macro), format);
  else if (warn)
   full = xasprintf (_("Warning: %s"), format);
  else if (macro)
-  full = xasprintf (_("%s: %s"), macro, format);
+  full = xasprintf (_("%s: %s"),
+           quotearg (safe_macro ? safe_macro : macro), format);
  verror_at_line (status, errnum, line ? file : NULL, line,
         full ? full : format, args);
  free (full);
+ free (safe_macro);
  if ((!warn || m4_get_fatal_warnings_opt (context))
    && !m4_get_exit_status (context))
   m4_set_exit_status (context, EXIT_FAILURE);
 
index 48d99d271703ca208ff3a93017b77aaf5d856917..e36c8267160f60b4fa43b7f432125b3ad576997d 100644 (file)
 /* GNU m4 -- A simple macro processor
  Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1999, 2000, 2003,
-  2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+  2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
  This file is part of GNU M4.
 #include "closein.h"
 #include "configmake.h"
 #include "getopt.h"
+#include "quotearg.h"
 #include "version-etc.h"
 #include "xstrtol.h"
@@ -363,6 +364,8 @@ main (int argc, char *const *argv, char *const *envp) 
    m4_set_posixly_correct_opt (context, true);
    m4_set_suppress_warnings_opt (context, true);
   }
+ set_quoting_style (NULL, escape_quoting_style);
+ set_char_quoting (NULL, ':', 1);
  /* First, we decode the arguments, to size up tables and stuff.
   Avoid lasting side effects; for example 'm4 --debugfile=oops
@@ -789,6 +792,7 @@ main (int argc, char *const *argv, char *const *envp) 
  m4_delete (context);
  m4_hash_exit ();
+ quotearg_free ();
 #ifdef USE_STACKOVF
  stackovf_exit ();