[php-src] Issue #8773: MySQL PDO: `PDOStatement::execute` returns `false` without neither throwing an exception nor setting `PDOStatement::errorCode`
if many (~1000) query parameters are bound
| From: | nagmat84 | Date: | Tue, 14 Jun 2022 07:19:57 +0000 |
| Subject: | [php-src] Issue #8773: MySQL PDO: `PDOStatement::execute` returns `false` without neither throwing an exception nor setting `PDOStatement::errorCode` if many (~1000) query parameters are bound |
||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-241726@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/8773
Author: nagmat84
### Description
### Summary
If a query binds many (i.e. around 1000) parameters, the method
PDOStatement::execute()
fails and returns false. Even though PDO::ERRMODE_EXCEPTION is set as part
of the PDO options no exception is thrown. PDOStatement::execute() neither sets
PDOStatement::errorCode(). However, a subsequent fetchAll returns an empty
array with zero query results.
Note, that the bug can be worked around, if the binding are resolved manually. This mean if all
placeholders '?' inside the query string are replaced by their actual value
before the query is passed to PDOStatement::prepare(), then
PDOStatement::execute() does not fail and a subsequent
PDOStatement::fetchAll() returns the expected number of results.
The issue has been reported by a couple of our users of https://github.com/LycheeOrg/Lychee. We have tracked
it down to the PDO layer, i.e. it is not a bug in our code nor in the Laravel framework. A MWE which
triggers the bug is located in https://github.com/LycheeOrg/MySQL1000Bug. The
bug only occurs for a couple of users not everyone. But if the bug occurs for a specific setup, then
the bug occurs deterministically. So far, we have seen bug reports from users with PHP 8.1.2 and
8.1.5 – 8.1.7. We haven't seen any bug reports for 8.0.x, but this doesn't mean
that the bug might not exist there as well. Among the core developer team @querty287 has been able
to reproduce the faulty behaviour on his development machine.
As the bug only occurs for many query parameters and only for specific setups it smells like a
memory corruption bug in the MySQL PDO code which is responsible for parameter binding.
### Steps to reproduce the problem
1. Checkout the repository https://github.com/LycheeOrg/MySQL1000Bug
2. Create a new MySQL/Maria DB
3. Load the included [MySQL
dump](https://github.com/LycheeOrg/MySQL1000Bug/blob/master/mysql_1000_bug.sql) into the DB.
4. Make a copy config.php of the provided
[config.php.example](https://github.com/LycheeOrg/MySQL1000Bug/blob/master/config.php.example) and
adopt it to your DB settings.
5. Run the test script
[./mysql_1000_bug](https://github.com/LycheeOrg/MySQL1000Bug/blob/master/mysql_1000_bug.php).
#### Output if the bug occurs
```
Test #1 - Query without bindings
bind_values() : bound 0 values in total
select_query() : $statement->fetchAll returned 7380 results
check_db_result() : Everything seems fine :-(
Test #2 - Query with bindings
bind_values() : binding value __OcYDO3i7Bm9MaCx5SWJj_D as string to placeholder 1 succeeded
...
bind_values() : binding value Zzik4C_-V-WhyyYcn2QLlaEG as string to placeholder 1074 succeeded
bind_values() : bound 1074 values in total
select_query() : $statement->execute() failed without exception, oh, oh
select_query() : $statement->execute() returned error: 00000
select_query() : $statement->execute() returned error info:
array(3) {
[0]=>
string(5) "00000"
[1]=>
NULL
[2]=>
NULL
}
select_query() : $statement->fetchAll returned 0 results
check_db_result : fetched wrong number of size variants; got 0, expected 7380
```
#### Expected output if the bug does not occur
```
Test #1 - Query without bindings
bind_values() : bound 0 values in total
select_query() : $statement->fetchAll returned 7380 results
check_db_result() : Everything seems fine :-(
Test #2 - Query with bindings
bind_values() : binding value __OcYDO3i7Bm9MaCx5SWJj_D as string to placeholder 1 succeeded
...
bind_values() : binding value Zzik4C_-V-WhyyYcn2QLlaEG as string to placeholder 1074 succeeded
bind_values() : bound 1074 values in total
select_query() : $statement->fetchAll returned 7380 results
check_db_result() : Everything seems fine :-(
```
### Further information
| | |
|:----------------------------|:-----------------------|
| **PHP version for which the bug has been observed:** | 8.1.2 and 8.1.5 – 8.1.7 |
| **Downstream issue:** | https://github.com/LycheeOrg/Lychee/issues/1326
|
| **MWE repo:** | https://github.com/LycheeOrg/MySQL1000Bug |
### PHP Version
PHP 8.1.7
### Operating System
_No response_