| --- a/src/btree/bt_cursor.c |
| +++ b/src/btree/bt_cursor.c |
| @@ -282,6 +282,8 @@ __bamc_refresh(dbc) |
| * |
| * Recno uses the btree bt_ovflsize value -- it's close enough. |
| */ |
| + if (t->bt_minkey == 0) |
| + return (DB_RECOVER); |
| cp->ovflsize = B_MINKEY_TO_OVFLSIZE( |
| dbp, F_ISSET(dbc, DBC_OPD) ? 2 : t->bt_minkey, dbp->pgsize); |
| |
| --- a/src/btree/bt_verify.c |
| +++ b/src/btree/bt_verify.c |
| @@ -611,7 +611,11 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentri |
| isbad = 1; |
| goto err; |
| default: |
| - DB_ASSERT(env, ret != 0); |
| + if (ret == 0) { |
| + isbad = 1; |
| + ret = DB_VERIFY_FATAL; |
| + goto err; |
| + } |
| break; |
| } |
| |
| @@ -922,7 +926,7 @@ __bam_vrfy_itemorder(dbp, vdp, ip, h, pg |
| DBT dbta, dbtb, dup_1, dup_2, *p1, *p2, *tmp; |
| ENV *env; |
| PAGE *child; |
| - db_pgno_t cpgno; |
| + db_pgno_t cpgno, grandparent; |
| VRFY_PAGEINFO *pip; |
| db_indx_t i, *inp; |
| int adj, cmp, freedup_1, freedup_2, isbad, ret, t_ret; |
| @@ -954,7 +958,8 @@ __bam_vrfy_itemorder(dbp, vdp, ip, h, pg |
| |
| buf1 = buf2 = NULL; |
| |
| - DB_ASSERT(env, !LF_ISSET(DB_NOORDERCHK)); |
| + if (LF_ISSET(DB_NOORDERCHK)) |
| + return (EINVAL); |
| |
| dupfunc = (dbp->dup_compare == NULL) ? __bam_defcmp : dbp->dup_compare; |
| if (TYPE(h) == P_LDUP) |
| @@ -963,6 +968,7 @@ __bam_vrfy_itemorder(dbp, vdp, ip, h, pg |
| func = __bam_defcmp; |
| if (dbp->bt_internal != NULL) { |
| bt = (BTREE *)dbp->bt_internal; |
| + grandparent = bt->bt_root; |
| if (TYPE(h) == P_IBTREE && (bt->bt_compare != NULL || |
| dupfunc != __bam_defcmp)) { |
| /* |
| @@ -974,8 +980,24 @@ __bam_vrfy_itemorder(dbp, vdp, ip, h, pg |
| */ |
| mpf = dbp->mpf; |
| child = h; |
| + cpgno = pgno; |
| while (TYPE(child) == P_IBTREE) { |
| + if (NUM_ENT(child) == 0) { |
| + EPRINT((env, DB_STR_A("1088", |
| + "Page %lu: internal page is empty and should not be", |
| + "%lu"), (u_long)cpgno)); |
| + ret = DB_VERIFY_BAD; |
| + goto err; |
| + } |
| bi = GET_BINTERNAL(dbp, child, 0); |
| + if (grandparent == bi->pgno) { |
| + EPRINT((env, DB_STR_A("5552", |
| + "Page %lu: found twice in the btree", |
| + "%lu"), (u_long)grandparent)); |
| + ret = DB_VERIFY_FATAL; |
| + goto err; |
| + } else |
| + grandparent = cpgno; |
| cpgno = bi->pgno; |
| if (child != h && |
| (ret = __memp_fput(mpf, |
| @@ -1231,7 +1253,10 @@ overflow: if (!ovflok) { |
| */ |
| if (dup_1.data == NULL || |
| dup_2.data == NULL) { |
| - DB_ASSERT(env, !ovflok); |
| + if (ovflok) { |
| + isbad = 1; |
| + goto err; |
| + } |
| if (pip != NULL) |
| F_SET(pip, |
| VRFY_INCOMPLETE); |
| @@ -1569,9 +1594,10 @@ bad_prev: isbad = 1; |
| (ret = __db_vrfy_ovfl_structure(dbp, vdp, |
| child->pgno, child->tlen, |
| flags | DB_ST_OVFL_LEAF)) != 0) { |
| - if (ret == DB_VERIFY_BAD) |
| + if (ret == DB_VERIFY_BAD) { |
| isbad = 1; |
| - else |
| + break; |
| + } else |
| goto done; |
| } |
| |
| @@ -1645,9 +1671,10 @@ bad_prev: isbad = 1; |
| stflags | DB_ST_TOPLEVEL, |
| NULL, NULL, NULL)) != 0) { |
| if (ret == |
| - DB_VERIFY_BAD) |
| + DB_VERIFY_BAD) { |
| isbad = 1; |
| - else |
| + break; |
| + } else |
| goto err; |
| } |
| } |
| @@ -1790,7 +1817,10 @@ bad_prev: isbad = 1; |
| */ |
| |
| /* Otherwise, __db_vrfy_childput would be broken. */ |
| - DB_ASSERT(env, child->refcnt >= 1); |
| + if (child->refcnt < 1) { |
| + isbad = 1; |
| + goto err; |
| + } |
| |
| /* |
| * An overflow referenced more than twice here |
| @@ -1807,9 +1837,10 @@ bad_prev: isbad = 1; |
| if ((ret = __db_vrfy_ovfl_structure(dbp, |
| vdp, child->pgno, child->tlen, |
| flags)) != 0) { |
| - if (ret == DB_VERIFY_BAD) |
| + if (ret == DB_VERIFY_BAD) { |
| isbad = 1; |
| - else |
| + break; |
| + } else |
| goto done; |
| } |
| } |
| @@ -1847,9 +1878,10 @@ bad_prev: isbad = 1; |
| if ((ret = __bam_vrfy_subtree(dbp, vdp, li->pgno, |
| i == 0 ? NULL : li, ri, flags, &child_level, |
| &child_nrecs, NULL)) != 0) { |
| - if (ret == DB_VERIFY_BAD) |
| + if (ret == DB_VERIFY_BAD) { |
| isbad = 1; |
| - else |
| + break; |
| + } else |
| goto done; |
| } |
| |
| @@ -2675,7 +2707,11 @@ __bam_meta2pgset(dbp, vdp, btmeta, flags |
| db_pgno_t current, p; |
| int err_ret, ret; |
| |
| - DB_ASSERT(dbp->env, pgset != NULL); |
| + if (pgset == NULL) { |
| + EPRINT((dbp->env, DB_STR("5542", |
| + "Error, database contains no visible pages."))); |
| + return (DB_RUNRECOVERY); |
| + } |
| |
| mpf = dbp->mpf; |
| h = NULL; |
| --- a/src/db/db_conv.c |
| +++ b/src/db/db_conv.c |
| @@ -493,8 +493,11 @@ __db_byteswap(dbp, pg, h, pagesize, pgin |
| db_indx_t i, *inp, len, tmp; |
| u_int8_t *end, *p, *pgend; |
| |
| - if (pagesize == 0) |
| - return (0); |
| + /* This function is also used to byteswap logs, so |
| + * the pagesize might not be an actual page size. |
| + */ |
| + if (!(pagesize >= 24 && pagesize <= DB_MAX_PGSIZE)) |
| + return (EINVAL); |
| |
| if (pgin) { |
| M_32_SWAP(h->lsn.file); |
| @@ -513,26 +516,41 @@ __db_byteswap(dbp, pg, h, pagesize, pgin |
| pgend = (u_int8_t *)h + pagesize; |
| |
| inp = P_INP(dbp, h); |
| - if ((u_int8_t *)inp >= pgend) |
| - goto out; |
| + if ((u_int8_t *)inp > pgend) |
| + return (__db_pgfmt(env, pg)); |
| |
| switch (TYPE(h)) { |
| case P_HASH_UNSORTED: |
| case P_HASH: |
| for (i = 0; i < NUM_ENT(h); i++) { |
| + if ((u_int8_t*)(inp + i) >= pgend) |
| + return (__db_pgfmt(env, pg)); |
| + if (inp[i] == 0) |
| + continue; |
| if (pgin) |
| M_16_SWAP(inp[i]); |
| + if (inp[i] >= pagesize) |
| + return (__db_pgfmt(env, pg)); |
| |
| - if (P_ENTRY(dbp, h, i) >= pgend) |
| - continue; |
| + if (P_ENTRY(dbp, h, i) >= pgend) |
| + return (__db_pgfmt(env, pg)); |
| |
| switch (HPAGE_TYPE(dbp, h, i)) { |
| case H_KEYDATA: |
| break; |
| case H_DUPLICATE: |
| + if (LEN_HITEM(dbp, h, pagesize, i) < |
| + HKEYDATA_SIZE(0)) |
| + return (__db_pgfmt(env, pg)); |
| + |
| len = LEN_HKEYDATA(dbp, h, pagesize, i); |
| p = HKEYDATA_DATA(P_ENTRY(dbp, h, i)); |
| - for (end = p + len; p < end;) { |
| + |
| + end = p + len; |
| + if (end > pgend) |
| + return (__db_pgfmt(env, pg)); |
| + |
| + while (p < end) { |
| if (pgin) { |
| P_16_SWAP(p); |
| memcpy(&tmp, |
| @@ -544,14 +562,20 @@ __db_byteswap(dbp, pg, h, pagesize, pgin |
| SWAP16(p); |
| } |
| p += tmp; |
| + if (p >= end) |
| + return (__db_pgfmt(env, pg)); |
| SWAP16(p); |
| } |
| break; |
| case H_OFFDUP: |
| + if ((inp[i] + HOFFDUP_SIZE) > pagesize) |
| + return (__db_pgfmt(env, pg)); |
| p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i)); |
| SWAP32(p); /* pgno */ |
| break; |
| case H_OFFPAGE: |
| + if ((inp[i] + HOFFPAGE_SIZE) > pagesize) |
| + return (__db_pgfmt(env, pg)); |
| p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i)); |
| SWAP32(p); /* pgno */ |
| SWAP32(p); /* tlen */ |
| @@ -559,7 +583,6 @@ __db_byteswap(dbp, pg, h, pagesize, pgin |
| default: |
| return (__db_pgfmt(env, pg)); |
| } |
| - |
| } |
| |
| /* |
| @@ -576,8 +599,12 @@ __db_byteswap(dbp, pg, h, pagesize, pgin |
| case P_LDUP: |
| case P_LRECNO: |
| for (i = 0; i < NUM_ENT(h); i++) { |
| + if ((u_int8_t *)(inp + i) >= pgend) |
| + return (__db_pgfmt(env, pg)); |
| if (pgin) |
| M_16_SWAP(inp[i]); |
| + if (inp[i] >= pagesize) |
| + return (__db_pgfmt(env, pg)); |
| |
| /* |
| * In the case of on-page duplicates, key information |
| @@ -597,7 +624,7 @@ __db_byteswap(dbp, pg, h, pagesize, pgin |
| |
| bk = GET_BKEYDATA(dbp, h, i); |
| if ((u_int8_t *)bk >= pgend) |
| - continue; |
| + return (__db_pgfmt(env, pg)); |
| switch (B_TYPE(bk->type)) { |
| case B_KEYDATA: |
| M_16_SWAP(bk->len); |
| @@ -605,6 +632,8 @@ __db_byteswap(dbp, pg, h, pagesize, pgin |
| case B_DUPLICATE: |
| case B_OVERFLOW: |
| bo = (BOVERFLOW *)bk; |
| + if (((u_int8_t *)bo + BOVERFLOW_SIZE) > pgend) |
| + return (__db_pgfmt(env, pg)); |
| M_32_SWAP(bo->pgno); |
| M_32_SWAP(bo->tlen); |
| break; |
| @@ -618,12 +647,17 @@ __db_byteswap(dbp, pg, h, pagesize, pgin |
| break; |
| case P_IBTREE: |
| for (i = 0; i < NUM_ENT(h); i++) { |
| + if ((u_int8_t *)(inp + i) > pgend) |
| + return (__db_pgfmt(env, pg)); |
| if (pgin) |
| M_16_SWAP(inp[i]); |
| + if ((u_int16_t)(inp[i] + |
| + BINTERNAL_SIZE(0) - 1) > pagesize) |
| + break; |
| |
| bi = GET_BINTERNAL(dbp, h, i); |
| - if ((u_int8_t *)bi >= pgend) |
| - continue; |
| + if (((u_int8_t *)bi + BINTERNAL_SIZE(0)) > pgend) |
| + return (__db_pgfmt(env, pg)); |
| |
| M_16_SWAP(bi->len); |
| M_32_SWAP(bi->pgno); |
| @@ -634,6 +668,10 @@ __db_byteswap(dbp, pg, h, pagesize, pgin |
| break; |
| case B_DUPLICATE: |
| case B_OVERFLOW: |
| + if ((u_int16_t)(inp[i] + |
| + BINTERNAL_SIZE(BOVERFLOW_SIZE) - 1) > |
| + pagesize) |
| + goto out; |
| bo = (BOVERFLOW *)bi->data; |
| M_32_SWAP(bo->pgno); |
| M_32_SWAP(bo->tlen); |
| @@ -648,12 +686,16 @@ __db_byteswap(dbp, pg, h, pagesize, pgin |
| break; |
| case P_IRECNO: |
| for (i = 0; i < NUM_ENT(h); i++) { |
| + if ((u_int8_t *)(inp + i) >= pgend) |
| + return (__db_pgfmt(env, pg)); |
| if (pgin) |
| M_16_SWAP(inp[i]); |
| + if (inp[i] >= pagesize) |
| + return (__db_pgfmt(env, pg)); |
| |
| ri = GET_RINTERNAL(dbp, h, i); |
| - if ((u_int8_t *)ri >= pgend) |
| - continue; |
| + if ((((u_int8_t *)ri) + RINTERNAL_SIZE) > pgend) |
| + return (__db_pgfmt(env, pg)); |
| |
| M_32_SWAP(ri->pgno); |
| M_32_SWAP(ri->nrecs); |
| --- a/src/db/db_vrfy.c |
| +++ b/src/db/db_vrfy.c |
| @@ -375,8 +375,10 @@ __db_verify(dbp, ip, name, subdb, handle |
| vdp, name, 0, lp, rp, flags)) != 0) { |
| if (t_ret == DB_VERIFY_BAD) |
| isbad = 1; |
| - else |
| - goto err; |
| + else { |
| + ret = t_ret; |
| + goto err; |
| + } |
| } |
| |
| /* |
| @@ -764,9 +766,10 @@ __db_vrfy_walkpages(dbp, vdp, handle, ca |
| */ |
| if ((t_ret = __memp_fget(mpf, &i, |
| vdp->thread_info, NULL, 0, &h)) != 0) { |
| - if (dbp->type == DB_HASH || |
| + if ((dbp->type == DB_HASH || |
| (dbp->type == DB_QUEUE && |
| - F_ISSET(dbp, DB_AM_INMEM))) { |
| + F_ISSET(dbp, DB_AM_INMEM))) && |
| + t_ret != DB_RUNRECOVERY) { |
| if ((t_ret = |
| __db_vrfy_getpageinfo(vdp, i, &pip)) != 0) |
| goto err1; |
| @@ -936,6 +939,8 @@ err: if (h != NULL && (t_ret = __memp_f |
| return (ret == 0 ? t_ret : ret); |
| } |
| |
| + if (ret == DB_PAGE_NOTFOUND && isbad == 1) |
| + ret = 0; |
| return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret); |
| } |
| |
| @@ -1567,7 +1572,7 @@ __db_vrfy_meta(dbp, vdp, meta, pgno, fla |
| if (pgno == PGNO_BASE_MD && |
| dbtype != DB_QUEUE && meta->last_pgno != vdp->last_pgno) { |
| #ifdef HAVE_FTRUNCATE |
| - isbad = 1; |
| + ret = DB_VERIFY_FATAL; |
| EPRINT((env, DB_STR_A("0552", |
| "Page %lu: last_pgno is not correct: %lu != %lu", |
| "%lu %lu %lu"), (u_long)pgno, |
| @@ -1608,7 +1613,11 @@ __db_vrfy_freelist(dbp, vdp, meta, flags |
| |
| env = dbp->env; |
| pgset = vdp->pgset; |
| - DB_ASSERT(env, pgset != NULL); |
| + if (pgset == NULL) { |
| + EPRINT((env, DB_STR("5543", |
| + "Error, database contains no visible pages."))); |
| + return (DB_RUNRECOVERY); |
| + } |
| |
| if ((ret = __db_vrfy_getpageinfo(vdp, meta, &pip)) != 0) |
| return (ret); |
| @@ -1993,7 +2002,8 @@ __db_salvage_pg(dbp, vdp, pgno, h, handl |
| int keyflag, ret, t_ret; |
| |
| env = dbp->env; |
| - DB_ASSERT(env, LF_ISSET(DB_SALVAGE)); |
| + if (!LF_ISSET(DB_SALVAGE)) |
| + return (EINVAL); |
| |
| /* |
| * !!! |
| @@ -2126,10 +2136,8 @@ __db_salvage_leaf(dbp, vdp, pgno, h, han |
| int (*callback) __P((void *, const void *)); |
| u_int32_t flags; |
| { |
| - ENV *env; |
| - |
| - env = dbp->env; |
| - DB_ASSERT(env, LF_ISSET(DB_SALVAGE)); |
| + if (!LF_ISSET(DB_SALVAGE)) |
| + return (EINVAL); |
| |
| /* If we got this page in the subdb pass, we can safely skip it. */ |
| if (__db_salvage_isdone(vdp, pgno)) |
| @@ -2223,8 +2231,8 @@ __db_salvage_unknowns(dbp, vdp, handle, |
| ret = t_ret; |
| break; |
| case SALVAGE_OVERFLOW: |
| - DB_ASSERT(env, 0); /* Shouldn't ever happen. */ |
| - break; |
| + EPRINT((env, DB_STR("5544", "Invalid page type to salvage."))); |
| + return (EINVAL); |
| case SALVAGE_HASH: |
| if ((t_ret = __ham_salvage(dbp, vdp, |
| pgno, h, handle, callback, flags)) != 0 && ret == 0) |
| @@ -2237,8 +2245,8 @@ __db_salvage_unknowns(dbp, vdp, handle, |
| * Shouldn't happen, but if it does, just do what the |
| * nice man says. |
| */ |
| - DB_ASSERT(env, 0); |
| - break; |
| + EPRINT((env, DB_STR("5545", "Invalid page type to salvage."))); |
| + return (EINVAL); |
| } |
| if ((t_ret = __memp_fput(mpf, |
| vdp->thread_info, h, dbp->priority)) != 0 && ret == 0) |
| @@ -2284,8 +2292,8 @@ __db_salvage_unknowns(dbp, vdp, handle, |
| ret = t_ret; |
| break; |
| default: |
| - DB_ASSERT(env, 0); /* Shouldn't ever happen. */ |
| - break; |
| + EPRINT((env, DB_STR("5546", "Invalid page type to salvage."))); |
| + return (EINVAL); |
| } |
| if ((t_ret = __memp_fput(mpf, |
| vdp->thread_info, h, dbp->priority)) != 0 && ret == 0) |
| @@ -2342,7 +2350,10 @@ __db_vrfy_inpitem(dbp, h, pgno, i, is_bt |
| |
| env = dbp->env; |
| |
| - DB_ASSERT(env, himarkp != NULL); |
| + if (himarkp == NULL) { |
| + __db_msg(env, "Page %lu index has no end.", (u_long)pgno); |
| + return (DB_VERIFY_FATAL); |
| + } |
| inp = P_INP(dbp, h); |
| |
| /* |
| @@ -2755,7 +2766,11 @@ __db_salvage_subdbpg(dbp, vdp, master, h |
| goto err; |
| ovfl_bufsz = bkkey->len + 1; |
| } |
| - DB_ASSERT(env, subdbname != NULL); |
| + if (subdbname == NULL) { |
| + EPRINT((env, DB_STR("5547", "Subdatabase cannot be null."))); |
| + ret = EINVAL; |
| + goto err; |
| + } |
| memcpy(subdbname, bkkey->data, bkkey->len); |
| subdbname[bkkey->len] = '\0'; |
| } |
| --- a/src/db/db_vrfyutil.c |
| +++ b/src/db/db_vrfyutil.c |
| @@ -208,7 +208,8 @@ __db_vrfy_getpageinfo(vdp, pgno, pipp) |
| if ((ret = __db_get(pgdbp, |
| vdp->thread_info, vdp->txn, &key, &data, 0)) == 0) { |
| /* Found it. */ |
| - DB_ASSERT(env, data.size == sizeof(VRFY_PAGEINFO)); |
| + if (data.size != sizeof(VRFY_PAGEINFO)) |
| + return (DB_VERIFY_FATAL); |
| pip = data.data; |
| LIST_INSERT_HEAD(&vdp->activepips, pip, links); |
| goto found; |
| @@ -336,7 +337,8 @@ __db_vrfy_pgset_get(dbp, ip, txn, pgno, |
| F_SET(&data, DB_DBT_USERMEM); |
| |
| if ((ret = __db_get(dbp, ip, txn, &key, &data, 0)) == 0) { |
| - DB_ASSERT(dbp->env, data.size == sizeof(int)); |
| + if (data.size != sizeof(int)) |
| + return (EINVAL); |
| } else if (ret == DB_NOTFOUND) |
| val = 0; |
| else |
| @@ -376,7 +378,8 @@ __db_vrfy_pgset_inc(dbp, ip, txn, pgno) |
| F_SET(&data, DB_DBT_USERMEM); |
| |
| if ((ret = __db_get(dbp, ip, txn, &key, &data, 0)) == 0) { |
| - DB_ASSERT(dbp->env, data.size == sizeof(int)); |
| + if (data.size != sizeof(int)) |
| + return (DB_VERIFY_FATAL); |
| } else if (ret != DB_NOTFOUND) |
| return (ret); |
| |
| @@ -413,7 +416,8 @@ __db_vrfy_pgset_next(dbc, pgnop) |
| if ((ret = __dbc_get(dbc, &key, &data, DB_NEXT)) != 0) |
| return (ret); |
| |
| - DB_ASSERT(dbc->env, key.size == sizeof(db_pgno_t)); |
| + if (key.size != sizeof(db_pgno_t)) |
| + return (DB_VERIFY_FATAL); |
| *pgnop = pgno; |
| |
| return (0); |
| @@ -560,7 +564,8 @@ __db_vrfy_ccset(dbc, pgno, cipp) |
| if ((ret = __dbc_get(dbc, &key, &data, DB_SET)) != 0) |
| return (ret); |
| |
| - DB_ASSERT(dbc->env, data.size == sizeof(VRFY_CHILDINFO)); |
| + if (data.size != sizeof(VRFY_CHILDINFO)) |
| + return (DB_VERIFY_FATAL); |
| *cipp = (VRFY_CHILDINFO *)data.data; |
| |
| return (0); |
| @@ -588,7 +593,8 @@ __db_vrfy_ccnext(dbc, cipp) |
| if ((ret = __dbc_get(dbc, &key, &data, DB_NEXT_DUP)) != 0) |
| return (ret); |
| |
| - DB_ASSERT(dbc->env, data.size == sizeof(VRFY_CHILDINFO)); |
| + if (data.size != sizeof(VRFY_CHILDINFO)) |
| + return (DB_VERIFY_FATAL); |
| *cipp = (VRFY_CHILDINFO *)data.data; |
| |
| return (0); |
| @@ -715,7 +721,8 @@ __db_salvage_getnext(vdp, dbcp, pgnop, p |
| return (ret); |
| |
| while ((ret = __dbc_get(*dbcp, &key, &data, DB_NEXT)) == 0) { |
| - DB_ASSERT(dbp->env, data.size == sizeof(u_int32_t)); |
| + if (data.size != sizeof(u_int32_t)) |
| + return (DB_VERIFY_FATAL); |
| memcpy(&pgtype, data.data, sizeof(pgtype)); |
| |
| if (skip_overflow && pgtype == SALVAGE_OVERFLOW) |
| @@ -724,8 +731,9 @@ __db_salvage_getnext(vdp, dbcp, pgnop, p |
| if ((ret = __dbc_del(*dbcp, 0)) != 0) |
| return (ret); |
| if (pgtype != SALVAGE_IGNORE) { |
| - DB_ASSERT(dbp->env, key.size == sizeof(db_pgno_t)); |
| - DB_ASSERT(dbp->env, data.size == sizeof(u_int32_t)); |
| + if (key.size != sizeof(db_pgno_t) |
| + || data.size != sizeof(u_int32_t)) |
| + return (DB_VERIFY_FATAL); |
| |
| *pgnop = *(db_pgno_t *)key.data; |
| *pgtypep = *(u_int32_t *)data.data; |
| --- a/src/db/partition.c |
| +++ b/src/db/partition.c |
| @@ -461,9 +461,19 @@ __partition_chk_meta(dbp, ip, txn, flags |
| } else |
| part->nparts = meta->nparts; |
| } else if (meta->nparts != 0 && part->nparts != meta->nparts) { |
| + ret = EINVAL; |
| __db_errx(env, DB_STR("0656", |
| "Number of partitions does not match.")); |
| + goto err; |
| + } |
| + /* |
| + * There is no limit on the number of partitions, but I cannot imagine a real |
| + * database having more than 10000. |
| + */ |
| + if (meta->nparts > 10000) { |
| ret = EINVAL; |
| + __db_errx(env, DB_STR_A("5553", |
| + "Too many partitions %lu", "%lu"), (u_long)(meta->nparts)); |
| goto err; |
| } |
| |
| @@ -1874,10 +1884,13 @@ __part_verify(dbp, vdp, fname, handle, c |
| memcpy(rp->data, key->data, key->size); |
| B_TSET(rp->type, B_KEYDATA); |
| } |
| -vrfy: if ((t_ret = __db_verify(*pdbp, ip, (*pdbp)->fname, |
| - NULL, handle, callback, |
| - lp, rp, flags | DB_VERIFY_PARTITION)) != 0 && ret == 0) |
| - ret = t_ret; |
| +vrfy: if ((t_ret = __db_verify(*pdbp, ip, (*pdbp)->fname, |
| + NULL, handle, callback, |
| + lp, rp, flags | DB_VERIFY_PARTITION)) != 0 && ret == 0) { |
| + ret = t_ret; |
| + if (ret == ENOENT) |
| + break; |
| + } |
| } |
| |
| err: if (lp != NULL) |
| --- a/src/hash/hash_page.c |
| +++ b/src/hash/hash_page.c |
| @@ -865,7 +865,11 @@ __ham_verify_sorted_page (dbc, p) |
| /* Validate that next, prev pointers are OK */ |
| n = NUM_ENT(p); |
| dbp = dbc->dbp; |
| - DB_ASSERT(dbp->env, n%2 == 0 ); |
| + if (n % 2 != 0) { |
| + __db_errx(dbp->env, DB_STR_A("5549", |
| + "Odd number of entries on page: %lu", "%lu"), (u_long)(p->pgno)); |
| + return (DB_VERIFY_FATAL); |
| + } |
| |
| env = dbp->env; |
| t = dbp->h_internal; |
| @@ -936,7 +940,12 @@ __ham_verify_sorted_page (dbc, p) |
| if ((ret = __db_prpage(dbp, p, DB_PR_PAGE)) != 0) |
| return (ret); |
| #endif |
| - DB_ASSERT(dbp->env, res < 0); |
| + if (res >= 0) { |
| + __db_errx(env, DB_STR_A("5550", |
| + "Odd number of entries on page: %lu", "%lu"), |
| + (u_long)p->pgno); |
| + return (DB_VERIFY_FATAL); |
| + } |
| } |
| |
| prev = curr; |
| --- a/src/hash/hash_verify.c |
| +++ b/src/hash/hash_verify.c |
| @@ -443,7 +443,7 @@ __ham_vrfy_structure(dbp, vdp, meta_pgno |
| isbad = 1; |
| else |
| goto err; |
| - } |
| + } |
| |
| /* |
| * There may be unused hash pages corresponding to buckets |
| @@ -574,7 +574,7 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, f |
| "Page %lu: impossible first page in bucket %lu", "%lu %lu"), |
| (u_long)pgno, (u_long)bucket)); |
| /* Unsafe to continue. */ |
| - isbad = 1; |
| + ret = DB_VERIFY_FATAL; |
| goto err; |
| } |
| |
| @@ -604,7 +604,7 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, f |
| EPRINT((env, DB_STR_A("1116", |
| "Page %lu: hash page referenced twice", "%lu"), |
| (u_long)pgno)); |
| - isbad = 1; |
| + ret = DB_VERIFY_FATAL; |
| /* Unsafe to continue. */ |
| goto err; |
| } else if ((ret = __db_vrfy_pgset_inc(vdp->pgset, |
| @@ -1049,7 +1049,11 @@ __ham_meta2pgset(dbp, vdp, hmeta, flags, |
| COMPQUIET(flags, 0); |
| ip = vdp->thread_info; |
| |
| - DB_ASSERT(dbp->env, pgset != NULL); |
| + if (pgset == NULL) { |
| + EPRINT((dbp->env, DB_STR("5548", |
| + "Error, database contains no visible pages."))); |
| + return (DB_VERIFY_FATAL); |
| + } |
| |
| mpf = dbp->mpf; |
| totpgs = 0; |
| --- a/src/qam/qam_verify.c |
| +++ b/src/qam/qam_verify.c |
| @@ -465,7 +465,14 @@ __qam_vrfy_walkqueue(dbp, vdp, handle, c |
| /* Verify/salvage each page. */ |
| if ((ret = __db_cursor(dbp, vdp->thread_info, NULL, &dbc, 0)) != 0) |
| return (ret); |
| -begin: for (; i <= stop; i++) { |
| +begin: if ((stop - i) > 100000) { |
| + EPRINT((env, DB_STR_A("5551", |
| +"Warning, many possible extends files (%lu), will take a long time to verify", |
| + "%lu"), (u_long)(stop - i))); |
| + } |
| + for (; i <= stop; i++) { |
| + if (i == UINT32_MAX) |
| + break; |
| /* |
| * If DB_SALVAGE is set, we inspect our database of completed |
| * pages, and skip any we've already printed in the subdb pass. |