Repository navigation
deps: update libdeflate to v1.26 - #9
Open
github-actions[bot] wants to merge 1 commit into
Open
github-actions[bot] wants to merge 1 commit into
github-actions[bot] wants to merge 1 commit into
Conversation
Seantheprogrammer93
pushed a commit
that referenced
this pull request
Sep 27, 2026
…p_until (oven-sh#41149) Fuzzilli found an ASAN stack-buffer-overflow in `run_tasks` -> `Log::add_msg` -> `Vec::push` during runtime auto-install. ## What happened `enqueue_dependency_to_root` blocks in `sleep_until`. `sleep_until` ticks the JS event loop between `is_done` polls. Each poll calls `run_tasks`, which reads `manager.log` to log manifest 4xx errors. The event loop tick can run module transpilation or `AsyncModule::resume_loading_module`. Both swap the VM's log pointers (`jsc_vm.log`, `transpiler.log`, `resolver.log`, `linker.log`, `pm.log`) and restore them on exit. They do not save from the same source: - `resolve_maybe_needs_trailing_slash` saves `jsc_vm.log` and swaps every pointer except `transpiler.log`. - `transpile_source_code_inner` saves `transpiler.log` and restores `pm.log` to it. - `AsyncModule::resume_loading_module` saves `jsc_vm.log` but restores `transpiler.log` to it. When a module transpile runs during a resolve's `sleep_until` tick, its restore sets `pm.log` to the old `transpiler.log`, not the resolve's scoped log. The 404 diagnostics from `run_tasks` then land in the wrong log. With more interleaving across calls `pm.log` ends up at a dead stack `Log`, and the next `run_tasks` poll reads it. ``` READ of size 8 at 0x7ffd98a149c0 thread T0 #0 RawVecInner::capacity #1 Log::add_msg (lib.rs:2369) #3 Log::add_error_fmt (lib.rs:2032) #4 run_tasks (runTasks.rs:494) #5 Closure::is_done (PackageManagerEnqueue.rs:534) #7 AnyEventLoop::tick_raw (AnyEventLoop.rs:148) #8 PackageManager::sleep_until (PackageManager.rs:1063) #9 enqueue_dependency_to_root (PackageManagerEnqueue.rs:571) ... oven-sh#18 resolve_maybe_needs_trailing_slash (VirtualMachine.rs:4259) Address is located in stack of thread T0 in frame #0 to_js_host_call (host_fn.rs:677) [144, 152) 'scope' <== Memory access at offset 160 overflows this variable [176, 240) 'scope_storage' ``` ## Fix - Swap and restore `transpiler.log` with the other log pointers in `resolve_maybe_needs_trailing_slash`. It can no longer drift from `jsc_vm.log` across a resolve. - Snapshot `pm.log` on entry to `enqueue_dependency_to_root`'s `sleep_until`. Re-assert it before each `run_tasks` poll. `run_tasks` always sees the caller's log, whatever the event loop tick did to it. ## Test The test runs a 404 registry in the parent process on `port: 0`. The child queues `require()` calls with `setImmediate`, so they run during `sleep_until`'s event-loop tick and trigger `transpile_source_code_inner`'s log swap. Without the fix, the 404 errors land in the VM log and print to stderr at exit. With the fix, stderr is empty. Verified on current `main` (6f27257): the test fails without the source change and passes with it. Supersedes oven-sh#31120, which the stale bot closed after 90 days. Same change, rebased onto current main; moved to this branch so the fix can be tracked. <!-- robobun:evidence:begin --> --- **[human-review]** gate passed · iteration 6 · 3 files touched <details><summary>fails on main (without fix)</summary> ```console ASAN without fix: 1 FAILED $ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test "--reporter=junit" "--reporter-outfile=/tmp/pr_gate.xml" test/js/bun/resolve/resolve-autoinstall-log-dangling.test.ts bun test v1.4.1 (a6c4cc2) test/js/bun/resolve/resolve-autoinstall-log-dangling.test.ts: (pass) repeated failing auto-install resolves at varying stack depth don't read a dangling pm.log [1075.94ms] 114 | stderr: "pipe", 115 | }); 116 | 117 | const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); 118 | 119 | expect(stderr).toBe(""); ^ error: expect(received).toBe(expected) - "" + "error: GET http://localhost:37987/autoinstall-missing-pkg-0 - 404 + + error: GET http://localhost:37987/autoinstall-missing-pkg-1 - 404 + + error: GET http://localhost:37987/autoinstall-missing-pkg-2 - 404 + + error: GET http://localhost:37987/autoinstall-missing-pkg-3 - 404 + + error: GET http://localhost:37987/autoinstall-missing-pkg-4 - 404 + + error: GET http://localhost:37987/autoinstall-missing-pkg-5 - 404 + + error: GET http://localhost:37987/autoinstall-missing-pkg-6 - 404 + + error: GET http:// ... (truncated) release without fix: 1 FAILED bun test v1.4.1-canary.1 (a6c4cc2) test/js/bun/resolve/resolve-autoinstall-log-dangling.test.ts: (pass) repeated failing auto-install resolves at varying stack depth don't read a dangling pm.log [22.63ms] 114 | stderr: "pipe", 115 | }); 116 | 117 | const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); 118 | 119 | expect(stderr).toBe(""); ^ error: expect(received).toBe(expected) - "" + "error: GET http://localhost:35697/autoinstall-missing-pkg-0 - 404 + + error: GET http://localhost:35697/autoinstall-missing-pkg-1 - 404 + + error: GET http://localhost:35697/autoinstall-missing-pkg-2 - 404 + + error: GET http://localhost:35697/autoinstall-missing-pkg-3 - 404 + + error: GET http://localhost:35697/autoinstall-missing-pkg-4 - 404 + + error: GET http://localhost:35697/autoinstall-missing-pkg-5 - 404 + + error: GET http://localhost:35697/autoinstall-missing-pkg-6 - 404 + + error: GET http://localhost:35697/autoinstall-missing-pkg-7 - 404 + + error: GET http://localhost:35697/autoinstall-missing-pkg-8 - 404 + + error: GET http://localhost:35697/autoinstall-missing-pkg-9 - ... (truncated) ``` </details> <details><summary>passes on PR (with fix)</summary> ```console ASAN with fix: all passed $ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test "--reporter=junit" "--reporter-outfile=/tmp/pr_gate.xml" test/js/bun/resolve/resolve-autoinstall-log-dangling.test.ts bun test v1.4.1 (a6c4cc2) test/js/bun/resolve/resolve-autoinstall-log-dangling.test.ts: (pass) repeated failing auto-install resolves at varying stack depth don't read a dangling pm.log [1104.72ms] (pass) module transpile during auto-install's event-loop tick doesn't desync pm.log [689.71ms] 2 pass 0 fail 8 expect() calls Ran 2 tests across 1 file. [3.73s] __F:0:S:0 release with fix: all passed $ bun scripts/build.ts --profile=release [configured] bun-profile → bun (stripped) in 590ms (unchanged) ninja: Entering directory `/workspace/bun/build/release' [1/141] gen generated_host_exports.rs generated_host_exports.rs: 122 exports (host=5, lazy=10, generic=107, rust=0); 244 extern-C blocks audited [2/141] gen JS modules (bundle-modules) Preprocess modules (8046ms) Bundle modules (666ms) Postprocesss modules (969ms) Bundle Functions (629ms) Generate Code (40ms) [10.36s] Bundled "src/js" for production 2594 kb 197 internal modules 13 native modules 50 internal functions across 16 files [2/141] cargo bun_runtime → libbun_runtime.a �[1m�[92m Compiling�[0m bun_output_tags v0.0.0 (/workspace/bun/src/bun_output_tags) �[1m�[92m Compiling�[0m bun_core v0.0.0 (/workspace/bun/src/bun_core) �[1m�[92m Compiling�[0m bun_parsers v0.0.0 (/workspace/bun/src/parsers) �[1m�[92m Compiling�[0m bun_install v0.0.0 (/workspace/bun/src/install) �[1m�[92m Compiling�[0m bun_jsc v0.0.0 (/workspace/bun/src/jsc) �[1m�[92m Compiling�[0m bun_dispatch v0.0.0 (/workspace/bun/src/dispatch) �[1m�[92m Compiling�[0m bun_jsc_macros v0.0.0 (/workspace/bun/src/jsc_macros) ... (truncated) ``` </details> <details><summary>diff hotspot</summary> ``` .../PackageManager/PackageManagerEnqueue.rs | 6 ++ src/jsc/VirtualMachine.rs | 5 ++ .../resolve-autoinstall-log-dangling.test.ts | 65 ++++++++++++++++++++++ 3 files changed, 76 insertions(+) ``` </details> **gate history** · 1 passed · 0 rejected · iteration 6 <details><summary>evidence per changed file</summary> ``` file reads edits tests src/install/PackageManager/PackageManagerEnqueue.rs 1 2 19 src/jsc/VirtualMachine.rs 5 3 19 …js/bun/resolve/resolve-autoinstall-log-dangling.test.ts 3 9 18 ``` </details> <!-- robobun:evidence:end -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Updates libdeflate to version v1.26
Compare: ebiggers/libdeflate@c8c56a2...92e6a0d
Auto-updated by this workflow