mirror of
https://github.com/isar/libmdbx.git
synced 2025-02-01 07:48:21 +08:00
mdbx: fix/refine mdbx_walk_tree() for working with invalid/corrupted DB.
Change-Id: I2594b785f675319027ff129d12683c4392e6e2f4
This commit is contained in:
parent
e762442917
commit
73647a5e46
58
src/core.c
58
src/core.c
@ -17750,12 +17750,12 @@ static MDBX_page_type_t walk_page_type(const MDBX_page *mp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Depth-first tree traversal. */
|
/* Depth-first tree traversal. */
|
||||||
static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, pgno_t pgno,
|
static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, const pgno_t pgno,
|
||||||
const char *name, int deep,
|
const char *name, int deep,
|
||||||
txnid_t parent_txnid) {
|
txnid_t parent_txnid) {
|
||||||
assert(pgno != P_INVALID);
|
assert(pgno != P_INVALID);
|
||||||
MDBX_page *mp = nullptr;
|
MDBX_page *mp = nullptr;
|
||||||
int err = mdbx_page_get(ctx->mw_cursor, pgno, &mp, NULL, parent_txnid);
|
int rc, err = mdbx_page_get(ctx->mw_cursor, pgno, &mp, NULL, parent_txnid);
|
||||||
if (err == MDBX_SUCCESS)
|
if (err == MDBX_SUCCESS)
|
||||||
err = mdbx_page_check(ctx->mw_cursor, mp, 0);
|
err = mdbx_page_check(ctx->mw_cursor, mp, 0);
|
||||||
|
|
||||||
@ -17772,19 +17772,21 @@ static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, pgno_t pgno,
|
|||||||
payload_size;
|
payload_size;
|
||||||
size_t align_bytes = 0;
|
size_t align_bytes = 0;
|
||||||
|
|
||||||
/* LY: Don't use mask here, e.g bitwise
|
if (err == MDBX_SUCCESS) {
|
||||||
* (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP).
|
/* LY: Don't use mask here, e.g bitwise
|
||||||
* Pages should not me marked dirty/loose or otherwise. */
|
* (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP).
|
||||||
switch (mp->mp_flags) {
|
* Pages should not me marked dirty/loose or otherwise. */
|
||||||
default:
|
switch (mp->mp_flags) {
|
||||||
err = MDBX_CORRUPTED;
|
default:
|
||||||
break;
|
|
||||||
case P_BRANCH:
|
|
||||||
if (unlikely(nentries < 2))
|
|
||||||
err = MDBX_CORRUPTED;
|
err = MDBX_CORRUPTED;
|
||||||
case P_LEAF:
|
break;
|
||||||
case P_LEAF | P_LEAF2:
|
case P_BRANCH:
|
||||||
break;
|
if (unlikely(nentries < 2))
|
||||||
|
err = MDBX_CORRUPTED;
|
||||||
|
case P_LEAF:
|
||||||
|
case P_LEAF | P_LEAF2:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; err == MDBX_SUCCESS && i < nentries;
|
for (int i = 0; err == MDBX_SUCCESS && i < nentries;
|
||||||
@ -17833,9 +17835,11 @@ static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, pgno_t pgno,
|
|||||||
|
|
||||||
pagesize = pgno2bytes(ctx->mw_txn->mt_env, npages);
|
pagesize = pgno2bytes(ctx->mw_txn->mt_env, npages);
|
||||||
const size_t over_unused = pagesize - over_payload - over_header;
|
const size_t over_unused = pagesize - over_payload - over_header;
|
||||||
err = ctx->mw_visitor(large_pgno, npages, ctx->mw_user, deep, name,
|
rc = ctx->mw_visitor(large_pgno, npages, ctx->mw_user, deep, name,
|
||||||
pagesize, MDBX_page_large, err, 1, over_payload,
|
pagesize, MDBX_page_large, err, 1, over_payload,
|
||||||
over_header, over_unused);
|
over_header, over_unused);
|
||||||
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return (rc == MDBX_RESULT_TRUE) ? MDBX_SUCCESS : rc;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case F_SUBDATA /* sub-db */: {
|
case F_SUBDATA /* sub-db */: {
|
||||||
@ -17893,10 +17897,11 @@ static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, pgno_t pgno,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err =
|
rc = ctx->mw_visitor(pgno, 0, ctx->mw_user, deep + 1, name, node_ds(node),
|
||||||
ctx->mw_visitor(pgno, 0, ctx->mw_user, deep + 1, name, node_ds(node),
|
subtype, err, nsubkeys, subpayload_size,
|
||||||
subtype, err, nsubkeys, subpayload_size,
|
subheader_size, subunused_size + subalign_bytes);
|
||||||
subheader_size, subunused_size + subalign_bytes);
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
return (rc == MDBX_RESULT_TRUE) ? MDBX_SUCCESS : rc;
|
||||||
header_size += subheader_size;
|
header_size += subheader_size;
|
||||||
unused_size += subunused_size;
|
unused_size += subunused_size;
|
||||||
payload_size += subpayload_size;
|
payload_size += subpayload_size;
|
||||||
@ -17908,12 +17913,11 @@ static int __cold mdbx_walk_tree(mdbx_walk_ctx_t *ctx, pgno_t pgno,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx->mw_visitor(mp->mp_pgno, 1, ctx->mw_user, deep, name,
|
rc = ctx->mw_visitor(pgno, 1, ctx->mw_user, deep, name,
|
||||||
ctx->mw_txn->mt_env->me_psize, type, err, nentries,
|
ctx->mw_txn->mt_env->me_psize, type, err, nentries,
|
||||||
payload_size, header_size, unused_size + align_bytes);
|
payload_size, header_size, unused_size + align_bytes);
|
||||||
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
if (unlikely(err != MDBX_SUCCESS))
|
return (rc == MDBX_RESULT_TRUE) ? MDBX_SUCCESS : rc;
|
||||||
return (err == MDBX_RESULT_TRUE) ? MDBX_SUCCESS : err;
|
|
||||||
|
|
||||||
for (int i = 0; err == MDBX_SUCCESS && i < nentries; i++) {
|
for (int i = 0; err == MDBX_SUCCESS && i < nentries; i++) {
|
||||||
if (type == MDBX_page_dupfixed_leaf)
|
if (type == MDBX_page_dupfixed_leaf)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user