diff --git a/src/bun.js/bindings/Fuzzilli.cpp b/src/bun.js/bindings/Fuzzilli.cpp index cbcdb74c22..a898a34371 100644 --- a/src/bun.js/bindings/Fuzzilli.cpp +++ b/src/bun.js/bindings/Fuzzilli.cpp @@ -35,11 +35,12 @@ #include #include -#define REPRL_CRFD 100 -#define REPRL_CWFD 101 -#define REPRL_DRFD 102 -#define REPRL_DWFD 103 -#define REPRL_MAX_DATA_SIZE (16 * 1024 * 1024) +static constexpr auto REPRL_CRFD = 100; +static constexpr auto REPRL_CWFD = 101; +static constexpr auto REPRL_DRFD = 102; +static constexpr auto REPRL_DWFD = 103; + +static constexpr auto REPRL_MAX_DATA_SIZE = 16 * 1024 * 1024; #define SHM_SIZE 0x100000 #define MAX_EDGES ((SHM_SIZE - 4) * 8) @@ -89,25 +90,49 @@ void Fuzzilli::waitForCommand() SUPPRESS_COVERAGE void Fuzzilli::initializeCoverage(uint32_t* start, uint32_t* stop) { + fprintf(stderr, "[FUZZILLI] initializeCoverage() called: start=%p, stop=%p\n", start, stop); + fflush(stderr); + RELEASE_ASSERT_WITH_MESSAGE(!edgesStart && !edgesStop, "Coverage instrumentation is only supported for a single module"); edgesStart = start; edgesStop = stop; + fprintf(stderr, "[FUZZILLI] Checking for SHM_ID environment variable\n"); + fflush(stderr); + if (const char* shmKey = getenv("SHM_ID")) { + fprintf(stderr, "[FUZZILLI] SHM_ID found: %s\n", shmKey); + fflush(stderr); + int32_t fd = shm_open(shmKey, O_RDWR, S_IREAD | S_IWRITE); RELEASE_ASSERT_WITH_MESSAGE(fd >= 0, "Failed to open shared memory region: %s", strerror(errno)); + fprintf(stderr, "[FUZZILLI] Shared memory opened, fd=%d\n", fd); + fflush(stderr); + sharedData = static_cast(mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); RELEASE_ASSERT_WITH_MESSAGE(sharedData != MAP_FAILED, "Failed to mmap shared memory region"); - dataLogLn("[COV] edge counters initialized. Shared memory: %s with %zu edges.", shmKey, edgesStop - edgesStart); - } else - sharedData = static_cast(malloc(SHM_SIZE)); + fprintf(stderr, "[FUZZILLI] Shared memory mapped at %p\n", sharedData); + fflush(stderr); + dataLogLn("[COV] edge counters initialized. Shared memory: %s with %zu edges.", shmKey, edgesStop - edgesStart); + } else { + fprintf(stderr, "[FUZZILLI] SHM_ID not found, using malloc\n"); + fflush(stderr); + sharedData = static_cast(malloc(SHM_SIZE)); + fprintf(stderr, "[FUZZILLI] Allocated sharedData at %p\n", sharedData); + fflush(stderr); + } + + fprintf(stderr, "[FUZZILLI] Resetting coverage edges\n"); + fflush(stderr); resetCoverageEdges(); sharedData->numEdges = static_cast(edgesStop - edgesStart); + fprintf(stderr, "[FUZZILLI] initializeCoverage() completed, numEdges=%u\n", sharedData->numEdges); + fflush(stderr); } void Fuzzilli::readInput(Vector* buffer) @@ -141,16 +166,31 @@ void Fuzzilli::flushReprl(int32_t result) void Fuzzilli::initializeReprl() { + fprintf(stderr, "[FUZZILLI] initializeReprl() starting\n"); + fflush(stderr); + std::array helo { 'H', 'E', 'L', 'O' }; + fprintf(stderr, "[FUZZILLI] Sending HELO handshake\n"); + fflush(stderr); WRITE_TO_FUZZILLI(helo.data(), helo.size()); + + fprintf(stderr, "[FUZZILLI] Reading HELO response\n"); + fflush(stderr); READ_FROM_FUZZILLI(helo.data(), helo.size()); + fprintf(stderr, "[FUZZILLI] Verifying HELO response\n"); + fflush(stderr); RELEASE_ASSERT_WITH_MESSAGE(equalSpans(std::span { helo } , "HELO"_span), "[REPRL] Invalid response from parent"); + fprintf(stderr, "[FUZZILLI] Mapping input buffer\n"); + fflush(stderr); // Mmap the data input buffer. reprlInputData = static_cast(mmap(0, REPRL_MAX_DATA_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, REPRL_DRFD, 0)); RELEASE_ASSERT(reprlInputData != MAP_FAILED); + + fprintf(stderr, "[FUZZILLI] initializeReprl() completed successfully\n"); + fflush(stderr); } @@ -187,26 +227,53 @@ WTF_ALLOW_UNSAFE_BUFFER_USAGE_END void Fuzzilli::runReprl(JSC::JSGlobalObject* globalObject) { + fprintf(stderr, "[FUZZILLI] runReprl() starting\n"); + fflush(stderr); + + fprintf(stderr, "[FUZZILLI] Getting VM from globalObject\n"); + fflush(stderr); JSC::VM& vm = JSC::getVM(globalObject); + + fprintf(stderr, "[FUZZILLI] Creating input buffer\n"); + fflush(stderr); Vector inputBuffer; + fprintf(stderr, "[FUZZILLI] Entering main REPRL loop\n"); + fflush(stderr); + // Main REPRL loop - mimics WebKit's jsc shell + int iteration = 0; while (true) { + fprintf(stderr, "[FUZZILLI] Loop iteration %d: waiting for command\n", iteration); + fflush(stderr); + // Wait for 'cexe' command from fuzzer waitForCommand(); + fprintf(stderr, "[FUZZILLI] Loop iteration %d: reading input\n", iteration); + fflush(stderr); + // Read the JavaScript code to execute readInput(&inputBuffer); + fprintf(stderr, "[FUZZILLI] Loop iteration %d: null-terminating input\n", iteration); + fflush(stderr); + // Null-terminate the input inputBuffer.append('\0'); int32_t result = 0; { + fprintf(stderr, "[FUZZILLI] Loop iteration %d: creating catch scope\n", iteration); + fflush(stderr); + // Create a new scope for each evaluation auto scope = DECLARE_CATCH_SCOPE(vm); + fprintf(stderr, "[FUZZILLI] Loop iteration %d: creating source code\n", iteration); + fflush(stderr); + // Create the source code WTF::String sourceString = WTF::String::fromUTF8(inputBuffer.span()); JSC::SourceCode sourceCode = JSC::makeSource( @@ -217,14 +284,22 @@ void Fuzzilli::runReprl(JSC::JSGlobalObject* globalObject) NakedPtr exception; + fprintf(stderr, "[FUZZILLI] Loop iteration %d: evaluating code\n", iteration); + fflush(stderr); + // Evaluate the code JSC::JSValue evalResult = JSC::evaluate(globalObject, sourceCode, globalObject->globalThis(), exception); + fprintf(stderr, "[FUZZILLI] Loop iteration %d: handling result\n", iteration); + fflush(stderr); + // Handle exceptions if (exception) { result = 1; // Non-zero indicates error scope.clearException(); + fprintf(stderr, "[FUZZILLI] Loop iteration %d: exception occurred\n", iteration); + fflush(stderr); } else if (evalResult) { // Optionally print the result (like a REPL would) // Convert result to string and print @@ -233,21 +308,41 @@ void Fuzzilli::runReprl(JSC::JSGlobalObject* globalObject) } } + fprintf(stderr, "[FUZZILLI] Loop iteration %d: flushing REPRL\n", iteration); + fflush(stderr); + // Flush results and send status back flushReprl(result); + fprintf(stderr, "[FUZZILLI] Loop iteration %d: clearing buffer\n", iteration); + fflush(stderr); + // Clear for next iteration inputBuffer.clear(); + + iteration++; } } extern "C" void Fuzzilli__runReprl(JSC::JSGlobalObject* globalObject) { + fprintf(stderr, "[FUZZILLI] Fuzzilli__runReprl() called from Zig\n"); + fprintf(stderr, "[FUZZILLI] globalObject = %p\n", globalObject); + fflush(stderr); + // Initialize REPRL protocol (handshake, mmap input buffer) + fprintf(stderr, "[FUZZILLI] Calling initializeReprl()\n"); + fflush(stderr); Fuzzilli::initializeReprl(); + fprintf(stderr, "[FUZZILLI] initializeReprl() returned, calling runReprl()\n"); + fflush(stderr); + // Run the main REPRL loop (never returns) Fuzzilli::runReprl(globalObject); + + fprintf(stderr, "[FUZZILLI] ERROR: runReprl() returned (should never happen)\n"); + fflush(stderr); } #endif // BUN_FUZZILLI_ENABLED diff --git a/src/bun.js/bindings/Fuzzilli.h b/src/bun.js/bindings/Fuzzilli.h index f6a08fab9f..f88b09c511 100644 --- a/src/bun.js/bindings/Fuzzilli.h +++ b/src/bun.js/bindings/Fuzzilli.h @@ -60,10 +60,5 @@ void runReprl(JSC::JSGlobalObject* globalObject); namespace Fuzzilli { -constexpr void tryInitialize() noexcept { -#ifdef BUN_FUZZILLI_ENABLED - initializeReprl(); -#endif -} } // namespace Fuzzilli diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 73c747b8e3..06c7b51812 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -325,8 +325,6 @@ extern "C" void JSCInitialize(const char* envp[], size_t envc, void (*onCrash)(c } JSC::Options::assertOptionsAreCoherent(); } - - Fuzzilli::tryInitialize(); }); // end std::call_once lambda // NOLINTEND diff --git a/src/bun.js/bindings/webcore/MessagePortChannelProviderImpl.cpp b/src/bun.js/bindings/webcore/MessagePortChannelProviderImpl.cpp index 62b9818bbb..b025e0d2f3 100644 --- a/src/bun.js/bindings/webcore/MessagePortChannelProviderImpl.cpp +++ b/src/bun.js/bindings/webcore/MessagePortChannelProviderImpl.cpp @@ -35,9 +35,7 @@ namespace WebCore { MessagePortChannelProviderImpl::MessagePortChannelProviderImpl() = default; MessagePortChannelProviderImpl::~MessagePortChannelProviderImpl() -{ - ASSERT_NOT_REACHED(); -} +{ } void MessagePortChannelProviderImpl::createNewMessagePortChannel(const MessagePortIdentifier& local, const MessagePortIdentifier& remote) { diff --git a/src/cli/fuzzilli_command.zig b/src/cli/fuzzilli_command.zig index 1a9b348335..2e08d310c1 100644 --- a/src/cli/fuzzilli_command.zig +++ b/src/cli/fuzzilli_command.zig @@ -7,6 +7,8 @@ const Run = bun.bun_js.Run; pub const FuzzilliCommand = struct { pub fn exec(ctx: bun.cli.Command.Context) !void { + bun.Output.prettyErrorln("[ZIG] FuzzilliCommand.exec() starting", .{}); + if (!bun.Environment.isPosix) { bun.Output.prettyErrorln( "error: Fuzzilli mode is only supported on POSIX systems", @@ -15,6 +17,8 @@ pub const FuzzilliCommand = struct { bun.Global.exit(1); } + bun.Output.prettyErrorln("[ZIG] Checking for REPRL file descriptors", .{}); + // Verify REPRL file descriptors are available const REPRL_CRFD: c_int = 100; if (!isValidFd(REPRL_CRFD)) { @@ -29,8 +33,13 @@ pub const FuzzilliCommand = struct { bun.Global.exit(1); } + bun.Output.prettyErrorln("[ZIG] REPRL fd check passed", .{}); + bun.Output.prettyErrorln("[ZIG] Initializing JSC", .{}); + bun.jsc.initialize(false); + bun.Output.prettyErrorln("[ZIG] JSC initialized, creating VM", .{}); + // Create minimal VM for REPRL const arena = bun.MimallocArena.init(); const vm = try bun.jsc.VirtualMachine.init(.{ @@ -40,11 +49,17 @@ pub const FuzzilliCommand = struct { .is_main_thread = true, }); + bun.Output.prettyErrorln("[ZIG] VM created, getting global object", .{}); + // Get the global object and run REPRL const global = vm.global; + bun.Output.prettyErrorln("[ZIG] Global object obtained: {*}", .{global}); + bun.Output.prettyErrorln("[ZIG] Calling Fuzzilli__runReprl()", .{}); + Fuzzilli__runReprl(global); // This never returns (REPRL is infinite loop) + bun.Output.prettyErrorln("[ZIG] ERROR: Fuzzilli__runReprl() returned!", .{}); unreachable; }