alpinelinux / docker-alpine

Official Alpine Linux Docker image. Win at minimalism!
MIT License
1.08k stars 262 forks source link

Linux alpine latest vulnerabilities #100

Open nelsonflorez11 opened 4 years ago

nelsonflorez11 commented 4 years ago

Hello I want to report these vulnerabilities, in the official image of alpine latest

Vulnerable packages libxt: 1.2.0-r0 db: 5.3.28-r1

Vulnerability Name CVE-2013-2063-> https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-2063 Integer overflow in X.org libXtst 1.2.1 and earlier allows X servers to trigger allocation of insufficient memory and a buffer overflow via vectors related to the XRecordGetContext function.

CVE-2020-2981-> https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-2981 Vulnerability in the Data Store component of Oracle Berkeley DB. The supported version that is affected is Prior to 18.1.40. Difficult to exploit vulnerability allows unauthenticated attacker with logon to the infrastructure where Data Store executes to compromise Data Store. Successful attacks require human interaction from a person other than the attacker. Successful attacks of this vulnerability can result in takeover of Data Store.

CVE-2019-2708-> https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-2708 Vulnerability in the Data Store component of Oracle Berkeley DB. Supported versions that are affected are Prior to 6.138, prior to 6.2.38 and prior to 18.1.32. Easily exploitable vulnerability allows low privileged attacker having Local Logon privilege with logon to the infrastructure where Data Store executes to compromise Data Store. Successful attacks of this vulnerability can result in unauthorized ability to cause a partial denial of service (partial DOS) of the Data Store.

ncopa commented 4 years ago

Looks like we fixed libXtst 7 years ago

Which CVE did you find for libxt?

Do you know where I can find the exact git commit (or source change) for the CVEs in Oracle Berkeley DB? We have ad CVE reports in the past that claims that berkely db 5.x is vulnerable, but I was difficult to find the exact change that needed to be backported and I didn't get any response from Oracle. When analyzing the raw diff between released version I only found changes in code that does not exist in db 5.x.

This time I have even difficulties finding source of previous release (where can I find db-18.1.39, or db-18.1.32?) Before I waste more time on this I'd like to have some more specific proof that db 5.x is actually affected.

ncopa commented 4 years ago

Ok, i found the 18.1.32 source. I made a diff with all the copyright comment updates removed in case someone wants to help analyze this:

--- db-18.1.32/src/btree/bt_cursor.c
+++ db-18.1.40/src/btree/bt_cursor.c
@@ -282,6 +282,8 @@
     *
     * 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);

--- db-18.1.32/src/btree/bt_verify.c
+++ db-18.1.40/src/btree/bt_verify.c
@@ -700,7 +700,11 @@
            isbad = 1;
            goto err;
        default:
-           DB_ASSERT(env, ret != 0);
+           if (ret == 0) {
+               isbad = 1;
+               ret = DB_VERIFY_FATAL;
+               goto err;
+           }
            break;
        }

@@ -1074,7 +1078,7 @@
    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;
@@ -1106,7 +1110,8 @@

    buf1 = buf2 = NULL;

-   DB_ASSERT(env, !LF_ISSET(DB_NOORDERCHK));
+   if (LF_ISSET(DB_NOORDERCHK))
+       return (EINVAL);

    dupfunc = (dbp->dup_compare == NULL) ? __dbt_defcmp : dbp->dup_compare;
    if (TYPE(h) == P_LDUP)
@@ -1115,6 +1120,7 @@
        func = __dbt_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 != __dbt_defcmp)) {
                /*
@@ -1136,6 +1142,14 @@
                        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,
@@ -1402,7 +1416,10 @@
                     */
                    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);
@@ -1747,9 +1764,10 @@
                (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;
            }

@@ -1823,9 +1841,10 @@
                            stflags | DB_ST_TOPLEVEL,
                            NULL, NULL, NULL)) != 0) {
                            if (ret ==
-                               DB_VERIFY_BAD)
+                               DB_VERIFY_BAD) {
                                isbad = 1;
-                           else
+                               break;
+                           } else
                                goto err;
                        }
                    }
@@ -1969,7 +1988,10 @@
             */

            /* 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
@@ -1986,9 +2008,10 @@
                    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;
                    }
        }
@@ -2026,9 +2049,10 @@
        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;
        }

@@ -2929,7 +2953,11 @@
    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;
--- db-18.1.32/src/db/db_conv.c
+++ db-18.1.40/src/db/db_conv.c
@@ -503,8 +503,11 @@
    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);
@@ -529,27 +532,29 @@
    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)
-               break;
+               return (__db_pgfmt(env, pg));

            if (P_ENTRY(dbp, h, i) >= pgend)
-               continue;
+               return (__db_pgfmt(env, pg));

            switch (HPAGE_TYPE(dbp, h, i)) {
            case H_BLOB:
                if ((inp[i] + HBLOB_SIZE) > pagesize)
-                   goto out;
+                   return (__db_pgfmt(env, pg));
                p = HBLOB_ID(P_ENTRY(dbp, h, i));
                SWAP64(p);          /* id */
                SWAP64(p);          /* size */
