|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2010-04-27 04:57 UTC] ww dot galen at gmail dot com
Description:
------------
After executing a prepared statement and calling PDOStatement::nextRowset (whether
or not there is more than one result set), then calling PDOStatement::execute a
second time, PDOStatement::getColumnMeta causes a segfault. I guess it really is
an experimental feature.
Platform info:
OS X 10.6.3
Apache 2.2.14
PHP 5.3.2 (also tested under 5.3.1 with same result)
MySQL 5.1.45
Test script:
---------------
$db = new PDO('mysql:...', ...);
$query = $db->prepare('SELECT 1 AS num;');
$query->execute();
$query->nextRowset();
$query->execute();
$query->getColumnMeta(0);
Expected result:
----------------
PDOStatement::getColumnMeta should return an array describing a column. For the
test script, something like:
<code>
array (
'native_type' => 'LONGLONG',
'pdo_type' => 2,
'flags' =>
array (
0 => 'not_null',
),
'table' => '',
'name' => 'num',
'len' => 1,
'precision' => 0,
)
</code>
Actual result:
--------------
Segfault. For example, on my machine I get:
Process: httpd [31734]
Path: /usr/sbin/httpd
Identifier: httpd
Version: ??? (???)
Code Type: X86-64 (Native)
Parent Process: httpd [31718]
Date/Time: 2010-04-26 19:02:55.650 -0700
OS Version: Mac OS X 10.6.3 (10D573)
Report Version: 6
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000000
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Thread 0 Crashed: Dispatch queue: com.apple.main-thread
0 libphp5.so 0x0000000101163923
zim_PDOStatement_getColumnMeta + 262
1 libphp5.so 0x0000000101334704
zend_do_fcall_common_helper_SPEC + 2409
2 libphp5.so 0x0000000101330fd9 execute + 585
3 libphp5.so 0x000000010130fe18 zend_execute_scripts
+ 376
4 libphp5.so 0x00000001012c2b3a php_execute_script +
705
5 libphp5.so 0x000000010138baf3 php_handler + 1237
6 httpd 0x00000001000012af ap_run_handler + 90
7 httpd 0x0000000100001b8e ap_invoke_handler +
346
8 httpd 0x000000010002e784 ap_process_request +
103
9 httpd 0x000000010002aff7
ap_process_http_connection + 116
10 httpd 0x000000010001280b
ap_run_process_connection + 90
11 httpd 0x0000000100012ca5 ap_process_connection
+ 91
12 httpd 0x00000001000353f2 child_main + 1257
13 httpd 0x00000001000355a8 make_child + 329
14 httpd 0x000000010003582e
perform_idle_server_maintenance + 498
15 httpd 0x0000000100035d58 ap_mpm_run + 1246
16 httpd 0x00000001000098f5 main + 2854
17 httpd 0x0000000100000914 start + 52
Thread 0 crashed with X86 Thread State (64-bit):
rax: 0x0000000000000001 rbx: 0x0000000000000000 rcx: 0x00007fff5fbfef48
rdx: 0x0000000000000028
rdi: 0x00000001007412be rsi: 0x00000001013dbdde rbp: 0x00007fff5fbfeff0
rsp: 0x00007fff5fbfefc0
r8: 0x0000000000000001 r9: 0x0000000000000006 r10: 0x00000001013cf158
r11: 0x00000001007412b8
r12: 0x000000010073d000 r13: 0x000000010073c4a0 r14: 0x0000000000000001
r15: 0x0000000000000000
rip: 0x0000000101163923 rfl: 0x0000000000000246 cr2: 0x0000000000000000
Patchesfix-nextRowset.getColumnMeta-segfault (last revision 2010-04-27 03:35 UTC by ww dot galen at gmail dot com)Pull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 01:00:01 2025 UTC |
In particular, it's failing on line 1864 of pdo_stmt.c: add_assoc_string(return_value, "name", col->name, 1); 'col' is null because 'stmt->columns' is null.The cause seems to be lines 513-523 of pdo_stmt.c: if (!stmt->executed) { /* this is the first execute */ if (stmt->dbh->alloc_own_columns && !stmt->columns) { /* for "big boy" drivers, we need to allocate memory to fetch * the results into, so lets do that now */ ret = pdo_stmt_describe_columns(stmt TSRMLS_CC); } stmt->executed = 1; } Columns are only described if the statement hasn't been executed.Moving the inner test to just after the outer test so that columns are described whenever "stmt->columns" is null seems to fix the segfault. This is what the patch does, reproduced here: if (!stmt->executed) { /* this is the first execute */ stmt->executed = 1; } // if nextRowset was called, we need to redescribe if (stmt->dbh->alloc_own_columns && !stmt->columns) { /* for "big boy" drivers, we need to allocate memory to fetch * the results into, so lets do that now */ ret = pdo_stmt_describe_columns(stmt TSRMLS_CC); } Whether this is appropriate and won't cause other bugs or even if it fixes all cases, I couldn't tell you.