You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
0 commit comments