Skip to content

Commit 1e0aadb

Browse files
ManishearthV8-internal LUCI CQ
authored andcommitted
[temporal] Bias towards using a generator for temporal types
Otherwise we end up generating massive chains of Temporal methods, e.g. "make a date and a datetime, call until on the date with the datetime, then call add on a third datetime with the result of that, then call toPlainYearMonth, then ..." We want to test these things, but not that much: ApiMethodCallGenerator should suffice for most of the chained method testing. This should eliminate the "Reached variable generation limit in generateType" warnings we keep seeing. Bug: 439921647 Change-Id: I6a6a6964015ce0b114f039295a5ef7bc471761a1 Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/8579369 Auto-Submit: Manish Goregaokar <[email protected]> Reviewed-by: Matthias Liedtke <[email protected]> Commit-Queue: Matthias Liedtke <[email protected]>
1 parent f232fc4 commit 1e0aadb

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

Sources/Fuzzilli/Base/ProgramBuilder.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,9 @@ public class ProgramBuilder {
723723
// so try and generate it using the generator in most cases
724724
let producingGenerator = self.fuzzer.environment.getProducingGenerator(ofType: type);
725725
if let producingGenerator {
726-
return producingGenerator(self)
726+
if probability(producingGenerator.probability) {
727+
return producingGenerator.generator(self)
728+
}
727729
}
728730

729731
let producingMethods = self.fuzzer.environment.getProducingMethods(ofType: type)

Sources/Fuzzilli/Environment/JavaScriptEnvironment.swift

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ public class JavaScriptEnvironment: ComponentBase {
297297
private var groups: [String: ObjectGroup] = [:]
298298

299299
// Producing generators, keyed on `type.group`
300-
private var producingGenerators: [String: EnvironmentValueGenerator] = [:]
300+
private var producingGenerators: [String: (generator: EnvironmentValueGenerator, probability: Double)] = [:]
301301
private var producingMethods: [ILType: [(group: String, method: String)]] = [:]
302302
private var producingProperties: [ILType: [(group: String, property: String)]] = [:]
303303
private var subtypes: [ILType: [ILType]] = [:]
@@ -430,9 +430,23 @@ public class JavaScriptEnvironment: ComponentBase {
430430
registerTemporalFieldsObject(.jsTemporalZonedDateTimeLikeObject, forWith: false, dateFields: true, timeFields: true, zonedFields: true)
431431
registerTemporalFieldsObject(.jsTemporalZonedDateTimeLikeObjectForWith, forWith: true, dateFields: true, timeFields: true, zonedFields: true)
432432

433+
// This isn't a normal "temporal fields object" but is similar, and needs a similar producing generator
433434
registerObjectGroup(.jsTemporalDurationLikeObject)
434435
addProducingGenerator(forType: ObjectGroup.jsTemporalDurationLikeObject.instanceType, with: { b in b.createTemporalDurationFieldsObject() })
435436

437+
// Temporal types are produced by a large number of methods; which means findOrGenerateType(), when asked to produce
438+
// a Temporal type, will tend towards trying to call a method on another Temporal type, which needs more Temporal types,
439+
// leading to a large amount of code generated. We do wish to test these codepaths as well, but by and large we
440+
// just want a freshly generated type.
441+
addProducingGenerator(forType: .jsTemporalInstant, with: { $0.constructTemporalInstant() }, probability: 0.9)
442+
addProducingGenerator(forType: .jsTemporalDuration, with: { $0.constructTemporalDuration() }, probability: 0.9)
443+
addProducingGenerator(forType: .jsTemporalPlainTime, with: { $0.constructTemporalTime() }, probability: 0.9)
444+
addProducingGenerator(forType: .jsTemporalPlainYearMonth, with: { $0.constructTemporalYearMonth() }, probability: 0.9)
445+
addProducingGenerator(forType: .jsTemporalPlainMonthDay, with: { $0.constructTemporalMonthDay() }, probability: 0.9)
446+
addProducingGenerator(forType: .jsTemporalPlainDate, with: { $0.constructTemporalDate() }, probability: 0.9)
447+
addProducingGenerator(forType: .jsTemporalPlainDateTime, with: { $0.constructTemporalDateTime() }, probability: 0.9)
448+
addProducingGenerator(forType: .jsTemporalZonedDateTime, with: { $0.constructTemporalZonedDateTime() }, probability: 0.9)
449+
436450
// Register builtins that should be available for fuzzing.
437451
// Here it is easy to selectively disable/enable some APIs for fuzzing by
438452
// just commenting out the corresponding lines.
@@ -550,10 +564,18 @@ public class JavaScriptEnvironment: ComponentBase {
550564

551565
// Add a generator that produces an object of the provided `type`.
552566
//
553-
// This is for groups that are never generated as return types of other objects; so we register
554-
// a generator that can be called.
555-
public func addProducingGenerator(forType type: ILType, with generator: @escaping EnvironmentValueGenerator) {
556-
producingGenerators[type.group!] = generator
567+
// The probability is how often this generator should be called when this type is required.
568+
//
569+
// The default probability (1) is for groups that are never generated as return types of other objects.
570+
// Use a lower probability if there are other ways to generate the object.
571+
//
572+
// Note that Fuzzilli is able to discover ways to construct types on its own. There are two use cases for this:
573+
// - "Options bag" type objects where no JS API produces them, so we *must* run a producing generator
574+
// - Temporal objects: These can be obtained from the result of other API calls, however a
575+
// a lot of these API calls need more Temporal objects, leading to runaway recursion attempting
576+
// to generate a large number of Temporal objects. Instead, we bias heavily towards the producing generator.
577+
public func addProducingGenerator(forType type: ILType, with generator: @escaping EnvironmentValueGenerator, probability: Double = 1.0) {
578+
producingGenerators[type.group!] = (generator, probability)
557579
}
558580

559581
private func addProducingMethod(forType type: ILType, by method: String, on group: String) {
@@ -724,7 +746,7 @@ public class JavaScriptEnvironment: ComponentBase {
724746

725747
// For ObjectGroups, get a generator that is registered as being able to produce this
726748
// ObjectGroup.
727-
public func getProducingGenerator(ofType type: ILType) -> EnvironmentValueGenerator? {
749+
public func getProducingGenerator(ofType type: ILType) -> (generator: EnvironmentValueGenerator, probability: Double)? {
728750
type.group.flatMap {producingGenerators[$0]}
729751
}
730752

0 commit comments

Comments
 (0)