php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #61183 Firebird PDO memory corruption
Submitted: 2012-02-25 09:20 UTC Modified: 2016-11-06 16:16 UTC
Votes:17
Avg. Score:4.7 ± 0.8
Reproduced:13 of 13 (100.0%)
Same Version:6 (46.2%)
Same OS:6 (46.2%)
From: noxwizard at gmail dot com Assigned: mariuz (profile)
Status: Closed Package: PDO Firebird
PHP Version: 5.5 OS: Windows Server 2008 x86
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: noxwizard at gmail dot com
New email:
PHP Version: OS:

 

 [2012-02-25 09:20 UTC] noxwizard at gmail dot com
Description:
------------
Running Firebird 2.5, and trying to use PDO to run a few queries, I ran into 
memory corruption. I've tested the same code on a few other DBMSs via PDO and they 
run fine, so it seems related to the Firebird PDO module. It also doesn't happen 
on every table structure. For example, I tried a table consisting of a single 
integer field and the error wasn't triggered. Playing with the script a bit, it 
eventually output: zend_mm_heap corrupted

The structure for the table in the example script can be found here: 
https://github.com/phpbb/phpbb3/blob/release-
3.0.10/phpBB/install/schemas/firebird_schema.sql#L1319

Test script:
---------------
<?php
try
{
	$dbh = new PDO('firebird:host=localhost;dbname=C:\\phpbb_test_data\\tests.fdb', 'SYSDBA', 'masterkey');
	for($i = 0; $i < 5000; $i++)
	{
		$statement = $dbh->prepare('INSERT INTO "PHPBB_USERS" ("USER_ID", "USERNAME", "USERNAME_CLEAN", "USER_PERMISSIONS", "USER_SIG", "USER_OCC", "USER_INTERESTS") VALUES (?, ?, ?, ?, ?, ?, ?)');
		$statement->execute(array (0 => '2', 1 => 'banned', 2 => 'banned', 3 => '', 4 => '', 5 => '', 6 => ''));
		echo 'Statement run: ' . $i . "\n";
	}
}
catch (PDOException $e)
{
	echo 'Exception: ' . $e->getMessage();
}

Expected result:
----------------
The script should run 5000 times and exit cleanly.

Actual result:
--------------
The script runs through a few iterations and PHP crashes. Altercations to the 
script can make it run longer or shorter (without trailing ?> crashes in 2 
iterations, with it, crashes after 1998 iterations).

This first backtrace is from a 32bit Windows Server 2008 install running in a 
VirtualBox VM:
Entry point   php!mainCRTStartup 
Create time   2/25/2012 2:40:53 AM 
Time spent in user mode   0 Days 0:0:0.15 
Time spent in kernel mode   0 Days 0:0:0.781 

Function     Arg 1     Arg 2     Arg 3   Source 
php5ts!zend_mm_set_custom_handlers+225     00000001     0212fa20     0212e7e0    
php5ts!_estrndup+35     02130770     00000000     02272f78    
php5ts!_zval_copy_ctor_func+42     0212e7e0     00000001     0212f490    
php5ts!pdo_stmt_describe_columns+701     00000001     02130810     00000000    
php5ts!execute+1130     02160080     02272f01     634b7838    
php5ts!execute+15ed     02272f78     0091f440     00000000    
php5ts!execute+2e8     0212e548     02272f00     02272f78    
php5ts!zend_execute_scripts+fe     00000008     02272f78     00000000    
php5ts!php_execute_script+24c     0091f6f0     02272f78     00ee742c    
php!main+b9b     00000002     02272f08     02271be0    
php!memcpy+160     7ffd7000     0091f830     777b1603    
kernel32!BaseThreadInitThunk+12     7ffd7000     75823a7e     00000000    
ntdll!RtlInitializeExceptionChain+63     00ee3002     7ffd7000     ffffffff    
ntdll!RtlInitializeExceptionChain+36     00ee3002     7ffd7000     00000000    

PHP5TS!ZEND_MM_SET_CUSTOM_HANDLERS+225In 
php__PID__4908__Date__02_25_2012__Time_02_41_07AM__420__Second_Chance_Exception_
C0000005.dmp the assembly instruction at 
php5ts!zend_mm_set_custom_handlers+225 in C:\php\php5ts.dll from The PHP Group 
has caused an access violation exception (0xC0000005) when trying to read from 
memory location 0x6e6e616a on thread 0

Module Information 
Image Name: C:\php\php5ts.dll   Symbol Type:  PDB 
Base address: 0x63490000   Time Stamp:  Thu Feb 02 13:36:49 2012  
Checksum: 0x005a3fb6   Comments:   
COM DLL: False   Company Name:  The PHP Group 
ISAPIExtension: False   File Description:  PHP Script Interpreter 
ISAPIFilter: False   File Version:  5.3.10 
Managed DLL: False   Internal Name:  PHP Script Interpreter 
VB DLL: False   Legal Copyright:  Copyright © 1997-2010 The PHP Group 
Loaded Image Name:  php5ts.dll   Legal Trademarks:  PHP 
Mapped Image Name:     Original filename:  php5ts.dll 
Module name:  php5ts   Private Build:   
Single Threaded:  False   Product Name:  PHP 
Module Size:  5.77 MBytes   Product Version:  5.3.10 
Symbol File Name:  C:\php_debug\php5ts.pdb   Special Build:  & 