@@ -560,7 +565,7 @@
            case H_KEYDATA:
                break;
            case H_DUPLICATE:
-               if (LEN_HITEM(dbp, h, pagesize, i) <= 
+               if (LEN_HITEM(dbp, h, pagesize, i) < 
                    HKEYDATA_SIZE(0))
                    return (__db_pgfmt(env, pg));

@@ -568,7 +573,7 @@
                p = HKEYDATA_DATA(P_ENTRY(dbp, h, i));

                end = p + len;
-               if (end >= pgend)
+               if (end > pgend)
                    return (__db_pgfmt(env, pg));

                while (p < end) {
@@ -590,13 +595,13 @@
                break;
            case H_OFFDUP:
                if ((inp[i] + HOFFDUP_SIZE) > pagesize)
-                   goto out;
+                   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)
-                   goto out;
+                   return (__db_pgfmt(env, pg));
                p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
                SWAP32(p);          /* pgno */
                SWAP32(p);          /* tlen */
@@ -604,7 +609,6 @@
            default:
                return (__db_pgfmt(env, pg));
            }
-
        }

        /*
@@ -622,11 +626,11 @@
    case P_LRECNO:
        for (i = 0; i < NUM_ENT(h); i++) {
            if ((u_int8_t *)(inp + i) >= pgend)
-               break;
+               return (__db_pgfmt(env, pg));
            if (pgin)
                M_16_SWAP(inp[i]);
            if (inp[i] >= pagesize)
-               break;
+               return (__db_pgfmt(env, pg));

            /*
             * In the case of on-page duplicates, key information
@@ -646,10 +650,12 @@

            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_BLOB:
                bl = (BBLOB *)bk;
+               if (((u_int8_t*)bl + BBLOB_SIZE) > pgend)
+                   return (__db_pgfmt(env, pg));
                M_16_SWAP(bl->len);
                M_64_SWAP(bl->id);      /* id */
                M_64_SWAP(bl->size);        /* size */
@@ -662,6 +668,8 @@
            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;
@@ -675,17 +683,17 @@
        break;
    case P_IBTREE:
        for (i = 0; i < NUM_ENT(h); i++) {
-           if ((u_int8_t *)(inp + i) >= pgend)
-               break;
+           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)
+               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);
@@ -697,7 +705,7 @@
            case B_DUPLICATE:
            case B_OVERFLOW:
                if ((u_int16_t)(inp[i] + 
-                   BINTERNAL_SIZE(BOVERFLOW_SIZE) - 1) >= 
+                   BINTERNAL_SIZE(BOVERFLOW_SIZE) - 1) >
                    pagesize)
                    goto out;
                bo = (BOVERFLOW *)bi->data;
@@ -715,15 +723,15 @@
    case P_IRECNO:
        for (i = 0; i < NUM_ENT(h); i++) {
            if ((u_int8_t *)(inp + i) >= pgend)
-               break;
+               return (__db_pgfmt(env, pg));
            if (pgin)
                M_16_SWAP(inp[i]);
            if (inp[i] >= pagesize)
-               break;
+               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);
@@ -735,13 +743,13 @@
    case P_HEAP:
        for (i = 0; i <= HEAP_HIGHINDX(h); i++) {
            if (i >= NUM_ENT(h))
-               break;
-           if ((u_int8_t *)(inp + i) >= pgend)
-               break;
+               return (__db_pgfmt(env, pg));
+           if ((u_int8_t *)(inp + i) > pgend)
+               return (__db_pgfmt(env, pg));
            if (pgin)
                M_16_SWAP(inp[i]);
            if (inp[i] >= pagesize)
-               break;
+               return (__db_pgfmt(env, pg));
            if (inp[i] == 0)
                continue;

@@ -753,11 +761,15 @@
                break;
            if (F_ISSET(hh, HEAP_RECSPLIT)) {
                hsh = (HEAPSPLITHDR *)hh;
+               if (((u_int8_t *)hsh + sizeof(HEAPSPLITHDR)) > pgend)
+                   return (__db_pgfmt(env, pg));
                M_32_SWAP(hsh->tsize);
                M_32_SWAP(hsh->nextpg);
                M_16_SWAP(hsh->nextindx);
            } else if (F_ISSET(hh, HEAP_RECBLOB)) {
                bhdr = (HEAPBLOBHDR *)hh;
+               if (((u_int8_t*)bhdr + HEAPBLOBREC_SIZE) > pgend)
+                   return (__db_pgfmt(env, pg));
                M_64_SWAP(bhdr->id);        /* id */
                M_64_SWAP(bhdr->size);      /* size */
                M_64_SWAP(bhdr->file_id);   /* file id */
--- db-18.1.32/src/db/db_vrfy.c
+++ db-18.1.40/src/db/db_vrfy.c
@@ -381,8 +381,10 @@
            vdp, name, 0, lp, rp, flags)) != 0) {
            if (t_ret == DB_VERIFY_BAD)
                isbad = 1;
-           else
-               goto err;
+           else {
+               ret = t_ret;
+               goto err;
+           }
        }

    /*
@@ -771,9 +773,10 @@
         */
        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;
