TestGetSystemVarBufferReuse verifies that getSystemVar returns a value that is not corrupted by the subsequent skipRows call. The row value returned by readRow points into the read buffer. skipRows may call fill(), which overwrites that memory. The test feeds each protocol packet as a separate Read
(t *testing.T)
| 298 | // packet as a separate Read call via chunkedConn (mimicking TLS record |
| 299 | // boundaries), guaranteeing that fill() is called for the trailing EOF. |
| 300 | func TestGetSystemVarBufferReuse(t *testing.T) { |
| 301 | // Protocol response for: SELECT @@max_allowed_packet → "67108864" |
| 302 | // |
| 303 | // Sequence numbers start at 1 (client sent COM_QUERY as seq 0). |
| 304 | // |
| 305 | // seq 1: column count = 1 |
| 306 | // seq 2: column definition (minimal valid) |
| 307 | // seq 3: EOF (end of column defs) |
| 308 | // seq 4: row data — length-encoded string "67108864" |
| 309 | // seq 5: EOF (end of rows) |
| 310 | |
| 311 | colCountPkt := makePacket(1, []byte{0x01}) |
| 312 | |
| 313 | colDef := []byte{ |
| 314 | 0x03, 'd', 'e', 'f', // catalog = "def" |
| 315 | 0x00, // schema = "" |
| 316 | 0x00, // table = "" |
| 317 | 0x00, // org_table = "" |
| 318 | 0x14, // name length = 20 |
| 319 | '@', '@', 'm', 'a', 'x', '_', 'a', 'l', 'l', 'o', |
| 320 | 'w', 'e', 'd', '_', 'p', 'a', 'c', 'k', 'e', 't', |
| 321 | 0x00, // org_name = "" |
| 322 | 0x0c, // length of fixed fields |
| 323 | 0x3f, 0x00, // charset = 63 (binary) |
| 324 | 0x14, 0x00, 0x00, 0x00, // column_length = 20 |
| 325 | 0x0f, // type = FIELD_TYPE_VARCHAR |
| 326 | 0x00, 0x00, // flags |
| 327 | 0x00, // decimals |
| 328 | 0x00, 0x00, // filler |
| 329 | } |
| 330 | colDefPkt := makePacket(2, colDef) |
| 331 | |
| 332 | eof1 := makePacket(3, []byte{0xfe, 0x00, 0x00, 0x02, 0x00}) |
| 333 | |
| 334 | // Row: length-encoded string "67108864" (8 bytes → length prefix 0x08) |
| 335 | rowPkt := makePacket(4, []byte{0x08, '6', '7', '1', '0', '8', '8', '6', '4'}) |
| 336 | |
| 337 | eof2 := makePacket(5, []byte{0xfe, 0x00, 0x00, 0x02, 0x00}) |
| 338 | |
| 339 | // Each packet arrives in its own Read call, simulating TLS record |
| 340 | // boundaries where each server Write becomes a separate TLS record |
| 341 | // and each client Read returns exactly one record. |
| 342 | conn := &chunkedConn{chunks: [][]byte{colCountPkt, colDefPkt, eof1, rowPkt, eof2}} |
| 343 | |
| 344 | mc := &mysqlConn{ |
| 345 | netConn: conn, |
| 346 | buf: newBuffer(), |
| 347 | cfg: NewConfig(), |
| 348 | closech: make(chan struct{}), |
| 349 | maxAllowedPacket: defaultMaxAllowedPacket, |
| 350 | sequence: 1, // after COM_QUERY (seq 0) |
| 351 | } |
| 352 | |
| 353 | val, err := mc.getSystemVar("max_allowed_packet") |
| 354 | if err != nil { |
| 355 | t.Fatalf("getSystemVar failed: %v", err) |
| 356 | } |
| 357 |
nothing calls this directly
no test coverage detected