mdbx: continued page-check.

Change-Id: Id4aa37284a12f49e359a6c9391d2fd5b6acb2ad0
This commit is contained in:
Leonid Yuriev 2020-09-02 03:49:14 +03:00
parent d6645f84f2
commit f0de3ff098

View File

@ -14652,6 +14652,7 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
} }
} }
int rc = MDBX_SUCCESS;
MDBX_val here, prev = {0, 0}; MDBX_val here, prev = {0, 0};
for (unsigned i = 0; i < nkeys; ++i) { for (unsigned i = 0; i < nkeys; ++i) {
if (IS_LEAF2(mp)) { if (IS_LEAF2(mp)) {
@ -14660,7 +14661,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, key + ksize <= end_of_page); mdbx_assert(env, key + ksize <= end_of_page);
if (unlikely(end_of_page < key + ksize)) { if (unlikely(end_of_page < key + ksize)) {
mdbx_error("leaf2-key %zu beyond page-end", key + ksize - end_of_page); mdbx_error("leaf2-key %zu beyond page-end", key + ksize - end_of_page);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
if ((options & C_COPYING) == 0) { if ((options & C_COPYING) == 0) {
@ -14671,7 +14673,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
ksize > mc->mc_dbx->md_klen_max)) { ksize > mc->mc_dbx->md_klen_max)) {
mdbx_error("leaf2-key %zu size < klen_min || size > klen_max", mdbx_error("leaf2-key %zu size < klen_min || size > klen_max",
ksize); ksize);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
mc->mc_dbx->md_klen_min = mc->mc_dbx->md_klen_max = ksize; mc->mc_dbx->md_klen_min = mc->mc_dbx->md_klen_max = ksize;
} }
@ -14682,7 +14685,7 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, mc->mc_dbx->md_cmp(&here, &prev) > 0); mdbx_assert(env, mc->mc_dbx->md_cmp(&here, &prev) > 0);
if (unlikely(mc->mc_dbx->md_cmp(&here, &prev) <= 0)) { if (unlikely(mc->mc_dbx->md_cmp(&here, &prev) <= 0)) {
mdbx_error("leaf2-key #%u wrong order", i); mdbx_error("leaf2-key #%u wrong order", i);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
} }
} }
prev = here; prev = here;
@ -14694,7 +14697,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, node_end <= end_of_page); mdbx_assert(env, node_end <= end_of_page);
if (unlikely(node_end > end_of_page)) { if (unlikely(node_end > end_of_page)) {
mdbx_error("node %zu beyond page-end", node_end - end_of_page); mdbx_error("node %zu beyond page-end", node_end - end_of_page);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
if (IS_LEAF(mp) || i > 0) { if (IS_LEAF(mp) || i > 0) {
size_t ksize = node_ks(node); size_t ksize = node_ks(node);
@ -14702,7 +14706,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, key + ksize <= end_of_page); mdbx_assert(env, key + ksize <= end_of_page);
if (unlikely(end_of_page < key + ksize)) { if (unlikely(end_of_page < key + ksize)) {
mdbx_error("node-key %zu beyond page-end", key + ksize - end_of_page); mdbx_error("node-key %zu beyond page-end", key + ksize - end_of_page);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
if ((options & C_COPYING) == 0) { if ((options & C_COPYING) == 0) {
@ -14712,7 +14717,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
ksize > mc->mc_dbx->md_klen_max)) { ksize > mc->mc_dbx->md_klen_max)) {
mdbx_error("node-key %zu size < klen_min || size > klen_max", mdbx_error("node-key %zu size < klen_min || size > klen_max",
ksize); ksize);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
if ((options & C_SKIPORD) == 0) { if ((options & C_SKIPORD) == 0) {
@ -14722,7 +14728,7 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, mc->mc_dbx->md_cmp(&here, &prev) > 0); mdbx_assert(env, mc->mc_dbx->md_cmp(&here, &prev) > 0);
if (unlikely(mc->mc_dbx->md_cmp(&here, &prev) <= 0)) { if (unlikely(mc->mc_dbx->md_cmp(&here, &prev) <= 0)) {
mdbx_error("node-key #%u wrong order", i); mdbx_error("node-key #%u wrong order", i);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
} }
} }
prev = here; prev = here;
@ -14736,12 +14742,18 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, ref < mc->mc_txn->mt_next_pgno); mdbx_assert(env, ref < mc->mc_txn->mt_next_pgno);
if (unlikely(ref < MIN_PAGENO || ref >= mc->mc_txn->mt_next_pgno)) { if (unlikely(ref < MIN_PAGENO || ref >= mc->mc_txn->mt_next_pgno)) {
mdbx_error("branch-node wrong pgno %u", ref); mdbx_error("branch-node wrong pgno %u", ref);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
} }
} }
continue; continue;
} }
if (node_flags(node) == F_BIGDATA /* data on large-page */) {
switch (node_flags(node)) {
default:
mdbx_error("invalid node flags %u", node_flags(node));
rc = MDBX_CORRUPTED;
break;
case F_BIGDATA /* data on large-page */: {
const size_t dsize = node_ds(node); const size_t dsize = node_ds(node);
if ((options & C_COPYING) == 0) { if ((options & C_COPYING) == 0) {
mdbx_assert(env, dsize > mc->mc_dbx->md_vlen_min); mdbx_assert(env, dsize > mc->mc_dbx->md_vlen_min);
@ -14750,7 +14762,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
dsize > mc->mc_dbx->md_vlen_max)) { dsize > mc->mc_dbx->md_vlen_max)) {
mdbx_error("big-node data %zu size <= vlen_min || size >= vlen_max", mdbx_error("big-node data %zu size <= vlen_min || size >= vlen_max",
dsize); dsize);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
} }
if ((options & C_RETIRING) == 0) { if ((options & C_RETIRING) == 0) {
@ -14763,15 +14776,22 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, number_of_ovpages(env, dsize) == lp->mp_pages); mdbx_assert(env, number_of_ovpages(env, dsize) == lp->mp_pages);
if (unlikely(!IS_OVERFLOW(lp))) { if (unlikely(!IS_OVERFLOW(lp))) {
mdbx_error("big-node refs to non-overflow page %u", lp->mp_pgno); mdbx_error("big-node refs to non-overflow page %u", lp->mp_pgno);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
if (unlikely(number_of_ovpages(env, dsize) != lp->mp_pages)) { if (unlikely(number_of_ovpages(env, dsize) != lp->mp_pages)) {
mdbx_error("big-node size %zu mismatch overflow npagse size %u", mdbx_error("big-node size %zu mismatch overflow npagse size %u",
dsize, lp->mp_pages); dsize, lp->mp_pages);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
}
} }
} }
continue; continue;
case 0 /* usual */:
case F_SUBDATA /* sub-db */:
case F_SUBDATA | F_DUPDATA /* dupsorted sub-tree */:
case F_DUPDATA /* short sub-page */:
break;
} }
const size_t dsize = node_ds(node); const size_t dsize = node_ds(node);
@ -14779,14 +14799,14 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, data + dsize <= end_of_page); mdbx_assert(env, data + dsize <= end_of_page);
if (unlikely(end_of_page < data + dsize)) { if (unlikely(end_of_page < data + dsize)) {
mdbx_error("node-data %zu beyond page end", data + dsize - end_of_page); mdbx_error("node-data %zu beyond page end", data + dsize - end_of_page);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
switch (node_flags(node)) { switch (node_flags(node)) {
default: default:
mdbx_assert(env, false); /* wrong, but already handled */
mdbx_error("invalid node flags %u", node_flags(node)); continue;
return MDBX_CORRUPTED;
case 0 /* usual */: case 0 /* usual */:
if ((options & C_COPYING) == 0) { if ((options & C_COPYING) == 0) {
mdbx_assert(env, dsize >= mc->mc_dbx->md_vlen_min); mdbx_assert(env, dsize >= mc->mc_dbx->md_vlen_min);
@ -14795,7 +14815,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
dsize > mc->mc_dbx->md_vlen_max)) { dsize > mc->mc_dbx->md_vlen_max)) {
mdbx_error("node-data %zu size <= vlen_min || size >= vlen_max", mdbx_error("node-data %zu size <= vlen_min || size >= vlen_max",
dsize); dsize);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
} }
break; break;
@ -14803,21 +14824,24 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, dsize >= sizeof(MDBX_db)); mdbx_assert(env, dsize >= sizeof(MDBX_db));
if (unlikely(dsize < sizeof(MDBX_db))) { if (unlikely(dsize < sizeof(MDBX_db))) {
mdbx_error("invalid sub-db record size %zu", dsize); mdbx_error("invalid sub-db record size %zu", dsize);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
break; break;
case F_SUBDATA | F_DUPDATA /* dupsorted sub-tree */: case F_SUBDATA | F_DUPDATA /* dupsorted sub-tree */:
mdbx_assert(env, dsize == sizeof(MDBX_db)); mdbx_assert(env, dsize == sizeof(MDBX_db));
if (unlikely(dsize != sizeof(MDBX_db))) { if (unlikely(dsize != sizeof(MDBX_db))) {
mdbx_error("invalid nested-db record size %zu", dsize); mdbx_error("invalid nested-db record size %zu", dsize);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
break; break;
case F_DUPDATA /* short sub-page */: case F_DUPDATA /* short sub-page */:
mdbx_assert(env, dsize > PAGEHDRSZ); mdbx_assert(env, dsize > PAGEHDRSZ);
if (unlikely(dsize <= PAGEHDRSZ)) { if (unlikely(dsize <= PAGEHDRSZ)) {
mdbx_error("invalid nested-page record size %zu", dsize); mdbx_error("invalid nested-page record size %zu", dsize);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} else { } else {
const MDBX_page *const sp = (MDBX_page *)data; const MDBX_page *const sp = (MDBX_page *)data;
const char *const end_of_subpage = data + dsize; const char *const end_of_subpage = data + dsize;
@ -14829,7 +14853,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
default: default:
mdbx_assert(env, false); mdbx_assert(env, false);
mdbx_error("invalid nested-page flags %u", sp->mp_flags); mdbx_error("invalid nested-page flags %u", sp->mp_flags);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
MDBX_val sub_here, sub_prev = {0, 0}; MDBX_val sub_here, sub_prev = {0, 0};
@ -14842,7 +14867,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
if (unlikely(end_of_subpage < sub_key + sub_ksize)) { if (unlikely(end_of_subpage < sub_key + sub_ksize)) {
mdbx_error("nested-leaf2-key %zu beyond nested-page", mdbx_error("nested-leaf2-key %zu beyond nested-page",
sub_key + sub_ksize - end_of_subpage); sub_key + sub_ksize - end_of_subpage);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
if ((options & C_COPYING) == 0) { if ((options & C_COPYING) == 0) {
@ -14854,7 +14880,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_error("nested-leaf2-key %zu size < vlen_min || size > " mdbx_error("nested-leaf2-key %zu size < vlen_min || size > "
"vlen_max", "vlen_max",
sub_ksize); sub_ksize);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
mc->mc_dbx->md_vlen_min = mc->mc_dbx->md_vlen_max = sub_ksize; mc->mc_dbx->md_vlen_min = mc->mc_dbx->md_vlen_max = sub_ksize;
} }
@ -14867,7 +14894,7 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
if (unlikely(mc->mc_dbx->md_dcmp(&sub_prev, &sub_here) >= if (unlikely(mc->mc_dbx->md_dcmp(&sub_prev, &sub_here) >=
0)) { 0)) {
mdbx_error("nested-leaf2-key #%u wrong order", j); mdbx_error("nested-leaf2-key #%u wrong order", j);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
} }
} }
sub_prev = sub_here; sub_prev = sub_here;
@ -14880,13 +14907,15 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
if (unlikely(sub_node_end > end_of_subpage)) { if (unlikely(sub_node_end > end_of_subpage)) {
mdbx_error("nested-node %zu beyond nested-page", mdbx_error("nested-node %zu beyond nested-page",
end_of_subpage - sub_node_end); end_of_subpage - sub_node_end);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
mdbx_assert(env, node_flags(sub_node) == 0); mdbx_assert(env, node_flags(sub_node) == 0);
if (unlikely(node_flags(sub_node) != 0)) { if (unlikely(node_flags(sub_node) != 0)) {
mdbx_error("nested-node invalid flags %u", mdbx_error("nested-node invalid flags %u",
node_flags(sub_node)); node_flags(sub_node));
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
size_t sub_ksize = node_ks(sub_node); size_t sub_ksize = node_ks(sub_node);
@ -14902,7 +14931,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_error( mdbx_error(
"nested-node-key %zu size < vlen_min || size > vlen_max", "nested-node-key %zu size < vlen_min || size > vlen_max",
sub_ksize); sub_ksize);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
if ((options & C_SKIPORD) == 0) { if ((options & C_SKIPORD) == 0) {
@ -14914,7 +14944,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
if (unlikely(mc->mc_dbx->md_dcmp(&sub_prev, &sub_here) >= if (unlikely(mc->mc_dbx->md_dcmp(&sub_prev, &sub_here) >=
0)) { 0)) {
mdbx_error("nested-node-key #%u wrong order", j); mdbx_error("nested-node-key #%u wrong order", j);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
} }
sub_prev = sub_here; sub_prev = sub_here;
@ -14923,20 +14954,23 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, sub_dsize == 0); mdbx_assert(env, sub_dsize == 0);
if (unlikely(sub_dsize != 0)) { if (unlikely(sub_dsize != 0)) {
mdbx_error("nested-node non-empty data size %zu", sub_dsize); mdbx_error("nested-node non-empty data size %zu", sub_dsize);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
mdbx_assert(env, sub_key + sub_ksize <= end_of_subpage); mdbx_assert(env, sub_key + sub_ksize <= end_of_subpage);
if (unlikely(end_of_subpage < sub_key + sub_ksize)) { if (unlikely(end_of_subpage < sub_key + sub_ksize)) {
mdbx_error("nested-node-key %zu beyond nested-page", mdbx_error("nested-node-key %zu beyond nested-page",
sub_key + sub_ksize - end_of_subpage); sub_key + sub_ksize - end_of_subpage);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
mdbx_assert(env, sub_data + sub_dsize <= end_of_subpage); mdbx_assert(env, sub_data + sub_dsize <= end_of_subpage);
if (unlikely(end_of_subpage < sub_data + sub_dsize)) { if (unlikely(end_of_subpage < sub_data + sub_dsize)) {
mdbx_error("nested-node-data %zu beyond nested-page", mdbx_error("nested-node-data %zu beyond nested-page",
sub_data + sub_dsize - end_of_subpage); sub_data + sub_dsize - end_of_subpage);
return MDBX_CORRUPTED; rc = MDBX_CORRUPTED;
continue;
} }
} }
} }
@ -14945,7 +14979,7 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
} }
} }
} }
return MDBX_SUCCESS; return rc;
} }
static __cold int mdbx_cursor_check(MDBX_cursor *mc, unsigned options) { static __cold int mdbx_cursor_check(MDBX_cursor *mc, unsigned options) {