Full_Name: Markus Junginger Version: mdb.master OS: Ubuntu URL: ftp://ftp.openldap.org/incoming/ Submission from: (NULL) (77.190.230.93)
Read cursors may outlive a transaction to be renewed with another. Thus, cursors should be correctly closed even after their last transaction was aborted. But they access the (already freed) transaction during closing when MDB_VL32 is used (mdb.master branch).
ASan captures this like this: ==19722==ERROR: AddressSanitizer: heap-use-after-free on address 0x61100001b140 at pc 0x000000ea2387 bp 0x7ffd36e3cd20 sp 0x7ffd36e3cd18 READ of size 8 at 0x61100001b140 thread T0 #0 0xea2386 in mdb_cursor_unref mdb.c:2082:18 #1 0xec577b in mdb_cursor_close mdb.c:8538:3
0x61100001b140 is located 128 bytes inside of 250-byte region [0x61100001b0c0,0x61100001b1ba) freed by thread T0 here: #0 0x74f840 in __interceptor_cfree.localalias.0 (...) #1 0xe8ea98 in mdb_txn_end mdb.c:3380:3 #2 0xe8ecc5 in mdb_txn_abort mdb.c:3405:2
Possible fix for line mdb.c:2082 (applying what I found in mdb_cursor_close): - if (mc->mc_txn->mt_rpages[0].mid) { + if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_rpages[0].mid) {
Code to reproduce using MDB_VL32: err = mdb_txn_begin(env, nullptr, MDB_RDONLY, &tx); err = mdb_cursor_open(tx, dbi, &cursor); // We must have data so get will set C_INITIALIZED err = mdb_cursor_get(cursor, &key, &value, MDB_SET_KEY); mdb_txn_abort(tx); mdb_cursor_close(cursor); // <- still uses tx