mdbx: check zero-size of the first key on a branch-page.

Change-Id: I2be86ea79f04ea8baea92a6e56ef6b22691eeda0
This commit is contained in:
Leonid Yuriev 2021-03-23 04:33:56 +03:00
parent 3c389d17e8
commit 72f3a2fc3f

View File

@ -15081,6 +15081,7 @@ static void mdbx_node_del(MDBX_cursor *mc, size_t ksize) {
} }
node = page_node(mp, indx); node = page_node(mp, indx);
mdbx_cassert(mc, !IS_BRANCH(mp) || indx || node_ks(node) == 0);
size_t sz = NODESIZE + node_ks(node); size_t sz = NODESIZE + node_ks(node);
if (IS_LEAF(mp)) { if (IS_LEAF(mp)) {
if (F_ISSET(node_flags(node), F_BIGDATA)) if (F_ISSET(node_flags(node), F_BIGDATA))
@ -16593,48 +16594,49 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
const MDBX_node *const node = page_node(mp, i); const MDBX_node *const node = page_node(mp, i);
const char *node_end = (char *)node + NODESIZE; const char *node_end = (char *)node + NODESIZE;
if (unlikely(node_end > end_of_page)) { if (unlikely(node_end > end_of_page)) {
rc = bad_page(mp, "node (%zu) beyond page-end\n", rc = bad_page(mp, "node[%u] (%zu) beyond page-end\n", i,
node_end - end_of_page); node_end - end_of_page);
continue; continue;
} }
if (IS_LEAF(mp) || i > 0) { size_t ksize = node_ks(node);
size_t ksize = node_ks(node); char *key = node_key(node);
char *key = node_key(node); if (unlikely(end_of_page < key + ksize)) {
if (unlikely(end_of_page < key + ksize)) { rc = bad_page(mp, "node[%u] key (%zu) beyond page-end\n", i,
rc = bad_page(mp, "node-key (%zu) beyond page-end\n", key + ksize - end_of_page);
key + ksize - end_of_page); continue;
continue; }
} if ((IS_LEAF(mp) || i > 0) && (options & C_COPYING) == 0) {
if (unlikely(ksize < mc->mc_dbx->md_klen_min ||
if ((options & C_COPYING) == 0) { ksize > mc->mc_dbx->md_klen_max))
if (unlikely(ksize < mc->mc_dbx->md_klen_min || rc = bad_page(
ksize > mc->mc_dbx->md_klen_max)) mp, "node[%u] key size (%zu) <> min/max key-length (%zu/%zu)\n",
rc = bad_page( i, ksize, mc->mc_dbx->md_klen_min, mc->mc_dbx->md_klen_max);
mp, "node-key size (%zu) <> min/max key-length (%zu/%zu)\n", if ((options & C_SKIPORD) == 0) {
ksize, mc->mc_dbx->md_klen_min, mc->mc_dbx->md_klen_max); here.iov_base = key;
here.iov_len = ksize;
if ((options & C_SKIPORD) == 0) { if (prev.iov_base && unlikely(mc->mc_dbx->md_cmp(&here, &prev) <= 0))
here.iov_base = key; rc = bad_page(mp, "node[%u] key wrong order\n", i);
here.iov_len = ksize; prev = here;
if (prev.iov_base &&
unlikely(mc->mc_dbx->md_cmp(&here, &prev) <= 0))
rc = bad_page(mp, "node-key #%u wrong order\n", i);
prev = here;
}
} }
} }
if (IS_BRANCH(mp)) { if (IS_BRANCH(mp)) {
if ((options & C_UPDATING) == 0 && i == 0 && unlikely(ksize != 0))
rc = bad_page(mp, "branch-node[%u] wrong 0-node key-length (%zu)\n",
i, ksize);
if ((options & C_RETIRING) == 0) { if ((options & C_RETIRING) == 0) {
const pgno_t ref = node_pgno(node); const pgno_t ref = node_pgno(node);
if (unlikely(ref < MIN_PAGENO || ref >= mc->mc_txn->mt_next_pgno)) if (unlikely(ref < MIN_PAGENO || ref >= mc->mc_txn->mt_next_pgno))
rc = bad_page(mp, "branch-node wrong pgno (%u)\n", ref); rc = bad_page(mp, "branch-node[%u] wrong pgno (%u)\n", i, ref);
} }
if (unlikely(node_flags(node)))
rc = bad_page(mp, "branch-node[%u] wrong flags (%u)\n", i,
node_flags(node));
continue; continue;
} }
switch (node_flags(node)) { switch (node_flags(node)) {
default: default:
rc = bad_page(mp, "invalid node flags (%u)\n", node_flags(node)); rc = bad_page(mp, "invalid node[%u] flags (%u)\n", i, node_flags(node));
break; break;
case F_BIGDATA /* data on large-page */: case F_BIGDATA /* data on large-page */:
case 0 /* usual */: case 0 /* usual */: