[Note crosspost: I'm not sure who's maintaining DB 1.x, but since OpenBSD is
still shipping it, I hope someone is taking bug reports. I'm not an OpenBSD
user but have got a bug report from a OpenBSD user about a program I wrote
that uses Berkeley DB, so I investigated DB 1.x and found the bug there]
The bug: In the hash access method, if there are many DB->get() calls in
between two consecutive DB->seq() calls, it is possible for the cursor page
to become the LRU, and then get overwritten by a new page read from disk.
After that happens, the next DB->seq() returns fragments of the new page
instead of the correct key and data.
This patch seems to work, although I'm not extremely familiar with DB
internals; there is probably a more elegant way to fix the problem (like
having hash_seq() check the validity of the page and reload it from disk if
necessary - I tried that but couldn't make it work so I switched to the easy
way).
=== CUT HERE ===
--- libdb-1.85.4.orig/hash/hash_buf.c Fri Jul 15 07:23:46 1994
+++ libdb-1.85.4.pac/hash/hash_buf.c Thu Sep 9 01:41:44 2004
@@ -171,11 +171,19 @@
oaddr = 0;
bp = LRU;
+
+ /* It is bad to overwrite the page under the cursor. */
+ if(bp==hashp->cpage) {
+ BUF_REMOVE(bp);
+ MRU_INSERT(bp);
+ bp = LRU;
+ }
+
/*
* If LRU buffer is pinned, the buffer pool is too small. We need to
* allocate more buffers.
*/
- if (hashp->nbufs || (bp->flags & BUF_PIN)) {
+ if (hashp->nbufs || (bp->flags & BUF_PIN) || bp==hashp->cpage) {
/* Allocate a new one */
if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL)
return (NULL);
=== CUT HERE ===
--
Alan Curry
pacman@clss.net