Skip to content

Comments

fix: prevent module point to wild pointer#13021

Merged
SyMind merged 1 commit intomainfrom
fix-module-binding-wild-pointer
Feb 10, 2026
Merged

fix: prevent module point to wild pointer#13021
SyMind merged 1 commit intomainfrom
fix-module-binding-wild-pointer

Conversation

@SyMind
Copy link
Member

@SyMind SyMind commented Feb 10, 2026

Summary

Fix: #12899

This PR fixes a critical memory safety issue where JavaScript modules could access freed Rust module memory through dangling pointers.

Problem

Currently in Rspack, JavaScript modules access Rust modules via raw pointers, which requires that Rust module addresses remain stable throughout their lifetime.

However, the existing code uses std::mem::replace in the NormalModule::build method, which violates this assumption by moving the module to a different memory location. This creates a race condition where:

  1. A JS module holds a raw pointer to a Rust module
  2. The Rust module is moved during the build process via std::mem::replace
  3. The original memory location is deallocated
  4. The JS module attempts to access the now-freed memory, causing a panic

Solution

This PR resolves the issue by changing the Module::build method signature from:

async fn build(&mut self, ...) -> Result<BuildResult>

to:

async fn build(self: Box<Self>, ...) -> Result<BuildResult>

The method now takes ownership of the boxed module and returns it within BuildResult, ensuring the module's heap allocation remains stable and its address doesn't change.

Next Steps

This PR lays the groundwork for a more comprehensive solution. In a follow-up PR, I plan to refactor BoxModule to store it within a BindingCell, which will provide stronger guarantees against dangling pointer issues at the type system level.

Related links

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).

@github-actions github-actions bot added release: bug fix release: bug related release(mr only) team The issue/pr is created by the member of Rspack. labels Feb 10, 2026
@github-actions
Copy link
Contributor

Rsdoctor Bundle Diff Analysis

Found 5 projects in monorepo, 0 projects with changes.

📊 Quick Summary
Project Total Size Change
react-10k 5.7 MB 0
react-1k 825.4 KB 0
react-5k 2.7 MB 0
rome 984.2 KB 0
ui-components 2.2 MB 0

Generated by Rsdoctor GitHub Action

@github-actions
Copy link
Contributor

📦 Binary Size-limit

Comparing d7f945a to refactor: wrap artifact in StealCell (#12979) by hardfist

❌ Size increased by 25.50KB from 48.65MB to 48.68MB (⬆️0.05%)

@SyMind SyMind marked this pull request as ready for review February 10, 2026 07:05
@SyMind SyMind requested a review from ahabhgk as a code owner February 10, 2026 07:05
Copilot AI review requested due to automatic review settings February 10, 2026 07:05
@codspeed-hq
Copy link

codspeed-hq bot commented Feb 10, 2026

Merging this PR will not alter performance

✅ 17 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing fix-module-binding-wild-pointer (d7f945a) with main (4ca63ec)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a critical memory-safety issue in Rspack’s Rust↔JS module interop by ensuring module heap addresses remain stable during build, preventing JS from holding dangling pointers to moved/freed Rust module memory.

Changes:

  • Change Module::build to consume self: Box<Self> and require returning the (boxed) module via BuildResult { module, ... }.
  • Refactor NormalModule (and loader runner context) to avoid mem::replace-style moves during loader execution.
  • Update core/plugins to the new build contract, including module concatenation and module-graph build pipeline.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
crates/rspack_core/src/module.rs Changes Module::build signature; makes BuildResult carry the built BoxModule; adds BoxModule::build helper.
crates/rspack_core/src/normal_module.rs Removes move-based ownership transfer; runs loaders while keeping module allocation stable; returns module via BuildResult.
crates/rspack_core/src/loader/loader_runner.rs Stores RunnerContext.module as Box<NormalModule> to keep allocation stable during loader execution.
crates/rspack_binding_api/src/plugins/js_loader/context.rs Adjusts JS loader context module pointer creation for the boxed module storage.
crates/rspack_core/src/compilation/build_module_graph/graph_updater/repair/build.rs Updates build task flow to retrieve the built module from BuildResult.module.
crates/rspack_core/src/concatenated_module.rs Updates ConcatenatedModule::build to the new boxed build contract and returns itself in BuildResult.
crates/rspack_plugin_javascript/src/plugin/module_concatenation_plugin.rs Updates concatenation flow to build via BoxModule::build and use identifier() with BoxModule.
crates/rspack_core/src/context_module.rs Adapts ContextModule::build to boxed self + BuildResult.module.
crates/rspack_core/src/external_module.rs Adapts ExternalModule::build to boxed self + BuildResult.module.
crates/rspack_core/src/raw_module.rs Adds build implementation returning itself in BuildResult under the new trait contract.
crates/rspack_core/src/self_module.rs Adds build implementation returning itself in BuildResult under the new trait contract.
crates/rspack_core/src/cache/persistent/occasion/make/alternatives/module.rs Adds build implementation for TempModule to satisfy the new trait contract.
crates/rspack_macros/src/runtime_module.rs Updates runtime-module macro output to implement boxed build returning BuildResult.module.
crates/rspack_plugin_extract_css/src/css_module.rs Updates CssModule::build to return itself in BuildResult.
crates/rspack_plugin_lazy_compilation/src/module.rs Updates lazy compilation proxy module build to boxed self + BuildResult.module.
crates/rspack_plugin_dll/src/dll_entry/dll_module.rs Updates DllModule::build to boxed self + BuildResult.module.
crates/rspack_plugin_dll/src/dll_reference/delegated_module.rs Updates DelegatedModule::build to boxed self + BuildResult.module.
crates/rspack_plugin_mf/src/container/container_entry_module.rs Updates MF container entry module build to boxed self + BuildResult.module.
crates/rspack_plugin_mf/src/container/fallback_module.rs Updates MF fallback module build to boxed self + BuildResult.module.
crates/rspack_plugin_mf/src/container/remote_module.rs Updates MF remote module build to boxed self + BuildResult.module.
crates/rspack_plugin_mf/src/sharing/consume_shared_module.rs Updates MF consume-shared module build to boxed self + BuildResult.module.
crates/rspack_plugin_mf/src/sharing/provide_shared_module.rs Updates MF provide-shared module build to boxed self + BuildResult.module.
Comments suppressed due to low confidence (1)

crates/rspack_core/src/module.rs:240

  • BuildResult's doc comment on dependencies says "Whether the result is cacheable" which doesn't match the field type/meaning (it's a list of dependencies). This looks misleading after the refactor; consider updating/removing the comment or moving it to the actual cacheability field (if any).
  pub module: BoxModule,
  /// Whether the result is cacheable, i.e shared between builds.
  pub dependencies: Vec<BoxDependency>,
  pub blocks: Vec<Box<AsyncDependenciesBlock>>,
  pub optimization_bailouts: Vec<String>,

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@SyMind SyMind merged commit 2865b34 into main Feb 10, 2026
64 checks passed
@SyMind SyMind deleted the fix-module-binding-wild-pointer branch February 10, 2026 07:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release: bug fix release: bug related release(mr only) team The issue/pr is created by the member of Rspack.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Memory crash (SIGBUS/SIGSEGV) when using swc-loader (npm) instead of builtin:swc-loader

2 participants