php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65946 pdo_sql_parser.c permanently converts values bound to strings
Submitted: 2013-10-22 13:53 UTC Modified: 2013-11-07 02:57 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: jakub dot lopuszanski at nasza-klasa dot pl Assigned: willfitch
Status: Closed Package: PDO related
PHP Version: Irrelevant OS: debian
Private report: No CVE-ID:
 [2013-10-22 13:53 UTC] jakub dot lopuszanski at nasza-klasa dot pl
Description:
------------
When a bindValue is used to bind a a PARAM_INT, then the first time execute() is called the value is inserted into query without quotes, but the second time it is called the value gets surrounded with quotes. This can obviously trigger MySQL parse errors if the placeholder is used in a position where a number must be used (for example in LIMIT :limit).

I suspect that the reason for that behaviour is that in pdo_parse_params method in pdo_sql_parser.c there is a switch statement with side effects:

                    switch (Z_TYPE_P(param->parameter)) {
                        case IS_NULL:
                            plc->quoted = "NULL";
                            plc->qlen = sizeof("NULL")-1;
                            plc->freeq = 0;
                            break;

                        case IS_BOOL:
                            convert_to_long(param->parameter);

                        case IS_LONG:
                        case IS_DOUBLE:
                            convert_to_string(param->parameter);
                            plc->qlen = Z_STRLEN_P(param->parameter);
                            plc->quoted = Z_STRVAL_P(param->parameter);
                            plc->freeq = 0;
                            break;

                        default:
                            convert_to_string(param->parameter);
                            if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter),
                                    Z_STRLEN_P(param->parameter), &plc->quoted, &plc->qlen,
                                    param->param_type TSRMLS_CC)) {
                                /* bork */
                                ret = -1;
                                strncpy(stmt->error_code, stmt->dbh->error_code, 6);
                                goto clean_up;
                            }
                            plc->freeq = 1;
                    }

in parcitular, it seems to me that when this switch is visited the first time, then the value is treated as IS_LONG, and convert_to_string is applied to it.
The next time it is already a string so it falls into the "default" category, and therefore gets treated with stmt->dbh->methods->quoter.


Test script:
---------------
//$db must be a MySQL database
$q=$db->prepare('SELECT * FROM test LIMIT :limit');
$q->bindValue('limit',1,PDO::PARAM_INT);
$q->execute();
$q->execute();



Expected result:
----------------
script not failing

Actual result:
--------------
PHP Fatal error:  Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' at line 1' in  ...

Patches

bug65946.diff (last revision 2013-11-07 17:58 UTC) by rasmus@php.net)

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-11-07 02:57 UTC] willfitch@php.net
-Assigned To: +Assigned To: willfitch
 [2013-11-07 03:49 UTC] willfitch@php.net
Confirmed in 5.5.
 [2013-11-07 17:54 UTC] rasmus@php.net
The following patch has been added/updated:

Patch Name: bug65946.diff
Revision:   1383846867
URL:        https://bugs.php.net/patch-display.php?bug=65946&patch=bug65946.diff&revision=1383846867
 [2013-11-07 17:56 UTC] rasmus@php.net
The following patch has been added/updated:

Patch Name: bug65946.diff
Revision:   1383846973
URL:        https://bugs.php.net/patch-display.php?bug=65946&patch=bug65946.diff&revision=1383846973
 [2013-11-07 17:58 UTC] rasmus@php.net
The following patch has been added/updated:

Patch Name: bug65946.diff
Revision:   1383847090
URL:        https://bugs.php.net/patch-display.php?bug=65946&patch=bug65946.diff&revision=1383847090
 [2013-11-08 02:10 UTC] rasmus@php.net
Automatic comment on behalf of rasmus
Revision: http://git.php.net/?p=php-src.git;a=commit;h=890ea8411f908ee8ab84389b42066f66d4a033e6
Log: Fix bug #65946 - pdo_sql_parser.c permanently converts values bound to strings
 [2013-11-08 02:10 UTC] rasmus@php.net
-Status: Assigned +Status: Closed
 [2013-11-08 02:17 UTC] rasmus@php.net
Automatic comment on behalf of rasmus
Revision: http://git.php.net/?p=php-src.git;a=commit;h=890ea8411f908ee8ab84389b42066f66d4a033e6
Log: Fix bug #65946 - pdo_sql_parser.c permanently converts values bound to strings
 [2013-11-09 10:21 UTC] ab@php.net
Automatic comment on behalf of rasmus
Revision: http://git.php.net/?p=php-src.git;a=commit;h=890ea8411f908ee8ab84389b42066f66d4a033e6
Log: Fix bug #65946 - pdo_sql_parser.c permanently converts values bound to strings
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Wed Apr 23 09:02:23 2014 UTC