Lex: Fix an invalid access into a SmallString
authorDavid Majnemer <david.majnemer@gmail.com>
Sat, 25 Oct 2014 11:40:40 +0000 (11:40 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Sat, 25 Oct 2014 11:40:40 +0000 (11:40 +0000)
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

clang/lib/Lex/MacroArgs.cpp
clang/lib/Lex/TokenLexer.cpp
clang/test/Preprocessor/macro_paste_bad.c

index a746fb7..0fa3239 100644 (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.
index 9d03e8d..45c8b01 100644 (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.
index ec10006..2377724 100644 (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}}