/* * Returns: * 0 OK * -1 error */ int __delpair(HTAB *hashp, BUFHEAD *bufp, int ndx) { u_int16_t *bp, newoff, pairlen; int n; bp = (u_int16_t *)bufp->page; n = bp[0]; if (bp[ndx + 1] < REAL_KEY) return (__big_delete(hashp, bufp)); if (ndx != 1) newoff = bp[ndx - 1]; else newoff = hashp->BSIZE; pairlen = newoff - bp[ndx + 1]; if (ndx != (n - 1)) { /* Hard Case -- need to shuffle keys */ int i; char *src = bufp->page + (int)OFFSET(bp); char *dst = src + (int)pairlen; memmove(dst, src, bp[ndx + 1] - OFFSET(bp)); /* Now adjust the pointers */ for (i = ndx + 2; i <= n; i += 2) { if (bp[i + 1] == OVFLPAGE) { bp[i - 2] = bp[i]; bp[i - 1] = bp[i + 1]; } else { bp[i - 2] = bp[i] + pairlen; 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; bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_int16_t); bp[0] = n - 2; hashp->NKEYS--; bufp->flags |= BUF_MOD; return (0); }
/* * Returns: * 0 OK * -1 error */ int __delpair(HTAB *hashp, BUFHEAD *bufp, int ndx) { uint16_t *bp, newoff; int n; uint16_t pairlen; size_t temp; bp = (uint16_t *)(void *)bufp->page; n = bp[0]; if (bp[ndx + 1] < REAL_KEY) return (__big_delete(hashp, bufp)); if (ndx != 1) newoff = bp[ndx - 1]; else newoff = hashp->BSIZE; pairlen = newoff - bp[ndx + 1]; if (ndx != (n - 1)) { /* Hard Case -- need to shuffle keys */ int i; char *src = bufp->page + (int)OFFSET(bp); char *dst = src + (int)pairlen; memmove(dst, src, (size_t)(bp[ndx + 1] - OFFSET(bp))); /* Now adjust the pointers */ for (i = ndx + 2; i <= n; i += 2) { if (bp[i + 1] == OVFLPAGE) { bp[i - 2] = bp[i]; bp[i - 1] = bp[i + 1]; } else { bp[i - 2] = bp[i] + pairlen; bp[i - 1] = bp[i + 1] + pairlen; } } } /* Finally adjust the page data */ bp[n] = OFFSET(bp) + pairlen; temp = bp[n + 1] + pairlen + 2 * sizeof(uint16_t); _DIAGASSERT(temp <= 0xffff); bp[n - 1] = (uint16_t)temp; bp[0] = n - 2; hashp->NKEYS--; bufp->flags |= BUF_MOD; return (0); }
/* * Returns: * 0 OK * -1 error */ extern int __delpair(HTAB *hashp, BUFHEAD *bufp, int ndx) { register uint16 *bp, newoff; register int n; uint16 pairlen; bp = (uint16 *)bufp->page; n = bp[0]; if (bp[ndx + 1] < REAL_KEY) return (__big_delete(hashp, bufp)); if (ndx != 1) newoff = bp[ndx - 1]; else newoff = hashp->BSIZE; pairlen = newoff - bp[ndx + 1]; if (ndx != (n - 1)) { /* Hard Case -- need to shuffle keys */ register int i; register char *src = bufp->page + (int)OFFSET(bp); uint32 dst_offset = (uint32)OFFSET(bp) + (uint32)pairlen; register char *dst = bufp->page + dst_offset; uint32 length = bp[ndx + 1] - OFFSET(bp); /* * +-----------+XXX+---------+XXX+---------+---------> +infinity * | | | | * 0 src_offset dst_offset BSIZE * * Dst_offset is > src_offset, so if src_offset were bad, dst_offset * would be too, therefore we check only dst_offset. * * If dst_offset is >= BSIZE, either OFFSET(bp), or pairlen, or both * is corrupted. * * Once we know dst_offset is < BSIZE, we can subtract it from BSIZE * to get an upper bound on length. */ if (dst_offset > (uint32)hashp->BSIZE) return (DATABASE_CORRUPTED_ERROR); if (length > (uint32)(hashp->BSIZE - dst_offset)) return (DATABASE_CORRUPTED_ERROR); memmove(dst, src, length); /* Now adjust the pointers */ for (i = ndx + 2; i <= n; i += 2) { if (bp[i + 1] == OVFLPAGE) { bp[i - 2] = bp[i]; bp[i - 1] = bp[i + 1]; } else { bp[i - 2] = bp[i] + pairlen; bp[i - 1] = bp[i + 1] + pairlen; } } } /* Finally adjust the page data */ bp[n] = OFFSET(bp) + pairlen; bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(uint16); bp[0] = n - 2; hashp->NKEYS--; bufp->flags |= BUF_MOD; return (0); }