Skip to content

Commit 6a16b25

Browse files
committed
Make randomVariable() return requested type more often
This patch removes the requirement of having at least 3 variables of the requested type be visible for `randomVariable()` to look for a variable whose type matches or subsumes the requested one. Bug: 40272934 Change-Id: I6827467701b29726a898d1b6642a2360793e4c19 Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/8585836 Reviewed-by: Matthias Liedtke <mliedtke@google.com>
1 parent 1011274 commit 6a16b25

2 files changed

Lines changed: 10 additions & 42 deletions

File tree

Sources/Fuzzilli/Base/ProgramBuilder.swift

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -794,12 +794,6 @@ public class ProgramBuilder {
794794
/// This is writable for use in tests, but it could also be used to change how "conservative" variable selection is.
795795
var probabilityOfVariableSelectionTryingToFindAnExactMatch = 0.5
796796

797-
/// This threshold affects the behavior of `randomVariable(forUseAs:)`. It determines how many existing variables of the
798-
/// requested type we want to have before we try to find an exact match. If there are fewer variables of the requested type, we'll
799-
/// always do a more general search which may also return variables of unknown (i.e. `.jsAnything`) type.
800-
/// This ensures that consecutive queries for the same type can return different variables.
801-
let minVisibleVariablesOfRequestedTypeForVariableSelection = 3
802-
803797
/// Returns a random variable to be used as the given type.
804798
///
805799
/// This function may return variables of a different type, or variables that may have the requested type, but could also have a different type.
@@ -818,8 +812,7 @@ public class ProgramBuilder {
818812
var result: Variable? = nil
819813

820814
// Prefer variables that are known to have the requested type if there's a sufficient number of them.
821-
if probability(probabilityOfVariableSelectionTryingToFindAnExactMatch) &&
822-
haveAtLeastNVisibleVariables(ofType: type, n: minVisibleVariablesOfRequestedTypeForVariableSelection) {
815+
if probability(probabilityOfVariableSelectionTryingToFindAnExactMatch) {
823816
result = findVariable(satisfying: { self.type(of: $0).Is(type) })
824817
}
825818

@@ -902,19 +895,6 @@ public class ProgramBuilder {
902895
return chooseUniform(from: candidates)
903896
}
904897

905-
/// Helper function to determine if we have a sufficient number of variables of a given type to ensure that
906-
/// consecutive queries for a variable of a given type will not always return the same variables.
907-
private func haveAtLeastNVisibleVariables(ofType t: ILType, n: Int) -> Bool {
908-
var count = 0
909-
for v in variablesInScope where !hiddenVariables.contains(v) && type(of: v).Is(t) {
910-
count += 1
911-
if count >= n {
912-
return true
913-
}
914-
}
915-
return false
916-
}
917-
918898
/// Find random variables to use as arguments for calling the specified function.
919899
///
920900
/// This function will attempt to find variables that are compatible with the functions parameter types (if any). However,

Tests/FuzzilliTests/ProgramBuilderTest.swift

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,7 @@ class ProgramBuilderTests: XCTestCase {
151151
// This testcase demonstrates the behavior of `b.randomVariable(forUseAs:)`
152152
// This API behaves in the following way:
153153
// - It prefers to return variables that are known to have the requested type
154-
// with probability `b.probabilityOfVariableSelectionTryingToFindAnExactMatch`,
155-
// but only if there's a sufficient number of them currently visible (to ensure
156-
// that consecutive queries return different variables. This threshold is
157-
// determined by `b.minVisibleVariablesOfRequestedTypeForVariableSelection`.
154+
// with probability `b.probabilityOfVariableSelectionTryingToFindAnExactMatch`.
158155
// - Otherwise, it tries a wider match, including all variables that may have the
159156
// requested type. This includes all variables that have unknown type.
160157
// - If even that doesn't find any matches, the function will return a random
@@ -165,8 +162,6 @@ class ProgramBuilderTests: XCTestCase {
165162
let b = fuzzer.makeBuilder()
166163

167164
let i = b.loadInt(42)
168-
// There is only one visible variable, so we always get that, no matter what we actually query
169-
XCTAssertLessThan(b.numberOfVisibleVariables, b.minVisibleVariablesOfRequestedTypeForVariableSelection)
170165
XCTAssertEqual(b.randomVariable(forUseAs: .integer), i)
171166
XCTAssertEqual(b.randomVariable(forUseAs: .jsAnything), i)
172167
XCTAssertEqual(b.randomVariable(forUseAs: .string), i)
@@ -178,31 +173,24 @@ class ProgramBuilderTests: XCTestCase {
178173
XCTAssert([i, s].contains(b.randomVariable(forUseAs: .primitive)))
179174
XCTAssertEqual(b.randomVariable(forUseAs: .string), s)
180175

181-
// Now there's also a variable of unknown type, which may be anything. Since we don't have enough variables
182-
// of a known type, all queries will use a `MayBe` type query to find matches and so may return the unknown variable.
176+
// Now there's also a variable of unknown type, which may be anything.
183177
let unknown = b.createNamedVariable(forBuiltin: "unknown")
184178
XCTAssertEqual(b.type(of: unknown), .jsAnything)
185179

180+
// There is now still a 50% chance that we will do a `MayBe` query, so we may return the unknown variable.
186181
XCTAssert([i, unknown].contains(b.randomVariable(forUseAs: .integer)))
187182
XCTAssert([i, unknown].contains(b.randomVariable(forUseAs: .number)))
188183
XCTAssert([s, unknown].contains(b.randomVariable(forUseAs: .string)))
189184
XCTAssert([i, s, unknown].contains(b.randomVariable(forUseAs: .primitive)))
190185
XCTAssert([i, s, unknown].contains(b.randomVariable(forUseAs: .jsAnything)))
191186

192-
// Now we add some more integers and set the probability of trying an exact match (i.e. an `Is` query instead of a
193-
// `MayBe` query) to 100%. Then, we expect to always get back the known integers when asking for them.
194-
let i2 = b.loadInt(43)
195-
let i3 = b.loadInt(44)
196-
XCTAssertGreaterThanOrEqual(b.numberOfVisibleVariables, b.minVisibleVariablesOfRequestedTypeForVariableSelection)
197187
b.probabilityOfVariableSelectionTryingToFindAnExactMatch = 1.0
198-
// Now we should always get back the integer when querying for that type.
199-
XCTAssert([i, i2, i3].contains(b.randomVariable(forUseAs: .integer)))
200-
XCTAssert([i, i2, i3].contains(b.randomVariable(forUseAs: .number)))
201-
// We don't have enough strings yet though.
202-
XCTAssert([s, unknown].contains(b.randomVariable(forUseAs: .string)))
203-
// But enough primitive values.
204-
XCTAssert([i, i2, i3, s].contains(b.randomVariable(forUseAs: .primitive)))
205-
XCTAssert([i, i2, i3, s, unknown].contains(b.randomVariable(forUseAs: .jsAnything)))
188+
// We should now always first look for a variable whose type matches or subsumes the requested one.
189+
XCTAssertEqual(b.randomVariable(ofType: .integer), i)
190+
XCTAssertEqual(b.randomVariable(ofType: .number), i)
191+
XCTAssertEqual(b.randomVariable(ofType: .string), s)
192+
XCTAssert([i, s].contains(b.randomVariable(forUseAs: .primitive)))
193+
XCTAssert([i, s, unknown].contains(b.randomVariable(forUseAs: .jsAnything)))
206194
}
207195

208196
func testVariableRetrieval2() {

0 commit comments

Comments
 (0)