@@ -945,6 +948,8 @@
            return (ret == 0 ? t_ret : ret);
    }

+   if (ret == DB_PAGE_NOTFOUND && isbad == 1)
+       ret = 0;
    return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
 }

@@ -1581,7 +1586,7 @@
    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,
@@ -1622,7 +1627,11 @@

    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);
@@ -2014,7 +2023,8 @@
    int keyflag, ret, t_ret;

    env = dbp->env;
-   DB_ASSERT(env, LF_ISSET(DB_SALVAGE));
+   if (!LF_ISSET(DB_SALVAGE))
+       return (EINVAL);

    /*
     * !!!
@@ -2147,9 +2157,10 @@
    int (*callback) __P((void *, const void *));
    u_int32_t flags;
 {
+   
+   if (!LF_ISSET(DB_SALVAGE))
+       return (EINVAL);

-   DB_ASSERT(dbp->env, LF_ISSET(DB_SALVAGE));
-
    /* If we got this page in the subdb pass, we can safely skip it. */
    if (__db_salvage_isdone(vdp, pgno))
        return (0);
@@ -2242,8 +2253,8 @@
                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)
@@ -2256,8 +2267,8 @@
             * 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)
@@ -2303,8 +2314,8 @@
                    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)
@@ -2361,7 +2372,10 @@

    env = dbp->env;

-   DB_ASSERT(env, himarkp != NULL);
+   if (himarkp == NULL) {
+       __db_msg(env, "Page %lu index has no end.", pgno);
+       return (DB_VERIFY_FATAL);
+   }
    inp = P_INP(dbp, h);

    /*
@@ -2783,7 +2797,11 @@
                    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';
        }
--- db-18.1.32/src/db/db_vrfyutil.c
+++ db-18.1.40/src/db/db_vrfyutil.c
@@ -214,7 +214,8 @@
    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;
@@ -342,7 +343,8 @@
    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
@@ -382,7 +384,8 @@
    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);

@@ -419,7 +422,8 @@
    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);
@@ -566,7 +570,8 @@
    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);
@@ -594,7 +599,8 @@
    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);
@@ -721,7 +727,8 @@
        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)
@@ -730,8 +737,9 @@
        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;
--- db-18.1.32/src/db/partition.c
+++ db-18.1.40/src/db/partition.c
@@ -589,6 +589,16 @@
            "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 = USR_ERR(env, EINVAL);
+       __db_errx(env, DB_STR_A("5553",
+           "Too many partitions %lu", "%lu"), meta->nparts);
+       goto err;
+   }

    if (meta->magic == DB_HASHMAGIC) {
        if (!F_ISSET(part, PART_CALLBACK)) {
@@ -2106,10 +2116,13 @@
            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)
--- db-18.1.32/src/hash/hash_page.c
+++ db-18.1.40/src/hash/hash_page.c
@@ -869,7 +869,11 @@
    /* 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;
@@ -940,7 +944,12 @@
            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;
--- db-18.1.32/src/hash/hash_verify.c
+++ db-18.1.40/src/hash/hash_verify.c
@@ -615,7 +615,7 @@
                isbad = 1;
            else
                goto err;
-           }
+       }

    /*
     * There may be unused hash pages corresponding to buckets
@@ -746,7 +746,7 @@
            "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;
    }

@@ -776,7 +776,7 @@
            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,
@@ -1307,7 +1307,11 @@
    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;
--- db-18.1.32/src/qam/qam_verify.c
+++ db-18.1.40/src/qam/qam_verify.c
@@ -507,7 +507,12 @@
    /* 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;
        /*