From f97552a83abb085bc44b1b578e550d64c1313a4b Mon Sep 17 00:00:00 2001 From: Hallvard Furuseth Date: Tue, 19 Feb 2013 22:02:37 +0100 Subject: [PATCH] Check DB flags when refreshing a stale MDB DBI. It's hairy to figure out when a DBI is valid. Catch destructive user errors, and flags which another process changed under us. --- libraries/liblmdb/lmdb.h | 4 +++- libraries/liblmdb/mdb.c | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/liblmdb/lmdb.h b/libraries/liblmdb/lmdb.h index b91de4d..5b6ff6e 100644 --- a/libraries/liblmdb/lmdb.h +++ b/libraries/liblmdb/lmdb.h @@ -362,7 +362,9 @@ typedef enum MDB_cursor_op { #define MDB_PAGE_FULL (-30786) /** Database contents grew beyond environment mapsize */ #define MDB_MAP_RESIZED (-30785) -#define MDB_LAST_ERRCODE MDB_MAP_RESIZED + /** Operation is incompatible with database */ +#define MDB_INCOMPATIBLE (-30784) +#define MDB_LAST_ERRCODE MDB_INCOMPATIBLE /** @} */ /** @brief Statistics for a database in the environment */ diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index c9dc1a5..f1b7480 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -1056,6 +1056,7 @@ static char *const mdb_errstr[] = { "MDB_CURSOR_FULL: Internal error - cursor stack limit reached", "MDB_PAGE_FULL: Internal error - page has no more space", "MDB_MAP_RESIZED: Database contents grew beyond environment mapsize", + "MDB_INCOMPATIBLE: Operation is incompatible with database", }; char * @@ -4056,6 +4057,12 @@ mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags) if (!exact) return MDB_NOTFOUND; mdb_node_read(mc->mc_txn, leaf, &data); + /* The txn may not know this DBI, or another process may + * have dropped and recreated the DB with other flags. + */ + if (mc->mc_db->md_flags != *(uint16_t *) + ((char *) data.mv_data + offsetof(MDB_db, md_flags))) + return MDB_INCOMPATIBLE; memcpy(mc->mc_db, data.mv_data, sizeof(MDB_db)); } if (flags & MDB_PS_MODIFY)