mdbx: add bad_page().

Change-Id: I5233e4a701ee11fd59d7083576f40f7df3068ddd
This commit is contained in:
Leonid Yuriev 2020-09-02 13:19:36 +03:00
parent f0de3ff098
commit 6e339fc849
2 changed files with 109 additions and 116 deletions

View File

@ -581,6 +581,23 @@ number_of_ovpages(const MDBX_env *env, size_t bytes) {
return bytes2pgno(env, PAGEHDRSZ - 1 + bytes) + 1; return bytes2pgno(env, PAGEHDRSZ - 1 + bytes) + 1;
} }
__cold static int bad_page(const MDBX_page *mp, const char *fmt, ...) {
if (mdbx_log_enabled(MDBX_LOG_ERROR)) {
static const MDBX_page *prev;
if (prev != mp) {
prev = mp;
mdbx_debug_log(MDBX_LOG_ERROR, "badpage", 0, "#%u, page-txnid %zu\n",
mp->mp_pgno, mp->mp_txnid);
}
va_list args;
va_start(args, fmt);
mdbx_debug_log_va(MDBX_LOG_ERROR, "badpage", 0, fmt, args);
va_end(args);
}
return MDBX_CORRUPTED;
}
/* Address of node i in page p */ /* Address of node i in page p */
__nothrow_pure_function static __always_inline MDBX_node * __nothrow_pure_function static __always_inline MDBX_node *
page_node(const MDBX_page *mp, unsigned i) { page_node(const MDBX_page *mp, unsigned i) {
@ -3350,11 +3367,8 @@ const char *mdbx_strerror_ANSI2OEM(int errnum) {
} }
#endif /* Bit of madness for Windows */ #endif /* Bit of madness for Windows */
void __cold mdbx_debug_log(int level, const char *function, int line, void __cold mdbx_debug_log_va(int level, const char *function, int line,
const char *fmt, ...) { const char *fmt, va_list args) {
va_list args;
va_start(args, fmt);
if (mdbx_debug_logger) if (mdbx_debug_logger)
mdbx_debug_logger(level, function, line, fmt, args); mdbx_debug_logger(level, function, line, fmt, args);
else { else {
@ -3390,6 +3404,13 @@ void __cold mdbx_debug_log(int level, const char *function, int line,
fflush(stderr); fflush(stderr);
#endif #endif
} }
}
void __cold mdbx_debug_log(int level, const char *function, int line,
const char *fmt, ...) {
va_list args;
va_start(args, fmt);
mdbx_debug_log_va(level, function, line, fmt, args);
va_end(args); va_end(args);
} }
@ -10860,7 +10881,7 @@ __hot static int mdbx_page_get(MDBX_cursor *mc, pgno_t pgno, MDBX_page **ret,
int *lvl, const txnid_t pp_txnid) { int *lvl, const txnid_t pp_txnid) {
MDBX_txn *txn = mc->mc_txn; MDBX_txn *txn = mc->mc_txn;
if (unlikely(pgno >= txn->mt_next_pgno)) { if (unlikely(pgno >= txn->mt_next_pgno)) {
mdbx_debug("page %" PRIaPGNO " not found", pgno); mdbx_error("page %" PRIaPGNO " beyond next-pgno", pgno);
goto corrupted; goto corrupted;
} }
@ -10894,16 +10915,17 @@ spilled:
dirty: dirty:
if (unlikely(p->mp_pgno != pgno)) { if (unlikely(p->mp_pgno != pgno)) {
mdbx_error("mismatch pgno %" PRIaPGNO " (actual) != %" PRIaPGNO bad_page(p,
" (expected)", "mismatch pgno %" PRIaPGNO " (actual) != %" PRIaPGNO " (expected)",
p->mp_pgno, pgno); p->mp_pgno, pgno);
goto corrupted; goto corrupted;
} }
if (unlikely(p->mp_txnid > if (unlikely(p->mp_txnid >
((p->mp_flags & P_DIRTY) ? UINT64_MAX : parentpage_txnid))) { ((p->mp_flags & P_DIRTY) ? UINT64_MAX : parentpage_txnid))) {
mdbx_error("invalid page's txnid %" PRIaTXN "> %" PRIaTXN " of parent page", bad_page(p,
p->mp_txnid, parentpage_txnid); "invalid page's txnid %" PRIaTXN "> %" PRIaTXN " of parent page",
p->mp_txnid, parentpage_txnid);
goto corrupted; goto corrupted;
} }
@ -10916,8 +10938,8 @@ dirty:
((p->mp_lower | p->mp_upper) & 1) != 0 || ((p->mp_lower | p->mp_upper) & 1) != 0 ||
PAGEHDRSZ + p->mp_upper > env->me_psize) && PAGEHDRSZ + p->mp_upper > env->me_psize) &&
!IS_OVERFLOW(p))) { !IS_OVERFLOW(p))) {
mdbx_error("invalid page lower(%u)/upper(%u), pg-limit %u", p->mp_lower, bad_page(p, "invalid page lower(%u)/upper(%u), pg-limit %u", p->mp_lower,
p->mp_upper, page_space(env)); p->mp_upper, page_space(env));
goto corrupted; goto corrupted;
} }
@ -11004,9 +11026,9 @@ __hot static int mdbx_page_search_root(MDBX_cursor *mc, const MDBX_val *key,
} }
if (unlikely(!IS_LEAF(mp))) { if (unlikely(!IS_LEAF(mp))) {
mdbx_error("index points to a page with 0x%02x flags", mp->mp_flags);
mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; mc->mc_txn->mt_flags |= MDBX_TXN_ERROR;
return MDBX_CORRUPTED; return bad_page(mp, "index points to a page with 0x%02x flags",
mp->mp_flags);
} }
mdbx_debug("found leaf page %" PRIaPGNO " for key [%s]", mp->mp_pgno, mdbx_debug("found leaf page %" PRIaPGNO " for key [%s]", mp->mp_pgno,
@ -14626,30 +14648,22 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
const unsigned nkeys = page_numkeys(mp); const unsigned nkeys = page_numkeys(mp);
char *const end_of_page = (char *)mp + env->me_psize; char *const end_of_page = (char *)mp + env->me_psize;
mdbx_assert(env, mp->mp_pgno >= MIN_PAGENO && mp->mp_pgno <= MAX_PAGENO); mdbx_assert(env, mp->mp_pgno >= MIN_PAGENO && mp->mp_pgno <= MAX_PAGENO);
if (unlikely(mp->mp_pgno < MIN_PAGENO || mp->mp_pgno > MAX_PAGENO)) { if (unlikely(mp->mp_pgno < MIN_PAGENO || mp->mp_pgno > MAX_PAGENO))
mdbx_error("invalid pgno %u", mp->mp_pgno); return bad_page(mp, "invalid pgno %u", mp->mp_pgno);
return MDBX_CORRUPTED;
}
if (IS_OVERFLOW(mp)) { if (IS_OVERFLOW(mp)) {
mdbx_assert(env, mp->mp_pages >= 1 && mp->mp_pages < MAX_PAGENO / 2); mdbx_assert(env, mp->mp_pages >= 1 && mp->mp_pages < MAX_PAGENO / 2);
if (unlikely(mp->mp_pages < 1 && mp->mp_pages >= MAX_PAGENO / 2)) { if (unlikely(mp->mp_pages < 1 && mp->mp_pages >= MAX_PAGENO / 2))
mdbx_error("invalid overflow n-pages %u", mp->mp_pages); return bad_page(mp, "invalid overflow n-pages %u", mp->mp_pages);
return MDBX_CORRUPTED;
}
mdbx_assert(env, mp->mp_pgno <= MAX_PAGENO - mp->mp_pages); mdbx_assert(env, mp->mp_pgno <= MAX_PAGENO - mp->mp_pages);
if (unlikely(mp->mp_pgno > mc->mc_txn->mt_next_pgno - mp->mp_pages)) { if (unlikely(mp->mp_pgno > mc->mc_txn->mt_next_pgno - mp->mp_pages))
mdbx_error("overflow page %u beyond next-pgno", return bad_page(mp, "overflow page %u beyond next-pgno",
mp->mp_pgno + mp->mp_pages); mp->mp_pgno + mp->mp_pages);
return MDBX_CORRUPTED;
}
return MDBX_SUCCESS; return MDBX_SUCCESS;
} }
if ((options & C_UPDATING) == 0 || !IS_DIRTY(mp)) { if ((options & C_UPDATING) == 0 || !IS_DIRTY(mp)) {
mdbx_assert(env, nkeys >= 2 || !IS_BRANCH(mp)); mdbx_assert(env, nkeys >= 2 || !IS_BRANCH(mp));
if (unlikely(nkeys < 2 && IS_BRANCH(mp))) { if (unlikely(nkeys < 2 && IS_BRANCH(mp)))
mdbx_error("branch-page %u nkey < 2", nkeys); return bad_page(mp, "branch-page %u nkey < 2", nkeys);
return MDBX_CORRUPTED;
}
} }
int rc = MDBX_SUCCESS; int rc = MDBX_SUCCESS;
@ -14660,8 +14674,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
char *const key = page_leaf2key(mp, i, ksize); char *const key = page_leaf2key(mp, i, ksize);
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); rc = bad_page(mp, "leaf2-key %zu beyond page-end",
rc = MDBX_CORRUPTED; key + ksize - end_of_page);
continue; continue;
} }
@ -14671,9 +14685,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, ksize <= mc->mc_dbx->md_klen_max); mdbx_assert(env, ksize <= mc->mc_dbx->md_klen_max);
if (unlikely(ksize < mc->mc_dbx->md_klen_min || if (unlikely(ksize < mc->mc_dbx->md_klen_min ||
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", rc = bad_page(
ksize); mp, "leaf2-key %zu size < klen_min || size > klen_max", ksize);
rc = MDBX_CORRUPTED;
continue; 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;
@ -14683,10 +14696,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
here.iov_base = key; here.iov_base = key;
if (prev.iov_base) { if (prev.iov_base) {
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); rc = bad_page(mp, "leaf2-key #%u wrong order", i);
rc = MDBX_CORRUPTED;
}
} }
prev = here; prev = here;
} }
@ -14696,8 +14707,7 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
const char *node_end = (char *)node + NODESIZE; const char *node_end = (char *)node + NODESIZE;
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); rc = bad_page(mp, "node %zu beyond page-end", node_end - end_of_page);
rc = MDBX_CORRUPTED;
continue; continue;
} }
if (IS_LEAF(mp) || i > 0) { if (IS_LEAF(mp) || i > 0) {
@ -14705,8 +14715,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
char *key = node_key(node); char *key = node_key(node);
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); rc = bad_page(mp, "node-key %zu beyond page-end",
rc = MDBX_CORRUPTED; key + ksize - end_of_page);
continue; continue;
} }
@ -14715,9 +14725,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, ksize <= mc->mc_dbx->md_klen_max); mdbx_assert(env, ksize <= mc->mc_dbx->md_klen_max);
if (unlikely(ksize < mc->mc_dbx->md_klen_min || if (unlikely(ksize < mc->mc_dbx->md_klen_min ||
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", rc = bad_page(mp, "node-key %zu size < klen_min || size > klen_max",
ksize); ksize);
rc = MDBX_CORRUPTED;
continue; continue;
} }
@ -14726,10 +14735,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
here.iov_len = ksize; here.iov_len = ksize;
if (prev.iov_base) { if (prev.iov_base) {
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); rc = bad_page(mp, "node-key #%u wrong order", i);
rc = MDBX_CORRUPTED;
}
} }
prev = here; prev = here;
} }
@ -14740,18 +14747,15 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
const pgno_t ref = node_pgno(node); const pgno_t ref = node_pgno(node);
mdbx_assert(env, ref >= MIN_PAGENO); mdbx_assert(env, ref >= MIN_PAGENO);
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); rc = bad_page(mp, "branch-node wrong pgno %u", ref);
rc = MDBX_CORRUPTED;
}
} }
continue; continue;
} }
switch (node_flags(node)) { switch (node_flags(node)) {
default: default:
mdbx_error("invalid node flags %u", node_flags(node)); rc = bad_page(mp, "invalid node flags %u", node_flags(node));
rc = MDBX_CORRUPTED;
break; break;
case F_BIGDATA /* data on large-page */: { case F_BIGDATA /* data on large-page */: {
const size_t dsize = node_ds(node); const size_t dsize = node_ds(node);
@ -14760,9 +14764,9 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, dsize <= mc->mc_dbx->md_vlen_max); mdbx_assert(env, dsize <= mc->mc_dbx->md_vlen_max);
if (unlikely(dsize <= mc->mc_dbx->md_vlen_min || if (unlikely(dsize <= mc->mc_dbx->md_vlen_min ||
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", rc = bad_page(
dsize); mp, "big-node data %zu size <= vlen_min || size >= vlen_max",
rc = MDBX_CORRUPTED; dsize);
continue; continue;
} }
} }
@ -14775,15 +14779,14 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, IS_OVERFLOW(lp)); mdbx_assert(env, IS_OVERFLOW(lp));
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); rc = bad_page(mp, "big-node refs to non-overflow page %u",
rc = MDBX_CORRUPTED; lp->mp_pgno);
continue; 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", rc = bad_page(mp,
dsize, lp->mp_pages); "big-node size %zu mismatch overflow npagse size %u",
rc = MDBX_CORRUPTED; dsize, lp->mp_pages);
}
} }
} }
continue; continue;
@ -14798,8 +14801,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
const char *const data = node_data(node); const char *const data = node_data(node);
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); rc = bad_page(mp, "node-data[%u of %u] %zu beyond page end", i, nkeys,
rc = MDBX_CORRUPTED; data + dsize - end_of_page);
continue; continue;
} }
@ -14813,9 +14816,9 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, dsize <= mc->mc_dbx->md_vlen_max); mdbx_assert(env, dsize <= mc->mc_dbx->md_vlen_max);
if (unlikely(dsize < mc->mc_dbx->md_vlen_min || if (unlikely(dsize < mc->mc_dbx->md_vlen_min ||
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", rc = bad_page(mp,
dsize); "node-data %zu size <= vlen_min || size >= vlen_max",
rc = MDBX_CORRUPTED; dsize);
continue; continue;
} }
} }
@ -14823,24 +14826,21 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
case F_SUBDATA /* sub-db */: case F_SUBDATA /* sub-db */:
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); rc = bad_page(mp, "invalid sub-db record size %zu", dsize);
rc = MDBX_CORRUPTED;
continue; 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); rc = bad_page(mp, "invalid nested-db record size %zu", dsize);
rc = MDBX_CORRUPTED;
continue; 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); rc = bad_page(mp, "invalid nested-page record size %zu", dsize);
rc = MDBX_CORRUPTED;
continue; continue;
} else { } else {
const MDBX_page *const sp = (MDBX_page *)data; const MDBX_page *const sp = (MDBX_page *)data;
@ -14852,8 +14852,7 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
break; break;
default: default:
mdbx_assert(env, false); mdbx_assert(env, false);
mdbx_error("invalid nested-page flags %u", sp->mp_flags); rc = bad_page(mp, "invalid nested-page flags %u", sp->mp_flags);
rc = MDBX_CORRUPTED;
continue; continue;
} }
@ -14865,9 +14864,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
char *sub_key = page_leaf2key(sp, j, sub_ksize); char *sub_key = page_leaf2key(sp, j, sub_ksize);
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-leaf2-key %zu beyond nested-page", rc = bad_page(mp, "nested-leaf2-key %zu beyond nested-page",
sub_key + sub_ksize - end_of_subpage); sub_key + sub_ksize - end_of_subpage);
rc = MDBX_CORRUPTED;
continue; continue;
} }
@ -14877,10 +14875,11 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, sub_ksize <= mc->mc_dbx->md_vlen_max); mdbx_assert(env, sub_ksize <= mc->mc_dbx->md_vlen_max);
if (unlikely(sub_ksize < mc->mc_dbx->md_vlen_min || if (unlikely(sub_ksize < mc->mc_dbx->md_vlen_min ||
sub_ksize > mc->mc_dbx->md_vlen_max)) { sub_ksize > mc->mc_dbx->md_vlen_max)) {
mdbx_error("nested-leaf2-key %zu size < vlen_min || size > " rc = bad_page(
"vlen_max", mp,
sub_ksize); "nested-leaf2-key %zu size < vlen_min || size > "
rc = MDBX_CORRUPTED; "vlen_max",
sub_ksize);
continue; 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;
@ -14892,10 +14891,8 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, mdbx_assert(env,
mc->mc_dbx->md_dcmp(&sub_prev, &sub_here) < 0); mc->mc_dbx->md_dcmp(&sub_prev, &sub_here) < 0);
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); rc = bad_page(mp, "nested-leaf2-key #%u wrong order", j);
rc = MDBX_CORRUPTED;
}
} }
sub_prev = sub_here; sub_prev = sub_here;
} }
@ -14905,16 +14902,14 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
const char *sub_node_end = (char *)sub_node + NODESIZE; const char *sub_node_end = (char *)sub_node + NODESIZE;
mdbx_assert(env, sub_node_end <= end_of_subpage); mdbx_assert(env, sub_node_end <= end_of_subpage);
if (unlikely(sub_node_end > end_of_subpage)) { if (unlikely(sub_node_end > end_of_subpage)) {
mdbx_error("nested-node %zu beyond nested-page", rc = bad_page(mp, "nested-node %zu beyond nested-page",
end_of_subpage - sub_node_end); end_of_subpage - sub_node_end);
rc = MDBX_CORRUPTED;
continue; 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", rc = bad_page(mp, "nested-node invalid flags %u",
node_flags(sub_node)); node_flags(sub_node));
rc = MDBX_CORRUPTED;
continue; continue;
} }
@ -14928,10 +14923,10 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mdbx_assert(env, sub_ksize <= mc->mc_dbx->md_vlen_max); mdbx_assert(env, sub_ksize <= mc->mc_dbx->md_vlen_max);
if (unlikely(sub_ksize < mc->mc_dbx->md_vlen_min || if (unlikely(sub_ksize < mc->mc_dbx->md_vlen_min ||
sub_ksize > mc->mc_dbx->md_vlen_max)) { sub_ksize > mc->mc_dbx->md_vlen_max)) {
mdbx_error( rc = bad_page(
mp,
"nested-node-key %zu size < vlen_min || size > vlen_max", "nested-node-key %zu size < vlen_min || size > vlen_max",
sub_ksize); sub_ksize);
rc = MDBX_CORRUPTED;
continue; continue;
} }
@ -14943,8 +14938,7 @@ static __cold int mdbx_page_check(MDBX_cursor *const mc,
mc->mc_dbx->md_dcmp(&sub_prev, &sub_here) < 0); mc->mc_dbx->md_dcmp(&sub_prev, &sub_here) < 0);
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); rc = bad_page(mp, "nested-node-key #%u wrong order", j);
rc = MDBX_CORRUPTED;
continue; continue;
} }
} }
@ -14953,23 +14947,21 @@ 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); rc = bad_page(mp, "nested-node non-empty data size %zu",
rc = MDBX_CORRUPTED; sub_dsize);
continue; 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", rc = bad_page(mp, "nested-node-key %zu beyond nested-page",
sub_key + sub_ksize - end_of_subpage); sub_key + sub_ksize - end_of_subpage);
rc = MDBX_CORRUPTED;
continue; 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", rc = bad_page(mp, "nested-node-data %zu beyond nested-page",
sub_data + sub_dsize - end_of_subpage); sub_data + sub_dsize - end_of_subpage);
rc = MDBX_CORRUPTED;
continue; continue;
} }
} }
@ -15557,8 +15549,7 @@ static int mdbx_page_split(MDBX_cursor *mc, const MDBX_val *newkey,
rc = mdbx_node_add_leaf2(mc, 0, newkey); rc = mdbx_node_add_leaf2(mc, 0, newkey);
} break; } break;
default: default:
mdbx_error("wrong page-type %u", PAGETYPE(rp)); rc = bad_page(rp, "wrong page-type %u", PAGETYPE(rp));
rc = MDBX_CORRUPTED;
} }
if (rc) if (rc)
goto done; goto done;
@ -15615,8 +15606,7 @@ static int mdbx_page_split(MDBX_cursor *mc, const MDBX_val *newkey,
rc = mdbx_node_add_leaf2(mc, n, &rkey); rc = mdbx_node_add_leaf2(mc, n, &rkey);
} break; */ } break; */
default: default:
mdbx_error("wrong page-type %u", PAGETYPE(rp)); rc = bad_page(rp, "wrong page-type %u", PAGETYPE(rp));
rc = MDBX_CORRUPTED;
} }
if (rc) if (rc)
goto done; goto done;

View File

@ -1037,9 +1037,12 @@ extern uint8_t mdbx_runtime_flags;
extern uint8_t mdbx_loglevel; extern uint8_t mdbx_loglevel;
extern MDBX_debug_func *mdbx_debug_logger; extern MDBX_debug_func *mdbx_debug_logger;
MDBX_INTERNAL_FUNC void mdbx_debug_log(int type, const char *function, int line, MDBX_INTERNAL_FUNC void mdbx_debug_log(int level, const char *function,
const char *fmt, ...) int line, const char *fmt, ...)
__printf_args(4, 5); __printf_args(4, 5);
MDBX_INTERNAL_FUNC void mdbx_debug_log_va(int level, const char *function,
int line, const char *fmt,
va_list args);
#if MDBX_DEBUG #if MDBX_DEBUG