From: Paul Hoad Date: Wed, 18 Sep 2019 18:57:09 +0000 (+0000) Subject: [clang-format][PR41964] Fix crash with SIGFPE when TabWidth is set to 0 and line... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=da7c99cf283cf1773550f372cb50d3320db77e92;p=clang [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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@372246 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/Encoding.h b/lib/Format/Encoding.h index fe3d5f0198..a0d664121b 100644 --- a/lib/Format/Encoding.h +++ b/lib/Format/Encoding.h @@ -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); } } diff --git a/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp index 009b884975..e59a059fd6 100644 --- a/lib/Format/FormatTokenLexer.cpp +++ b/lib/Format/FormatTokenLexer.cpp @@ -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')) diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp index 33c0d53402..5a44500d35 100644 --- a/lib/Format/WhitespaceManager.cpp +++ b/lib/Format/WhitespaceManager.cpp @@ -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) { + if (Style.TabWidth) { + 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"); + + Text.append(Spaces / Style.TabWidth, '\t'); + Text.append(Spaces % Style.TabWidth, ' '); + } else if (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, ' '); 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; diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index b1fcd39a49..dc20faf70c 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -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"