preprocessor: Fix use after free when #undef the macro being invoked
BUG=chromium:648031
BUG=angleproject:1522
Change-Id: I825cea9e736a2c99133408249cfcd525431d31de
Reviewed-on: https://chromium-review.googlesource.com/386853
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/compiler/preprocessor/DiagnosticsBase.cpp b/src/compiler/preprocessor/DiagnosticsBase.cpp
index 9f62a9e..3281206 100644
--- a/src/compiler/preprocessor/DiagnosticsBase.cpp
+++ b/src/compiler/preprocessor/DiagnosticsBase.cpp
@@ -74,6 +74,8 @@
return "predefined macro undefined";
case PP_MACRO_UNTERMINATED_INVOCATION:
return "unterminated macro invocation";
+ case PP_MACRO_UNDEFINED_WHILE_INVOKED:
+ return "macro undefined while being invoked";
case PP_MACRO_TOO_FEW_ARGS:
return "Not enough arguments for macro";
case PP_MACRO_TOO_MANY_ARGS:
diff --git a/src/compiler/preprocessor/DiagnosticsBase.h b/src/compiler/preprocessor/DiagnosticsBase.h
index a089920..6c3fe9e 100644
--- a/src/compiler/preprocessor/DiagnosticsBase.h
+++ b/src/compiler/preprocessor/DiagnosticsBase.h
@@ -44,6 +44,7 @@
PP_MACRO_PREDEFINED_REDEFINED,
PP_MACRO_PREDEFINED_UNDEFINED,
PP_MACRO_UNTERMINATED_INVOCATION,
+ PP_MACRO_UNDEFINED_WHILE_INVOKED,
PP_MACRO_TOO_FEW_ARGS,
PP_MACRO_TOO_MANY_ARGS,
PP_MACRO_DUPLICATE_PARAMETER_NAMES,
diff --git a/src/compiler/preprocessor/DirectiveParser.cpp b/src/compiler/preprocessor/DirectiveParser.cpp
index aceb3b2..ebe72f1 100644
--- a/src/compiler/preprocessor/DirectiveParser.cpp
+++ b/src/compiler/preprocessor/DirectiveParser.cpp
@@ -445,6 +445,13 @@
{
mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
token->location, token->text);
+ return;
+ }
+ else if (iter->second.expansionCount > 0)
+ {
+ mDiagnostics->report(Diagnostics::PP_MACRO_UNDEFINED_WHILE_INVOKED, token->location,
+ token->text);
+ return;
}
else
{
diff --git a/src/compiler/preprocessor/Macro.h b/src/compiler/preprocessor/Macro.h
index 31ee22c..557df16 100644
--- a/src/compiler/preprocessor/Macro.h
+++ b/src/compiler/preprocessor/Macro.h
@@ -26,16 +26,12 @@
typedef std::vector<std::string> Parameters;
typedef std::vector<Token> Replacements;
- Macro()
- : predefined(false),
- disabled(false),
- type(kTypeObj)
- {
- }
+ Macro() : predefined(false), disabled(false), expansionCount(0), type(kTypeObj) {}
bool equals(const Macro &other) const;
bool predefined;
mutable bool disabled;
+ mutable int expansionCount;
Type type;
std::string name;
diff --git a/src/compiler/preprocessor/MacroExpander.cpp b/src/compiler/preprocessor/MacroExpander.cpp
index 3c0423e..51b69f8 100644
--- a/src/compiler/preprocessor/MacroExpander.cpp
+++ b/src/compiler/preprocessor/MacroExpander.cpp
@@ -151,6 +151,8 @@
assert(identifier.type == Token::IDENTIFIER);
assert(identifier.text == macro.name);
+ macro.expansionCount++;
+
std::vector<Token> replacements;
if (!expandMacro(macro, identifier, &replacements))
return false;
@@ -174,7 +176,9 @@
assert(context->empty());
assert(context->macro->disabled);
+ assert(context->macro->expansionCount > 0);
context->macro->disabled = false;
+ context->macro->expansionCount--;
delete context;
}