php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #53551 PDOStatement execute segfaults for pdo_mysql driver
Submitted: 2010-12-15 22:31 UTC Modified: 2011-01-31 10:25 UTC
From: eddawley at gmail dot com Assigned: mysql (profile)
Status: Closed Package: PDO related
PHP Version: 5.3.4 OS: Centos 5
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 you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: eddawley at gmail dot com
New email:
PHP Version: OS:

 

 [2010-12-15 22:31 UTC] eddawley at gmail dot com
Description:
------------
A segfault will occur when a PDOStatement is reused after failing due to a NOT 
NULL integrity constraint.  This occurred when using the pdo_mysql driver as 
opposed to the mysqlnd driver.

Also to avoid confusion, I was only able to test this on PHP 5.3.2.  I could find 
nothing in the changelogs that would imply this bug has been fixed.  I 
unfortunately did not have the time to free up hardware or vms for an upgrade.

Test script:
---------------
$dbh = new PDO('mysql:host=127.0.0.1;dbname=foo', 'user', 'pass');
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);

$createSql = "CREATE TABLE `foo` (
  `count` bigint(20) unsigned NOT NULL DEFAULT '0'
)";

$dbh->exec('drop table if exists foo');
$dbh->exec($createSql);
$dbh->exec("insert into foo set `count` = 1 ");

$sql = 'UPDATE foo SET `count` = :count';
$stmt = $dbh->prepare($sql);

$values = array (
  'count' => NULL,
);

echo "1\n";
$stmt->execute($values);
var_dump($stmt->errorInfo());

echo "2\n";
$stmt->execute($values);
var_dump($stmt->errorInfo());

echo "\ndone\n";


Expected result:
----------------
[ed@foo ~]$ php ed.php
1
array(3) {
  [0]=>
  string(5) "23000"
  [1]=>
  int(1048)
  [2]=>
  string(29) "Column 'count' cannot be null"
}
2
array(3) {
  [0]=>
  string(5) "23000"
  [1]=>
  int(1048)
  [2]=>
  string(29) "Column 'count' cannot be null"
}
done


Actual result:
--------------
[ed@foo ~]$ php ed.php
1
array(3) {
  [0]=>
  string(5) "23000"
  [1]=>
  int(1048)
  [2]=>
  string(29) "Column 'count' cannot be null"
}
2
Segmentation fault (core dumped)



Core was generated by `php ed.php'.
Program terminated with signal 11, Segmentation fault.
[New process 16072]
#0  0x00000000005aa8be in pdo_mysql_stmt_param_hook (stmt=0xe5c12e8, 
param=0xe5c1a78, event_type=<value optimized out>) at /tmp/php-
5.3.2/ext/pdo_mysql/mysql_statement.c:490
490                                     b->is_null = &S->in_null[param-
>paramno];
(gdb) bt
#0  0x00000000005aa8be in pdo_mysql_stmt_param_hook (stmt=0xe5c12e8, 
param=0xe5c1a78, event_type=<value optimized out>) at /tmp/php-
5.3.2/ext/pdo_mysql/mysql_statement.c:490
#1  0x00000000005a34d9 in really_register_bound_param (param=0x7ffff7cb9990, 
stmt=0xe5c12e8, is_param=1) at /tmp/php-5.3.2/ext/pdo/pdo_stmt.c:408
#2  0x00000000005a4940 in zim_PDOStatement_execute (ht=<value optimized out>, 
return_value=0xe5c18d0, return_value_ptr=<value optimized out>, this_ptr=<value 
optimized out>, 
    return_value_used=<value optimized out>) at /tmp/php-
5.3.2/ext/pdo/pdo_stmt.c:474
#3  0x0000000000789059 in zend_do_fcall_common_helper_SPEC 
(execute_data=0x2ae09210b050) at /tmp/php-5.3.2/Zend/zend_vm_execute.h:313
#4  0x000000000075f98e in execute (op_array=0xe5be920) at /tmp/php-
5.3.2/Zend/zend_vm_execute.h:104
#5  0x000000000073c439 in zend_execute_scripts (type=8, retval=0x0, 
file_count=3) at /tmp/php-5.3.2/Zend/zend.c:1194
#6  0x00000000006ea968 in php_execute_script (primary_file=0x7ffff7cbc190) at 
/tmp/php-5.3.2/main/main.c:2260
#7  0x00000000007c617e in main (argc=2, argv=0x7ffff7cbc408) at /tmp/php-
5.3.2/sapi/cli/php_cli.c:1192
(gdb) print *param
$1 = {paramno = 0, name = 0xe5c0750 ":count", namelen = 6, max_value_len = 0, 
parameter = 0xe5c1900, param_type = PDO_PARAM_STR, driver_params = 0x0, 
driver_data = 0x0, 
  stmt = 0xe5c12e8, is_param = 1}
(gdb) print param
$2 = (struct pdo_bound_param_data *) 0xe5c1a78


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-12-16 01:29 UTC] felipe@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: mysql
 [2010-12-16 22:58 UTC] kalle@php.net
I cannot reproduce with php-trunk using pdo_mysql linked to mysqlnd on Windows:

C:\php>php test.php
1
array(3) {
  [0]=>
  string(5) "00000"
  [1]=>
  NULL
  [2]=>
  NULL
}
2
array(3) {
  [0]=>
  string(5) "00000"
  [1]=>
  NULL
  [2]=>
  NULL
}

done

C:\php>php -v
PHP 5.3.99-dev (cli) (built: Dec 11 2010 12:14:13)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2010 Zend Technologies
 [2010-12-17 19:38 UTC] eddawley at gmail dot com
I would like to add that this happens for other mysql-level errors.  For 
example, the following will also cause a segfault when reused:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a 
child 
row: a foreign key constraint fails ...

SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for 
column...

And again, this was noticed with the pdo_mysql driver.  NOT the mysqlnd native 
driver.
 [2010-12-17 20:44 UTC] kalle@php.net
MySQLnd is not a driver, its a library backend. MySQL, MySQLi and PDO_MySQL can all be powered by either libmysql or mysqlnd.

So what you are saying is that you built pdo_mysql against libmysql which segfaults?
 [2010-12-17 20:58 UTC] eddawley at gmail dot com
Sorry, I didn't realize I was being unclear.  The segfault is occurring with PDO 
using libmysql.

Here are my relevant configure options:

'--with-mysql=mysqlnd' '--with-mysqli' '--with-pdo-mysql'
 [2011-01-06 12:03 UTC] uw@php.net
That fix should do it, however, I'd like to wait until Johannes returns from vacation and reviews it. PDO is a bit of a beast. With the fix the code should neither crash nor leak, nor behave differently from PDO_SQlite. Anyway, the result is still pretty, well, PDOish weird: error codes not cleaned up properly upon rebinding. Not my cup of coffee...

Index: ext/pdo_mysql/mysql_statement.c                                          
===================================================================             
--- ext/pdo_mysql/mysql_statement.c     (Revision 307155)                       
+++ ext/pdo_mysql/mysql_statement.c     (Arbeitskopie)    
@@ -141,10 +141,12 @@                                                           
                                                                                
        /* (re)bind the parameters */                                           
        if (mysql_stmt_bind_param(S->stmt, S->params) || mysql_stmt_execute(S->stmt)) {
+               /*                                                                     
                if (S->params) {                                                       
                        efree(S->params);                                              
                        S->params = 0;                                                 
                }                                                                      
+               */                                                                     
                pdo_mysql_error_stmt(stmt);                                            
                if (mysql_stmt_errno(S->stmt) == 2057) {                               
                        /* CR_NEW_STMT_METADATA makes the statement unusable */
 [2011-01-14 15:57 UTC] johannes@php.net
Automatic comment from SVN on behalf of johannes
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=307478
Log: - Fix #53551 (PDOStatement execute segfaults for pdo_mysql driver)
 [2011-01-31 10:25 UTC] uw@php.net
-Status: Assigned +Status: Closed
 [2011-01-31 10:25 UTC] uw@php.net
See SVN note
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 13:01:29 2024 UTC