Full_Name: Hallvard B Furuseth
Version: master, d235778c71a50da91741b8b17c572a44b143831b
OS: Linux x86_64
Submission from: (NULL) (18.104.22.168)
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).
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.