mdbx: more checks mdbx_read_header() for metapage's content.

This commit is contained in:
Leo Yuriev 2017-05-26 17:25:08 +03:00
parent 1c170cb866
commit 93c5a84bcd

View File

@ -3292,52 +3292,118 @@ static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *meta) {
const unsigned offset = guess_pagesize * meta_number; const unsigned offset = guess_pagesize * meta_number;
int rc = mdbx_pread(env->me_fd, &page, sizeof(page), offset); int rc = mdbx_pread(env->me_fd, &page, sizeof(page), offset);
if (rc != MDBX_SUCCESS) { if (rc != MDBX_SUCCESS) {
mdbx_debug("read meta[%u,%u]: %i, %s", offset, (unsigned)sizeof(page), rc, mdbx_error("read meta[%u,%u]: %i, %s", offset, (unsigned)sizeof(page), rc,
mdbx_strerror(rc)); mdbx_strerror(rc));
return rc; return rc;
} }
if (page.mp_pgno != meta_number) { if (page.mp_pgno != meta_number) {
mdbx_debug("meta[%u] has invalid pageno %" PRIaPGNO, meta_number, mdbx_error("meta[%u] has invalid pageno %" PRIaPGNO, meta_number,
page.mp_pgno); page.mp_pgno);
return MDBX_INVALID; return MDBX_INVALID;
} }
if (!F_ISSET(page.mp_flags, P_META)) { if (!F_ISSET(page.mp_flags, P_META)) {
mdbx_debug("page #%u not a meta-page", meta_number); mdbx_error("page #%u not a meta-page", meta_number);
return MDBX_INVALID; return MDBX_INVALID;
} }
if (page.mp_meta.mm_magic != MDBX_MAGIC) { if (page.mp_meta.mm_magic != MDBX_MAGIC) {
mdbx_debug("meta[%u] has invalid magic", meta_number); mdbx_error("meta[%u] has invalid magic", meta_number);
return MDBX_INVALID; return MDBX_INVALID;
} }
if (page.mp_meta.mm_version != MDBX_DATA_VERSION) { if (page.mp_meta.mm_version != MDBX_DATA_VERSION) {
mdbx_debug("database is version %u, expected version %u", mdbx_error("database is version %u, expected version %u",
page.mp_meta.mm_version, MDBX_DATA_VERSION); page.mp_meta.mm_version, MDBX_DATA_VERSION);
return MDBX_VERSION_MISMATCH; return MDBX_VERSION_MISMATCH;
} }
/* LY: check pagesize */ /* LY: check pagesize */
STATIC_ASSERT(MIN_PAGESIZE < MAX_PAGESIZE);
if (!is_power2(page.mp_meta.mm_psize) || if (!is_power2(page.mp_meta.mm_psize) ||
page.mp_meta.mm_psize < MIN_PAGESIZE || page.mp_meta.mm_psize < MIN_PAGESIZE ||
page.mp_meta.mm_psize > MAX_PAGESIZE) { page.mp_meta.mm_psize > MAX_PAGESIZE) {
mdbx_debug("meta[%u] has invalid pagesize %u", meta_number, mdbx_notice("meta[%u] has invalid pagesize %u, skip it", meta_number,
page.mp_meta.mm_psize); page.mp_meta.mm_psize);
continue; continue;
} }
/* LY: check mapsize limits */
STATIC_ASSERT(MAX_MAPSIZE < SSIZE_MAX - MAX_PAGESIZE);
STATIC_ASSERT(MIN_MAPSIZE < MAX_MAPSIZE);
if (page.mp_meta.mm_mapsize < MIN_MAPSIZE ||
page.mp_meta.mm_mapsize > MAX_MAPSIZE) {
mdbx_notice("meta[%u] has invalid mapsize %" PRIu64 ", skip it",
meta_number, page.mp_meta.mm_mapsize);
continue;
}
/* LY: check signature as a checksum */ /* LY: check signature as a checksum */
if (META_IS_STEADY(&page.mp_meta) && if (META_IS_STEADY(&page.mp_meta) &&
page.mp_meta.mm_datasync_sign != mdbx_meta_sign(&page.mp_meta)) { page.mp_meta.mm_datasync_sign != mdbx_meta_sign(&page.mp_meta)) {
mdbx_debug("meta[%u] has invalid steady-checksum (0x%" PRIx64 mdbx_notice("meta[%u] has invalid steady-checksum (0x%" PRIx64
" != 0x%" PRIx64 ")", " != 0x%" PRIx64 "), skip it",
meta_number, page.mp_meta.mm_datasync_sign, meta_number, page.mp_meta.mm_datasync_sign,
mdbx_meta_sign(&page.mp_meta)); mdbx_meta_sign(&page.mp_meta));
continue; continue;
} }
/* LY: check mapsize with given given pagesize */
if (page.mp_meta.mm_mapsize <
MIN_PAGENO * (uint64_t)page.mp_meta.mm_psize ||
page.mp_meta.mm_mapsize >
MAX_PAGENO * (uint64_t)page.mp_meta.mm_psize) {
mdbx_notice("meta[%u] has invalid mapsize %" PRIu64
", with given pagesize %u, skip it",
meta_number, page.mp_meta.mm_mapsize, page.mp_meta.mm_psize);
continue;
}
/* LY: check last_pgno */
if (page.mp_meta.mm_last_pg < MIN_PAGENO ||
page.mp_meta.mm_last_pg > MAX_PAGENO ||
page.mp_meta.mm_last_pg >
page.mp_meta.mm_mapsize / page.mp_meta.mm_psize) {
mdbx_notice("meta[%u] has invalid last-pageno %" PRIaPGNO ", skip it",
meta_number, page.mp_meta.mm_last_pg);
continue;
}
/* LY: FreeDB root */
if (page.mp_meta.mm_dbs[FREE_DBI].md_root == P_INVALID) {
if (page.mp_meta.mm_dbs[FREE_DBI].md_branch_pages ||
page.mp_meta.mm_dbs[FREE_DBI].md_depth ||
page.mp_meta.mm_dbs[FREE_DBI].md_entries ||
page.mp_meta.mm_dbs[FREE_DBI].md_leaf_pages ||
page.mp_meta.mm_dbs[FREE_DBI].md_overflow_pages) {
mdbx_notice("meta[%u] has false-empty freedb, skip it", meta_number);
continue;
}
} else if (page.mp_meta.mm_dbs[FREE_DBI].md_root >
page.mp_meta.mm_last_pg) {
mdbx_notice("meta[%u] has invalid freedb-root %" PRIaPGNO ", skip it",
meta_number, page.mp_meta.mm_dbs[FREE_DBI].md_root);
continue;
}
/* LY: MainDB root */
if (page.mp_meta.mm_dbs[MAIN_DBI].md_root == P_INVALID) {
if (page.mp_meta.mm_dbs[MAIN_DBI].md_branch_pages ||
page.mp_meta.mm_dbs[MAIN_DBI].md_depth ||
page.mp_meta.mm_dbs[MAIN_DBI].md_entries ||
page.mp_meta.mm_dbs[MAIN_DBI].md_leaf_pages ||
page.mp_meta.mm_dbs[MAIN_DBI].md_overflow_pages) {
mdbx_notice("meta[%u] has false-empty maindb", meta_number);
continue;
}
} else if (page.mp_meta.mm_dbs[MAIN_DBI].md_root >
page.mp_meta.mm_last_pg) {
mdbx_notice("meta[%u] has invalid maindb-root %" PRIaPGNO ", skip it",
meta_number, page.mp_meta.mm_dbs[MAIN_DBI].md_root);
continue;
}
if (mdbx_meta_ot(meta, &page.mp_meta, true)) { if (mdbx_meta_ot(meta, &page.mp_meta, true)) {
*meta = page.mp_meta; *meta = page.mp_meta;
if (META_IS_WEAK(meta)) if (META_IS_WEAK(meta))
@ -3346,7 +3412,7 @@ static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *meta) {
} }
if (META_IS_WEAK(meta)) { if (META_IS_WEAK(meta)) {
mdbx_debug("both meta-pages are weak, database is corrupted"); mdbx_error("no usable meta-pages, database is corrupted");
return MDBX_CORRUPTED; return MDBX_CORRUPTED;
} }