Fix uninitialized TransactionContext::invalidation_policy and auto_rollback members by evertlammerts · Pull Request #23321 · duckdb/duckdb · GitHub
Skip to content

Fix uninitialized TransactionContext::invalidation_policy and auto_rollback members - #23321

Merged
Mytherin merged 1 commit into
duckdb:mainfrom
evertlammerts:fix-transaction-context-uninit-members
Jun 17, 2026
Merged

Mytherin merged 1 commit into
duckdb:mainfrom
evertlammerts:fix-transaction-context-uninit-members

Conversation

@evertlammerts

@evertlammerts evertlammerts commented Jun 16, 2026 •

Copy link
Copy Markdown
Member

TransactionContext didn't invalidation_policy or auto_rollback in the constructor. When running C API V2 tests we got a UBSanitizer error:

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/src/include/duckdb/transaction/transaction_context.hpp:67:10
build/relassert/test/run --track-runtime=100 [capi_v2],[capi]
CI detected, enabling retry=2 per batch
config: patterns=['[capi_v2],[capi]'], workers=12, retry=2, max_retries=4, batch_size=10, batch_timeout_seconds=300, runtime_threshold_seconds=100, fail_require_skip=False
.................................................. [ 50%]
.......................................
retrying failed test V2: destroying a half-executed expanded group is clean (attempt 1/2, retry 1/4)
......
retrying failed test V2: destroying a half-executed expanded group is clean (attempt 2/2, retry 2/4)
error: test batch failed

/home/runner/work/duckdb-capi-v2/duckdb-capi-v2/src/include/duckdb/transaction/transaction_context.hpp:67:10: runtime error: load of value 190, which is not a valid value for type 'bool'
#0 0x7f8eda60293c in duckdb::TransactionContext::GetAutoRollback() /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/src/include/duckdb/transaction/transaction_context.hpp:67:10
#1 0x7f8eda60293c in duckdb::ResultWrapperV2::RollbackIncompleteGroup() /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/src/main/capi_v2/capi_v2_internal.hpp:317:57

--- raw unittest stdout ---

[0/10] (0%): V2: result_wait after interrupt is clean
[1/10] (10%): V2: result_wait after interrupt is clean took 0.076s
[2/10] (20%): V2: result_fetch_chunk drains a CHANGED_ROWS result took 0.064s
[3/10] (30%): V2: an undrained result survives disconnect and close took 0.056s
[4/10] (40%): V2: PIVOT expands to a group and streams the pivoted rows took 0.087s
[5/10] (50%): V2: ALTER with a non-constant DEFAULT expands and executes fully took 0.070s
[6/10] (60%): V2: result_drain runs an expanded group to completion took 0.067s
[7/10] (70%): V2: query-backed PRAGMA reparses at connection_query took 0.050s
[8/10] (80%): V2: an error inside an expanded group is sticky and rolls back took 0.065s
[9/10] (90%): V2: interrupt during an expanded group cancels and rolls back took 0.194s

