mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-10-02 15:25:32 +00:00

Previously, `TextRow::decode_with` would read a length-encoded field size and attempt to advance the buffer by that amount. If the server sent a malformed packet containing a length value larger than the remaining data in the buffer, the call to `buf.advance(size)` would panic. eg: ``` thread 'main' panicked at /home/user/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.10.1/src/bytes.rs:711:9: cannot advance past remaining: 8590116092 <= 0 stack backtrace: 0: 0x56119b657e00 - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::h6d42cc84fc840290 1: 0x56119b67edd3 - core::fmt::write::h5af61a909e3ec64d 2: 0x56119b653ee3 - std::io::Write::write_fmt::h5a7b54aa6e4a315d 3: 0x56119b657c52 - std::sys::backtrace::BacktraceLock::print::h555579e7396c26ac 4: 0x56119b658cef - std::panicking::default_hook::{{closure}}::h9128866118196224 5: 0x56119b658b5a - std::panicking::default_hook::h52e9e7314e0255f6 6: 0x56119b659712 - std::panicking::rust_panic_with_hook::h541791bcc774ef34 7: 0x56119b65949a - std::panicking::begin_panic_handler::{{closure}}::h6479a2f0137c7d19 8: 0x56119b658319 - std::sys::backtrace::__rust_end_short_backtrace::ha04e7c0fc61ded91 9: 0x56119b65912d - rust_begin_unwind 10: 0x56119b67c390 - core::panicking::panic_fmt::h5764ee7030b7a73d 11: 0x56119b572b18 - <sqlx_mysql::protocol::text::row::TextRow as sqlx_core::io::decode::ProtocolDecode<&[sqlx_mysql::column::MySqlColumn]>>::decode_with::h17ac8b44140b5469 12: 0x56119b42df1f - sqlx_mysql::connection::executor::<impl sqlx_mysql::connection::MySqlConnection>::run::{{closure}}::{{closure}}::{{closure}}::h4874a0f73925d55a ``` This commit introduces a bounds check immediately after reading the field length from a packet. This panic condition was specifically observed when executing a TiDB `BATCH ON ... DELETE` statement via `pool.execute()`. It sends an OK packet immediately followed by a full result set describing the batch status (column defs, row data, EOF). Observed TiDB response sequence for `BATCH DML` via `COM_QUERY`: 1. OK Packet (seq=1, `SERVER_MORE_RESULTS_EXISTS` = false) 2. Column Count Packet (seq=1, non-standard, protocol violation) 3. Column Definition Packet (seq=2) 4. Column Definition Packet (seq=3) 5. Text Row Data Packet (seq=4) 6. EOF Packet (seq=5, `SERVER_MORE_RESULTS_EXISTS` = false) This differs from standard MySQL DML response (OK/ERR packet only) and causes `sqlx` using `execute()` to attempt parsing the unexpected result set packets after the initial OK packet.