mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Parse] Fix buffer overrun in advanceIfMultilineDelimiter
Make sure we don't scan off the end of the buffer, and scan for the delimiter before attempting the lookahead.
This commit is contained in:
@@ -1379,14 +1379,27 @@ static bool delimiterMatches(unsigned CustomDelimiterLen, const char *&BytesPtr,
|
||||
|
||||
/// advanceIfMultilineDelimiter - Centralized check for multiline delimiter.
|
||||
static bool advanceIfMultilineDelimiter(unsigned CustomDelimiterLen,
|
||||
const char *&CurPtr,
|
||||
const char *&CurPtr, const char *EndPtr,
|
||||
DiagnosticEngine *Diags,
|
||||
bool IsOpening = false) {
|
||||
auto scanDelimiter = [&]() -> const char * {
|
||||
// CurPtr here points to the character after `"`.
|
||||
const char *TmpPtr = CurPtr;
|
||||
if (*(TmpPtr - 1) == '"' &&
|
||||
diagnoseZeroWidthMatchAndAdvance('"', TmpPtr, Diags) &&
|
||||
diagnoseZeroWidthMatchAndAdvance('"', TmpPtr, Diags)) {
|
||||
return TmpPtr;
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
auto *DelimEnd = scanDelimiter();
|
||||
if (!DelimEnd)
|
||||
return false;
|
||||
|
||||
// Test for single-line string literals that resemble multiline delimiter.
|
||||
const char *TmpPtr = CurPtr + 1;
|
||||
const char *TmpPtr = DelimEnd - 1;
|
||||
if (IsOpening && CustomDelimiterLen) {
|
||||
while (*TmpPtr != '\r' && *TmpPtr != '\n') {
|
||||
while (TmpPtr != EndPtr && *TmpPtr != '\r' && *TmpPtr != '\n') {
|
||||
if (*TmpPtr == '"') {
|
||||
if (delimiterMatches(CustomDelimiterLen, ++TmpPtr, nullptr)) {
|
||||
return false;
|
||||
@@ -1397,15 +1410,8 @@ static bool advanceIfMultilineDelimiter(unsigned CustomDelimiterLen,
|
||||
}
|
||||
}
|
||||
|
||||
TmpPtr = CurPtr;
|
||||
if (*(TmpPtr - 1) == '"' &&
|
||||
diagnoseZeroWidthMatchAndAdvance('"', TmpPtr, Diags) &&
|
||||
diagnoseZeroWidthMatchAndAdvance('"', TmpPtr, Diags)) {
|
||||
CurPtr = TmpPtr;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
CurPtr = DelimEnd;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// lexCharacter - Read a character and return its UTF32 code. If this is the
|
||||
@@ -1450,8 +1456,8 @@ unsigned Lexer::lexCharacter(const char *&CurPtr, char StopQuote,
|
||||
|
||||
DiagnosticEngine *D = EmitDiagnostics ? getTokenDiags() : nullptr;
|
||||
auto TmpPtr = CurPtr;
|
||||
if (IsMultilineString &&
|
||||
!advanceIfMultilineDelimiter(CustomDelimiterLen, TmpPtr, D))
|
||||
if (IsMultilineString && !advanceIfMultilineDelimiter(
|
||||
CustomDelimiterLen, TmpPtr, BufferEnd, D))
|
||||
return '"';
|
||||
if (CustomDelimiterLen &&
|
||||
!delimiterMatches(CustomDelimiterLen, TmpPtr, D, /*IsClosing=*/true))
|
||||
@@ -1587,9 +1593,8 @@ static const char *skipToEndOfInterpolatedExpression(const char *CurPtr,
|
||||
if (!inStringLiteral()) {
|
||||
// Open string literal.
|
||||
OpenDelimiters.push_back(CurPtr[-1]);
|
||||
AllowNewline.push_back(advanceIfMultilineDelimiter(CustomDelimiterLen,
|
||||
CurPtr, nullptr,
|
||||
true));
|
||||
AllowNewline.push_back(advanceIfMultilineDelimiter(
|
||||
CustomDelimiterLen, CurPtr, EndPtr, nullptr, true));
|
||||
CustomDelimiter.push_back(CustomDelimiterLen);
|
||||
continue;
|
||||
}
|
||||
@@ -1602,7 +1607,8 @@ static const char *skipToEndOfInterpolatedExpression(const char *CurPtr,
|
||||
|
||||
// Multi-line string can only be closed by '"""'.
|
||||
if (AllowNewline.back() &&
|
||||
!advanceIfMultilineDelimiter(CustomDelimiterLen, CurPtr, nullptr))
|
||||
!advanceIfMultilineDelimiter(CustomDelimiterLen, CurPtr, EndPtr,
|
||||
nullptr))
|
||||
continue;
|
||||
|
||||
// Check whether we have equivalent number of '#'s.
|
||||
@@ -1947,7 +1953,7 @@ void Lexer::lexStringLiteral(unsigned CustomDelimiterLen) {
|
||||
assert((QuoteChar == '"' || QuoteChar == '\'') && "Unexpected start");
|
||||
|
||||
bool IsMultilineString = advanceIfMultilineDelimiter(
|
||||
CustomDelimiterLen, CurPtr, getTokenDiags(), true);
|
||||
CustomDelimiterLen, CurPtr, BufferEnd, getTokenDiags(), true);
|
||||
if (IsMultilineString && *CurPtr != '\n' && *CurPtr != '\r')
|
||||
diagnose(CurPtr, diag::lex_illegal_multiline_string_start)
|
||||
.fixItInsert(Lexer::getSourceLoc(CurPtr), "\n");
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: echo '#"' > %t/main1.swift
|
||||
// RUN: echo -n '#"' > %t/main2.swift
|
||||
|
||||
// RUN: env DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib not %target-swift-frontend -typecheck %t/main1.swift
|
||||
// RUN: env DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib not %target-swift-frontend -typecheck %t/main2.swift
|
||||
|
||||
// guardmalloc is incompatible with ASAN
|
||||
// REQUIRES: no_asan
|
||||
Reference in New Issue
Block a user