[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: (ITS#8447) LMDB: Overwriting values in MDB_DUPSORT databases broken
- To: openldap-its@OpenLDAP.org
- Subject: Re: (ITS#8447) LMDB: Overwriting values in MDB_DUPSORT databases broken
- From: hyc@symas.com
- Date: Mon, 20 Jun 2016 23:35:26 +0000
- Auto-submitted: auto-generated (OpenLDAP-ITS)
lukaswhl@gmail.com wrote:
> Full_Name: Lukas W
> Version: mdb.master c367c1f69685a4d307acb8cea6945c1d67e1cc7e
> OS: Linux
> URL: ftp://ftp.openldap.org/incoming/
> Submission from: (NULL) (114.23.231.86)
>
>
> Replacing values in sub-databases (with MDB_DUPSORT) can lead to the new data's
> length being ignored. This specific example reproduces the problem (creating the
> entries "1"->"ABC", and "1"->2a2abc"):
>
> [â?¦]
> mdb_dbi_open(txn, NULL, MDB_DUPSORT, &dbi);
> key.mv_size = 2;
> key.mv_data = "1";
> data.mv_size = 4;
> data.mv_data = "ABC";
> mdb_put(txn, dbi, &key, &data, 0);
> data.mv_data = "abc";
> mdb_put(txn, dbi, &key, &data, 0);
>
> If one later tries to change a value of one of the existing entries, the new
> value is being copied, but the size is not changed. This could lead to database
> corruption if the new value is longer than the old one as the length of the new
> value is used in memcpy.
>
> key.mv_ze % = 2;
> key.mv_data = "1";
> data.mv_size = 4;
> data.mv_data = "abc";
> mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH);
>
> data.mv_size = 2;
> data.mv_data = "Q";
> mdb_cursor_put(cursor, &key, &data, MDB_CURRENT);
This is a misuse of MDB_CURRENT: as documented, the new value is supposed to
be the same size as the existing value.
>
> mdb_cursor_get(cursor, &key, &data, MDB_GET_CURRENT);
> printf("%s (%d)\n", data.mv_size);
>
> This will output "Q (4)", while it should output "Q (2)". Note that the data in
> the DB probably is "Q\0c", printf just stops at the null character.
> The value is written in mdb.c:7516. Context:
>
> [â?¦]
> /* same size, just replace it. Note that we could
> * also reuse this node if the new data is smaller,
> * but instead we opt to shrink the node in that case.
> */
> if (F_ISSET(flags, MDB_RESERVE))
> data->mv_data = olddata.mv_data;
> else if (!(mc->mc_flags & C_SUB))
> memcpy(olddata.mv_data, data->mv_data, data->mv_size);
> else {
> 7516: memcpy(NODEKEY(leaf), key->mv_data, key->mv_size);
> goto fix_parent;
> }
> [â?¦]
>
>
>
--
-- Howard Chu
CTO, Symas Corp. http://www.symas.com
Director, Highland Sun http://highlandsun.com/hyc/
Chief Architect, OpenLDAP http://www.openldap.org/project/