What happens?
PostgresCatalogSet::Scan hands its callback a bare CatalogEntry& without pinning it into the calling transaction first. GetEntry and CreateEntry both keep the underlying shared_ptr<CatalogEntry> alive in PostgresTransaction::referenced_entries for the rest of the transaction. Scan does not.
If pg_clear_cache runs after a Scan but before every reference handed out by that Scan is done being used, ClearEntries drops the shared_ptr for those entries and destroys them. Anything still holding a reference from the earlier Scan is then reading freed memory; i.e., funcs from Duckdb core like duckdb_tables() or duckdb_views()
To Reproduce
Needs concurrent pressure. Have one connection repeatedly calling pg_clear_cache(), another concurrently running SELECT * FROM duckdb_tables() (or duckdb_indexes()) against an attached postgres catalog. Timing-dependent so needs to be ran multiple times. Reproduced under ASAN with a 200-iteration concurrent loop, crashed on the 2nd iteration in one run, took up to 5 in others.
==ERROR: AddressSanitizer: heap-use-after-free on address ...
READ of size 8 at ... thread T114 #0 std::__cxx11::basic_string<...>::_M_data() const
#1 std::__cxx11::basic_string<...>::basic_string(basic_string const&)
#2 duckdb::Value::Value(duckdb::Identifier const&) duckdb/src/common/types/value.cpp:155
#3 duckdb::DuckDBTablesFunction(...) duckdb/src/function/table/system/duckdb_tables.cpp:153
...
SUMMARY: AddressSanitizer: heap-use-after-free ... in duckdb::Value::Value(duckdb::Identifier const&)
OS:
arch linux
PostgreSQL Version:
16-alpine
DuckDB Version:
v1.5.4-8377-g2daa4fc9a4
DuckDB Client:
cli
Full Name:
brandon freeman
Affiliation:
hallow
Have you tried this on the latest main branch?
Have you tried the steps to reproduce? Do they include all relevant data and configuration? Does the issue you report still appear there?
What happens?
PostgresCatalogSet::Scanhands its callback a bareCatalogEntry&without pinning it into the calling transaction first.GetEntryandCreateEntryboth keep the underlyingshared_ptr<CatalogEntry>alive inPostgresTransaction::referenced_entriesfor the rest of the transaction.Scandoes not.If
pg_clear_cacheruns after aScanbut before every reference handed out by thatScanis done being used,ClearEntriesdrops theshared_ptrfor those entries and destroys them. Anything still holding a reference from the earlierScanis then reading freed memory; i.e., funcs from Duckdb core likeduckdb_tables()orduckdb_views()To Reproduce
Needs concurrent pressure. Have one connection repeatedly calling
pg_clear_cache(), another concurrently runningSELECT * FROM duckdb_tables()(orduckdb_indexes()) against an attached postgres catalog. Timing-dependent so needs to be ran multiple times. Reproduced under ASAN with a 200-iteration concurrent loop, crashed on the 2nd iteration in one run, took up to 5 in others.OS:
arch linux
PostgreSQL Version:
16-alpine
DuckDB Version:
v1.5.4-8377-g2daa4fc9a4
DuckDB Client:
cli
Full Name:
brandon freeman
Affiliation:
hallow
Have you tried this on the latest
mainbranch?Have you tried the steps to reproduce? Do they include all relevant data and configuration? Does the issue you report still appear there?