summaryrefslogtreecommitdiff
path: root/m4
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2008-02-06 12:01:29 -0700
committerEric Blake <ebb9@byu.net>2008-02-06 12:01:29 -0700
commit4f1f438e49632dbd5c5061d8992498acea8cf4b3 (patch)
tree468836b0bc0cac814f4ecbf913c1b2bdad5a39cf /m4
parent74f73804d6c375516ad834a9db980afea286fa4c (diff)
downloadm4-4f1f438e49632dbd5c5061d8992498acea8cf4b3.tar.gz
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. Signed-off-by: Eric Blake <ebb9@byu.net>
Diffstat (limited to 'm4')
-rw-r--r--m4/utility.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/m4/utility.c b/m4/utility.c
index 69349fea..60b76446 100644
--- a/m4/utility.c
+++ b/m4/utility.c
@@ -24,6 +24,7 @@
#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);