Full_Name: Hallvard B Furuseth Version: master, d235778c71a50da91741b8b17c572a44b143831b OS: Linux x86_64 URL: Submission from: (NULL) (193.69.163.163) Submitted by: hallvard
mdb_cursor_put() can return MDB_SUCCESS with mc.mc_flags == 0. mdb_cursor_del() requires mc.mc_flags & C_INITIALIZED. mdb_txn_commit() can call _del() which fails after _put() succeeds, at the /* was completely used up */ case.
This breaks slapadd -l frontier.ldif (without -q) at ada.openldap.org, at "uid=smithhehehe,ou=people,dc=frontiernet,dc=net" (line=527182). Config ~hallvard/frontiercf.ldif.
Or to trigger it a lot quicker, insert assert(rc || (mc->mc_flags & C_INITIALIZED)); before 'done:' in mdb_cursor_put(). I'm guessing that is required, since ldbm.h says _put() positions the cursor at the newly inserted item. Or is that only when _inserting_ a new item, not _modifying_ an existing one?
The mdb_cursor_del() check for C_INITIALIZED is incorrect, it is evaluated as if ((!mc->mc_flags) & C_INITIALIZED). Maybe that's why this has not been caught before. Same with the test in mdb_cursor_get case MDB_GET_CURRENT.