[GIT-PULLS] [php-src] PR #22739: Prevent reentrant PDOStatement operations
[email protected] (iliaal)
| Newsgroups | php.git-pulls |
|---|---|
| Message-ID | <[email protected]> |
Pull Request: https://github.com/php/php-src/pull/22739
Author: iliaal
PDO core runs userland PHP while holding or mutating a statement's live binding and fetch state (object parameter stringification, bound-value destructors, error/fetch/output handlers). That code can reenter the same statement's `execute()` or `bind*()` and free the hash or parameter the outer call is still using, a use-after-free in pure PDO core affecting every driver (confirmed on pdo_sqlite and pdo_odbc under debug+ASan, `USE_ZEND_ALLOC=0`). Minimal reproducer, UAF in `really_register_bound_param`:
```php
class Reenter {
public PDOStatement $s;
public function __toString(): string {
$this->s->execute([]);
return "x";
}
}
$pdo = new PDO('sqlite::memory:');
$stmt = $pdo->prepare('SELECT ?');
$r = new Reenter();
$r->s = $stmt;
$stmt->bindParam(1, $r);
```
A per-statement guard rejects reentry into any binding or fetch operation already in progress, throwing an `Error`; it holds across Fiber suspension and invalidates weak references before callback-capable teardown. The flag reuses a spare `pdo_stmt_t` reserved bit, so size and offsets are unchanged; since that edits the driver-facing header, master only.