--- raw unittest stderr ---
/home/runner/work/duckdb-capi-v2/duckdb-capi-v2/src/include/duckdb/transaction/transaction_context.hpp:67:10: runtime error: load of value 190, which is not a valid value for type 'bool'
    #0 0x7f8eda60293c in duckdb::TransactionContext::GetAutoRollback() /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/src/include/duckdb/transaction/transaction_context.hpp:67:10
    #1 0x7f8eda60293c in duckdb::ResultWrapperV2::RollbackIncompleteGroup() /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/src/main/capi_v2/capi_v2_internal.hpp:317:57
    #2 0x7f8eda603a94 in duckdb::ResultWrapperV2::~ResultWrapperV2() /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/src/main/capi_v2/capi_v2_internal.hpp:262:5
    #3 0x7f8eda5bc55a in duckdb_v2_result_destroy::$_0::operator()() const /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/src/main/capi_v2/query_result-v2.cpp:412:4
    #4 0x7f8eda5bc55a in unsigned int duckdb::WithErrorHandler<duckdb_v2_result_destroy::$_0>(_duckdb_v2_error_info**, duckdb_v2_result_destroy::$_0) /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/src/main/capi_v2/capi_v2_internal.hpp:903:3
    #5 0x7f8eda5bc55a in duckdb_v2_result_destroy /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/src/main/capi_v2/query_result-v2.cpp:407:9
    #6 0x557f516e39c5 in ____C_A_T_C_H____T_E_S_T____420() /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/test/api/capi_v2/test_capi_v2_query_result.cpp:1697:2
    #7 0x557f51f08749 in Catch::TestCase::invoke() const /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/test/../third_party/catch/catch.hpp:14418:15
    #8 0x557f51f08749 in Catch::RunContext::invokeActiveTestCase() /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/test/../third_party/catch/catch.hpp:13169:27
    #9 0x557f51f01b3f in Catch::RunContext::runCurrentTest(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&) /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/test/../third_party/catch/catch.hpp:13142:17
    #10 0x557f51efed69 in Catch::RunContext::runTest(Catch::TestCase const&) /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/test/../third_party/catch/catch.hpp:12887:13
    #11 0x557f51f11cd5 in Catch::(anonymous namespace)::TestGroup::execute() /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/test/../third_party/catch/catch.hpp:13596:45
    #12 0x557f51f11cd5 in Catch::Session::runInternal() /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/test/../third_party/catch/catch.hpp:13811:39
    #13 0x557f51f0f45a in Catch::Session::run() /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/test/../third_party/catch/catch.hpp:13767:24
    #14 0x557f51f526f6 in main /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/test/unittest.cpp:86:32
    #15 0x7f8ed25441c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #16 0x7f8ed254428a in __libc_start_main csu/../csu/libc-start.c:360:3
    #17 0x557f51112e74 in _start (/home/runner/work/duckdb-capi-v2/duckdb-capi-v2/build/relassert/test/unittest+0x883e74) (BuildId: 6f82002c4c1ef4cea3d354d552a4d76d97f4a8cf)

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/runner/work/duckdb-capi-v2/duckdb-capi-v2/src/include/duckdb/transaction/transaction_context.hpp:67:10

reproduce:
build/relassert/test/unittest 'V2: result_wait after interrupt is clean,V2: result_fetch_chunk drains a CHANGED_ROWS result,V2: an undrained result survives disconnect and close,V2: PIVOT expands to a group and streams the pivoted rows,V2: ALTER with a non-constant DEFAULT expands and executes fully,V2: result_drain runs an expanded group to completion,V2: query-backed PRAGMA reparses at connection_query,V2: an error inside an expanded group is sticky and rolls back,V2: interrupt during an expanded group cancels and rolls back,V2: destroying a half-executed expanded group is clean'

The test path basically calls GetAutoRollback() while an autocommit transaction was active but no BEGIN was executed yet, and UBSan flagged the invalid bool load (190).

I ran a test with Valgrind on my Linux box to confirm the leak:

CREATE TABLE t(i INTEGER PRIMARY KEY);
INSERT INTO t VALUES (1);
INSERT INTO t VALUES (1);  -- Constraint error
SELECT count(*) FROM t;  -- Calls GetAutoRollback

@evertlammerts
evertlammerts marked this pull request as ready for review June 17, 2026 14:10
@evertlammerts
evertlammerts force-pushed the fix-transaction-context-uninit-members branch from 86b8a18 to 8b23eea Compare June 17, 2026 14:10
@Mytherin
Mytherin added this pull request to the merge queue Jun 17, 2026
@Mytherin

Copy link
Copy Markdown
Member

Merged via the queue into duckdb:main with commit 38e33b3 Jun 17, 2026
52 checks passed
@evertlammerts
evertlammerts deleted the fix-transaction-context-uninit-members branch July 21, 2026 09:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants