svn commit: r190494 - head/lib/libc/db/hash
Xin LI
delphij at FreeBSD.org
Fri Mar 27 23:47:06 PDT 2009
Author: delphij
Date: Sat Mar 28 06:47:05 2009
New Revision: 190494
URL: http://svn.freebsd.org/changeset/base/190494
Log:
- If (keysize+datasize)%(bsize=14)==0, insertion of a `big key' would cause
an invariant (actually, an ugly hack) to fail, and all Hell would break
loose.
When deleting a big key, the offset of an empty page should be bsize, not
bsize-1; otherwise an insertion into the empty page will cause the new key to
be elongated by 1 byte.
Make the packing more dense in a couple of cases.
- fix NULL dereference exposed on big bsize values;
Obtained from: NetBSD via OpenBSD
Modified:
head/lib/libc/db/hash/hash_bigkey.c
Modified: head/lib/libc/db/hash/hash_bigkey.c
==============================================================================
--- head/lib/libc/db/hash/hash_bigkey.c Sat Mar 28 06:40:48 2009 (r190493)
+++ head/lib/libc/db/hash/hash_bigkey.c Sat Mar 28 06:47:05 2009 (r190494)
@@ -118,18 +118,30 @@ __big_insert(HTAB *hashp, BUFHEAD *bufp,
return (-1);
n = p[0];
if (!key_size) {
- if (FREESPACE(p)) {
- move_bytes = MIN(FREESPACE(p), val_size);
+ space = FREESPACE(p);
+ if (space) {
+ move_bytes = MIN(space, val_size);
+ /*
+ * If the data would fit exactly in the
+ * remaining space, we must overflow it to the
+ * next page; otherwise the invariant that the
+ * data must end on a page with FREESPACE
+ * non-zero would fail.
+ */
+ if (space == val_size && val_size == val->size)
+ goto toolarge;
off = OFFSET(p) - move_bytes;
- p[n] = off;
memmove(cp + off, val_data, move_bytes);
val_data += move_bytes;
val_size -= move_bytes;
+ p[n] = off;
p[n - 2] = FULL_KEY_DATA;
FREESPACE(p) = FREESPACE(p) - move_bytes;
OFFSET(p) = off;
- } else
+ } else {
+ toolarge:
p[n - 2] = FULL_KEY;
+ }
}
p = (u_int16_t *)bufp->page;
cp = bufp->page;
@@ -239,12 +251,12 @@ __big_delete(HTAB *hashp, BUFHEAD *bufp)
n -= 2;
bp[0] = n;
FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
- OFFSET(bp) = hashp->BSIZE - 1;
+ OFFSET(bp) = hashp->BSIZE;
bufp->flags |= BUF_MOD;
if (rbufp)
__free_ovflpage(hashp, rbufp);
- if (last_bfp != rbufp)
+ if (last_bfp && last_bfp != rbufp)
__free_ovflpage(hashp, last_bfp);
hashp->NKEYS--;
More information about the svn-src-head
mailing list