[clang-format][PR41964] Fix crash with SIGFPE when TabWidth is set to 0 and line starts with tab

Summary:
clang-format 8.0 crashes with SIGFPE (floating point exception) when formatting following file:
app.cpp:
void a() {
	//line starts with '\t'
}

$ clang-format -style='{TabWidth: 0}' app.cpp

Reviewers: owenpan, klimek, russellmcc, timwoj

Reviewed By: klimek

Subscribers: cfe-commits

Tags: #clang-tools-extra, #clang

Differential Revision: https://reviews.llvm.org/D67670

llvm-svn: 372246
This commit is contained in:
Paul Hoad 2019-09-18 18:57:09 +00:00
parent ba4cad9039
commit 79983be5a0
4 changed files with 100 additions and 18 deletions

View File

@ -67,7 +67,8 @@ inline unsigned columnWidthWithTabs(StringRef Text, unsigned StartColumn,
if (TabPos == StringRef::npos)
return TotalWidth + columnWidth(Tail, Encoding);
TotalWidth += columnWidth(Tail.substr(0, TabPos), Encoding);
TotalWidth += TabWidth - (TotalWidth + StartColumn) % TabWidth;
if (TabWidth)
TotalWidth += TabWidth - (TotalWidth + StartColumn) % TabWidth;
Tail = Tail.substr(TabPos + 1);
}
}

View File

@ -657,7 +657,8 @@ FormatToken *FormatTokenLexer::getNextToken() {
++Column;
break;
case '\t':
Column += Style.TabWidth - Column % Style.TabWidth;
Column +=
Style.TabWidth - (Style.TabWidth ? Column % Style.TabWidth : 0);
break;
case '\\':
if (i + 1 == e || (Text[i + 1] != '\r' && Text[i + 1] != '\n'))

View File

@ -815,19 +815,24 @@ void WhitespaceManager::appendIndentText(std::string &Text,
Text.append(Spaces, ' ');
break;
case FormatStyle::UT_Always: {
unsigned FirstTabWidth =
Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
// Insert only spaces when we want to end up before the next tab.
if (Spaces < FirstTabWidth || Spaces == 1) {
Text.append(Spaces, ' ');
break;
}
// Align to the next tab.
Spaces -= FirstTabWidth;
Text.append("\t");
if (Style.TabWidth) {
unsigned FirstTabWidth =
Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
Text.append(Spaces / Style.TabWidth, '\t');
Text.append(Spaces % Style.TabWidth, ' ');
// Insert only spaces when we want to end up before the next tab.
if (Spaces < FirstTabWidth || Spaces == 1) {
Text.append(Spaces, ' ');
break;
}
// Align to the next tab.
Spaces -= FirstTabWidth;
Text.append("\t");
Text.append(Spaces / Style.TabWidth, '\t');
Text.append(Spaces % Style.TabWidth, ' ');
} else if (Spaces == 1) {
Text.append(Spaces, ' ');
}
break;
}
case FormatStyle::UT_ForIndentation:
@ -837,14 +842,16 @@ void WhitespaceManager::appendIndentText(std::string &Text,
// the first one.
if (Indentation > Spaces)
Indentation = Spaces;
unsigned Tabs = Indentation / Style.TabWidth;
Text.append(Tabs, '\t');
Spaces -= Tabs * Style.TabWidth;
if (Style.TabWidth) {
unsigned Tabs = Indentation / Style.TabWidth;
Text.append(Tabs, '\t');
Spaces -= Tabs * Style.TabWidth;
}
}
Text.append(Spaces, ' ');
break;
case FormatStyle::UT_ForContinuationAndIndentation:
if (WhitespaceStartColumn == 0) {
if (WhitespaceStartColumn == 0 && Style.TabWidth) {
unsigned Tabs = Spaces / Style.TabWidth;
Text.append(Tabs, '\t');
Spaces -= Tabs * Style.TabWidth;

View File

@ -9877,6 +9877,79 @@ TEST_F(FormatTest, ConfigurableUseOfTab) {
Tab);
}
TEST_F(FormatTest, ZeroTabWidth) {
FormatStyle Tab = getLLVMStyleWithColumns(42);
Tab.IndentWidth = 8;
Tab.UseTab = FormatStyle::UT_Never;
Tab.TabWidth = 0;
EXPECT_EQ("void a(){\n"
" // line starts with '\t'\n"
"};",
format("void a(){\n"
"\t// line starts with '\t'\n"
"};",
Tab));
EXPECT_EQ("void a(){\n"
" // line starts with '\t'\n"
"};",
format("void a(){\n"
"\t\t// line starts with '\t'\n"
"};",
Tab));
Tab.UseTab = FormatStyle::UT_ForIndentation;
EXPECT_EQ("void a(){\n"
" // line starts with '\t'\n"
"};",
format("void a(){\n"
"\t// line starts with '\t'\n"
"};",
Tab));
EXPECT_EQ("void a(){\n"
" // line starts with '\t'\n"
"};",
format("void a(){\n"
"\t\t// line starts with '\t'\n"
"};",
Tab));
Tab.UseTab = FormatStyle::UT_ForContinuationAndIndentation;
EXPECT_EQ("void a(){\n"
" // line starts with '\t'\n"
"};",
format("void a(){\n"
"\t// line starts with '\t'\n"
"};",
Tab));
EXPECT_EQ("void a(){\n"
" // line starts with '\t'\n"
"};",
format("void a(){\n"
"\t\t// line starts with '\t'\n"
"};",
Tab));
Tab.UseTab = FormatStyle::UT_Always;
EXPECT_EQ("void a(){\n"
"// line starts with '\t'\n"
"};",
format("void a(){\n"
"\t// line starts with '\t'\n"
"};",
Tab));
EXPECT_EQ("void a(){\n"
"// line starts with '\t'\n"
"};",
format("void a(){\n"
"\t\t// line starts with '\t'\n"
"};",
Tab));
}
TEST_F(FormatTest, CalculatesOriginalColumn) {
EXPECT_EQ("\"qqqqqqqqqqqqqqqqqqqqqqqqqq\\\n"
"q\"; /* some\n"