Skip to content

Commit

Permalink
Introduce randomVariable(preferablyNotOfType:)
Browse files Browse the repository at this point in the history
This variant can be used in cases where we prefer to not get a random
variable of a specific type, but are fine with for example receiving
variables of unknown types. See the documentation and added tests for
more information about its behavior.
  • Loading branch information
Samuel Groß committed Feb 16, 2024
1 parent b843760 commit 60b39a8
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
10 changes: 10 additions & 0 deletions Sources/Fuzzilli/Base/ProgramBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,16 @@ public class ProgramBuilder {
return findVariable(satisfying: { self.type(of: $0).Is(type) })
}

/// Returns a random variable that is not known to have the given type.
///
/// This will return a variable for which `b.type(of: v).Is(type)` is false, i.e. for which our type inference
/// could not prove that it has the given type. Note that this is different from a variable that is known not to have
/// the given type: this function can return variables for which `b.type(of: v).MayBe(type)` is true.
/// If no such variable is found, this function returns nil.
public func randomVariable(preferablyNotOfType type: ILType) -> Variable? {
return findVariable(satisfying: { !self.type(of: $0).Is(type) })
}

/// Returns a random variable satisfying the given constraints or nil if none is found.
func findVariable(satisfying filter: ((Variable) -> Bool) = { _ in true }) -> Variable? {
assert(hasVisibleVariables)
Expand Down
27 changes: 27 additions & 0 deletions Tests/FuzzilliTests/ProgramBuilderTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,33 @@ class ProgramBuilderTests: XCTestCase {
XCTAssertEqual(b.randomVariable(ofType: .primitive), n)
}

func testVariableRetrieval3() {
// This testcase demonstrates the behavior of `b.randomVariable(preferablyNotOfType:)`
// This API will always return a variable for which `type(of: v).Is(requestedType)` is false,
// i.e. for which we cannot statically infer that the variable has the requested type.

let fuzzer = makeMockFuzzer()
let b = fuzzer.makeBuilder()

let v = b.loadInt(42)
XCTAssertEqual(b.randomVariable(preferablyNotOfType: .nothing), v)
XCTAssertEqual(b.randomVariable(preferablyNotOfType: .string), v)
XCTAssertEqual(b.randomVariable(preferablyNotOfType: .integer), nil)

let s = b.loadString("foobar")
XCTAssertEqual(b.randomVariable(preferablyNotOfType: .integer), s)
XCTAssertEqual(b.randomVariable(preferablyNotOfType: .string), v)
XCTAssert([v, s].contains(b.randomVariable(preferablyNotOfType: .boolean)))
XCTAssertEqual(b.randomVariable(preferablyNotOfType: .primitive), nil)
XCTAssertEqual(b.randomVariable(preferablyNotOfType: .anything), nil)

let unknown = b.loadBuiltin("unknown")
XCTAssertEqual(b.type(of: unknown), .anything)
XCTAssert([v, unknown].contains(b.randomVariable(preferablyNotOfType: .string)))
XCTAssertEqual(b.randomVariable(preferablyNotOfType: .primitive), unknown)
XCTAssertEqual(b.randomVariable(preferablyNotOfType: .anything), nil)
}

func testRandomVarableInternal() {
let fuzzer = makeMockFuzzer()
let b = fuzzer.makeBuilder()
Expand Down

0 comments on commit 60b39a8

Please sign in to comment.