Commit d2f195b5 by Corentin Wallez Committed by Commit Bot

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: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent f979524a
...@@ -74,6 +74,8 @@ std::string Diagnostics::message(ID id) ...@@ -74,6 +74,8 @@ std::string Diagnostics::message(ID id)
return "predefined macro undefined"; return "predefined macro undefined";
case PP_MACRO_UNTERMINATED_INVOCATION: case PP_MACRO_UNTERMINATED_INVOCATION:
return "unterminated macro invocation"; return "unterminated macro invocation";
case PP_MACRO_UNDEFINED_WHILE_INVOKED:
return "macro undefined while being invoked";
case PP_MACRO_TOO_FEW_ARGS: case PP_MACRO_TOO_FEW_ARGS:
return "Not enough arguments for macro"; return "Not enough arguments for macro";
case PP_MACRO_TOO_MANY_ARGS: case PP_MACRO_TOO_MANY_ARGS:
......
...@@ -44,6 +44,7 @@ class Diagnostics ...@@ -44,6 +44,7 @@ class Diagnostics
PP_MACRO_PREDEFINED_REDEFINED, PP_MACRO_PREDEFINED_REDEFINED,
PP_MACRO_PREDEFINED_UNDEFINED, PP_MACRO_PREDEFINED_UNDEFINED,
PP_MACRO_UNTERMINATED_INVOCATION, PP_MACRO_UNTERMINATED_INVOCATION,
PP_MACRO_UNDEFINED_WHILE_INVOKED,
PP_MACRO_TOO_FEW_ARGS, PP_MACRO_TOO_FEW_ARGS,
PP_MACRO_TOO_MANY_ARGS, PP_MACRO_TOO_MANY_ARGS,
PP_MACRO_DUPLICATE_PARAMETER_NAMES, PP_MACRO_DUPLICATE_PARAMETER_NAMES,
......
...@@ -445,6 +445,13 @@ void DirectiveParser::parseUndef(Token *token) ...@@ -445,6 +445,13 @@ void DirectiveParser::parseUndef(Token *token)
{ {
mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED, mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
token->location, token->text); 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 else
{ {
......
...@@ -26,16 +26,12 @@ struct Macro ...@@ -26,16 +26,12 @@ struct Macro
typedef std::vector<std::string> Parameters; typedef std::vector<std::string> Parameters;
typedef std::vector<Token> Replacements; typedef std::vector<Token> Replacements;
Macro() Macro() : predefined(false), disabled(false), expansionCount(0), type(kTypeObj) {}
: predefined(false),
disabled(false),
type(kTypeObj)
{
}
bool equals(const Macro &other) const; bool equals(const Macro &other) const;
bool predefined; bool predefined;
mutable bool disabled; mutable bool disabled;
mutable int expansionCount;
Type type; Type type;
std::string name; std::string name;
......
...@@ -151,6 +151,8 @@ bool MacroExpander::pushMacro(const Macro &macro, const Token &identifier) ...@@ -151,6 +151,8 @@ bool MacroExpander::pushMacro(const Macro &macro, const Token &identifier)
assert(identifier.type == Token::IDENTIFIER); assert(identifier.type == Token::IDENTIFIER);
assert(identifier.text == macro.name); assert(identifier.text == macro.name);
macro.expansionCount++;
std::vector<Token> replacements; std::vector<Token> replacements;
if (!expandMacro(macro, identifier, &replacements)) if (!expandMacro(macro, identifier, &replacements))
return false; return false;
...@@ -174,7 +176,9 @@ void MacroExpander::popMacro() ...@@ -174,7 +176,9 @@ void MacroExpander::popMacro()
assert(context->empty()); assert(context->empty());
assert(context->macro->disabled); assert(context->macro->disabled);
assert(context->macro->expansionCount > 0);
context->macro->disabled = false; context->macro->disabled = false;
context->macro->expansionCount--;
delete context; delete context;
} }
......
...@@ -938,4 +938,20 @@ TEST_F(DefineTest, NegativeShiftInLineDirective) ...@@ -938,4 +938,20 @@ TEST_F(DefineTest, NegativeShiftInLineDirective)
EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_UNDEFINED_SHIFT, _, _)).Times(4); EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_UNDEFINED_SHIFT, _, _)).Times(4);
EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INVALID_LINE_NUMBER, _, _)).Times(2); EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_INVALID_LINE_NUMBER, _, _)).Times(2);
preprocess(input, expected); preprocess(input, expected);
} }
\ No newline at end of file
// Undefining a macro in its invocation parameters produces and error
TEST_F(DefineTest, UndefineInInvocation)
{
const char *input =
"#define G(a, b) a b\n"
"G(\n"
"#undef G\n"
"1, 2)\n";
const char *expected = "\n\n\n1 2\n";
EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_MACRO_UNDEFINED_WHILE_INVOKED,
pp::SourceLocation(0, 3), _));
preprocess(input, expected);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment