php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80637 bindParam() changes type property to string
Submitted: 2021-01-17 19:45 UTC Modified: 2021-06-08 13:23 UTC
From: php at evilazrael dot de Assigned:
Status: Verified Package: PDO Core
PHP Version: 7.4.14 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 this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: php at evilazrael dot de
New email:
PHP Version: OS:

 

 [2021-01-17 19:45 UTC] 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. 

Patches

bindparam-typed-props (last revision 2021-06-08 13:23 UTC by cmb@php.net)

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-01-19 12:44 UTC] cmb@php.net
There appears to be a more general issue:
<https://3v4l.org/F6pnT>.
 [2021-01-19 13:22 UTC] nikic@php.net
@cmb: You didn't use the right property there: https://3v4l.org/tXjhi
 [2021-01-26 12:17 UTC] cmb@php.net
@nikic: oops!
 [2021-06-08 13:23 UTC] 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-06-08 13:23 UTC] cmb@php.net
-Status: Open +Status: Verified -Operating System: Linux +Operating System: *
 [2021-06-08 13:23 UTC] cmb@php.net
> 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>
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Fri Oct 22 01:03:33 2021 UTC