summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2008-05-11 22:21:26 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2008-05-11 22:21:26 +0000
commit7eb9b2c9806f4234440c285967032043f8ddcb06 (patch)
tree154ff246966c3939266fcd33541244d4bd677f1f /lib/libc
parentc08e12cb4bc1fb7c6dd0eb0017f1ed139d2fc4dd (diff)
Fix a crash when iterating over a hash and removing its elements.
From Patrick Keshishian. OK pvalchev@
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/db/hash/hash.c23
-rw-r--r--lib/libc/db/hash/hash_page.c10
2 files changed, 22 insertions, 11 deletions
diff --git a/lib/libc/db/hash/hash.c b/lib/libc/db/hash/hash.c
index adc13c708ed..1ec9ec8bf00 100644
--- a/lib/libc/db/hash/hash.c
+++ b/lib/libc/db/hash/hash.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hash.c,v 1.21 2006/03/19 19:51:53 otto Exp $ */
+/* $OpenBSD: hash.c,v 1.22 2008/05/11 22:21:25 millert Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -705,7 +705,7 @@ hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag)
hashp->cndx = 1;
hashp->cpage = NULL;
}
-
+ next_bucket:
for (bp = NULL; !bp || !bp[0]; ) {
if (!(bufp = hashp->cpage)) {
for (bucket = hashp->cbucket;
@@ -724,8 +724,18 @@ hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag)
hashp->cbucket = -1;
return (ABNORMAL);
}
- } else
+ } else {
bp = (u_int16_t *)hashp->cpage->page;
+ if (flag == R_NEXT) {
+ hashp->cndx += 2;
+ if (hashp->cndx > bp[0]) {
+ hashp->cpage = NULL;
+ hashp->cbucket++;
+ hashp->cndx = 1;
+ goto next_bucket;
+ }
+ }
+ }
#ifdef DEBUG
assert(bp);
@@ -755,13 +765,6 @@ hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag)
key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
data->data = (u_char *)hashp->cpage->page + bp[ndx + 1];
data->size = bp[ndx] - bp[ndx + 1];
- ndx += 2;
- if (ndx > bp[0]) {
- hashp->cpage = NULL;
- hashp->cbucket++;
- hashp->cndx = 1;
- } else
- hashp->cndx = ndx;
}
return (SUCCESS);
}
diff --git a/lib/libc/db/hash/hash_page.c b/lib/libc/db/hash/hash_page.c
index a744e689b41..05bc2734506 100644
--- a/lib/libc/db/hash/hash_page.c
+++ b/lib/libc/db/hash/hash_page.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hash_page.c,v 1.18 2007/09/17 07:07:23 moritz Exp $ */
+/* $OpenBSD: hash_page.c,v 1.19 2008/05/11 22:21:25 millert Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -149,6 +149,14 @@ __delpair(HTAB *hashp, BUFHEAD *bufp, int ndx)
bp[i - 1] = bp[i + 1] + pairlen;
}
}
+ if (ndx == hashp->cndx) {
+ /*
+ * We just removed pair we were "pointing" to.
+ * By moving back the cndx we ensure subsequent
+ * hash_seq() calls won't skip over any entries.
+ */
+ hashp->cndx -= 2;
+ }
}
/* Finally adjust the page data */
bp[n] = OFFSET(bp) + pairlen;