Skip to content

fix: sanitize Wasm function names - #1342

Closed
mooori wants to merge 1 commit into
nextfrom
mooori/duplicate-wasm-fn-name
Closed

fix: sanitize Wasm function names#1342
mooori wants to merge 1 commit into
nextfrom
mooori/duplicate-wasm-fn-name

Conversation

@mooori

@mooori mooori commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Closes #1341

Approach is deduplicating function names in the NameSection by prepending the function index.

Potential other approach: Keep two maps, one for function names as listed in the Wasm name section and for unique names. I suspect that would be a bigger change as the new map with unique names would need to be switched in to NameSection.

Related issues/changes

Working on this I found some (unlikely/contrived) edge cases that are currently not handled. When sanitizing function names, these edge cases break in a different way.

Are these things we want to fix?

Library exports with duplicate names

Undefined item instead of compilation error

Consider this WAT:

(module $math
    (type $ret-i32 (func (result i32)))

    ;; The library’s public Wasm API is named "add".
    (export "add" (func $implementation_a))

    ;; Both functions have the same name-section name.
    (func $implementation_a (@name "add") (type $ret-i32) (result i32)
      i32.const 1)

    (func $implementation_b (@name "add") (type $ret-i32) (result i32)
      i32.const 2)
)

After sanitation, the library roughly looks like

pub proc add_func0
    push.1
end

proc add_func1
    push.2
end

So the package exports add_func0 instead of add. Callers might not be aware of this and when they call add it cannot be resolved.

Previously this would fail compilation due to the duplicate function name, see #1341.

Debug info

Some subtle changes

Pasting LLM output here as I haven't really looked into this yet:

  • Function debug records remain keyed by FuncIndex, so attaching debug info to translated bodies is safe.
  • Instruction source locations use DWARF addresses, not names.
  • The emitted di.subprogram name is explicitly the sanitized HIR name (frontend/wasm/src/module/ debug_info.rs:170). Thus debuggers, traces, and symbol-based breakpoints will expose foo_func0; the original name is no longer retained.
  • DWARF local-variable collection first attempts DW_AT_name/DW_AT_linkage_name against a map of sanitized names, then falls back to DW_AT_low_pc (frontend/wasm/src/module/debug_info.rs:443, frontend/wasm/src/module/debug_info.rs:602).

For normal Rust/LLVM DWARF containing DW_AT_low_pc, renamed functions should still receive the right locals. It may actually improve duplicate-name handling: previously the duplicate name map selected only one FuncIndex, potentially attaching both DIEs to the same function.

However, a producer whose subprogram DIE relies only on its original name and lacks a usable low_pc will lose local/parameter debug data after renaming. Since sanitation mutates the name section in place, there is no original-name fallback.

Also debug info incorrectly assumes that functions in the name section are unique:

for (func_index, _) in module.functions.iter() {
let name = module.func_name(func_index).as_str().to_owned();
func_by_name.insert(name, func_index);
}

For a wasm section like below, the second insertion silently replaces the first.

FuncIndex(0) → "foo"
FuncIndex(1) → "foo"

Opened #1343 for that.

@mooori
mooori force-pushed the mooori/duplicate-wasm-fn-name branch from 1d0dcc9 to bf48ef8 Compare August 21, 2026 16:59
@github-actions

Copy link
Copy Markdown
Contributor

Miden examples benchmark

Candidate 1abf8f783498 compared with next 62c4318f44f2. Lower is better.

example VM cycles (vs next) MAST size (vs next)
auth-component-no-auth n/a 6,300B (~0%)
auth-component-rpo-falcon512 n/a 12,654B (~0%)
basic-wallet n/a 7,982B (~0%)
basic-wallet-tx-script n/a 13,556B (~0%)
collatz 5,263 (~0%) 2,401B (~0%)
counter-contract n/a 13,099B (~0%)
counter-note n/a 3,197B (~0%)
fibonacci 869 (~0%) 3,219B (~0%)
is-prime 2,332,731 (~0%) 5,864B (~0%)
p2id-note n/a 17,024B (~0%)
p2id-tx-script n/a 11,455B (~0%)
p2ide-note n/a 13,103B (~0%)
storage-example n/a 15,214B (~0%)

SVG flamegraphs and compiled packages are attached to the workflow run.

@mooori
mooori marked this pull request as ready for review August 21, 2026 17:38
@mooori

mooori commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

cc @djolertrk regarding debuginfo

@mooori
mooori requested review from bitwalker and greenhat August 21, 2026 17:39
@mooori
mooori marked this pull request as draft August 24, 2026 15:39
@mooori

mooori commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Reverted to draft mode as it needs to be reworked as discussed in the sync.

@mooori

mooori commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Closing in favor of #1357

@mooori mooori closed this Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Frontend assumes names from Wasm's name section are unique

1 participant