blob: a86388c64f3847220ebd71b660359e93b31be4e5 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001--- a/src/btree/bt_cursor.c
2+++ b/src/btree/bt_cursor.c
3@@ -282,6 +282,8 @@ __bamc_refresh(dbc)
4 *
5 * Recno uses the btree bt_ovflsize value -- it's close enough.
6 */
7+ if (t->bt_minkey == 0)
8+ return (DB_RECOVER);
9 cp->ovflsize = B_MINKEY_TO_OVFLSIZE(
10 dbp, F_ISSET(dbc, DBC_OPD) ? 2 : t->bt_minkey, dbp->pgsize);
11
12--- a/src/btree/bt_verify.c
13+++ b/src/btree/bt_verify.c
14@@ -611,7 +611,11 @@ __bam_vrfy_inp(dbp, vdp, h, pgno, nentri
15 isbad = 1;
16 goto err;
17 default:
18- DB_ASSERT(env, ret != 0);
19+ if (ret == 0) {
20+ isbad = 1;
21+ ret = DB_VERIFY_FATAL;
22+ goto err;
23+ }
24 break;
25 }
26
27@@ -922,7 +926,7 @@ __bam_vrfy_itemorder(dbp, vdp, ip, h, pg
28 DBT dbta, dbtb, dup_1, dup_2, *p1, *p2, *tmp;
29 ENV *env;
30 PAGE *child;
31- db_pgno_t cpgno;
32+ db_pgno_t cpgno, grandparent;
33 VRFY_PAGEINFO *pip;
34 db_indx_t i, *inp;
35 int adj, cmp, freedup_1, freedup_2, isbad, ret, t_ret;
36@@ -954,7 +958,8 @@ __bam_vrfy_itemorder(dbp, vdp, ip, h, pg
37
38 buf1 = buf2 = NULL;
39
40- DB_ASSERT(env, !LF_ISSET(DB_NOORDERCHK));
41+ if (LF_ISSET(DB_NOORDERCHK))
42+ return (EINVAL);
43
44 dupfunc = (dbp->dup_compare == NULL) ? __bam_defcmp : dbp->dup_compare;
45 if (TYPE(h) == P_LDUP)
46@@ -963,6 +968,7 @@ __bam_vrfy_itemorder(dbp, vdp, ip, h, pg
47 func = __bam_defcmp;
48 if (dbp->bt_internal != NULL) {
49 bt = (BTREE *)dbp->bt_internal;
50+ grandparent = bt->bt_root;
51 if (TYPE(h) == P_IBTREE && (bt->bt_compare != NULL ||
52 dupfunc != __bam_defcmp)) {
53 /*
54@@ -974,8 +980,24 @@ __bam_vrfy_itemorder(dbp, vdp, ip, h, pg
55 */
56 mpf = dbp->mpf;
57 child = h;
58+ cpgno = pgno;
59 while (TYPE(child) == P_IBTREE) {
60+ if (NUM_ENT(child) == 0) {
61+ EPRINT((env, DB_STR_A("1088",
62+ "Page %lu: internal page is empty and should not be",
63+ "%lu"), (u_long)cpgno));
64+ ret = DB_VERIFY_BAD;
65+ goto err;
66+ }
67 bi = GET_BINTERNAL(dbp, child, 0);
68+ if (grandparent == bi->pgno) {
69+ EPRINT((env, DB_STR_A("5552",
70+ "Page %lu: found twice in the btree",
71+ "%lu"), (u_long)grandparent));
72+ ret = DB_VERIFY_FATAL;
73+ goto err;
74+ } else
75+ grandparent = cpgno;
76 cpgno = bi->pgno;
77 if (child != h &&
78 (ret = __memp_fput(mpf,
79@@ -1231,7 +1253,10 @@ overflow: if (!ovflok) {
80 */
81 if (dup_1.data == NULL ||
82 dup_2.data == NULL) {
83- DB_ASSERT(env, !ovflok);
84+ if (ovflok) {
85+ isbad = 1;
86+ goto err;
87+ }
88 if (pip != NULL)
89 F_SET(pip,
90 VRFY_INCOMPLETE);
91@@ -1569,9 +1594,10 @@ bad_prev: isbad = 1;
92 (ret = __db_vrfy_ovfl_structure(dbp, vdp,
93 child->pgno, child->tlen,
94 flags | DB_ST_OVFL_LEAF)) != 0) {
95- if (ret == DB_VERIFY_BAD)
96+ if (ret == DB_VERIFY_BAD) {
97 isbad = 1;
98- else
99+ break;
100+ } else
101 goto done;
102 }
103
104@@ -1645,9 +1671,10 @@ bad_prev: isbad = 1;
105 stflags | DB_ST_TOPLEVEL,
106 NULL, NULL, NULL)) != 0) {
107 if (ret ==
108- DB_VERIFY_BAD)
109+ DB_VERIFY_BAD) {
110 isbad = 1;
111- else
112+ break;
113+ } else
114 goto err;
115 }
116 }
117@@ -1790,7 +1817,10 @@ bad_prev: isbad = 1;
118 */
119
120 /* Otherwise, __db_vrfy_childput would be broken. */
121- DB_ASSERT(env, child->refcnt >= 1);
122+ if (child->refcnt < 1) {
123+ isbad = 1;
124+ goto err;
125+ }
126
127 /*
128 * An overflow referenced more than twice here
129@@ -1807,9 +1837,10 @@ bad_prev: isbad = 1;
130 if ((ret = __db_vrfy_ovfl_structure(dbp,
131 vdp, child->pgno, child->tlen,
132 flags)) != 0) {
133- if (ret == DB_VERIFY_BAD)
134+ if (ret == DB_VERIFY_BAD) {
135 isbad = 1;
136- else
137+ break;
138+ } else
139 goto done;
140 }
141 }
142@@ -1847,9 +1878,10 @@ bad_prev: isbad = 1;
143 if ((ret = __bam_vrfy_subtree(dbp, vdp, li->pgno,
144 i == 0 ? NULL : li, ri, flags, &child_level,
145 &child_nrecs, NULL)) != 0) {
146- if (ret == DB_VERIFY_BAD)
147+ if (ret == DB_VERIFY_BAD) {
148 isbad = 1;
149- else
150+ break;
151+ } else
152 goto done;
153 }
154
155@@ -2675,7 +2707,11 @@ __bam_meta2pgset(dbp, vdp, btmeta, flags
156 db_pgno_t current, p;
157 int err_ret, ret;
158
159- DB_ASSERT(dbp->env, pgset != NULL);
160+ if (pgset == NULL) {
161+ EPRINT((dbp->env, DB_STR("5542",
162+ "Error, database contains no visible pages.")));
163+ return (DB_RUNRECOVERY);
164+ }
165
166 mpf = dbp->mpf;
167 h = NULL;
168--- a/src/db/db_conv.c
169+++ b/src/db/db_conv.c
170@@ -493,8 +493,11 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
171 db_indx_t i, *inp, len, tmp;
172 u_int8_t *end, *p, *pgend;
173
174- if (pagesize == 0)
175- return (0);
176+ /* This function is also used to byteswap logs, so
177+ * the pagesize might not be an actual page size.
178+ */
179+ if (!(pagesize >= 24 && pagesize <= DB_MAX_PGSIZE))
180+ return (EINVAL);
181
182 if (pgin) {
183 M_32_SWAP(h->lsn.file);
184@@ -513,26 +516,41 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
185 pgend = (u_int8_t *)h + pagesize;
186
187 inp = P_INP(dbp, h);
188- if ((u_int8_t *)inp >= pgend)
189- goto out;
190+ if ((u_int8_t *)inp > pgend)
191+ return (__db_pgfmt(env, pg));
192
193 switch (TYPE(h)) {
194 case P_HASH_UNSORTED:
195 case P_HASH:
196 for (i = 0; i < NUM_ENT(h); i++) {
197+ if ((u_int8_t*)(inp + i) >= pgend)
198+ return (__db_pgfmt(env, pg));
199+ if (inp[i] == 0)
200+ continue;
201 if (pgin)
202 M_16_SWAP(inp[i]);
203+ if (inp[i] >= pagesize)
204+ return (__db_pgfmt(env, pg));
205
206- if (P_ENTRY(dbp, h, i) >= pgend)
207- continue;
208+ if (P_ENTRY(dbp, h, i) >= pgend)
209+ return (__db_pgfmt(env, pg));
210
211 switch (HPAGE_TYPE(dbp, h, i)) {
212 case H_KEYDATA:
213 break;
214 case H_DUPLICATE:
215+ if (LEN_HITEM(dbp, h, pagesize, i) <
216+ HKEYDATA_SIZE(0))
217+ return (__db_pgfmt(env, pg));
218+
219 len = LEN_HKEYDATA(dbp, h, pagesize, i);
220 p = HKEYDATA_DATA(P_ENTRY(dbp, h, i));
221- for (end = p + len; p < end;) {
222+
223+ end = p + len;
224+ if (end > pgend)
225+ return (__db_pgfmt(env, pg));
226+
227+ while (p < end) {
228 if (pgin) {
229 P_16_SWAP(p);
230 memcpy(&tmp,
231@@ -544,14 +562,20 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
232 SWAP16(p);
233 }
234 p += tmp;
235+ if (p >= end)
236+ return (__db_pgfmt(env, pg));
237 SWAP16(p);
238 }
239 break;
240 case H_OFFDUP:
241+ if ((inp[i] + HOFFDUP_SIZE) > pagesize)
242+ return (__db_pgfmt(env, pg));
243 p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
244 SWAP32(p); /* pgno */
245 break;
246 case H_OFFPAGE:
247+ if ((inp[i] + HOFFPAGE_SIZE) > pagesize)
248+ return (__db_pgfmt(env, pg));
249 p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
250 SWAP32(p); /* pgno */
251 SWAP32(p); /* tlen */
252@@ -559,7 +583,6 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
253 default:
254 return (__db_pgfmt(env, pg));
255 }
256-
257 }
258
259 /*
260@@ -576,8 +599,12 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
261 case P_LDUP:
262 case P_LRECNO:
263 for (i = 0; i < NUM_ENT(h); i++) {
264+ if ((u_int8_t *)(inp + i) >= pgend)
265+ return (__db_pgfmt(env, pg));
266 if (pgin)
267 M_16_SWAP(inp[i]);
268+ if (inp[i] >= pagesize)
269+ return (__db_pgfmt(env, pg));
270
271 /*
272 * In the case of on-page duplicates, key information
273@@ -597,7 +624,7 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
274
275 bk = GET_BKEYDATA(dbp, h, i);
276 if ((u_int8_t *)bk >= pgend)
277- continue;
278+ return (__db_pgfmt(env, pg));
279 switch (B_TYPE(bk->type)) {
280 case B_KEYDATA:
281 M_16_SWAP(bk->len);
282@@ -605,6 +632,8 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
283 case B_DUPLICATE:
284 case B_OVERFLOW:
285 bo = (BOVERFLOW *)bk;
286+ if (((u_int8_t *)bo + BOVERFLOW_SIZE) > pgend)
287+ return (__db_pgfmt(env, pg));
288 M_32_SWAP(bo->pgno);
289 M_32_SWAP(bo->tlen);
290 break;
291@@ -618,12 +647,17 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
292 break;
293 case P_IBTREE:
294 for (i = 0; i < NUM_ENT(h); i++) {
295+ if ((u_int8_t *)(inp + i) > pgend)
296+ return (__db_pgfmt(env, pg));
297 if (pgin)
298 M_16_SWAP(inp[i]);
299+ if ((u_int16_t)(inp[i] +
300+ BINTERNAL_SIZE(0) - 1) > pagesize)
301+ break;
302
303 bi = GET_BINTERNAL(dbp, h, i);
304- if ((u_int8_t *)bi >= pgend)
305- continue;
306+ if (((u_int8_t *)bi + BINTERNAL_SIZE(0)) > pgend)
307+ return (__db_pgfmt(env, pg));
308
309 M_16_SWAP(bi->len);
310 M_32_SWAP(bi->pgno);
311@@ -634,6 +668,10 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
312 break;
313 case B_DUPLICATE:
314 case B_OVERFLOW:
315+ if ((u_int16_t)(inp[i] +
316+ BINTERNAL_SIZE(BOVERFLOW_SIZE) - 1) >
317+ pagesize)
318+ goto out;
319 bo = (BOVERFLOW *)bi->data;
320 M_32_SWAP(bo->pgno);
321 M_32_SWAP(bo->tlen);
322@@ -648,12 +686,16 @@ __db_byteswap(dbp, pg, h, pagesize, pgin
323 break;
324 case P_IRECNO:
325 for (i = 0; i < NUM_ENT(h); i++) {
326+ if ((u_int8_t *)(inp + i) >= pgend)
327+ return (__db_pgfmt(env, pg));
328 if (pgin)
329 M_16_SWAP(inp[i]);
330+ if (inp[i] >= pagesize)
331+ return (__db_pgfmt(env, pg));
332
333 ri = GET_RINTERNAL(dbp, h, i);
334- if ((u_int8_t *)ri >= pgend)
335- continue;
336+ if ((((u_int8_t *)ri) + RINTERNAL_SIZE) > pgend)
337+ return (__db_pgfmt(env, pg));
338
339 M_32_SWAP(ri->pgno);
340 M_32_SWAP(ri->nrecs);
341--- a/src/db/db_vrfy.c
342+++ b/src/db/db_vrfy.c
343@@ -375,8 +375,10 @@ __db_verify(dbp, ip, name, subdb, handle
344 vdp, name, 0, lp, rp, flags)) != 0) {
345 if (t_ret == DB_VERIFY_BAD)
346 isbad = 1;
347- else
348- goto err;
349+ else {
350+ ret = t_ret;
351+ goto err;
352+ }
353 }
354
355 /*
356@@ -764,9 +766,10 @@ __db_vrfy_walkpages(dbp, vdp, handle, ca
357 */
358 if ((t_ret = __memp_fget(mpf, &i,
359 vdp->thread_info, NULL, 0, &h)) != 0) {
360- if (dbp->type == DB_HASH ||
361+ if ((dbp->type == DB_HASH ||
362 (dbp->type == DB_QUEUE &&
363- F_ISSET(dbp, DB_AM_INMEM))) {
364+ F_ISSET(dbp, DB_AM_INMEM))) &&
365+ t_ret != DB_RUNRECOVERY) {
366 if ((t_ret =
367 __db_vrfy_getpageinfo(vdp, i, &pip)) != 0)
368 goto err1;
369@@ -936,6 +939,8 @@ err: if (h != NULL && (t_ret = __memp_f
370 return (ret == 0 ? t_ret : ret);
371 }
372
373+ if (ret == DB_PAGE_NOTFOUND && isbad == 1)
374+ ret = 0;
375 return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
376 }
377
378@@ -1567,7 +1572,7 @@ __db_vrfy_meta(dbp, vdp, meta, pgno, fla
379 if (pgno == PGNO_BASE_MD &&
380 dbtype != DB_QUEUE && meta->last_pgno != vdp->last_pgno) {
381 #ifdef HAVE_FTRUNCATE
382- isbad = 1;
383+ ret = DB_VERIFY_FATAL;
384 EPRINT((env, DB_STR_A("0552",
385 "Page %lu: last_pgno is not correct: %lu != %lu",
386 "%lu %lu %lu"), (u_long)pgno,
387@@ -1608,7 +1613,11 @@ __db_vrfy_freelist(dbp, vdp, meta, flags
388
389 env = dbp->env;
390 pgset = vdp->pgset;
391- DB_ASSERT(env, pgset != NULL);
392+ if (pgset == NULL) {
393+ EPRINT((env, DB_STR("5543",
394+ "Error, database contains no visible pages.")));
395+ return (DB_RUNRECOVERY);
396+ }
397
398 if ((ret = __db_vrfy_getpageinfo(vdp, meta, &pip)) != 0)
399 return (ret);
400@@ -1993,7 +2002,8 @@ __db_salvage_pg(dbp, vdp, pgno, h, handl
401 int keyflag, ret, t_ret;
402
403 env = dbp->env;
404- DB_ASSERT(env, LF_ISSET(DB_SALVAGE));
405+ if (!LF_ISSET(DB_SALVAGE))
406+ return (EINVAL);
407
408 /*
409 * !!!
410@@ -2126,10 +2136,8 @@ __db_salvage_leaf(dbp, vdp, pgno, h, han
411 int (*callback) __P((void *, const void *));
412 u_int32_t flags;
413 {
414- ENV *env;
415-
416- env = dbp->env;
417- DB_ASSERT(env, LF_ISSET(DB_SALVAGE));
418+ if (!LF_ISSET(DB_SALVAGE))
419+ return (EINVAL);
420
421 /* If we got this page in the subdb pass, we can safely skip it. */
422 if (__db_salvage_isdone(vdp, pgno))
423@@ -2223,8 +2231,8 @@ __db_salvage_unknowns(dbp, vdp, handle,
424 ret = t_ret;
425 break;
426 case SALVAGE_OVERFLOW:
427- DB_ASSERT(env, 0); /* Shouldn't ever happen. */
428- break;
429+ EPRINT((env, DB_STR("5544", "Invalid page type to salvage.")));
430+ return (EINVAL);
431 case SALVAGE_HASH:
432 if ((t_ret = __ham_salvage(dbp, vdp,
433 pgno, h, handle, callback, flags)) != 0 && ret == 0)
434@@ -2237,8 +2245,8 @@ __db_salvage_unknowns(dbp, vdp, handle,
435 * Shouldn't happen, but if it does, just do what the
436 * nice man says.
437 */
438- DB_ASSERT(env, 0);
439- break;
440+ EPRINT((env, DB_STR("5545", "Invalid page type to salvage.")));
441+ return (EINVAL);
442 }
443 if ((t_ret = __memp_fput(mpf,
444 vdp->thread_info, h, dbp->priority)) != 0 && ret == 0)
445@@ -2284,8 +2292,8 @@ __db_salvage_unknowns(dbp, vdp, handle,
446 ret = t_ret;
447 break;
448 default:
449- DB_ASSERT(env, 0); /* Shouldn't ever happen. */
450- break;
451+ EPRINT((env, DB_STR("5546", "Invalid page type to salvage.")));
452+ return (EINVAL);
453 }
454 if ((t_ret = __memp_fput(mpf,
455 vdp->thread_info, h, dbp->priority)) != 0 && ret == 0)
456@@ -2342,7 +2350,10 @@ __db_vrfy_inpitem(dbp, h, pgno, i, is_bt
457
458 env = dbp->env;
459
460- DB_ASSERT(env, himarkp != NULL);
461+ if (himarkp == NULL) {
462+ __db_msg(env, "Page %lu index has no end.", (u_long)pgno);
463+ return (DB_VERIFY_FATAL);
464+ }
465 inp = P_INP(dbp, h);
466
467 /*
468@@ -2755,7 +2766,11 @@ __db_salvage_subdbpg(dbp, vdp, master, h
469 goto err;
470 ovfl_bufsz = bkkey->len + 1;
471 }
472- DB_ASSERT(env, subdbname != NULL);
473+ if (subdbname == NULL) {
474+ EPRINT((env, DB_STR("5547", "Subdatabase cannot be null.")));
475+ ret = EINVAL;
476+ goto err;
477+ }
478 memcpy(subdbname, bkkey->data, bkkey->len);
479 subdbname[bkkey->len] = '\0';
480 }
481--- a/src/db/db_vrfyutil.c
482+++ b/src/db/db_vrfyutil.c
483@@ -208,7 +208,8 @@ __db_vrfy_getpageinfo(vdp, pgno, pipp)
484 if ((ret = __db_get(pgdbp,
485 vdp->thread_info, vdp->txn, &key, &data, 0)) == 0) {
486 /* Found it. */
487- DB_ASSERT(env, data.size == sizeof(VRFY_PAGEINFO));
488+ if (data.size != sizeof(VRFY_PAGEINFO))
489+ return (DB_VERIFY_FATAL);
490 pip = data.data;
491 LIST_INSERT_HEAD(&vdp->activepips, pip, links);
492 goto found;
493@@ -336,7 +337,8 @@ __db_vrfy_pgset_get(dbp, ip, txn, pgno,
494 F_SET(&data, DB_DBT_USERMEM);
495
496 if ((ret = __db_get(dbp, ip, txn, &key, &data, 0)) == 0) {
497- DB_ASSERT(dbp->env, data.size == sizeof(int));
498+ if (data.size != sizeof(int))
499+ return (EINVAL);
500 } else if (ret == DB_NOTFOUND)
501 val = 0;
502 else
503@@ -376,7 +378,8 @@ __db_vrfy_pgset_inc(dbp, ip, txn, pgno)
504 F_SET(&data, DB_DBT_USERMEM);
505
506 if ((ret = __db_get(dbp, ip, txn, &key, &data, 0)) == 0) {
507- DB_ASSERT(dbp->env, data.size == sizeof(int));
508+ if (data.size != sizeof(int))
509+ return (DB_VERIFY_FATAL);
510 } else if (ret != DB_NOTFOUND)
511 return (ret);
512
513@@ -413,7 +416,8 @@ __db_vrfy_pgset_next(dbc, pgnop)
514 if ((ret = __dbc_get(dbc, &key, &data, DB_NEXT)) != 0)
515 return (ret);
516
517- DB_ASSERT(dbc->env, key.size == sizeof(db_pgno_t));
518+ if (key.size != sizeof(db_pgno_t))
519+ return (DB_VERIFY_FATAL);
520 *pgnop = pgno;
521
522 return (0);
523@@ -560,7 +564,8 @@ __db_vrfy_ccset(dbc, pgno, cipp)
524 if ((ret = __dbc_get(dbc, &key, &data, DB_SET)) != 0)
525 return (ret);
526
527- DB_ASSERT(dbc->env, data.size == sizeof(VRFY_CHILDINFO));
528+ if (data.size != sizeof(VRFY_CHILDINFO))
529+ return (DB_VERIFY_FATAL);
530 *cipp = (VRFY_CHILDINFO *)data.data;
531
532 return (0);
533@@ -588,7 +593,8 @@ __db_vrfy_ccnext(dbc, cipp)
534 if ((ret = __dbc_get(dbc, &key, &data, DB_NEXT_DUP)) != 0)
535 return (ret);
536
537- DB_ASSERT(dbc->env, data.size == sizeof(VRFY_CHILDINFO));
538+ if (data.size != sizeof(VRFY_CHILDINFO))
539+ return (DB_VERIFY_FATAL);
540 *cipp = (VRFY_CHILDINFO *)data.data;
541
542 return (0);
543@@ -715,7 +721,8 @@ __db_salvage_getnext(vdp, dbcp, pgnop, p
544 return (ret);
545
546 while ((ret = __dbc_get(*dbcp, &key, &data, DB_NEXT)) == 0) {
547- DB_ASSERT(dbp->env, data.size == sizeof(u_int32_t));
548+ if (data.size != sizeof(u_int32_t))
549+ return (DB_VERIFY_FATAL);
550 memcpy(&pgtype, data.data, sizeof(pgtype));
551
552 if (skip_overflow && pgtype == SALVAGE_OVERFLOW)
553@@ -724,8 +731,9 @@ __db_salvage_getnext(vdp, dbcp, pgnop, p
554 if ((ret = __dbc_del(*dbcp, 0)) != 0)
555 return (ret);
556 if (pgtype != SALVAGE_IGNORE) {
557- DB_ASSERT(dbp->env, key.size == sizeof(db_pgno_t));
558- DB_ASSERT(dbp->env, data.size == sizeof(u_int32_t));
559+ if (key.size != sizeof(db_pgno_t)
560+ || data.size != sizeof(u_int32_t))
561+ return (DB_VERIFY_FATAL);
562
563 *pgnop = *(db_pgno_t *)key.data;
564 *pgtypep = *(u_int32_t *)data.data;
565--- a/src/db/partition.c
566+++ b/src/db/partition.c
567@@ -461,9 +461,19 @@ __partition_chk_meta(dbp, ip, txn, flags
568 } else
569 part->nparts = meta->nparts;
570 } else if (meta->nparts != 0 && part->nparts != meta->nparts) {
571+ ret = EINVAL;
572 __db_errx(env, DB_STR("0656",
573 "Number of partitions does not match."));
574+ goto err;
575+ }
576+ /*
577+ * There is no limit on the number of partitions, but I cannot imagine a real
578+ * database having more than 10000.
579+ */
580+ if (meta->nparts > 10000) {
581 ret = EINVAL;
582+ __db_errx(env, DB_STR_A("5553",
583+ "Too many partitions %lu", "%lu"), (u_long)(meta->nparts));
584 goto err;
585 }
586
587@@ -1874,10 +1884,13 @@ __part_verify(dbp, vdp, fname, handle, c
588 memcpy(rp->data, key->data, key->size);
589 B_TSET(rp->type, B_KEYDATA);
590 }
591-vrfy: if ((t_ret = __db_verify(*pdbp, ip, (*pdbp)->fname,
592- NULL, handle, callback,
593- lp, rp, flags | DB_VERIFY_PARTITION)) != 0 && ret == 0)
594- ret = t_ret;
595+vrfy: if ((t_ret = __db_verify(*pdbp, ip, (*pdbp)->fname,
596+ NULL, handle, callback,
597+ lp, rp, flags | DB_VERIFY_PARTITION)) != 0 && ret == 0) {
598+ ret = t_ret;
599+ if (ret == ENOENT)
600+ break;
601+ }
602 }
603
604 err: if (lp != NULL)
605--- a/src/hash/hash_page.c
606+++ b/src/hash/hash_page.c
607@@ -865,7 +865,11 @@ __ham_verify_sorted_page (dbc, p)
608 /* Validate that next, prev pointers are OK */
609 n = NUM_ENT(p);
610 dbp = dbc->dbp;
611- DB_ASSERT(dbp->env, n%2 == 0 );
612+ if (n % 2 != 0) {
613+ __db_errx(dbp->env, DB_STR_A("5549",
614+ "Odd number of entries on page: %lu", "%lu"), (u_long)(p->pgno));
615+ return (DB_VERIFY_FATAL);
616+ }
617
618 env = dbp->env;
619 t = dbp->h_internal;
620@@ -936,7 +940,12 @@ __ham_verify_sorted_page (dbc, p)
621 if ((ret = __db_prpage(dbp, p, DB_PR_PAGE)) != 0)
622 return (ret);
623 #endif
624- DB_ASSERT(dbp->env, res < 0);
625+ if (res >= 0) {
626+ __db_errx(env, DB_STR_A("5550",
627+ "Odd number of entries on page: %lu", "%lu"),
628+ (u_long)p->pgno);
629+ return (DB_VERIFY_FATAL);
630+ }
631 }
632
633 prev = curr;
634--- a/src/hash/hash_verify.c
635+++ b/src/hash/hash_verify.c
636@@ -443,7 +443,7 @@ __ham_vrfy_structure(dbp, vdp, meta_pgno
637 isbad = 1;
638 else
639 goto err;
640- }
641+ }
642
643 /*
644 * There may be unused hash pages corresponding to buckets
645@@ -574,7 +574,7 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, f
646 "Page %lu: impossible first page in bucket %lu", "%lu %lu"),
647 (u_long)pgno, (u_long)bucket));
648 /* Unsafe to continue. */
649- isbad = 1;
650+ ret = DB_VERIFY_FATAL;
651 goto err;
652 }
653
654@@ -604,7 +604,7 @@ __ham_vrfy_bucket(dbp, vdp, m, bucket, f
655 EPRINT((env, DB_STR_A("1116",
656 "Page %lu: hash page referenced twice", "%lu"),
657 (u_long)pgno));
658- isbad = 1;
659+ ret = DB_VERIFY_FATAL;
660 /* Unsafe to continue. */
661 goto err;
662 } else if ((ret = __db_vrfy_pgset_inc(vdp->pgset,
663@@ -1049,7 +1049,11 @@ __ham_meta2pgset(dbp, vdp, hmeta, flags,
664 COMPQUIET(flags, 0);
665 ip = vdp->thread_info;
666
667- DB_ASSERT(dbp->env, pgset != NULL);
668+ if (pgset == NULL) {
669+ EPRINT((dbp->env, DB_STR("5548",
670+ "Error, database contains no visible pages.")));
671+ return (DB_VERIFY_FATAL);
672+ }
673
674 mpf = dbp->mpf;
675 totpgs = 0;
676--- a/src/qam/qam_verify.c
677+++ b/src/qam/qam_verify.c
678@@ -465,7 +465,14 @@ __qam_vrfy_walkqueue(dbp, vdp, handle, c
679 /* Verify/salvage each page. */
680 if ((ret = __db_cursor(dbp, vdp->thread_info, NULL, &dbc, 0)) != 0)
681 return (ret);
682-begin: for (; i <= stop; i++) {
683+begin: if ((stop - i) > 100000) {
684+ EPRINT((env, DB_STR_A("5551",
685+"Warning, many possible extends files (%lu), will take a long time to verify",
686+ "%lu"), (u_long)(stop - i)));
687+ }
688+ for (; i <= stop; i++) {
689+ if (i == UINT32_MAX)
690+ break;
691 /*
692 * If DB_SALVAGE is set, we inspect our database of completed
693 * pages, and skip any we've already printed in the subdb pass.