summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTom Yu <tlyu@mit.edu>2008-02-01 01:03:11 +0000
committerTom Yu <tlyu@mit.edu>2008-02-01 01:03:11 +0000
commit85df09ef7fa81dc4db8490740cbf8e989204791c (patch)
tree977ff317437d8f450c75efefa76ea02691afbb67 /src
parent63d05278674313f56b0b9299b43e69c8cf31c177 (diff)
downloadkrb5-85df09ef7fa81dc4db8490740cbf8e989204791c.tar.gz
krb5-85df09ef7fa81dc4db8490740cbf8e989204791c.tar.xz
krb5-85df09ef7fa81dc4db8490740cbf8e989204791c.zip
libdb btree page split on zero index corrupts db
Splitting a btree page on index 0 can corrupt the database if the key length plus data length is exactly a certain value. This certain size causes the item to get the left page to itself, and causes the right page to contain an erroneous additional index "hole" having an uninitialized value. This bug may be one of the remaining causes of unexplained database corruption reported over the years. Shawn Emery provided useful data from actual instances of this corruption. Add a test case for this bug. (Raw libdb test rather than kdb; the latter would be much harder.) ticket: new target_version: 1.6.4 tags: pullup component: krb5-kdc git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20214 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/plugins/kdb/db2/libdb2/btree/bt_split.c4
-rw-r--r--src/plugins/kdb/db2/libdb2/test/run.test54
2 files changed, 54 insertions, 4 deletions
diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_split.c b/src/plugins/kdb/db2/libdb2/btree/bt_split.c
index 62ec823a1..9b2708e76 100644
--- a/src/plugins/kdb/db2/libdb2/btree/bt_split.c
+++ b/src/plugins/kdb/db2/libdb2/btree/bt_split.c
@@ -727,7 +727,7 @@ bt_psplit(t, h, l, r, pskip, ilen)
* the right page.
*/
if (skip <= off) {
- skip = 0;
+ skip = (indx_t)-1;
rval = l;
} else {
rval = r;
@@ -737,7 +737,7 @@ bt_psplit(t, h, l, r, pskip, ilen)
for (off = 0; nxt < top; ++off) {
if (skip == nxt) {
++off;
- skip = 0;
+ skip = (indx_t)-1;
}
switch (h->flags & P_TYPE) {
case P_BINTERNAL:
diff --git a/src/plugins/kdb/db2/libdb2/test/run.test b/src/plugins/kdb/db2/libdb2/test/run.test
index 48c3a63d0..377d6f794 100644
--- a/src/plugins/kdb/db2/libdb2/test/run.test
+++ b/src/plugins/kdb/db2/libdb2/test/run.test
@@ -34,7 +34,7 @@ main()
bindir=/bin/.
if [ $# -eq 0 ]; then
- for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20; do
+ for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20 40; do
test$t
done
else
@@ -45,7 +45,7 @@ main()
[0-9]*)
test$1;;
btree)
- for t in 1 2 3 7 8 9 10 12 13; do
+ for t in 1 2 3 7 8 9 10 12 13 40; do
test$t
done;;
hash)
@@ -743,4 +743,54 @@ bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
done
}
+# Test for a weird page split condition where an insertion into index
+# 0 of a page that would cause the new item to be the only item on the
+# left page results in index 0 of the right page being erroneously
+# skipped; this only happens with one particular key+data length for
+# each page size.
+test40 () {
+ echo "Test 40: btree: page split on index 0"
+ e=:
+ for psize in 512 1024 2048 4096 8192; do
+ echo " page size $psize"
+ kdsizes=`awk 'BEGIN {
+ psize = '$psize'; hsize = int(psize/2);
+ for (kdsize = hsize-40; kdsize <= hsize; kdsize++) {
+ print kdsize;
+ }
+ }' /dev/null`
+
+ # Use a series of keylen+datalen values in the right
+ # neighborhood to find the one that triggers the bug.
+ # We could compute the exact size that triggers the
+ # bug but this additional fuzz may be useful.
+
+ # Insert keys in reverse order to maximize the chances
+ # for a split on index 0.
+
+ for kdsize in $kdsizes; do
+ awk 'BEGIN {
+ kdsize = '$kdsize';
+ for (i = 8; i-- > 0; ) {
+ s = sprintf("a%03d:%09d", i, kdsize);
+ for (j = 0; j < kdsize-20; j++) {
+ s = s "x";
+ }
+ printf("p\nka%03d\nd%s\n", i, s);
+ }
+ print "o";
+ }' /dev/null > $TMP2
+ sed -n 's/^d//p' $TMP2 | sort > $TMP1
+ $PROG -o $TMP3 -i psize=$psize btree $TMP2
+ if (cmp -s $TMP1 $TMP3); then :
+ else
+ echo "test40: btree: page size $psize, \
+keylen+datalen=$kdsize failed"
+ e='exit 1'
+ fi
+ done
+ done
+ $e
+}
+
main $*