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.

llvm-svn: 220614
This commit is contained in:
David Majnemer 2014-10-25 11:40:40 +00:00
parent a63672665f
commit d3c3e78ac1
3 changed files with 14 additions and 5 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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}}