Fix obscure MDB_MULTIPLE bug

If a key has a single existing value, and then a put (MDB_MULTIPLE)
is done where the first of the multiple values matches the existing
value, the put would return SUCCESS without writing any of the
values. Fixed to loop to the next value as intended.
vmware
Howard Chu 11 years ago
parent 76f8b77e36
commit 5a5d33ff33
  1. 18
      libraries/liblmdb/mdb.c

@ -5653,9 +5653,16 @@ more:
mc->mc_dbx->md_dcmp = mdb_cmp_cint; mc->mc_dbx->md_dcmp = mdb_cmp_cint;
#endif #endif
#endif #endif
/* if data matches, ignore it */ /* if data matches, skip it */
if (!mc->mc_dbx->md_dcmp(data, &dkey)) if (!mc->mc_dbx->md_dcmp(data, &dkey)) {
return (flags == MDB_NODUPDATA) ? MDB_KEYEXIST : MDB_SUCCESS; if (flags == MDB_NODUPDATA)
rc = MDB_KEYEXIST;
else if (flags & MDB_MULTIPLE)
goto next_mult;
else
rc = MDB_SUCCESS;
return rc;
}
/* create a fake page for the dup items */ /* create a fake page for the dup items */
memcpy(dbuf, dkey.mv_data, dkey.mv_size); memcpy(dbuf, dkey.mv_data, dkey.mv_size);
@ -5936,15 +5943,16 @@ put_sub:
mc->mc_db->md_entries++; mc->mc_db->md_entries++;
if (flags & MDB_MULTIPLE) { if (flags & MDB_MULTIPLE) {
if (!rc) { if (!rc) {
next_mult:
mcount++; mcount++;
/* let caller know how many succeeded, if any */
data[1].mv_size = mcount;
if (mcount < dcount) { if (mcount < dcount) {
data[0].mv_data = (char *)data[0].mv_data + data[0].mv_size; data[0].mv_data = (char *)data[0].mv_data + data[0].mv_size;
leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
goto more; goto more;
} }
} }
/* let caller know how many succeeded, if any */
data[1].mv_size = mcount;
} }
} }
done: done:

Loading…
Cancel
Save