From c58c5c9d0c9a4577863961f6122bd2c03e342d44 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Sat, 25 Oct 2014 11:40:40 +0000 Subject: [PATCH] Lex: Fix an invalid access into a SmallString We would crash because we used operator[] to access past the end of a SmallString. This occured because our token had length zero. Instead, form the pointer using .data() and arithmetic. This is safe because this forms a one-past-the-end pointer and it is only used to compare with another one-past-the-end pointer. This fixes PR21379. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@220614 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Lex/MacroArgs.cpp | 4 ++-- lib/Lex/TokenLexer.cpp | 7 ++++--- test/Preprocessor/macro_paste_bad.c | 8 ++++++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/Lex/MacroArgs.cpp b/lib/Lex/MacroArgs.cpp index a746fb7f48..0fa32399bc 100644 --- a/lib/Lex/MacroArgs.cpp +++ b/lib/Lex/MacroArgs.cpp @@ -233,14 +233,14 @@ Token MacroArgs::StringifyArgument(const Token *ArgToks, // in place and avoid copies where possible. unsigned CurStrLen = Result.size(); Result.resize(CurStrLen+Tok.getLength()); - const char *BufPtr = &Result[CurStrLen]; + const char *BufPtr = Result.data() + CurStrLen; bool Invalid = false; unsigned ActualTokLen = PP.getSpelling(Tok, BufPtr, &Invalid); if (!Invalid) { // If getSpelling returned a pointer to an already uniqued version of // the string instead of filling in BufPtr, memcpy it onto our string. - if (BufPtr != &Result[CurStrLen]) + if (ActualTokLen && BufPtr != &Result[CurStrLen]) memcpy(&Result[CurStrLen], BufPtr, ActualTokLen); // If the token was dirty, the spelling may be shorter than the token. diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index 9d03e8d30b..45c8b010b3 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -531,12 +531,13 @@ bool TokenLexer::PasteTokens(Token &Tok) { memcpy(&Buffer[0], BufPtr, LHSLen); if (Invalid) return true; - - BufPtr = &Buffer[LHSLen]; + + BufPtr = Buffer.data() + LHSLen; unsigned RHSLen = PP.getSpelling(RHS, BufPtr, &Invalid); if (Invalid) return true; - if (BufPtr != &Buffer[LHSLen]) // Really, we want the chars in Buffer! + if (RHSLen && BufPtr != &Buffer[LHSLen]) + // Really, we want the chars in Buffer! memcpy(&Buffer[LHSLen], BufPtr, RHSLen); // Trim excess space. diff --git a/test/Preprocessor/macro_paste_bad.c b/test/Preprocessor/macro_paste_bad.c index ec10006ae3..23777240cb 100644 --- a/test/Preprocessor/macro_paste_bad.c +++ b/test/Preprocessor/macro_paste_bad.c @@ -34,3 +34,11 @@ int VA; // expected-warning {{__VA_ARGS__ can only appear in the expansion of #define LOG_ON_ERROR(x) x ## #y; // expected-error {{'#' is not followed by a macro parameter}} LOG_ON_ERROR(0); + +#define PR21379A(x) printf ##x // expected-note {{macro 'PR21379A' defined here}} +PR21379A(0 {, }) // expected-error {{too many arguments provided to function-like macro invocation}} + // expected-note@-1 {{parentheses are required around macro argument containing braced initializer list}} + +#define PR21379B(x) printf #x // expected-note {{macro 'PR21379B' defined here}} +PR21379B(0 {, }) // expected-error {{too many arguments provided to function-like macro invocation}} + // expected-note@-1 {{parentheses are required around macro argument containing braced initializer list}} -- 2.40.0