[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: (ITS#8447) LMDB: Overwriting values in MDB_DUPSORT databases broken



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/