Fix a crash when iterating over a hash and removing its elements.
Obtained from: OpenBSD
This commit is contained in:
parent
3130c353f8
commit
213bceeead
lib/libc/db/hash
@ -539,8 +539,7 @@ hash_put(const DB *dbp, DBT *key, const DBT *data, u_int32_t flag)
|
||||
|
||||
hashp = (HTAB *)dbp->internal;
|
||||
if (flag && flag != R_NOOVERWRITE) {
|
||||
hashp->error = EINVAL;
|
||||
errno = EINVAL;
|
||||
hashp->error = errno = EINVAL;
|
||||
return (ERROR);
|
||||
}
|
||||
if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
|
||||
@ -719,7 +718,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;
|
||||
@ -738,8 +737,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);
|
||||
@ -767,13 +776,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);
|
||||
}
|
||||
|
@ -155,6 +155,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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user