Skip to content

Commit 0c44f01

Browse files
tbantikyanv8-internal-scoped@luci-project-accounts.iam.gserviceaccount.com
authored andcommitted
[general] Extend OptionsBag with mode for picking only 1 option
This CL adds the `selectionMode` property to the `OptionsBag` struct to configure how `OptionsBag` selects the properties for the object literal it generates. The default behavior is preserved with the `anySubset` case. The new `exactlyOne` case configures `OptionsBag` to select exactly one property for the object literal. This CL also makes `OptionsBag` easily usable in profiles by adding an `additionalOptionsBag` property to the `Profile` struct and by removing the strict assert on the supported `OptionsBag` properties array. Bug: 512875834 Change-Id: I6b6348f515cc736ee281af9c9e384ac93eaf762c Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9311541 Commit-Queue: Tigran Bantikyan <bantikyan@google.com> Reviewed-by: Matthias Liedtke <mliedtke@google.com>
1 parent d6f31a1 commit 0c44f01

18 files changed

Lines changed: 129 additions & 35 deletions

Sources/Fuzzilli/Base/ProgramBuilder.swift

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6588,30 +6588,36 @@ public class ProgramBuilder {
65886588
// property might still be filtered out.
65896589
@discardableResult
65906590
func createOptionsBag(_ bag: OptionsBag, predefined: [String: Variable] = [:]) -> Variable {
6591-
// We run .filter() to pick a subset of fields, but we generally want to set as many as possible
6592-
// and let the mutator prune things
6593-
let dict = [String: Variable](
6594-
uniqueKeysWithValues: bag.properties.filter { _ in probability(0.8) }.map {
6595-
let (propertyName, type) = $0
6596-
if let predefinedVar = predefined[propertyName] {
6597-
return (propertyName, predefinedVar)
6598-
} else if type.isEnumeration {
6599-
return (propertyName, loadEnum(type))
6600-
// relativeTo doesn't have an ObjectGroup so we cannot just register a producingGenerator for it
6601-
} else if type.Is(OptionsBag.jsTemporalRelativeTo) {
6602-
return (
6603-
propertyName,
6604-
findOrGenerateType(
6605-
chooseUniform(from: [
6606-
.jsTemporalZonedDateTime, .jsTemporalPlainDateTime,
6607-
.jsTemporalPlainDate, .string,
6608-
]))
6609-
)
6610-
} else {
6611-
return (propertyName, findOrGenerateType(type))
6612-
}
6613-
})
6614-
return createObject(with: dict)
6591+
switch bag.selectionMode {
6592+
case .anySubset:
6593+
// We run .filter() to pick a subset of fields, but we generally want to set as many as possible
6594+
// and let the mutator prune things
6595+
let dict = [String: Variable](
6596+
uniqueKeysWithValues: bag.properties.filter { _ in probability(0.8) }.map {
6597+
let (propertyName, type) = $0
6598+
if let predefinedVar = predefined[propertyName] {
6599+
return (propertyName, predefinedVar)
6600+
} else if type.isEnumeration {
6601+
return (propertyName, loadEnum(type))
6602+
// relativeTo doesn't have an ObjectGroup so we cannot just register a producingGenerator for it
6603+
} else if type.Is(OptionsBag.jsTemporalRelativeTo) {
6604+
return (
6605+
propertyName,
6606+
findOrGenerateType(
6607+
chooseUniform(from: [
6608+
.jsTemporalZonedDateTime, .jsTemporalPlainDateTime,
6609+
.jsTemporalPlainDate, .string,
6610+
]))
6611+
)
6612+
} else {
6613+
return (propertyName, findOrGenerateType(type))
6614+
}
6615+
})
6616+
return createObject(with: dict)
6617+
case .exactlyOne:
6618+
let (propertyName, type) = bag.properties.randomElement()!
6619+
return createObject(with: [propertyName: findOrGenerateType(type)])
6620+
}
66156621
}
66166622

66176623
// Generate a Temporal.Duration object

Sources/Fuzzilli/Environment/JavaScriptEnvironment.swift

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ public class JavaScriptEnvironment: ComponentBase {
357357

358358
public init(
359359
additionalBuiltins: [String: ILType] = [:], additionalObjectGroups: [ObjectGroup] = [],
360-
additionalEnumerations: [ILType] = []
360+
additionalEnumerations: [ILType] = [], additionalOptionsBags: [OptionsBag] = []
361361
) {
362362

363363
super.init(name: "JavaScriptEnvironment")
@@ -620,6 +620,10 @@ public class JavaScriptEnvironment: ComponentBase {
620620
registerOptionsBag(.jsIntlLocaleMatcherSettings)
621621
registerOptionsBag(.jsIteratorZipSettings)
622622

623+
for optionsBag in additionalOptionsBags {
624+
registerOptionsBag(optionsBag)
625+
}
626+
623627
registerTemporalFieldsObject(
624628
.jsTemporalPlainTimeLikeObject, forWith: false, dateFields: false, timeFields: true,
625629
zonedFields: false)
@@ -983,6 +987,7 @@ public class JavaScriptEnvironment: ComponentBase {
983987
public func registerOptionsBag(_ bag: OptionsBag) {
984988
registerObjectGroup(bag.group)
985989

990+
assert(!bag.properties.isEmpty, "OptionsBag with should have at least one property")
986991
for property in bag.properties.values {
987992
if property.isEnumeration {
988993
assert(
@@ -1189,27 +1194,31 @@ public struct ObjectGroup {
11891194
//
11901195
// It is useful to be able to represent simple options bags so that we can efficiently codegen them
11911196
public struct OptionsBag {
1197+
public enum SelectionMode {
1198+
// Select any random subset of options
1199+
case anySubset
1200+
// Select exactly one random option
1201+
case exactlyOne
1202+
}
1203+
11921204
// The type of each property, not including `| .undefined`.
11931205
// We may extend this once we start supporting more complex bags
11941206
public var properties: [String: ILType]
11951207
// An ObjectGroup representing this bag
11961208
public var group: ObjectGroup
1209+
// Determines how the OptionsBag selects from among the possible options
1210+
public var selectionMode: SelectionMode
11971211

1198-
public init(name: String, properties: [String: ILType]) {
1212+
public init(
1213+
name: String, properties: [String: ILType], selectionMode: SelectionMode = .anySubset
1214+
) {
11991215
self.properties = properties
12001216
let properties = properties.mapValues {
1201-
// This list can be expanded over time as long as createOptionsBag() supports this
1202-
assert(
1203-
$0.isEnumeration || $0.Is(.number | .integer | .boolean | .iterable())
1204-
// Has a producing generator registered
1205-
|| $0.Is(.jsTemporalPlainTime)
1206-
// Has explicit support in createOptionsBag
1207-
|| $0.Is(OptionsBag.jsTemporalRelativeTo),
1208-
"Found unsupported option type \($0) in options bag \(name)")
12091217
return $0 | .undefined
12101218
}
12111219
self.group = ObjectGroup(
12121220
name: name, instanceType: nil, properties: properties, overloads: [:])
1221+
self.selectionMode = selectionMode
12131222
}
12141223
}
12151224

Sources/Fuzzilli/Profiles/DuktapeProfile.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,7 @@ let duktapeProfile = Profile(
6565

6666
additionalEnumerations: [],
6767

68+
additionalOptionsBags: [],
69+
6870
optionalPostProcessor: nil
6971
)

Sources/Fuzzilli/Profiles/JSCProfile.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,5 +134,7 @@ let jscProfile = Profile(
134134

135135
additionalEnumerations: [],
136136

137+
additionalOptionsBags: [],
138+
137139
optionalPostProcessor: nil
138140
)

Sources/Fuzzilli/Profiles/JerryscriptProfile.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,7 @@ let jerryscriptProfile = Profile(
6161

6262
additionalEnumerations: [],
6363

64+
additionalOptionsBags: [],
65+
6466
optionalPostProcessor: nil
6567
)

Sources/Fuzzilli/Profiles/NjsProfile.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,7 @@ let njsProfile = Profile(
5757

5858
additionalEnumerations: [],
5959

60+
additionalOptionsBags: [],
61+
6062
optionalPostProcessor: nil
6163
)

Sources/Fuzzilli/Profiles/Profile.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public struct Profile {
3636
public let additionalBuiltins: [String: ILType]
3737
public let additionalObjectGroups: [ObjectGroup]
3838
public let additionalEnumerations: [ILType]
39+
public let additionalOptionsBags: [OptionsBag]
3940

4041
// An optional post-processor that is executed for every sample generated for fuzzing and can modify it.
4142
public let optionalPostProcessor: FuzzingPostProcessor?

Sources/Fuzzilli/Profiles/QjsProfile.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,7 @@ let qjsProfile = Profile(
5959

6060
additionalEnumerations: [],
6161

62+
additionalOptionsBags: [],
63+
6264
optionalPostProcessor: nil
6365
)

Sources/Fuzzilli/Profiles/QtjsProfile.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,7 @@ let qtjsProfile = Profile(
7070

7171
additionalEnumerations: [],
7272

73+
additionalOptionsBags: [],
74+
7375
optionalPostProcessor: nil
7476
)

Sources/Fuzzilli/Profiles/Serenity.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,7 @@ let serenityProfile = Profile(
5353

5454
additionalEnumerations: [],
5555

56+
additionalOptionsBags: [],
57+
5658
optionalPostProcessor: nil
5759
)

0 commit comments

Comments
 (0)