Re: PR 30308 more unbounded recursion
Alan Modra <[email protected]> Thu, 30 Jul 2026 17:04:32 +0930
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
Commit 85fb82cc8c had some errors. The extra places marking and
clearing syms as resolving didn't take into account that the sym might
already be so marked and thus should not be cleared. Fixing that
cured the first testcase addition, but not the second. Even worse is
that fact that marking X_add_symbol when trying to simplify
X_op_symbol would make it impossible to simplify x==x or other such
expressions where the symbols are the same (or the same via equates,
making a test for X_add_symbol != X_op_symbol harder). So commit
85fb82cc8c needs reverting.
When I analysed what was going on with the second testcase addition,
and reanalysed the testcase added in commit 85fb82cc8c, I decided a
better fix was to immediately fail on hitting a symbol loop; It was
the simplification done in i386_intel_simplify_symbol after hitting a
symbol loop that made the "resolving" mark set on syms insufficient.
I won't be at all surprised if oss-fuzz and other fuzzing projects
find other ways to make this code recurse until stack overflow. If so
I'm fast reaching the limit of my interest in these functions..
* config/tc-i386-intel.c (i386_intel_simplify_symbol): Return
NULL on finding symbol loops.
(i386_intel_simplify): Revert commit 85fb82cc8c marking and
clearing "resolved" for X_add_symbol. For O_add, don't
simplify after i386_intel_simplify_symbol returns NULL.
* testsuite/gas/i386/intel-equ-loop.l,
* testsuite/gas/i386/intel-equ-loop.s: Extend testcase.
diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c
index aafaaba0c9a..aee19446c8c 100644
--- a/gas/config/tc-i386-intel.c
+++ b/gas/config/tc-i386-intel.c
@@ -384,12 +384,14 @@ static symbolS *
i386_intel_simplify_symbol (symbolS *sym)
{
if (symbol_resolving_p (sym))
- return sym;
+ return NULL;
symbolS *orig = sym;
offsetT off;
sym = symbol_equated_to (sym, &off);
- if (sym == NULL || off != 0)
+ if (sym == NULL)
+ return NULL;
+ if (off != 0)
return orig;
segT seg = S_GET_SEGMENT (sym);
@@ -443,13 +445,10 @@ i386_intel_simplify (expressionS *e)
intel_state.index))
return 0;
e->X_add_symbol = newsym;
- symbol_mark_resolving (e->X_add_symbol);
}
if (!intel_state.in_offset)
++intel_state.in_bracket;
newsym = i386_intel_simplify_symbol (e->X_op_symbol);
- if (e->X_add_symbol)
- symbol_clear_resolving (e->X_add_symbol);
if (!intel_state.in_offset)
--intel_state.in_bracket;
if (!newsym)
@@ -549,35 +548,31 @@ i386_intel_simplify (expressionS *e)
segT leftseg = NULL, rightseg = NULL;
newsym = i386_intel_simplify_symbol (e->X_add_symbol);
- if (newsym)
- {
- e->X_add_symbol = newsym;
+ if (!newsym)
+ return 0;
+ e->X_add_symbol = newsym;
- if (base != intel_state.base || state_index != intel_state.index)
- {
- base = intel_state.base;
- state_index = intel_state.index;
- left = symbol_get_value_expression (newsym);
- resolve_expression (left);
- leftseg = S_GET_SEGMENT (newsym);
- }
+ if (base != intel_state.base || state_index != intel_state.index)
+ {
+ base = intel_state.base;
+ state_index = intel_state.index;
+ left = symbol_get_value_expression (newsym);
+ resolve_expression (left);
+ leftseg = S_GET_SEGMENT (newsym);
}
- symbol_mark_resolving (e->X_add_symbol);
newsym = i386_intel_simplify_symbol (e->X_op_symbol);
- symbol_clear_resolving (e->X_add_symbol);
- if (newsym)
- {
- e->X_op_symbol = newsym;
+ if (!newsym)
+ return 0;
+ e->X_op_symbol = newsym;
- if (base != intel_state.base || state_index != intel_state.index)
- {
- base = intel_state.base;
- state_index = intel_state.index;
- right = symbol_get_value_expression (newsym);
- resolve_expression (right);
- rightseg = S_GET_SEGMENT (newsym);
- }
+ if (base != intel_state.base || state_index != intel_state.index)
+ {
+ base = intel_state.base;
+ state_index = intel_state.index;
+ right = symbol_get_value_expression (newsym);
+ resolve_expression (right);
+ rightseg = S_GET_SEGMENT (newsym);
}
if (left && right
@@ -622,9 +617,7 @@ i386_intel_simplify (expressionS *e)
other = symbol_get_value_expression (e->X_add_symbol);
}
- symbol_mark_resolving (e->X_add_symbol);
newsym = i386_intel_simplify_symbol (e->X_op_symbol);
- symbol_clear_resolving (e->X_add_symbol);
}
if (newsym)
@@ -726,11 +719,7 @@ i386_intel_simplify (expressionS *e)
return 0;
if (e->X_op_symbol)
{
- if (e->X_add_symbol)
- symbol_mark_resolving (e->X_add_symbol);
newsym = i386_intel_simplify_symbol (e->X_op_symbol);
- if (e->X_add_symbol)
- symbol_clear_resolving (e->X_add_symbol);
if (!newsym)
return 0;
e->X_op_symbol = newsym;
diff --git a/gas/testsuite/gas/i386/intel-equ-loop.l b/gas/testsuite/gas/i386/intel-equ-loop.l
index 03f21082c3f..18a1bc93abc 100644
--- a/gas/testsuite/gas/i386/intel-equ-loop.l
+++ b/gas/testsuite/gas/i386/intel-equ-loop.l
@@ -9,4 +9,11 @@
.*: Error: can't resolve .*
.*: Error: symbol definition loop .*
.*: Error: can't resolve .*
+#...
+.*: Error: symbol definition loop .*
+#...
+.*: Error: can't resolve .*
+.*: Error: symbol definition loop .*
+#...
+.*: Error: can't resolve .*
#pass
diff --git a/gas/testsuite/gas/i386/intel-equ-loop.s b/gas/testsuite/gas/i386/intel-equ-loop.s
index f7d1d63395b..f68cb596c8c 100644
--- a/gas/testsuite/gas/i386/intel-equ-loop.s
+++ b/gas/testsuite/gas/i386/intel-equ-loop.s
@@ -23,3 +23,9 @@
j=h
i=j+h
.int i
+
+ k=k+esi
+ mov [k],al
+
+ l=l+edx
+ mov [2*l+edx],al
--
Alan Modra