Skip to content

MDEV-40497 KEY_OP_ADD_PREFIX copies changed_length without checking header_end - #5582

Open
KhaledR57 wants to merge 1 commit into
10.11from
10.11-MDEV-40497
Open

MDEV-40497 KEY_OP_ADD_PREFIX copies changed_length without checking header_end#5582
KhaledR57 wants to merge 1 commit into
10.11from
10.11-MDEV-40497

Conversation

@KhaledR57

Copy link
Copy Markdown
Contributor

The KEY_OP_ADD_PREFIX branch of _ma_apply_redo_index() passed changed_length from the redo record to memcpy() without checking it against the end of that record, and bounded the page side with a DBUG_ASSERT that release builds compile out. That assert never bounded changed_length at all, it only related it to insert_length, so a record could satisfy it and still copy past the page.

Turn the assert into a runtime check with the four bounds the branch needs. The prefix data must be inside the record, the memcpy must stay inside the page, the bmove_upp destination must stay inside the page, and insert_length must not exceed changed_length. The last one is the relation the assert already tested, without it the gap between the two lengths keeps whatever was on the page, and recovery reports success on an index that is corrupt.

The test forges one operand per record with four debug keywords, then crashes the server so recovery has to replay them, and each record trips exactly one of the four bounds. The workload splits and then merges index pages, this record comes from the underflow path, so plain inserts never produce one.

…eader_end

The KEY_OP_ADD_PREFIX branch of _ma_apply_redo_index() passed changed_length
from the redo record to memcpy() without checking it against the end of that
record, and bounded the page side with a DBUG_ASSERT that release builds
compile out. That assert never bounded changed_length at all: it only related
it to insert_length, so a record could satisfy it and still copy past the page.

Turn the assert into a runtime check with the four bounds the branch needs.
The prefix data must be inside the record, the memcpy must stay inside the
page, the bmove_upp destination must stay inside the page, and insert_length
must not exceed changed_length. The last one is the relation the assert
already tested, without it the gap between the two lengths keeps whatever was
on the page, and recovery reports success on an index that is corrupt.

The test forges one operand per record with four debug keywords, then crashes
the server so recovery has to replay them, and each record trips exactly one
of the four bounds. The workload splits and then merges index pages, this
record comes from the underflow path, so plain inserts never produce one.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

1 participant