From 5a5d33ff330aaf7c630174dcd65b914783e2f8e4 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Sun, 11 Aug 2013 17:15:03 -0700 Subject: [PATCH] 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. --- libraries/liblmdb/mdb.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 9b8b675..c1f0d03 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -5653,9 +5653,16 @@ more: mc->mc_dbx->md_dcmp = mdb_cmp_cint; #endif #endif - /* if data matches, ignore it */ - if (!mc->mc_dbx->md_dcmp(data, &dkey)) - return (flags == MDB_NODUPDATA) ? MDB_KEYEXIST : MDB_SUCCESS; + /* if data matches, skip it */ + if (!mc->mc_dbx->md_dcmp(data, &dkey)) { + 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 */ memcpy(dbuf, dkey.mv_data, dkey.mv_size); @@ -5936,15 +5943,16 @@ put_sub: mc->mc_db->md_entries++; if (flags & MDB_MULTIPLE) { if (!rc) { +next_mult: mcount++; + /* let caller know how many succeeded, if any */ + data[1].mv_size = mcount; if (mcount < dcount) { 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]); goto more; } } - /* let caller know how many succeeded, if any */ - data[1].mv_size = mcount; } } done: