Bug #65946 [NEW]: pdo_sql_parser.c permanently converts values bound to strings

From: Date: Tue, 22 Oct 2013 13:53:56 +0000
Subject: Bug #65946 [NEW]: pdo_sql_parser.c permanently converts values bound to strings
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-182385@lists.php.net to get a copy of this message
From:             jakub dot lopuszanski at nasza-klasa dot pl
Operating system: debian
PHP version:      Irrelevant
Package:          PDO related
Bug Type:         Bug
Bug description:pdo_sql_parser.c permanently converts values bound to strings

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  ...

-- 
Edit bug report at https://bugs.php.net/bug.php?id=65946&edit=1
-- 
Try a snapshot (PHP 5.4):   https://bugs.php.net/fix.php?id=65946&r=trysnapshot54
Try a snapshot (PHP 5.5):   https://bugs.php.net/fix.php?id=65946&r=trysnapshot55
Try a snapshot (trunk):     https://bugs.php.net/fix.php?id=65946&r=trysnapshottrunk
Fixed in SVN:               https://bugs.php.net/fix.php?id=65946&r=fixed
Fixed in release:           https://bugs.php.net/fix.php?id=65946&r=alreadyfixed
Need backtrace:             https://bugs.php.net/fix.php?id=65946&r=needtrace
Need Reproduce Script:      https://bugs.php.net/fix.php?id=65946&r=needscript
Try newer version:          https://bugs.php.net/fix.php?id=65946&r=oldversion
Not developer issue:        https://bugs.php.net/fix.php?id=65946&r=support
Expected behavior:          https://bugs.php.net/fix.php?id=65946&r=notwrong
Not enough info:            https://bugs.php.net/fix.php?id=65946&r=notenoughinfo
Submitted twice:            https://bugs.php.net/fix.php?id=65946&r=submittedtwice
register_globals:           https://bugs.php.net/fix.php?id=65946&r=globals
PHP 4 support discontinued: https://bugs.php.net/fix.php?id=65946&r=php4
Daylight Savings:           https://bugs.php.net/fix.php?id=65946&r=dst
IIS Stability:              https://bugs.php.net/fix.php?id=65946&r=isapi
Install GNU Sed:            https://bugs.php.net/fix.php?id=65946&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=65946&r=float
No Zend Extensions:         https://bugs.php.net/fix.php?id=65946&r=nozend
MySQL Configuration Error:  https://bugs.php.net/fix.php?id=65946&r=mysqlcfg



Thread (6 messages)

« previous php.bugs (#182385) next »