Skip to content

Commit fb46c8c

Browse files
LiedtkeV8-internal LUCI CQ
authored andcommitted
FuzzILLifter: Limit line size to 300
Some of our infrastructure doesn't like it if we print too long single lines, so limit it arbitrarily. Let's hope the indentation level never reaches this length. Bug: 433646300 Change-Id: I4cfc3234bbd4738558054731e98eb991b186bf7b Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/8449617 Reviewed-by: Michael Achenbach <[email protected]> Reviewed-by: Carl Smith <[email protected]> Commit-Queue: Matthias Liedtke <[email protected]>
1 parent d9412bd commit fb46c8c

File tree

3 files changed

+120
-5
lines changed

3 files changed

+120
-5
lines changed

Sources/Fuzzilli/Lifting/FuzzILLifter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1323,7 +1323,7 @@ public class FuzzILLifter: Lifter {
13231323
}
13241324

13251325
public func lift(_ code: Code) -> String {
1326-
var w = ScriptWriter()
1326+
var w = ScriptWriter(maxLineLength: 300)
13271327

13281328
for instr in code {
13291329
lift(instr, with: &w)

Sources/Fuzzilli/Lifting/ScriptWriter.swift

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,55 @@ struct ScriptWriter {
2929
/// Whether to include line numbers in the output.
3030
private let includeLineNumbers: Bool
3131

32+
// Split lines after this length. Do not use this in combination with JavaScript as it might
33+
// split line comments, string literals, ... across multiple lines which changes semantics.
34+
private let maxLineLength: Int
35+
3236
/// Current line, used when including line numbers in the output.
3337
public private(set) var currentLineNumber = 0
3438

35-
public init (stripComments: Bool = false, includeLineNumbers: Bool = false, indent: Int = 4, initialIndentionLevel: Int = 0) {
39+
public init (stripComments: Bool = false, includeLineNumbers: Bool = false, indent: Int = 4, initialIndentionLevel: Int = 0, maxLineLength: Int = Int.max) {
3640
self.indent = String(repeating: " ", count: indent)
3741
self.currentIndention = String(repeating: " ", count: indent * initialIndentionLevel)
3842
self.stripComments = stripComments
3943
self.includeLineNumbers = includeLineNumbers
44+
self.maxLineLength = maxLineLength
4045
}
4146

42-
/// Emit one line of code.
43-
mutating func emit<S: StringProtocol>(_ line: S) {
44-
assert(!line.contains("\n"))
47+
private mutating func emitImpl<S: StringProtocol>(_ line: S) {
4548
currentLineNumber += 1
4649
if includeLineNumbers { code += "\(String(format: "%3i", currentLineNumber)). " }
4750
code += currentIndention + line + "\n"
4851
}
4952

53+
/// Emit one line of code.
54+
mutating func emit<S: StringProtocol>(_ line: S) {
55+
assert(maxLineLength > currentIndention.count)
56+
let splitAt = maxLineLength - currentIndention.count
57+
assert(!line.contains("\n"))
58+
var line = line.prefix(line.count)
59+
while line.count > splitAt {
60+
var lineToPrint = line.prefix(splitAt + 1)
61+
if let spaceIndex = lineToPrint.lastIndex(of: " "),
62+
spaceIndex != lineToPrint.startIndex {
63+
// Only print the line if it contains non-space characters trimming all trailing
64+
// spaces.
65+
lineToPrint = lineToPrint.prefix(upTo: spaceIndex)
66+
if let lastChar = (lineToPrint.lastIndex { $0 != " " }) {
67+
emitImpl(line.prefix(through: lastChar))
68+
}
69+
line = line.suffix(from: line.index(after: spaceIndex))
70+
} else {
71+
emitImpl(line.prefix(splitAt))
72+
line = line.suffix(line.count - splitAt)
73+
}
74+
line = line.suffix(from: line.firstIndex {$0 != " "} ?? line.endIndex)
75+
}
76+
if !line.isEmpty {
77+
emitImpl(line)
78+
}
79+
}
80+
5081
/// Emit a comment.
5182
mutating func emitComment(_ comment: String) {
5283
guard !stripComments else { return }
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import XCTest
16+
@testable import Fuzzilli
17+
18+
class ScriptWriterTest: XCTestCase {
19+
20+
func testLineSplitting() {
21+
var w = ScriptWriter(indent: 2, initialIndentionLevel: 0, maxLineLength: 10)
22+
w.emit("My name is Ozymandias, king of kings. Look on my works, ye Mighty, and despair!")
23+
let expected = """
24+
My name is
25+
Ozymandias
26+
, king of
27+
kings.
28+
Look on my
29+
works, ye
30+
Mighty,
31+
and
32+
despair!
33+
34+
"""
35+
XCTAssertEqual(expected, w.code)
36+
}
37+
38+
func testLineSplittingWithIndentation() {
39+
var w = ScriptWriter(indent: 2, initialIndentionLevel: 0, maxLineLength: 8)
40+
w.emit("My name is Ozymandias,")
41+
w.increaseIndentionLevel()
42+
w.emit("king of kings.")
43+
w.decreaseIndentionLevel()
44+
w.emit("Look on my works, ye Mighty,")
45+
w.increaseIndentionLevel()
46+
w.emit("and despair!")
47+
w.decreaseIndentionLevel()
48+
let expected = """
49+
My name
50+
is
51+
Ozymandi
52+
as,
53+
king
54+
of
55+
kings.
56+
Look on
57+
my
58+
works,
59+
ye
60+
Mighty,
61+
and
62+
despai
63+
r!
64+
65+
"""
66+
XCTAssertEqual(expected, w.code)
67+
}
68+
69+
func testLineSplittingMultiSpace() {
70+
var w = ScriptWriter(indent: 2, initialIndentionLevel: 0, maxLineLength: 8)
71+
let str = (0...10).map {"\($0)\(String(repeating: " ", count: $0))"}.joined()
72+
w.emit(str)
73+
let expected = """
74+
01 2 3
75+
4 5
76+
6 7
77+
8
78+
9
79+
10
80+
81+
"""
82+
XCTAssertEqual(expected, w.code)
83+
}
84+
}

0 commit comments

Comments
 (0)