BFS: _SplitNode() could overflow the new node.
* When the keys were large enough, a large key entering the node could overflow the available data in the target node. This caused tree and memory corruption. * This fixes bug #6034.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2014, Axel Dörfler, [email protected].
|
* Copyright 2001-2015, Axel Dörfler, [email protected].
|
||||||
* This file may be used under the terms of the MIT License.
|
* This file may be used under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Roughly based on 'btlib' written by Marcus J. Ranum - it shares
|
* Roughly based on 'btlib' written by Marcus J. Ranum - it shares
|
||||||
@@ -1433,8 +1433,8 @@ BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// how many keys will fit in one (half) page?
|
// How many keys will fit in one (half) page?
|
||||||
// that loop will find the answer to this question and
|
// The following loop will find the answer to this question and
|
||||||
// change the key lengths indices for their new home
|
// change the key lengths indices for their new home
|
||||||
|
|
||||||
// "bytes" is the number of bytes written for the new key,
|
// "bytes" is the number of bytes written for the new key,
|
||||||
@@ -1444,25 +1444,23 @@ BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
|||||||
|
|
||||||
size_t size = fNodeSize >> 1;
|
size_t size = fNodeSize >> 1;
|
||||||
int32 out, in;
|
int32 out, in;
|
||||||
|
size_t keyLengths = 0;
|
||||||
for (in = out = 0; in < node->NumKeys() + 1;) {
|
for (in = out = 0; in < node->NumKeys() + 1;) {
|
||||||
if (!bytes) {
|
keyLengths = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in]);
|
||||||
bytesBefore = in > 0
|
|
||||||
? BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in - 1]) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in == keyIndex && !bytes) {
|
if (in == keyIndex && !bytes) {
|
||||||
bytes = *_keyLength;
|
bytes = *_keyLength;
|
||||||
|
bytesBefore = in > 0
|
||||||
|
? BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in - 1]) : 0;
|
||||||
} else {
|
} else {
|
||||||
if (keyIndex < out) {
|
if (keyIndex < out)
|
||||||
bytesAfter = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in])
|
bytesAfter = keyLengths - bytesBefore;
|
||||||
- bytesBefore;
|
|
||||||
}
|
|
||||||
|
|
||||||
in++;
|
in++;
|
||||||
}
|
}
|
||||||
out++;
|
out++;
|
||||||
|
|
||||||
if (key_align(sizeof(bplustree_node) + bytesBefore + bytesAfter + bytes)
|
if (key_align(sizeof(bplustree_node) + bytes + keyLengths)
|
||||||
+ out * (sizeof(uint16) + sizeof(off_t)) >= size) {
|
+ out * (sizeof(uint16) + sizeof(off_t)) >= size) {
|
||||||
// we have found the number of keys in the new node!
|
// we have found the number of keys in the new node!
|
||||||
break;
|
break;
|
||||||
@@ -1471,8 +1469,11 @@ BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
|||||||
|
|
||||||
// if the new key was not inserted, set the length of the keys
|
// if the new key was not inserted, set the length of the keys
|
||||||
// that can be copied directly
|
// that can be copied directly
|
||||||
|
|
||||||
if (keyIndex >= out && in > 0)
|
if (keyIndex >= out && in > 0)
|
||||||
bytesBefore = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in - 1]);
|
bytesBefore = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in - 1]);
|
||||||
|
else if (keyIndex + 1 < out)
|
||||||
|
bytesAfter = keyLengths - bytesBefore;
|
||||||
|
|
||||||
if (bytesBefore < 0 || bytesAfter < 0)
|
if (bytesBefore < 0 || bytesAfter < 0)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|||||||
Reference in New Issue
Block a user