ITS#8181 Verify that records are/aren't DBs.

Except we don't catch the user passing F_SUBDATA to
mdb_cursor_<put/del>, like an internal LMDB call.
vl32b
Hallvard Furuseth 10 years ago
parent 749633e48a
commit 45e405528b
  1. 14
      libraries/liblmdb/lmdb.h
  2. 17
      libraries/liblmdb/mdb.c

@ -421,7 +421,14 @@ typedef enum MDB_cursor_op {
#define MDB_PAGE_FULL (-30786) #define MDB_PAGE_FULL (-30786)
/** Database contents grew beyond environment mapsize */ /** Database contents grew beyond environment mapsize */
#define MDB_MAP_RESIZED (-30785) #define MDB_MAP_RESIZED (-30785)
/** MDB_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed */ /** Operation and DB incompatible, or DB type changed. This can mean:
* <ul>
* <li>The operation expects an #MDB_DUPSORT / #MDB_DUPFIXED database.
* <li>Opening a named DB when the unnamed DB has #MDB_DUPSORT / #MDB_INTEGERKEY.
* <li>Accessing a data record as a database, or vice versa.
* <li>The database was dropped and recreated with different flags.
* </ul>
*/
#define MDB_INCOMPATIBLE (-30784) #define MDB_INCOMPATIBLE (-30784)
/** Invalid reuse of reader locktable slot */ /** Invalid reuse of reader locktable slot */
#define MDB_BAD_RSLOT (-30783) #define MDB_BAD_RSLOT (-30783)
@ -1057,8 +1064,9 @@ int mdb_txn_renew(MDB_txn *txn);
* any other transaction in the process may use this function. * any other transaction in the process may use this function.
* *
* To use named databases (with name != NULL), #mdb_env_set_maxdbs() * To use named databases (with name != NULL), #mdb_env_set_maxdbs()
* must be called before opening the environment. Database names * must be called before opening the environment. Database names are
* are kept as keys in the unnamed database. * keys in the unnamed database, and may be read but not written.
*
* @param[in] txn A transaction handle returned by #mdb_txn_begin() * @param[in] txn A transaction handle returned by #mdb_txn_begin()
* @param[in] name The name of the database to open. If only a single * @param[in] name The name of the database to open. If only a single
* database is needed in the environment, this value may be NULL. * database is needed in the environment, this value may be NULL.

@ -3519,7 +3519,8 @@ mdb_txn_commit(MDB_txn *txn)
goto fail; goto fail;
} }
data.mv_data = &txn->mt_dbs[i]; data.mv_data = &txn->mt_dbs[i];
rc = mdb_cursor_put(&mc, &txn->mt_dbxs[i].md_name, &data, 0); rc = mdb_cursor_put(&mc, &txn->mt_dbxs[i].md_name, &data,
F_SUBDATA);
if (rc) if (rc)
goto fail; goto fail;
} }
@ -5413,6 +5414,8 @@ mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags)
&mc->mc_dbx->md_name, &exact); &mc->mc_dbx->md_name, &exact);
if (!exact) if (!exact)
return MDB_NOTFOUND; return MDB_NOTFOUND;
if ((leaf->mn_flags & (F_DUPDATA|F_SUBDATA)) != F_SUBDATA)
return MDB_INCOMPATIBLE; /* not a named DB */
rc = mdb_node_read(mc->mc_txn, leaf, &data); rc = mdb_node_read(mc->mc_txn, leaf, &data);
if (rc) if (rc)
return rc; return rc;
@ -6604,6 +6607,9 @@ prep_subDB:
goto new_sub; goto new_sub;
} }
current: current:
/* LMDB passes F_SUBDATA in 'flags' to write a DB record */
if ((leaf->mn_flags ^ flags) & F_SUBDATA)
return MDB_INCOMPATIBLE;
/* overflow page overwrites need special handling */ /* overflow page overwrites need special handling */
if (F_ISSET(leaf->mn_flags, F_BIGDATA)) { if (F_ISSET(leaf->mn_flags, F_BIGDATA)) {
MDB_page *omp; MDB_page *omp;
@ -6874,6 +6880,11 @@ mdb_cursor_del(MDB_cursor *mc, unsigned int flags)
goto fail; goto fail;
} }
} }
/* LMDB passes F_SUBDATA in 'flags' to delete a DB record */
else if ((leaf->mn_flags ^ flags) & F_SUBDATA) {
rc = MDB_INCOMPATIBLE;
goto fail;
}
/* add overflow pages to free list */ /* add overflow pages to free list */
if (F_ISSET(leaf->mn_flags, F_BIGDATA)) { if (F_ISSET(leaf->mn_flags, F_BIGDATA)) {
@ -9358,7 +9369,7 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *db
if (rc == MDB_SUCCESS) { if (rc == MDB_SUCCESS) {
/* make sure this is actually a DB */ /* make sure this is actually a DB */
MDB_node *node = NODEPTR(mc.mc_pg[mc.mc_top], mc.mc_ki[mc.mc_top]); MDB_node *node = NODEPTR(mc.mc_pg[mc.mc_top], mc.mc_ki[mc.mc_top]);
if (!(node->mn_flags & F_SUBDATA)) if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) != F_SUBDATA)
return MDB_INCOMPATIBLE; return MDB_INCOMPATIBLE;
} else if (rc == MDB_NOTFOUND && (flags & MDB_CREATE)) { } else if (rc == MDB_NOTFOUND && (flags & MDB_CREATE)) {
/* Create if requested */ /* Create if requested */
@ -9554,7 +9565,7 @@ int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
/* Can't delete the main DB */ /* Can't delete the main DB */
if (del && dbi > MAIN_DBI) { if (del && dbi > MAIN_DBI) {
rc = mdb_del0(txn, MAIN_DBI, &mc->mc_dbx->md_name, NULL, 0); rc = mdb_del0(txn, MAIN_DBI, &mc->mc_dbx->md_name, NULL, F_SUBDATA);
if (!rc) { if (!rc) {
txn->mt_dbflags[dbi] = DB_STALE; txn->mt_dbflags[dbi] = DB_STALE;
mdb_dbi_close(txn->mt_env, dbi); mdb_dbi_close(txn->mt_env, dbi);

Loading…
Cancel
Save