Bug #80637 [Opn->Ver]: bindParam() changes type property to string

From: Date: Tue, 08 Jun 2021 13:23:50 +0000
Subject: Bug #80637 [Opn->Ver]: bindParam() changes type property to string
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-234261@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=80637&edit=1 ID: 80637 Updated by: cmb@php.net Reported by: php at evilazrael dot de Summary: bindParam() changes type property to string -Status: Open +Status: Verified Type: Bug Package: PDO Core -Operating System: Linux +Operating System: * PHP Version: 7.4.14 Block user comment: N Private report: N New Comment: > According to comments on bindParam() this is the normal > behaviour for at least 11 years, […] That info is also in the manual proper: | Most parameters are input parameters, that is, parameters that | are used in a read-only fashion to build up the query (but may | nonetheless be cast according to $type). However, I can confirm that PDOStatement::bindParam() and ::bindColumn() are not prepared to work with typed properties, since they directly convert the parameter to the $type[1]. This appears to be fixable; minimal PoC for the given case attached. Still, when the actual binding at the DB API level happens, the parameter has to be bound according to the given type, see e.g. the respective PDO_SQLITE implementation[2]. To properly support typed properties, we would need to bind a temporary zval, and to assign that back to the original zval on PDO_PARAM_EVT_EXEC_POST. The temporary zval would need to be stored in the respective struct pdo_bound_param_data variable, what *might* constitute an ABI break. Another option to fix this issue would be to reject potentially incompatible bindings in ::bindParam() and ::bindColumn() right away. That would, however, impose strict type semantics, and such constitute an inconsistency, and a BC break for coercive type mode. It had, however, the advantage that the fundamental invariant of typed properties would not be violated, regardless of individual PDO drivers being fixed. Not sure how to proceed here. [1] <https://github.com/php/php-src/blob/php-7.4.20/ext/pdo/pdo_stmt.c#L301-L322> [2] <https://github.com/php/php-src/blob/php-7.4.20/ext/pdo_sqlite/sqlite_statement.c#L135-L233> Previous Comments: ------------------------------------------------------------------------ [2021-06-08 13:23:39] cmb@php.net The following patch has been added/updated: Patch Name: bindparam-typed-props Revision: 1623158619 URL: https://bugs.php.net/patch-display.php?bug=80637&patch=bindparam-typed-props&revision=1623158619 ------------------------------------------------------------------------ [2021-01-26 12:17:12] cmb@php.net @nikic: oops! ------------------------------------------------------------------------ [2021-01-19 13:22:19] nikic@php.net @cmb: You didn't use the right property there: https://3v4l.org/tXjhi ------------------------------------------------------------------------ [2021-01-19 12:44:06] cmb@php.net There appears to be a more general issue: <https://3v4l.org/F6pnT>. ------------------------------------------------------------------------ [2021-01-17 19:45:52] php at evilazrael dot de Description: ------------ Nothing new, but still unexpected. bindParam() changes the bound variable to type string. According to comments on bindParam() this is the normal behaviour for at least 11 years, but with the typed property support introduced in 7.4 this is even more unexpected to have an int property containing a string, something you can do directly. I tested this with SQLite and PostgreSQL and seems to be independent of the used database. Test script: --------------- <?php class TestClass { public int $a; } $x = new TestClass; $x->a = 17; var_dump($x); /* class TestClass#3 (1) { public int $a => int(17) } */ $db = new PDO("sqlite::memory:"); $stmt = $db->prepare("SELECT :val"); $stmt->bindValue(":val", $x->a); $stmt->execute(); $stmt->closeCursor(); var_dump($x); /* class TestClass#3 (1) { public int $a => int(17) } */ $stmt->bindParam(":val", $x->a); $stmt->execute(); $stmt->closeCursor(); var_dump($x); /* class TestClass#3 (1) { public int $a => string(2) "17" } */ Expected result: ---------------- Int typed property containing an int value Actual result: -------------- Int typed property containing a string. ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=80637&edit=1

« previous php.bugs (#234261) next »