Validate the length of a BIT column value coming from MySQL - #119680
Conversation
The value of a `MYSQL_TYPE_BIT` column was copied into an eight-byte stack local with `memcpy`, using the length reported by the server without checking it first. A `BIT` column holds at most 64 bits, but nothing bounded what the server actually sent: the length comes from the row packet of the text protocol and is unrelated to the declared width of the column. The `std::reverse` that follows then walked the same out-of-bounds range. So any MySQL endpoint that ClickHouse connects to - through the `mysql` table function, a `MySQL` table or database engine, or a MySQL dictionary - could overflow that local. The translation unit is compiled without a stack protector and without `_FORTIFY_SOURCE`, so nothing detected it. Confirmed against a fake MySQL server: a hundred-byte value produced `4702111234474983745`, the first eight of its bytes, having written the other ninety two past the end of the destination; a 2200-byte value, which is enough to reach the saved return address of `insertValue`, crashed with `SIGBUS` after jumping to an address made out of the value bytes. The length is now checked before the copy, and the new test covers values of two, eight, and a hundred bytes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Workflow [PR], commit [8807675] Summary: ✅
AI ReviewSummaryThis PR adds a length check before copying Findings
Final VerdictNeeds changes before approval: fix the remaining big-endian LLVM Coverage ReportMeasured on commit 8807675.
Changed lines: Changed C/C++ lines covered: 9/9 (100.00%) · Uncovered code |
Build profile diff (arm_release)Comparing ✅ No significant changes. Binary sizes
The official master build is compiled with Compile time of recompiled translation units7 translation units recompiled, 11 s compile time in total, 7 of them have a recent master baseline. |
… coming from MySQL
Backport #119680 to 26.8: Validate the length of a `BIT` column value coming from MySQL
Cherry pick #119680 to 26.3: Validate the length of a `BIT` column value coming from MySQL
Cherry pick #119680 to 26.6: Validate the length of a `BIT` column value coming from MySQL
Backport #119680 to 26.6: Validate the length of a `BIT` column value coming from MySQL
Backport #119680 to 26.3: Validate the length of a `BIT` column value coming from MySQL
… coming from MySQL
Backport #119680 to 26.7: Validate the length of a `BIT` column value coming from MySQL
The value of a
MYSQL_TYPE_BITcolumn was copied into an eight-byte stack local withmemcpy, using the length reported by the server without checking it first. ABITcolumn holds at most 64 bits, but nothing bounded what the server actually sent:value.size()is the field length taken from the row packet of the text protocol, unrelated to the declared width of the column. Thestd::reversethat follows then walked the same out-of-bounds range.So any MySQL endpoint that ClickHouse connects to - through the
mysqltable function, aMySQLtable or database engine, or a MySQL dictionary - could overflow that local.insertValueis a real out-of-line function, and the translation unit is compiled without a stack protector and without_FORTIFY_SOURCE, so nothing detected the overflow.Confirmed against a fake MySQL server:
4702111234474983745, the first eight of itsAbytes, having written the other ninety two past the end of the destination;aarch64release build), crashed withSIGBUSafter jumping to an address made out of the value bytes.The length is now checked before the copy. The new test
04870_mysql_bit_column_oversized_valuestarts a fake MySQL server that returns aBITvalue of two, eight, or a hundred bytes depending on the remote table name: the first two must still be read correctly, most significant byte first, and the last must be rejected.Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):
Fixed a stack buffer overflow when reading a
BITcolumn from MySQL, reachable through themysqltable function, theMySQLtable and database engines, and MySQL dictionaries. The length of the value sent by the server was copied without being validated.Workflow [PR]
Sync PR [sync-upstream/pr/119680]
Version info
26.8.3.105,26.7.8.12,26.6.6.5,26.3.33.73