|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2009-04-08 20:37 UTC] jjuergens at web dot de
Description:
------------
When trying to retrieve data from a MySQL-Database using a mysqli-statement, PHP just crashes. I excerpted the code below from a larger web-application and invoked it via the PHP-Cli and it still fails with a memory-error.
Interestingly enough though, if you just change a single value within $arg1 and $arg2 (e.g. replace the last 8 from $arg1 with a 7), the bug doesn't occur anymore.
I've included a Valgrind-output which shows the error.
MySQL-Version is 5.0.67.
Reproduce code:
---------------
<?php
/*
This is the database-table used:
CREATE TABLE `sessionData` (
`sessionId` varchar(60) collate utf8_unicode_ci NOT NULL,
`pathHash` varchar(32) collate utf8_unicode_ci NOT NULL,
`path` varchar(100) collate utf8_unicode_ci NOT NULL,
`data` longtext collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`sessionId`,`pathHash`),
CONSTRAINT `sessionData_ibfk_1` FOREIGN KEY (`sessionId`) REFERENCES `sessionIndex` (`sessionId`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
*/
//create db-link
$dbLink=new mysqli("host","user","pass","db",3306);
//create the statement
$stmt=$dbLink->prepare("SELECT * FROM `sessionData` WHERE `sessionId`=? AND `pathHash`=? LIMIT 1");
//bind params
$arg1="e75c7781166e3a361b7cff546563d5e8";
$arg2="9ddec3abec5c92628022210892e76afb";
$stmt->bind_param("ss",$arg1,$arg2);
//execute
$stmt->execute();
//create set of result-fields (see http://php.net/manual/de/mysqli-stmt.bind-result.php#85470)
$resData=$stmt->result_metadata();
$resFields=array();
$bindArray=array();
while($field=mysqli_fetch_field($resData)){
$resFields[]=&$bindArray[$field->name];
}
//bind result-fields
call_user_func_array(array($stmt,'bind_result'),$resFields);
//fetch result
$res=0;
while($stmt->fetch()){
$tmpRes=array();
foreach($bindArray as $key=>$value){
$tmpRes[$key]=$value;
}
//add this row (not needed for bug reproduction)
// array_push($result,$tmpRes);
$res++;
}
//close statement
$stmt->close();
Expected result:
----------------
In this case, the script should just exit normally without a result.
Actual result:
--------------
Running it in a shell, I get a memory-error.
Using Valgrind, I get the following:
==13749== Memcheck, a memory error detector.
==13749== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==13749== Using LibVEX rev 1854, a library for dynamic binary translation.
==13749== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==13749== Using valgrind-3.3.1, a dynamic binary instrumentation framework.
==13749== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==13749== For more details, rerun with: -v
==13749==
==13749== Invalid read of size 4
==13749== at 0x51AA261: mysql_stmt_fetch (in /usr/lib/libmysqlclient.so.15.0.0)
==13749== by 0x5187D5C: zif_mysqli_stmt_fetch (in /usr/lib/php5/extensions/mysqli.so)
==13749== by 0x81DE342: (within /usr/bin/php5)
==13749== by 0x81C94BA: execute (in /usr/bin/php5)
==13749== by 0x81A3D4F: zend_execute_scripts (in /usr/bin/php5)
==13749== by 0x81589F9: php_execute_script (in /usr/bin/php5)
==13749== by 0x821C780: main (in /usr/bin/php5)
==13749== Address 0x84 is not stack'd, malloc'd or (recently) free'd
==13749==
==13749== Process terminating with default action of signal 11 (SIGSEGV)
==13749== Access not within mapped region at address 0x84
==13749== at 0x51AA261: mysql_stmt_fetch (in /usr/lib/libmysqlclient.so.15.0.0)
==13749== by 0x5187D5C: zif_mysqli_stmt_fetch (in /usr/lib/php5/extensions/mysqli.so)
==13749== by 0x81DE342: (within /usr/bin/php5)
==13749== by 0x81C94BA: execute (in /usr/bin/php5)
==13749== by 0x81A3D4F: zend_execute_scripts (in /usr/bin/php5)
==13749== by 0x81589F9: php_execute_script (in /usr/bin/php5)
==13749== by 0x821C780: main (in /usr/bin/php5)
==13749==
==13749== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 118 from 2)
==13749== malloc/free: in use at exit: 1,296,363 bytes in 13,676 blocks.
==13749== malloc/free: 14,687 allocs, 1,011 frees, 2,096,685 bytes allocated.
==13749== For counts of detected errors, rerun with: -v
==13749== searching for pointers to 13,676 not-freed blocks.
==13749== checked 1,736,688 bytes.
==13749==
==13749== LEAK SUMMARY:
==13749== definitely lost: 30,599 bytes in 11 blocks.
==13749== possibly lost: 10,263 bytes in 2 blocks.
==13749== still reachable: 1,255,501 bytes in 13,663 blocks.
==13749== suppressed: 0 bytes in 0 blocks.
==13749== Rerun with --leak-check=full to see details of leaked memory.
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 01:00:01 2025 UTC |
<?php //IMPORTANT: Database-Name (here: tst) needs to have exactly 3 characters! $dbLink=new mysqli("localhost","user","pass","tst",3306); $dbLink->query("CREATE TABLE IF NOT EXISTS `sessionData` ( `sessionId` varchar(60) collate utf8_unicode_ci NOT NULL, `pathHash` varchar(32) collate utf8_unicode_ci NOT NULL, `path` varchar(100) collate utf8_unicode_ci NOT NULL, `data` longtext collate utf8_unicode_ci NOT NULL, PRIMARY KEY (`sessionId`,`pathHash`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci"); $dbLink->query("INSERT INTO `sessionData` (`sessionId`, `pathHash`, `path`, `data`) VALUES ('e75c7781166e3a361b7cff546563d5e8', '633fed500f479acaaaf54be8ec9ac657', '/bla', '0018a901234001222425678901235678345612341315789012345678901234567890123423456789012223456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678')"); $stmt=$dbLink->prepare("SELECT * FROM `sessionData` WHERE `sessionId`=? AND `pathHash`=? LIMIT 1"); $arg1="e75c7781166e3a361b7cff546563d5e8"; $arg2="633fed500f479acaaaf54be8ec9ac657"; $stmt->bind_param("ss",$arg1,$arg2); $stmt->execute(); $resData=$stmt->result_metadata(); while($field=mysqli_fetch_field($resData)){ $resFields[$field->name]=null; } call_user_func_array(array($stmt,'bind_result'),$resFields); $result=array(); while($stmt->fetch()){ $tmpRes=array(); foreach($resFields as $key=>$value){ $tmpRes[$key]=$value; } array_push($result,$tmpRes); } $stmt->close(); print_r($result); ?>Here is the shortest possible test I could come up with: <?php /* Test database and table with data: drop database crashtest; create database crashtest; use crashtest; create table crash ( test longtext ); insert into crash set test='123456789'; grant select on crashtest.* to 'test'@'localhost'; */ $dbLink=new mysqli("localhost","test","","crashtest",3306); $stmt=$dbLink->prepare("SELECT test FROM crash"); $stmt->execute(); $stmt->bind_result($foo); while($stmt->fetch()); $stmt->close(); ?> The problem seems to be with the longtext column. If that is changed to text column, everything works just fine.