From: Alexander Kornienko Date: Thu, 20 Jun 2013 13:58:37 +0000 (+0000) Subject: Use the same set of whitespace characters for all operations in BreakableToken. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8afa39b271d94969891dba014e0fc545b4873479;p=clang Use the same set of whitespace characters for all operations in BreakableToken. Summary: Fixes a problem where \t,\v or \f could lead to a crash when placed as a first character in a line comment. The cause is that rtrim and ltrim handle these characters, but our code didn't, so some invariants could be broken. Reviewers: klimek Reviewed By: klimek CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1013 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184425 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp index 2b559cf8c3..e340f4f2e3 100644 --- a/lib/Format/BreakableToken.cpp +++ b/lib/Format/BreakableToken.cpp @@ -26,6 +26,19 @@ namespace clang { namespace format { namespace { +static const char *Blanks = " \t\v\f"; +static bool IsBlank(char C) { + switch (C) { + case ' ': + case '\t': + case '\v': + case '\f': + return true; + default: + return false; + } +} + BreakableToken::Split getCommentSplit(StringRef Text, unsigned ContentStartColumn, unsigned ColumnLimit, @@ -41,22 +54,22 @@ BreakableToken::Split getCommentSplit(StringRef Text, MaxSplitBytes += encoding::getCodePointNumBytes(Text[MaxSplitBytes], Encoding); - StringRef::size_type SpaceOffset = Text.rfind(' ', MaxSplitBytes); + StringRef::size_type SpaceOffset = Text.find_last_of(Blanks, MaxSplitBytes); if (SpaceOffset == StringRef::npos || // Don't break at leading whitespace. - Text.find_last_not_of(' ', SpaceOffset) == StringRef::npos) { + Text.find_last_not_of(Blanks, SpaceOffset) == StringRef::npos) { // Make sure that we don't break at leading whitespace that // reaches past MaxSplit. - StringRef::size_type FirstNonWhitespace = Text.find_first_not_of(" "); + StringRef::size_type FirstNonWhitespace = Text.find_first_not_of(Blanks); if (FirstNonWhitespace == StringRef::npos) // If the comment is only whitespace, we cannot split. return BreakableToken::Split(StringRef::npos, 0); - SpaceOffset = - Text.find(' ', std::max(MaxSplitBytes, FirstNonWhitespace)); + SpaceOffset = Text.find_first_of( + Blanks, std::max(MaxSplitBytes, FirstNonWhitespace)); } if (SpaceOffset != StringRef::npos && SpaceOffset != 0) { - StringRef BeforeCut = Text.substr(0, SpaceOffset).rtrim(); - StringRef AfterCut = Text.substr(SpaceOffset).ltrim(); + StringRef BeforeCut = Text.substr(0, SpaceOffset).rtrim(Blanks); + StringRef AfterCut = Text.substr(SpaceOffset).ltrim(Blanks); return BreakableToken::Split(BeforeCut.size(), AfterCut.begin() - BeforeCut.end()); } @@ -92,11 +105,11 @@ BreakableToken::Split getStringSplit(StringRef Text, if (Chars > MaxSplit) break; - if (Text[0] == ' ') + if (IsBlank(Text[0])) SpaceOffset = SplitPoint; if (Text[0] == '/') SlashOffset = SplitPoint; - if (Text[0] != '\\' && !isAlphanumeric(Text[0])) + if (Advance == 1 && !isAlphanumeric(Text[0])) WordStartOffset = SplitPoint; SplitPoint += Advance; @@ -280,13 +293,13 @@ void BreakableBlockComment::adjustWhitespace(const FormatStyle &Style, // Calculate the end of the non-whitespace text in the previous line. EndOfPreviousLine = - Lines[LineIndex - 1].find_last_not_of(" \t", EndOfPreviousLine); + Lines[LineIndex - 1].find_last_not_of(Blanks, EndOfPreviousLine); if (EndOfPreviousLine == StringRef::npos) EndOfPreviousLine = 0; else ++EndOfPreviousLine; // Calculate the start of the non-whitespace text in the current line. - size_t StartOfLine = Lines[LineIndex].find_first_not_of(" \t"); + size_t StartOfLine = Lines[LineIndex].find_first_not_of(Blanks); if (StartOfLine == StringRef::npos) StartOfLine = Lines[LineIndex].size(); diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index f20eca1119..e4d4c7afeb 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -893,6 +893,9 @@ TEST_F(FormatTest, SplitsLongCxxComments) { " int bbb, // xxxxxxx yyyyyyyyy\n" " int c, int d, int e) {}", getLLVMStyleWithColumns(40))); + EXPECT_EQ("//\t aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + format("//\t aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + getLLVMStyleWithColumns(20))); } TEST_F(FormatTest, PriorityOfCommentBreaking) {