[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] symtab: Fix memory corruption when tracing a popdef'd macro
From: |
Eric Blake |
Subject: |
[PATCH] symtab: Fix memory corruption when tracing a popdef'd macro |
Date: |
Fri, 13 Jan 2023 12:37:20 -0600 |
While debugging a script with 'm4 -daeqt', I was surprised to see
uninitialized memory in the trace for one of the macro invocations.
Rerunning it under valgrind confirmed a use-after-free.
* src/symtab.c (free_symbol): When popdef marks an in-expansion nested
definition unused, clone its name in case it is being traced.
(lookup_symbol) [SYMBOL_INSERT]: Consistently use SYMBOL_NAME(), and
share the name across a symbol stack instead of needing to clone.
* doc/m4.texi (Undefine): Test this.
* NEWS: Document the fix.
Fixes: ee427b83b5 ("symtab: use less memory in pushdef stacks")
---
NEWS | 4 ++++
doc/m4.texi | 15 +++++++++++++++
src/symtab.c | 13 +++++++++----
3 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/NEWS b/NEWS
index ee443ca5..73db6309 100644
--- a/NEWS
+++ b/NEWS
@@ -5,4 +5,8 @@ GNU M4 NEWS - User visible changes.
** The `syscmd' and `esyscmd' builtins no longer mishandle a command line
starting with `-' or `+'.
+** Fix regression introduced in 1.4.19 where trace output (such as with
+ `debugmode(t)') could read invalid memory when tracing a series of
+ pushed macros that are popped during argument collection.
+
* Noteworthy changes in release 1.4.19 (2021-05-28) [stable]
** A number of portability improvements inherited from gnulib, including
diff --git a/doc/m4.texi b/doc/m4.texi
index 99c248be..65f701a6 100644
--- a/doc/m4.texi
+++ b/doc/m4.texi
@@ -2227,6 +2227,21 @@ Undefine
@result{}f(bye)
@end example
+@ignore
+@comment This example is not worth putting in the manual, but triggers a
+@comment memory corruption regression during tracing in 1.4.19.
+
+@example
+define(`a', `popdef(`a')1')pushdef(`a', `2$*')dnl
+debugmode(`t')a(popdef(`a')a)
+@error{}m4trace: -2- popdef
+@error{}m4trace: -2- a
+@error{}m4trace: -2- popdef
+@error{}m4trace: -1- a
+@result{}21
+@end example
+@end ignore
+
It is not an error for @var{name} to have no macro definition. In that
case, @code{undefine} does nothing.
diff --git a/src/symtab.c b/src/symtab.c
index 742f192b..766eed69 100644
--- a/src/symtab.c
+++ b/src/symtab.c
@@ -141,7 +141,13 @@ void
free_symbol (symbol *sym)
{
if (SYMBOL_PENDING_EXPANSIONS (sym) > 0)
- SYMBOL_DELETED (sym) = true;
+ {
+ SYMBOL_DELETED (sym) = true;
+ if (SYMBOL_STACK (sym)) {
+ SYMBOL_NAME (sym) = xstrdup (SYMBOL_NAME (sym));
+ SYMBOL_STACK (sym) = NULL;
+ }
+ }
else
{
if (SYMBOL_STACK (sym) == NULL)
@@ -220,15 +226,14 @@ lookup_symbol (const char *name, symbol_lookup mode)
SYMBOL_TYPE (sym) = TOKEN_VOID;
SYMBOL_TRACED (sym) = SYMBOL_TRACED (old);
sym->hash = h;
- SYMBOL_NAME (sym) = old->name;
- old->name = xstrdup (name);
+ SYMBOL_NAME (sym) = SYMBOL_NAME (old);
SYMBOL_MACRO_ARGS (sym) = false;
SYMBOL_BLIND_NO_ARGS (sym) = false;
SYMBOL_DELETED (sym) = false;
SYMBOL_PENDING_EXPANSIONS (sym) = 0;
SYMBOL_STACK (sym) = SYMBOL_STACK (old);
- SYMBOL_STACK (old) = NULL;
+ SYMBOL_STACK (old) = sym;
sym->next = old->next;
old->next = NULL;
*spp = sym;
--
2.39.0
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] symtab: Fix memory corruption when tracing a popdef'd macro,
Eric Blake <=