Moving it to my main system, Windows 7 x64 (32bit Firebird 2.5 still), with 
Visual Studio 2010, I captured the following stack trace when it crashed:
php5ts.dll!_zend_mm_alloc_int(_zend_mm_heap * heap=0x6e6e6162, unsigned int 
size=1)  Line 1835
php5ts.dll!_estrndup(const char * s=0x02cb1308, unsigned int length=0)  Line 
2503 + 0x33 bytes
php5ts.dll!_zval_copy_ctor_func(_zval_struct * zvalue=0x02cb1d80)  Line 120 + 
0xc bytes
php5ts.dll!zim_PDOStatement_execute(int ht=1, _zval_struct * 
return_value=0x02cb1028, _zval_struct * * return_value_ptr=0x00000000, 
_zval_struct * 
this_ptr=0x02cb1088, int return_value_used=0, void * * * tsrm_ls=0x02c91ad0)  
Line 478 + 0x3f bytes
php5ts.dll!zend_do_fcall_common_helper_SPEC(_zend_execute_data * 
execute_data=0x02ce0080, void * * * tsrm_ls=0x02c91a01)  Line 320 + 0x41 bytes
php5ts.dll!ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(_zend_execute_data * 
execute_data=0x00000000, void * * * tsrm_ls=0x00000001)  Line 426
php5ts.dll!execute(_zend_op_array * op_array=0x02caee80, void * * * 
tsrm_ls=0x02c91a00)  Line 107 + 0xa bytes
php5ts.dll!zend_execute_scripts(int type=8, void * * * tsrm_ls=0x02c91ad0, 
_zval_struct * * retval=0x00000000, int file_count=3, ...)  Line 1237
php5ts.dll!php_execute_script(_zend_file_handle * primary_file=0x010afc84, void 
* * * tsrm_ls=0x02c91ad0)  Line 2308 + 0x12 bytes
php.exe!main(int argc=2, char * * argv=0x02c92fa8)  Line 1185
php.exe!__tmainCRTStartup()  Line 586 + 0x17 bytes
kernel32.dll!7646339a() 
[Frames below may be incorrect and/or missing, no symbols loaded for 
kernel32.dll]
ntdll.dll!770a9ef2()
ntdll.dll!770a9ec5()

Patches

firebird_bind_blob (last revision 2016-09-16 17:22 UTC by cmb@php.net)
Blob_Bind_Fix (last revision 2012-10-25 02:31 UTC by james at kenjim dot com)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-03-30 06:36 UTC] mariuz@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: mariuz
 [2012-10-04 08:30 UTC] james at kenjim dot com
This problem appears to comes from the handling of blobs.  In the function firebird_bind_blob in firebird_statement.c we pass param in and are destroying it with zval_dtor.  I think we should not be destroying it because it was provided by firebird_stmt_param_hook and no other path destroys this variable.  

Commenting out the zval_dtor(param) line fixes the crashing.

I also don't think we need to call SEPARATE_ZVAL(&param) or convert_to_string_ex(&param) as param appears to always be a string regardless of what we bind.
 [2012-10-05 08:25 UTC] james at kenjim dot com
After further testing I've found that NULL zval's may be passed into firebird_bind_blob so convert_to_string_ex needs to be called or a check for NULL param needs to be done before calling Z_STRLEN_P.
 [2012-10-16 03:08 UTC] paul dot ishenin at gmail dot com
I have a crash (0xc0000005 exception) when I execute a statement which inserts or 
updates blob and values are bind using bindValue(). But if I use bindParam() 
instead there is no crash. For example:

$q = Yii::app()->db->createCommand('INSERT INTO TEST (BL) VALUES (:bl)');
// this will crash $q->bindValue(':bl', bl, PDO::PARAM_LOB);
$q->bindParam(':bl', bl, PDO::PARAM_LOB); // this will not crash
$q->execute();
 [2014-01-01 12:40 UTC] felipe@php.net
-Package: PDO related +Package: PDO Firebird
 [2015-07-16 13:41 UTC] mariuz@php.net
-PHP Version: 5.3.10 +PHP Version: 5.5
 [2015-07-16 13:41 UTC] mariuz@php.net
Started to test the patch 

patch -p1 < ~/Downloads/Blob_Bind_Fix.patch.txt 
patching file ext/pdo_firebird/firebird_statement.c
Hunk #1 succeeded at 422 (offset -2 lines).
 [2016-09-16 17:22 UTC] cmb@php.net
The following patch has been added/updated:

Patch Name: firebird_bind_blob
Revision:   1474046532
URL:        https://bugs.php.net/patch-display.php?bug=61183&patch=firebird_bind_blob&revision=1474046532
 [2016-09-16 17:23 UTC] cmb@php.net
I can't reproduce this issue with the supplied test script, but
the reproducer of bug 73087 also exhibits this bug. James'
assessment is basically correct. Firstly, it should be noted that
the zval_dtor() is wrong; that should be zval_ptr_dtor(). But that
wouldn't solve the issue due to the aliasing of param. The actual
problem is indeed the SEPARATE_ZVAL(), which simply can't work
there. If the refcount is 1, SEPARATE_ZVAL() is a no-op, and
zval_ptr_dtor() would destroy the zval, albeit it is later used
elsewhere. The clean solution would be to make a copy of the zval,
so the convert_to_string_ex() can savely be applied, and to
destroy that copy later. However, it appears to me that there's no
need to use a copy at all, and that the convert_to_string_ex() can
nonetheless savely be applied (see attached patch
firebird_bind_blob).
 [2016-11-06 16:16 UTC] ab@php.net
-Status: Assigned +Status: Closed
 [2016-11-06 16:16 UTC] ab@php.net
Fixed with https://github.com/php/php-src/pull/2183/

Thanks.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 12:01:29 2024 UTC