php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78797 mysqlnd cannot read large OK/ERR packets
Submitted: 2019-11-08 22:54 UTC Modified: -
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: as@php.net Assigned:
Status: Open Package: PDO MySQL
PHP Version: 7.4.0RC5 OS:
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: as@php.net
New email:
PHP Version: OS:

 

 [2019-11-08 22:54 UTC] as@php.net
Description:
------------
mysqlnd hits this condition[0] when it receives an OK/ERR packet larger than `mysqlnd.net_cmd_buffer_size`, resulting in "Error reading result set's header...".

These packets have variable-length fields (e.g., error_message[1]) which are not guaranteed to fit in a statically-sized buffer. I'm unsure if popular MySQL versions (Oracle, Percona, MariaDB) will ever emit such packets, however some niche servers that speak the MySQL protocol (e.g., Vitess) do.

[0] https://github.com/php/php-src/blob/4d529757f84cb81d5eba53e77e8395efe4e54334/ext/mysqlnd/mysqlnd_wireprotocol.c#L300-L304

[1] https://dev.mysql.com/doc/internals/en/packet-ERR_Packet.html


Test script:
---------------
Normal behavior (ERR packet shorter than `mysqlnd.net_cmd_buffer_size`)

```
$ # Fake MySQL server that sends handshake, then OK, then 4kb ERR packet
$ { echo -en "\x34\x00\x00\x00\x0aversion\x00TTTTAAAAAAAA\x00\x00\x00\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; echo -en "\x07\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00"; echo -en "\x00\x10\x00\x01\xff\xff\xff$(for i in {1..4093}; do echo -n A; done)" ; } | nc -l 1234

$ php -n -r '$p = new PDO("mysql:host=127.0.0.1;port=1234", "user", "pass", [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ]); $p->query("select 1");'

Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 65535 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA in Command line code:1
Stack trace:
#0 Command line code(1): PDO->query('select 1')
#1 {main}
  thrown in Command line code on line 1
```


Bug behavior (ERR packet longer than `mysqlnd.net_cmd_buffer_size`)
```
$ # Fake MySQL server that sends handshake, then OK, then 8kb ERR packet
$ { echo -en "\x34\x00\x00\x00\x0aversion\x00TTTTAAAAAAAA\x00\x00\x00\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; echo -en "\x07\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00"; echo -en "\x00\x20\x00\x01\xff\xff\xff$(for i in {1..8189}; do echo -n A; done)" ; } | nc -l 1234

$ php -n -r '$p = new PDO("mysql:host=127.0.0.1;port=1234", "user", "pass", [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ]); $p->query("select 1");'

Warning: PDO::query(): Error reading result set's header in Command line code on line 1
```



Patches

Pull Requests

 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 16:01:29 2024 UTC