From 6d8acee9dbf0cce9e9c80a3aa6ca80f07fa30bb4 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Wed, 20 Aug 2025 10:44:26 -0400 Subject: [PATCH] [ty] Demonstrate SIGSEGV via salsa This is a demonstration of what I believe must imply unsoundness somewhere inside of Salsa. That is, I don't use any `unsafe`, but I get an "invalid memory reference" error. Here is the backtrace I get from `gdb`: ``` (gdb) bt #0 ty_python_semantic::module_resolver::path::{impl#33}::eq (self=, other=0x7ffff106fcb0) at crates/ty_python_semantic/src/module_resolver/path.rs:452 #1 0x0000555555ccc9fb in alloc::sync::{impl#50}::eq (self=0x7ffff0110470, other=0x7ffff1033660) at /home/andrew/.rustup/toolchains/1.89-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/sync.rs:3358 #2 0x0000555555ccc6a4 in alloc::sync::{impl#51}::eq (self=0x7ffff0110470, other=0x7ffff1033660) at /home/andrew/.rustup/toolchains/1.89-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/sync.rs:3388 #3 0x0000555555b92744 in ty_python_semantic::module_resolver::path::{impl#40}::eq (self=0x7ffff0110470, other=0x7ffff1033660) at crates/ty_python_semantic/src/module_resolver/path.rs:491 #4 0x00005555562a4239 in core::cmp::impls::{impl#9}::eq (self=0x7ffff0e88f50, other=0x7ffff7c755c8) at /home/andrew/.rustup/toolchains/1.89-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/cmp.rs:2027 #5 0x00005555562a4436 in core::tuple::{impl#10}::eq<(), &ty_python_semantic::module_resolver::path::SearchPath> (self=0x7ffff0e88f50, other=0x7ffff7c755c8) at /home/andrew/.rustup/toolchains/1.89-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/tuple.rs:32 #6 0x00005555562a44f2 in core::cmp::impls::{impl#9}::eq<((), &ty_python_semantic::module_resolver::path::SearchPath), ((), &ty_python_semantic::module_resolver::path::SearchPath)> (self=0x7ffff7c75178, other=0x7ffff7c75180) at /home/andrew/.rustup/toolchains/1.89-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/cmp.rs:2027 #7 salsa::interned::{impl#14}::eq<((), &ty_python_semantic::module_resolver::path::SearchPath)> (self=0x7ffff0e88f50, data=0x7ffff7c755c8) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/interned.rs:1161 #8 0x0000555555c172e7 in salsa::interned::IngredientImpl::value_eq (id=..., key=0x7ffff7c755c8, zalsa=0x7ffff000daa0, found_value=0x7ffff7c755e8) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/interned.rs:763 #9 0x0000555555ca12b7 in salsa::interned::{impl#7}::intern_id::{closure#0} (id=0x7ffff0e3a588) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/interned.rs:374 #10 0x00005555565a907e in hashbrown::raw::{impl#8}::find::{closure#0}> (index=0) at /home/andrew/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hashbrown-0.15.5/src/raw/mod.rs:1197 #11 0x00005555565821ec in hashbrown::raw::RawTableInner::find_inner (self=0x7ffff0098e08, hash=16887370829962692076, eq=...) at /home/andrew/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hashbrown-0.15.5/src/raw/mod.rs:1921 #12 hashbrown::raw::RawTable::find> ( self=0x7ffff0098e08, hash=16887370829962692076, eq=...) at /home/andrew/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hashbrown-0.15.5/src/raw/mod.rs:1197 #13 0x0000555555c4f7f7 in hashbrown::raw::RawTable::get> (self=0x7ffff0098e08, hash=16887370829962692076, eq=...) at /home/andrew/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hashbrown-0.15.5/src/raw/mod.rs:1212 #14 hashbrown::table::HashTable::find> ( self=0x7ffff0098e08, hash=16887370829962692076, eq=...) at /home/andrew/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hashbrown-0.15.5/src/table.rs:224 #15 salsa::interned::IngredientImpl::intern_id (self=0x7ffff00982c0, zalsa=0x7ffff000daa0, zalsa_local=0x7ffff7c785a8, key=..., assemble=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/interned.rs:377 #16 0x0000555555a24e68 in ty_python_semantic::module_resolver::list::list_modules_in::{closure#0} () at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/components/salsa-macro-rules/src/setup_tracked_fn.rs:473 #17 0x000055555647410c in salsa::attach::Attached::attach, ty_python_semantic::module_resolver::list::list_modules_in::{closure_env#0}> (self=0x7ffff7c7a618, db=..., op=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/attach.rs:79 #18 0x0000555556470f92 in salsa::attach::attach::{closure#0}, dyn ty_python_semantic::db::Db, ty_python_semantic::module_resolver::list::list_modules_in::{closure_env#0}> (a=0x7ffff7c7a618) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/attach.rs:103 #19 0x0000555556304feb in std::thread::local::LocalKey::try_with, dyn ty_python_semantic::db::Db, ty_python_semantic::module_resolver::list::list_modules_in::{closure_env#0}>, alloc::vec::Vec> ( self=0x555557db8810, f=...) at /home/andrew/.rustup/toolchains/1.89-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:315 #20 0x00005555562e7c8d in std::thread::local::LocalKey::with, dyn ty_python_semantic::db::Db, ty_python_semantic::module_resolver::list::list_modules_in::{closure_env#0}>, alloc::vec::Vec> ( self=0x555557db8810, f=) at /home/andrew/.rustup/toolchains/1.89-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:279 #21 0x000055555646f5e4 in salsa::attach::attach, dyn ty_python_semantic::db::Db, ty_python_semantic::module_resolver::list::list_modules_in::{closure_env#0}> (db=..., op=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/attach.rs:101 #22 0x0000555555cc9f94 in ty_python_semantic::module_resolver::list::list_modules_in (db=..., search_path=0x7ffff1033660) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/components/salsa-macro-rules/src/setup_tracked_fn.rs:468 #23 0x0000555555cc95b5 in ty_python_semantic::module_resolver::list::list_modules::{impl#2}::execute::inner_ (db=...) at crates/ty_python_semantic/src/module_resolver/list.rs:20 #24 0x0000555555cc946b in ty_python_semantic::module_resolver::list::list_modules::{impl#2}::execute (db=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/components/salsa-macro-rules/src/setup_tracked_fn.rs:302 #25 0x00005555561c575a in salsa::function::IngredientImpl::execute_query (db=..., zalsa=0x7ffff000daa0, active_query=..., opt_old_memo=..., id=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/function/execute.rs:311 #26 0x0000555556211b9d in salsa::function::IngredientImpl::execute (self=0x7ffff0098010, db=..., active_query=..., opt_old_memo=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/function/execute.rs:46 #27 0x0000555556143974 in salsa::function::IngredientImpl::fetch_cold (self=0x7ffff0098010, zalsa=0x7ffff000daa0, zalsa_local=0x7ffff7c785a8, db=..., id=..., memo_ingredient_index=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/function/fetch.rs:235 #28 0x00005555561775d0 in salsa::function::IngredientImpl::fetch_cold_with_retry (self=0x7ffff0098010, zalsa=0x7ffff000daa0, zalsa_local=0x7ffff7c785a8, db=..., id=..., memo_ingredient_index=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/function/fetch.rs:107 #29 0x0000555556754069 in salsa::function::fetch::{impl#0}::refresh_memo::{closure#0} () at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/function/fetch.rs:64 #30 0x00005555562d0891 in core::option::Option<&salsa::function::memo::Memo>::or_else<&salsa::function::memo::Memo, salsa::function::fetch::{impl#0}::refresh_memo::{closure_env#0}> (self=..., f=...) --Type for more, q to quit, c to continue without paging-- at /home/andrew/.rustup/toolchains/1.89-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:1609 #31 0x0000555556183e04 in salsa::function::IngredientImpl::refresh_memo (self=0x7ffff0098010, db=..., zalsa=0x7ffff000daa0, zalsa_local=0x7ffff7c785a8, id=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/function/fetch.rs:63 #32 salsa::function::IngredientImpl::fetch ( self=0x7ffff0098010, db=..., zalsa=0x7ffff000daa0, zalsa_local=0x7ffff7c785a8, id=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/function/fetch.rs:30 #33 0x0000555555a24d85 in ty_python_semantic::module_resolver::list::list_modules::{closure#0} () at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/components/salsa-macro-rules/src/setup_tracked_fn.rs:474 #34 0x0000555556474dd4 in salsa::attach::Attached::attach, ty_python_semantic::module_resolver::list::list_modules::{closure_env#0}> (self=0x7ffff7c7a618, db=..., op=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/attach.rs:79 #35 0x0000555556470491 in salsa::attach::attach::{closure#0}, dyn ty_python_semantic::db::Db, ty_python_semantic::module_resolver::list::list_modules::{closure_env#0}> (a=0x7ffff7c7a618) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/attach.rs:103 #36 0x00005555563064e6 in std::thread::local::LocalKey::try_with, dyn ty_python_semantic::db::Db, ty_python_semantic::module_resolver::list::list_modules::{closure_env#0}>, alloc::vec::Vec> ( self=0x555557db8810, f=...) at /home/andrew/.rustup/toolchains/1.89-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:315 #37 0x00005555562e897d in std::thread::local::LocalKey::with, dyn ty_python_semantic::db::Db, ty_python_semantic::module_resolver::list::list_modules::{closure_env#0}>, alloc::vec::Vec> (self=0x555557db8810, f=) at /home/andrew/.rustup/toolchains/1.89-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:279 #38 0x000055555646f265 in salsa::attach::attach, dyn ty_python_semantic::db::Db, ty_python_semantic::module_resolver::list::list_modules::{closure_env#0}> (db=..., op=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/src/attach.rs:101 #39 0x0000555555cc93c7 in ty_python_semantic::module_resolver::list::list_modules (db=...) at /home/andrew/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/a3ffa22/components/salsa-macro-rules/src/setup_tracked_fn.rs:468 #40 0x00005555557e2186 in ty_test::run_module_resolution_consistency_test (db=0x7ffff7c78598) at crates/ty_test/src/lib.rs:450 #41 0x00005555557defec in ty_test::run (absolute_fixture_path=..., relative_fixture_path=..., snapshot_path=..., short_title=..., test_name=..., output_format=ty_test::OutputFormat::Cli) at crates/ty_test/src/lib.rs:73 #42 0x0000555555793c06 in mdtest::mdtest (fixture=...) at crates/ty_python_semantic/tests/mdtest.rs:29 #43 0x00005555557959c1 in mdtest::mdtest__generics_pep695_classes () at crates/ty_python_semantic/tests/mdtest.rs:7 #44 0x00005555557903a7 in mdtest::mdtest__generics_pep695_classes::{closure#0} () at crates/ty_python_semantic/tests/mdtest.rs:10 #45 0x000055555579a1b6 in core::ops::function::FnOnce::call_once () at /home/andrew/.rustup/toolchains/1.89-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250 #46 0x00005555557d98eb in core::ops::function::FnOnce::call_once core::result::Result<(), alloc::string::String>, ()> () at library/core/src/ops/function.rs:250 #47 test::__rust_begin_short_backtrace, fn() -> core::result::Result<(), alloc::string::String>> () at library/test/src/lib.rs:648 #48 0x00005555557d8b6e in test::run_test_in_process::{closure#0} () at library/test/src/lib.rs:671 #49 core::panic::unwind_safe::{impl#23}::call_once, test::run_test_in_process::{closure_env#0}> () at library/core/src/panic/unwind_safe.rs:272 #50 std::panicking::catch_unwind::do_call, core::result::Result<(), alloc::string::String>> () at library/std/src/panicking.rs:589 #51 std::panicking::catch_unwind, core::panic::unwind_safe::AssertUnwindSafe> () at library/std/src/panicking.rs:552 #52 std::panic::catch_unwind, core::result::Result<(), alloc::string::String>> () at library/std/src/panic.rs:359 #53 test::run_test_in_process () at library/test/src/lib.rs:671 #54 test::run_test::{closure#0} () at library/test/src/lib.rs:592 #55 0x000055555579d944 in test::run_test::{closure#1} () at library/test/src/lib.rs:622 #56 std::sys::backtrace::__rust_begin_short_backtrace () at library/std/src/sys/backtrace.rs:152 #57 0x00005555557a10ca in std::thread::{impl#0}::spawn_unchecked_::{closure#1}::{closure#0} () at library/std/src/thread/mod.rs:559 #58 core::panic::unwind_safe::{impl#23}::call_once<(), std::thread::{impl#0}::spawn_unchecked_::{closure#1}::{closure_env#0}> () at library/core/src/panic/unwind_safe.rs:272 #59 std::panicking::catch_unwind::do_call>, ()> () at library/std/src/panicking.rs:589 #60 std::panicking::catch_unwind<(), core::panic::unwind_safe::AssertUnwindSafe>> () at library/std/src/panicking.rs:552 #61 std::panic::catch_unwind>, ()> () at library/std/src/panic.rs:359 #62 std::thread::{impl#0}::spawn_unchecked_::{closure#1} () at library/std/src/thread/mod.rs:557 #63 core::ops::function::FnOnce::call_once, ()> () at library/core/src/ops/function.rs:250 #64 0x000055555705088f in alloc::boxed::{impl#28}::call_once<(), dyn core::ops::function::FnOnce<(), Output=()>, alloc::alloc::Global> () at library/alloc/src/boxed.rs:1966 #65 std::sys::pal::unix::thread::{impl#2}::new::thread_start () at library/std/src/sys/pal/unix/thread.rs:107 #66 0x00007ffff7d127eb in ?? () from /usr/lib/libc.so.6 #67 0x00007ffff7d9618c in ?? () from /usr/lib/libc.so.6 ``` --- .../src/module_resolver/list.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/crates/ty_python_semantic/src/module_resolver/list.rs b/crates/ty_python_semantic/src/module_resolver/list.rs index 2374a24212..c3d2f11275 100644 --- a/crates/ty_python_semantic/src/module_resolver/list.rs +++ b/crates/ty_python_semantic/src/module_resolver/list.rs @@ -17,7 +17,7 @@ use super::resolver::{ pub fn list_modules(db: &dyn Db) -> Vec> { let mut modules = BTreeMap::new(); for search_path in search_paths(db, ModuleResolveMode::StubsAllowed) { - for module in list_modules_in(db, SearchPathIngredient::new(db, search_path.clone())) { + for module in list_modules_in(db, (), search_path) { match modules.entry(module.name(db)) { Entry::Vacant(entry) => { entry.insert(module); @@ -39,20 +39,15 @@ pub fn list_modules(db: &dyn Db) -> Vec> { modules.into_values().collect() } -#[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)] -struct SearchPathIngredient<'db> { - #[returns(ref)] - path: SearchPath, -} - /// List all available top-level modules in the given `SearchPath`. #[salsa::tracked] fn list_modules_in<'db>( db: &'db dyn Db, - search_path: SearchPathIngredient<'db>, + _dummy: (), + search_path: &'db SearchPath, ) -> Vec> { - let mut lister = Lister::new(db, search_path.path(db)); - match search_path.path(db).as_path() { + let mut lister = Lister::new(db, search_path); + match search_path.as_path() { SystemOrVendoredPathRef::System(system_search_path) => { // Read the revision on the corresponding file root to // register an explicit dependency on this directory. When