ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/external/subpack/libs/db/patches/110-CVE-2019-2708.patch b/external/subpack/libs/db/patches/110-CVE-2019-2708.patch
new file mode 100644
index 0000000..a86388c
--- /dev/null
+++ b/external/subpack/libs/db/patches/110-CVE-2019-2708.patch
@@ -0,0 +1,693 @@
+--- 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.