https://bugs.openldap.org/show_bug.cgi?id=9723
Issue ID: 9723 Summary: C_EOF not reset in mdb_cursor_get with MDB_FIRST_DUP Product: LMDB Version: unspecified Hardware: All OS: All Status: UNCONFIRMED Keywords: needs_review Severity: normal Priority: --- Component: liblmdb Assignee: bugs@openldap.org Reporter: stephan.j.bircher@gmail.com Target Milestone: ---
I'm on the master branch of lmdb.
Steps to reproduce
// search for an non-existent key rc = mdb_cursor_get(cursor, &key, &val, MDB_SET_RANGE); if (rc == MDB_NOTFOUND) { // C_EOF is not set on the cursor flags
// go to the last. // C_EOF remains set which is ok mdb_cursor_get(mdbCursor, &key, &val, MDB_LAST);
// go to the first dup of the last // C_EOF remains set which is NOT OK mdb_cursor_get(mdbCursor, &key, &val, MDB_FIRST_DUP);
// return MDB_NOTFOUND in any case whether there are duplicates or not // because C_EOF was not cleared mdb_cursor_get(mdbCursor, &key, &val, MDB_NEXT_NODUP); }
Possible fix:
case MDB_FIRST_DUP: mfunc = mdb_cursor_first; mmove: if (data == NULL || !(mc->mc_flags & C_INITIALIZED)) { rc = EINVAL; break; } if (mc->mc_xcursor == NULL) { rc = MDB_INCOMPATIBLE; break; } if (mc->mc_ki[mc->mc_top] >= NUMKEYS(mc->mc_pg[mc->mc_top])) { mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]); rc = MDB_NOTFOUND; break; } { MDB_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) { MDB_GET_KEY(leaf, key); rc = mdb_node_read(mc, leaf, data); break; } } if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) { rc = EINVAL; break; } rc = mfunc(&mc->mc_xcursor->mx_cursor, data, NULL); // FIX: clear C_EOF if (rc == MDB_SUCCESS && mc->mc_flags & C_EOF && mfunc == mdb_cursor_first) { mc->mc_flags ^= C_EOF; } break;