mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-12 19:02:12 +00:00
table_helper: fix use-after-free on prepared-statement invalidation
insert() held no local strong ref to the prepared modification_statement across the suspension in execute(). On a single shard: 1. Fiber A suspends inside _insert_stmt->execute(). 2. DROP TABLE / DROP KEYSPACE on the target, or LRU eviction, removes the prepared_statements_cache entry, releasing its strong ref. 3. Fiber B re-enters cache_table_info(), sees _prepared_stmt (checked_weak_ptr) invalidated, and runs _insert_stmt = nullptr, releasing the last strong ref. The modification_statement is freed. 4. Fiber A resumes inside execute() and touches freed *this. Pin strong ref to _insert_stmt locally before the suspension.
This commit is contained in:
@@ -152,9 +152,13 @@ future<> table_helper::insert(cql3::query_processor& qp, service::migration_mana
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Pin a strong ref locally: while we suspend in execute(), a concurrent
|
||||
// insert() on this shard may reset _insert_stmt to nullptr if the
|
||||
// prepared_statements_cache entry gets invalidated, freeing the object.
|
||||
auto stmt = _insert_stmt;
|
||||
auto opts = opt_maker();
|
||||
opts.prepare(_prepared_stmt->bound_names);
|
||||
co_await _insert_stmt->execute(qp, qs, opts, std::nullopt);
|
||||
co_await stmt->execute(qp, qs, opts, std::nullopt);
|
||||
}
|
||||
|
||||
future<> table_helper::setup_keyspace(cql3::query_processor& qp, service::migration_manager& mm, std::string_view keyspace_name, sstring replication_strategy_name,
|
||||
|
||||
Reference in New Issue
Block a user