Skip to content

Commit 59842f9

Browse files
committed
Fix crash on wrapping deeply nested string and improve peformance
1 parent 623e71e commit 59842f9

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

formatter/generic/genericformatter.cpp

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,15 @@ static vector<InstructionTextToken> ParseStringToken(
280280
vector<InstructionTextToken> result;
281281
size_t curStart = 0, curEnd = 0;
282282

283+
string scratch;
284+
scratch.reserve(maxParsingLength);
285+
283286
auto ConstructToken = [&](size_t start, size_t end) {
287+
scratch.assign(src.data() + start, end - start);
284288
InstructionTextToken token = unprocessedStringToken;
285-
const string newTxt = string(src.substr(start, end - start));
286-
token.text = newTxt;
287-
token.width = newTxt.size();
288-
result.emplace_back(token);
289+
token.text.swap(scratch);
290+
token.width = token.text.size();
291+
result.emplace_back(std::move(token));
289292
};
290293

291294
auto flushToken = [&](size_t start, size_t end)
@@ -791,7 +794,7 @@ vector<DisassemblyTextLine> GenericLineFormatter::FormatLines(
791794
{
792795
case BraceToken:
793796
// Beginning of string
794-
if (trimmedText == "\"" && currentLine.tokens[tokenIndex + 1].type == StringToken)
797+
if (trimmedText == "\"" && tokenIndex + 1 <= currentLine.tokens.size() && currentLine.tokens[tokenIndex + 1].type == StringToken)
795798
{
796799
// Create a ContainerContents item and place it onto the item stack. This will hold anything
797800
// inside the container once the end of the container is found.
@@ -803,7 +806,7 @@ vector<DisassemblyTextLine> GenericLineFormatter::FormatLines(
803806
items.push_back(Item {StartOfContainer, {}, {token}, 0});
804807
}
805808
// End of string
806-
else if (trimmedText == "\"" && currentLine.tokens[tokenIndex - 1].type == StringToken)
809+
else if (trimmedText == "\"" && tokenIndex > 0 && currentLine.tokens[tokenIndex - 1].type == StringToken)
807810
{
808811
items.push_back(Item {EndOfContainer, {}, {token}, 0});
809812

@@ -940,7 +943,7 @@ vector<DisassemblyTextLine> GenericLineFormatter::FormatLines(
940943
stack<ItemLayoutStackEntry> layoutStack;
941944
layoutStack.push({items, additionalContinuationIndentation, desiredWidth, desiredContinuationWidth, desiredStringWidth, false});
942945

943-
auto newLine = [&](bool forString = false) {
946+
auto newLine = [&](const bool forString = false) {
944947
if (!firstTokenOfLine)
945948
{
946949
string lastTokenText = outputLine.tokens.back().text;
@@ -990,10 +993,26 @@ vector<DisassemblyTextLine> GenericLineFormatter::FormatLines(
990993
{
991994
if (item->type == StringComponent && currentWidth + item->width > desiredStringWidth)
992995
{
993-
// If a string is too wide to fit on the current line, create a newline
994-
// without additional indentation
996+
auto next = item;
997+
++next;
998+
999+
if (next != items.end())
1000+
{
1001+
layoutStack.push({vector(next, items.end()), additionalContinuationIndentation,
1002+
desiredWidth, desiredContinuationWidth, desiredStringWidth, false});
1003+
}
1004+
9951005
newLine(true);
996-
continue;
1006+
1007+
additionalContinuationIndentation += settings.tabWidth;
1008+
if (desiredContinuationWidth < settings.minimumContentLength + settings.tabWidth)
1009+
desiredContinuationWidth = settings.minimumContentLength;
1010+
else
1011+
desiredContinuationWidth -= settings.tabWidth;
1012+
1013+
layoutStack.push({item->items, additionalContinuationIndentation, desiredWidth,
1014+
desiredContinuationWidth, desiredStringWidth, false});
1015+
break;
9971016
}
9981017
if (currentWidth + item->width > desiredWidth && item->type != StringWhitespace && item->type != StringComponent)
9991018
{

0 commit comments

Comments
 (0)