Fix infinite recursion in macro expansion
BUG=angleproject:1600
TEST=angle_unittests
Change-Id: I72bf81ec060f36255a0f13b132a4fd69b89672ff
Reviewed-on: https://chromium-review.googlesource.com/412744
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/preprocessor/MacroExpander.cpp b/src/compiler/preprocessor/MacroExpander.cpp
index 25dc741..11f677e 100644
--- a/src/compiler/preprocessor/MacroExpander.cpp
+++ b/src/compiler/preprocessor/MacroExpander.cpp
@@ -51,13 +51,44 @@
} // anonymous namespace
+class MacroExpander::ScopedMacroReenabler final : angle::NonCopyable
+{
+ public:
+ ScopedMacroReenabler(MacroExpander *expander);
+ ~ScopedMacroReenabler();
+
+ private:
+ MacroExpander *mExpander;
+};
+
+MacroExpander::ScopedMacroReenabler::ScopedMacroReenabler(MacroExpander *expander)
+ : mExpander(expander)
+{
+ mExpander->mDeferReenablingMacros = true;
+}
+
+MacroExpander::ScopedMacroReenabler::~ScopedMacroReenabler()
+{
+ mExpander->mDeferReenablingMacros = false;
+ for (auto *macro : mExpander->mMacrosToReenable)
+ {
+ macro->disabled = false;
+ }
+ mExpander->mMacrosToReenable.clear();
+}
+
MacroExpander::MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics)
- : mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics), mTotalTokensInContexts(0)
+ : mLexer(lexer),
+ mMacroSet(macroSet),
+ mDiagnostics(diagnostics),
+ mTotalTokensInContexts(0),
+ mDeferReenablingMacros(false)
{
}
MacroExpander::~MacroExpander()
{
+ ASSERT(mMacrosToReenable.empty());
for (MacroContext *context : mContextStack)
{
delete context;
@@ -187,7 +218,14 @@
ASSERT(context->empty());
ASSERT(context->macro->disabled);
ASSERT(context->macro->expansionCount > 0);
- context->macro->disabled = false;
+ if (mDeferReenablingMacros)
+ {
+ mMacrosToReenable.push_back(context->macro);
+ }
+ else
+ {
+ context->macro->disabled = false;
+ }
context->macro->expansionCount--;
mTotalTokensInContexts -= context->replacements.size();
delete context;
@@ -263,6 +301,11 @@
args->push_back(MacroArg());
+ // Defer reenabling macros until args collection is finished to avoid the possibility of
+ // infinite recursion. Otherwise infinite recursion might happen when expanding the args after
+ // macros have been popped from the context stack when parsing the args.
+ ScopedMacroReenabler deferReenablingMacros(this);
+
int openParens = 1;
while (openParens != 0)
{