[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#7701) Deletion triggers SEGV on next access of existing cursor



Full_Name: David Wilson
Version: 919a0f5b54dad3acf2f84e7993bb00e7aa098037
OS: Linux
URL: http://www.h1.botanicus.net/20130919-lmdb.trace.bz2
Submission from: (NULL) (178.238.153.20)


In some circumstances LMDB will segfault in mdb_cursor_get() on a cursor that
existed prior to a deletion that just occurred. It is apparently related to the
page the cursor points to becoming mutated by the deletion.

In LMDB 0.9.8, the issue may manifest as a NULL ptr dereference:

#0 mdb_xcursor_init1 (mc=mc@entry=0x1013da0, node=node@entry=0x7ffd76031ac2) at
lib/mdb.c:6525
#1 0x00007ffff5209b73 in mdb_cursor_next (mc=0x1013da0, key=0xce39a0,
data=data@entry=0xce3660, op=<optimized out>) at lib/mdb.c:5042
#2 0x00007ffff5208a6e in mdb_cursor_get (mc=0x1013da0, key=0xce39a0,
data=0xce3660, op=op@entry=MDB_NEXT) at lib/mdb.c:5526
#3 0x00007ffff5202a83 in _cffi_f_mdb_cursor_get (self=<optimized out>,
args=<optimized out>) at lmdb/__pycache__/lmdb_cffi.c:714
#4 0x0000000000471a8b in call_function (oparg=<optimized out>,
pp_stack=0x7fffffffcf30) at ../Python/ceval.c:4021
#5 PyEval_EvalFrameEx (

Due to F_DUPDATA bit being set as tested on line 5041. Examining the leaf
structure reveals a large chunk of ASCII text (which should have been written to
the DB), interspersed with some integer values.

Versions of LMDB <= 0.9.7 exhibit similar crashes, although in a different
place: "assert(mc)" at the start of mdb_cursor_get().

Various MDB versions going back 6 months were tested, and none exhibited any
better behaviour. In the attached trace/replay, version
c0575825730dd2aab4031100b25d632a3d052447 from April exhibited the bug after only
1993 operations executed from the trace file. Any more recent version requires
the entire trace file to execute before triggering the assert or SEGV.

http://www.h1.botanicus.net/20130919-lmdb.trace.bz2 is a 33MiB trace file that
can be loaded and executed using
https://github.com/dw/acid/blob/master/misc/lmdb-replay.c

The apparent workaround is to reinitialize any existing cursors should a
deletion occur within a transaction, as demonstrated in
https://github.com/dw/acid/commit/56f183c71a668e540df58d5137e946616a446c49