diff --git a/Sources/Fuzzilli/Execution/REPRL.swift b/Sources/Fuzzilli/Execution/REPRL.swift index 22bb3c34f..005310ec8 100644 --- a/Sources/Fuzzilli/Execution/REPRL.swift +++ b/Sources/Fuzzilli/Execution/REPRL.swift @@ -24,8 +24,8 @@ public class REPRL: ComponentBase, ScriptRunner { /// Commandline arguments for the executable public private(set) var processArguments: [String] - /// Environment variables for the child process - private var env = [String]() + /// Environment variables for the child process. Shape: [(key, value)] + public private(set) var env = [(String, String)]() /// Number of script executions since start of child process private var execsSinceReset = 0 @@ -50,7 +50,7 @@ public class REPRL: ComponentBase, ScriptRunner { super.init(name: "REPRL") for (key, value) in processEnvironment { - env.append(key + "=" + value) + env.append((key, value)) } } @@ -61,7 +61,7 @@ public class REPRL: ComponentBase, ScriptRunner { } let argv = convertToCArray(processArguments) - let envp = convertToCArray(env) + let envp = convertToCArray(env.map({ $0 + "=" + $1 })) if reprl_initialize_context(reprlContext, argv, envp, /* capture stdout */ 1, /* capture stderr: */ 1) != 0 { logger.fatal("Failed to initialize REPRL context: \(String(cString: reprl_get_last_error(reprlContext)))") @@ -76,7 +76,7 @@ public class REPRL: ComponentBase, ScriptRunner { } public func setEnvironmentVariable(_ key: String, to value: String) { - env.append(key + "=" + value) + env.append((key, value)) } public func run(_ script: String, withTimeout timeout: UInt32) -> Execution { diff --git a/Sources/Fuzzilli/Execution/ScriptRunner.swift b/Sources/Fuzzilli/Execution/ScriptRunner.swift index 36bccf7e8..fcd408d1d 100644 --- a/Sources/Fuzzilli/Execution/ScriptRunner.swift +++ b/Sources/Fuzzilli/Execution/ScriptRunner.swift @@ -14,6 +14,7 @@ public protocol ScriptRunner: Component { var processArguments: [String] { get } + var env: [(String, String)] { get } /// Executes a script, waits for it to complete, and returns the result. func run(_ script: String, withTimeout timeout: UInt32) -> Execution diff --git a/Sources/Fuzzilli/Fuzzer.swift b/Sources/Fuzzilli/Fuzzer.swift index 3be0dadb1..e9d10abf9 100644 --- a/Sources/Fuzzilli/Fuzzer.swift +++ b/Sources/Fuzzilli/Fuzzer.swift @@ -1013,7 +1013,9 @@ public class Fuzzer { // Wrap the executor in a JavaScriptTestRunner // If we can execute it standalone, it could inform us if any flags that were passed are incorrect, stale or conflicting. - let executor = JavaScriptExecutor(withExecutablePath: runner.processArguments[0], arguments: Array(runner.processArguments[1...])) + let executor = JavaScriptExecutor( + withExecutablePath: runner.processArguments[0], + arguments: Array(runner.processArguments[1...]), env: runner.env) do { let output = try executor.executeScript("", withTimeout: 300).output if output.lengthOfBytes(using: .utf8) > 0 { diff --git a/Sources/Fuzzilli/Util/JavaScriptExecutor.swift b/Sources/Fuzzilli/Util/JavaScriptExecutor.swift index 1f0ae1d50..4340c67ef 100644 --- a/Sources/Fuzzilli/Util/JavaScriptExecutor.swift +++ b/Sources/Fuzzilli/Util/JavaScriptExecutor.swift @@ -38,9 +38,12 @@ public class JavaScriptExecutor { let arguments: [String] + let env: [(String, String)] + /// Depending on the type this constructor will try to find the requested shell or fail - public init?(type: ExecutorType = .any, withArguments maybeArguments: [String]? = nil) { + public init?(type: ExecutorType = .any, withArguments maybeArguments: [String]? = nil, withEnv maybeEnv: [(String, String)]? = nil) { self.arguments = maybeArguments ?? [] + self.env = maybeEnv ?? [] let path: String? switch type { @@ -59,23 +62,24 @@ public class JavaScriptExecutor { self.executablePath = path! } - public init(withExecutablePath executablePath: String, arguments: [String]) { + public init(withExecutablePath executablePath: String, arguments: [String], env: [(String, String)]) { self.executablePath = executablePath self.arguments = arguments + self.env = env } /// Executes the JavaScript script using the configured engine and returns the stdout. public func executeScript(_ script: String, withTimeout timeout: TimeInterval? = nil) throws -> Result { - return try execute(executablePath, withInput: prefix + script.data(using: .utf8)!, withArguments: self.arguments, timeout: timeout) + return try execute(executablePath, withInput: prefix + script.data(using: .utf8)!, withArguments: self.arguments, withEnv: self.env, timeout: timeout) } /// Executes the JavaScript script at the specified path using the configured engine and returns the stdout. public func executeScript(at url: URL, withTimeout timeout: TimeInterval? = nil) throws -> Result { let script = try Data(contentsOf: url) - return try execute(executablePath, withInput: prefix + script, withArguments: self.arguments, timeout: timeout) + return try execute(executablePath, withInput: prefix + script, withArguments: self.arguments, withEnv: self.env, timeout: timeout) } - func execute(_ path: String, withInput input: Data = Data(), withArguments arguments: [String] = [], timeout maybeTimeout: TimeInterval? = nil) throws -> Result { + func execute(_ path: String, withInput input: Data = Data(), withArguments arguments: [String] = [], withEnv env: [(String, String)] = [], timeout maybeTimeout: TimeInterval? = nil) throws -> Result { let inputPipe = Pipe() let outputPipe = Pipe() let errorPipe = Pipe() @@ -89,6 +93,8 @@ public class JavaScriptExecutor { // Close stdin try inputPipe.fileHandleForWriting.close() + let environment = ProcessInfo.processInfo.environment.merging(env, uniquingKeysWith: { _, new in new }) + // Execute the subprocess. let task = Process() task.standardOutput = outputPipe @@ -96,6 +102,7 @@ public class JavaScriptExecutor { task.arguments = arguments + [url.path] task.executableURL = URL(fileURLWithPath: path) task.standardInput = inputPipe + task.environment = environment try task.run() var timedOut = false diff --git a/Sources/Fuzzilli/Util/MockFuzzer.swift b/Sources/Fuzzilli/Util/MockFuzzer.swift index a7bab9463..44feb77f4 100644 --- a/Sources/Fuzzilli/Util/MockFuzzer.swift +++ b/Sources/Fuzzilli/Util/MockFuzzer.swift @@ -26,6 +26,7 @@ struct MockExecution: Execution { class MockScriptRunner: ScriptRunner { var processArguments: [String] = [] + var env: [(String, String)] = [] func run(_ script: String, withTimeout timeout: UInt32) -> Execution { return MockExecution(outcome: .succeeded,