Crafted COM_STMT_EXECUTE triggers index out of range [0] with length 0 in `chunk.(*Column).GetBytes`
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
## Bug Report
Please answer these questions before submitting your issue. Thanks!
### 1. Minimal reproduce step (Required)
1. Start a TiDB server.
2. Install the client dependency:
```bash
pip install pymysql
```
3. Save and run the attached PoC script:
```bash
python3 tidb_panic_poc_2.py --host --port 4000 --user root
```
4. The script will:
- create database `poc_db`
- run the following setup SQL:
```sql
DROP TABLE IF EXISTS t3;
DROP TABLE IF EXISTS t13;
DROP TABLE IF EXISTS t25;
CREATE TABLE t3 (
c1 int,
c2 tinyint,
PRIMARY KEY(c1),
UNIQUE(c1)
);
INSERT IGNORE INTO t3 (c1, c2) VALUES
(coalesce(round(127, (cast(((coalesce(
cast(128 as signed),
cast(null as signed)
) &0xffffffff)+2147483648)&0xffffffff as signed)-2147483648)), -2147483648), (NOT NOT (cast(null as char) != instr((-128 + (1=1)),
cast(case when (NOT NOT (cast(32767 as signed) || -3)) then '66' else '^%c' end as char))))),
(coalesce((cast(((round(-2147483648) &0xffffffff)+2147483648)&0xffffffff as signed)-2147483648), 100663045), ((1=1)
or
(64 between 255 and 0))),
(1, (0<>0));
CREATE TABLE t13 (
c1 int not null,
c2 double,
c3 double not null,
c4 text,
c5 tinyint not null,
c6 text,
c7 double,
PRIMARY KEY(c1),
UNIQUE(c7)
);
CREATE TABLE t25 (
c1 int not null,
c2 double,
c3 int,
c4 double,
c5 text,
c6 text,
c7 int,
PRIMARY KEY(c1, c3),
UNIQUE(c2, c3)
);
```
- send one `COM_STMT_PREPARE`
- send two crafted `COM_STMT_EXECUTE` packets over the MySQL protocol
5. On my side, the panic is triggered by the second `COM_STMT_EXECUTE`.
[tidb_panic_poc_2.py](https://github.com/user-attachments/files/26437438/tidb_panic_poc_2.py)
PoC summary:
- The prepared statement contains 12 bound parameters.
- The prepared SQL is a complex `SELECT ... UNION ALL ... ORDER BY` query over `t3`, `t13`, and `t25`.
- `COM_STMT_EXECUTE #1` uses `new_params_bound_flag=1` with one NULL bitmap and one parameter-type layout.
- `COM_STMT_EXECUTE #2` also uses `new_params_bound_flag=1`, but with a different NULL bitmap and a different parameter-type layout.
- This leads to a server-side panic while handling the prepared statement result.
### 2. What did you expect to see? (Required)
Expect no crashes.
### 3. What did you see instead (Required)
TiDB panicked while handling `COM_STMT_EXECUTE`.
The client side observed an error containing `runtime error`, and the TiDB server log is:
```
[2026/03/27 03:36:25.484 +00:00] [ERROR] [conn.go:1042] ["connection running loop panic"] [conn=2092958350] [session_alias=]
[err="runtime error: index out of range [0] with length 0"]
[stack="github.com/pingcap/tidb/pkg/server.(*clientConn).Run.func1
/data/db/vendor/tidb/tidb/pkg/server/conn.go:1045
runtime.gopanic
/home/fzx/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.23.6.linux-amd64/src/runtime/panic.go:785
github.com/pingcap/tidb/pkg/server.(*clientConn).writeResultSet.func1
/data/db/vendor/tidb/tidb/pkg/server/conn.go:2250
runtime.gopanic
/home/fzx/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.23.6.linux-amd64/src/runtime/panic.go:785
runtime.goPanicIndex
/home/fzx/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.23.6.linux-amd64/src/runtime/panic.go:115
github.com/pingcap/tidb/pkg/util/chunk.(*Column).GetBytes
/data/db/vendor/tidb/tidb/pkg/util/chunk/column.go:688
github.com/pingcap/tidb/pkg/util/chunk.Row.GetBytes
/data/db/vendor/tidb/tidb/pkg/util/chunk/row.go:81
github.com/pingcap/tidb/pkg/server/internal/column.DumpBinaryRow
/data/db/vendor/tidb/tidb/pkg/server/internal/column/column.go:263
github.com/pingcap/tidb/pkg/server.(*clientConn).writeChunks
/data/db/vendor/tidb/tidb/pkg/server/conn.go:2364
github.com/pingcap/tidb/pkg/server.(*clientConn).writeResultSet
/data/db/vendor/tidb/tidb/pkg/server/conn.go:2269
github.com/pingcap/tidb/pkg/server.(*clientConn).executePreparedStmtAndWriteResult
/data/db/vendor/tidb/tidb/pkg/server/conn_stmt.go:342
github.com/pingcap/tidb/pkg/server.(*clientConn).executePlanCacheStmt
/data/db/vendor/tidb/tidb/pkg/server/conn_stmt.go:234
github.com/pingcap/tidb/pkg/server.(*clientConn).handleStmtExecute
/data/db/vendor/tidb/tidb/pkg/server/conn_stmt.go:225
github.com/pingcap/tidb/pkg/server.(*clientConn).dispatch
/data/db/vendor/tidb/tidb/pkg/server/conn.go:1406
github.com/pingcap/tidb/pkg/server.(*clientConn).Run
/data/db/vendor/tidb/tidb/pkg/server/conn.go:1148
github.com/pingcap/tidb/pkg/server.(*Server).onConn
/data/db/vendor/tidb/tidb/pkg/server/server.go:741"]
```
### 4. What is your TiDB version? (Required)
```
Release Version: v8.5.3
Edition: Community
Git Commit Hash: dc2548aac79a712265e831cff2a3a896bc0a5a38
Git Branch: HEAD
UTC Build Time: 2025-09-26 10:07:20
GoVersion: go1.23.6
Race Enabled: false
Check Table Before Drop: false
Store: tikv
```
We are the BASS team from the School of Cyber Science and Technology at Beihang University. Our main focus is on system software security, operating systems, and program analysis research, as well as the development of automated program testing frameworks for detecting software defects. Using our self-developed database vulnerability testing tool, we have identified the above-mentioned vulnerabilities in TiDB that may lead to database crashes.
Contributor guide
Research direction
Start by running the attached tidb_panic_poc_2.py against TiDB v8.5.3, then trace the stack through pkg/util/chunk/column.go, row.go, server/internal/column/column.go, and server/conn_stmt.go. Done means the crafted COM_STMT_EXECUTE sequence returns an error or result without panicking, with regression coverage if an existing test location is identified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, python
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100