rust-lang / rust-lang/backtrace-rs
`resolve` passes symbols which can be invalidated
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 628
- Forks
- 291
- PR merge metrics
- No merged PRs in 30d
Description
resolve in src/symbolize/gimli.rs passes cb a Symbol built from name/location references into the current cached Mapping, and then continues iterating the same DWARF state after the callback returns. Because Cache::with_global is reentrant on the same thread, a callback can call clear_symbol_cache() or recursively call resolve() and clear/evict that Mapping while the outer call is still active, leaving both the in-callback &Symbol and the outer frames iterator with dangling references to freed debug data (use-after-free UB).
This can be reproduced by:
fn clear_symbol_cache_during_resolve_callback() {
#[inline(never)]
fn target() -> *mut c_void {
let mut frames = Vec::new();
backtrace::trace(|frame| {
frames.push(frame.ip());
frames.len() < 32
});
frames
.into_iter()
.find(|ip| {
let mut found = false;
backtrace::resolve(*ip, |_| found = true);
found
})
.expect("expected to capture a resolvable frame")
}
let ip = target();
let mut saw_symbol = false;
backtrace::resolve(ip, |symbol| {
saw_symbol = true;
// This reproduces the gimli cache lifetime bug by evicting the mapping
// that backs the borrowed name/location data passed to the callback,
// then touching the borrowed symbol again.
backtrace::clear_symbol_cache();
let _ = symbol.filename().map(|path| path.as_os_str().len());
let _ = symbol.name().map(|name| name.to_string());
});
assert!(saw_symbol, "expected to resolve at least one symbol");
}
cargo test --test smoke clear_symbol_cache_during_resolve_callback --no-run
valgrind --tool=memcheck target/debug/deps/smoke-b6b34c31904af23c clear_symbol_cache_during_resolve_callback
==26174== Invalid read of size 1
==26174== at 0x41E172C: run_utf8_validation (validations.rs:0)
==26174== by 0x41E172C: core::str::converts::from_utf8 (converts.rs:91)
==26174== by 0x4135AC1: <backtrace::symbolize::SymbolName>::new (mod.rs:310)
==26174== by 0x411BBCD: <backtrace::symbolize::gimli::Symbol>::name (gimli.rs:521)
==26174== by 0x4135B95: <backtrace::symbolize::Symbol>::name (mod.rs:208)
==26174== by 0x407EDBA: smoke::clear_symbol_cache_during_resolve_callback::{closure#0} (smoke.rs:272)
==26174== by 0x41540DA: backtrace::symbolize::gimli::resolve::{closure#0} (gimli.rs:449)
==26174== by 0x4154464: backtrace::symbolize::gimli::resolve::{closure#1} (gimli.rs:473)
==26174== by 0x4153AEF: <backtrace::symbolize::gimli::Cache>::with_global::<backtrace::symbolize::gimli::resolve::{closure#1}> (gimli.rs:379)
==26174== by 0x411CD31: backtrace::symbolize::gimli::resolve (gimli.rs:453)
==26174== by 0x408203C: backtrace::symbolize::resolve_unsynchronized::<smoke::clear_symbol_cache_during_resolve_callback::{closure#0}> (mod.rs:162)
==26174== by 0x40823A2: backtrace::symbolize::resolve::<smoke::clear_symbol_cache_during_resolve_callback::{closure#0}> (mod.rs:63)
==26174== by 0x407BE3F: smoke::clear_symbol_cache_during_resolve_callback (smoke.rs:263)
==26174== Address 0x5a35ee6 is not stack'd, malloc'd or (recently) free'd
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/symbolize/gimli.rs, especially resolve and Cache::with_global, then review the smoke test clear_symbol_cache_during_resolve_callback described in the issue. Run the cargo test command and Valgrind reproduction first. Done means callbacks can clear or re-enter the symbol cache without invalid reads, while symbol resolution continues safely.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100