Repository navigation
Validate index node key size in the duplicate scanner - #9242
Conversation
IndexDuplicateScanner::find() rebuilds each key from a leaf node with
m_keyLength = node.length + node.prefix;
memcpy(currentKey + node.prefix, node.data, node.length);
where prefix and length are taken straight from the index page while
currentKey holds BTR_key_length() bytes. Nothing checked the expanded
key against the buffer, so a corrupted leaf node with an inflated
prefix (the varint allows up to 16383) made the copy run past the
buffer. walk_index() in validation.cpp already guards its own scan
this way, the scanner did not.
Add IndexNode::keyFits() and raise BUGCHECK(204) in the scanner when
the node does not fit the key buffer. Checked with a database whose
unique unvalidated index has a leaf node with prefix = 16383: ALTER
INDEX ... VALIDATE UNIQUE used to crash the engine reading that page,
it now stops with the index inconsistency error, and validating a sane
index still reports duplicates as before. The range check is covered
by the new IndexNodeTest cases running as part of libEngine14_test.
|
It is enough to check |
As suggested in the review: the check does not need a helper method on IndexNode, it is a single comparison at the call site. The bound covers the whole copy (prefix + length), since a node with a small prefix but a large length also runs past the key buffer. The trivial unit test goes away with the helper.
|
Agreed, dropped the helper and the test, the check is inline now. One note on the bound itself: checking only |
|
Much better, thanks.
Sure, and I already corrected myself in this regards. Before BUGCHECK is it necessary to |
|
Right, the window must be released on this path. I'll also move the check right after |
As discussed in the review: reject a node as soon as it is read instead of at the copy, and release the CCH window before raising BUGCHECK so the error path does not leave the page latched.
IndexDuplicateScanner::find()rebuilds each key from a leaf node withwhere
prefixandlengthare taken straight from the index page whilecurrentKeyholdsBTR_key_length()bytes. Nothing checked the expanded key against the buffer, so a corrupted leaf node with an inflatedprefix(the varint encoding allows up to 16383) made the copy run past the key buffer and crash the engine.walk_index()in validation.cpp already guards its own scan this way; the scanner did not.This adds
IndexNode::keyFits()and raises BUGCHECK(204) in the scanner when the node does not fit the key buffer, mirroring the check done during validation.Checked with a database whose unique unvalidated index (left over by a failed
CREATE UNIQUE INDEX ... CONCURRENTLY) carries a leaf node withprefix = 16383:ALTER INDEX ... VALIDATE UNIQUEused to segfault reading that page, it now stops with the index inconsistency error, and validating a sane index still reports duplicates exactly as before. The range check is covered by the newIndexNodeTestcases running as part oflibEngine14_test.