php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #67348 Reading $dbc->stat modifies $dbc->affected_rows
Submitted: 2014-05-27 22:31 UTC Modified: 2019-06-21 20:50 UTC
Votes:66
Avg. Score:4.5 ± 0.9
Reproduced:65 of 66 (98.5%)
Same Version:19 (29.2%)
Same OS:21 (32.3%)
From: derick@php.net Assigned: derick (profile)
Status: Closed Package: MySQLi related
PHP Version: 5.6Git-2014-05-27 (Git) OS: Linux
Private report: No CVE-ID: None
 [2014-05-27 22:31 UTC] derick@php.net
Description:
------------
When a script reads $dbc->stat, subsequent reads of $dbc->affected_rows return a different result. 

This was first reported to me as Xdebug bug #1053: http://bugs.xdebug.org/view.php?id=1053. I traced this back to the reading of ->stat as follows:

- Xdebug's debugging command "context_get" reads all the variables in the local scope
- For each object variable, the debug handlers are called (through Z_OBJDEBUG_PP): https://github.com/derickr/xdebug/blob/master/xdebug_var.c#L1725
- MySQLi debug handler loops over a list of properties: https://github.com/php/php-src/blob/master/ext/mysqli/mysqli_prop.c#L449
- The debug handler for affected_rows is at https://github.com/php/php-src/blob/master/ext/mysqli/mysqli_prop.c#L158
- The debug handler for stat is at https://github.com/php/php-src/blob/master/ext/mysqli/mysqli_prop.c#L256
- The debug handler for stat is defined at https://github.com/php/php-src/blob/master/ext/mysqlnd/mysqlnd.h#L212
- When I do *not* call "$foo = $dbc->stat", everything works.
- I can not created a work around, because the debug handler loops over all properties, and I have no chance to prevent ->stat from being read from the Xdebug side.


Test script:
---------------
<?php
$dbc = mysqli_connect('localhost', 'root', 'passwd', 'test');

$q = "INSERT INTO test1053 VALUES(7)";
$r = mysqli_query($dbc, $q);

var_dump($dbc->affected_rows);

$foo = $dbc->stat;

var_dump($dbc->affected_rows);
?>


Expected result:
----------------
int(1)
int(1)

Actual result:
--------------
int(1)
int(-1)

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-06-21 21:31 UTC] stephan dot eicher at check24 dot de
We are affected by this bug and it's very important for us because our framework relies on valid return values for "affected_rows".

We can reproduce this issue on Debian Jessie with package php5 (5.6.x) and xdebug installed.
 [2015-06-30 16:17 UTC] chealer at gmail dot com
This is a recipe to make a developer crazy. You hit a bug in your code, add breakpoints to try debugging it, and get crazy results. I can't believe this persists. I am experiencing this under PHP 5.5.12.

This was reported by figiemmi to NetBeans Forums on 2012-11-24, but he did not specify which PHP version he was using. This is visibly an old bug, but it's hard to believe it's always been that way.

This was also reported against NetBeans: https://netbeans.org/bugzilla/show_bug.cgi?id=244714

Thank you very much for reporting, your test case and your analysis, Derick.
 [2015-06-30 17:20 UTC] chealer at gmail dot com
I should have specified this affected me while using XDebug on Windows (8.1). This happened when I migrated an application from mysql to mysqli, which is its closest equivalent. And the reason why I migrated from mysql is that I upgraded to 5.5... which deprecates the mysql extension! Unfortunately, there will probably many others affected.

And unfortunately, the procedural style mysqli_affected_rows() is also affected, so the best workarounds I see is to go back to mysql, go to PDO instead, or wrap the critical part of our high-level query() function in big "DO NOT STEP THROUGH THIS CODE" comments. We wouldn't have the last choice if we didn't use such a wrapper, so we're in fact among the luckiest...
 [2015-08-25 19:40 UTC] myk at illinois dot edu
I have this problem regardless of whether I step through the code in my Eclipse/Xdebug/MAMP environment.  It seems if I try to open/close mysqli connections when used, the problem occurs.  If I don't close the connections, I get no errors about accessing properties, but I do then get the expected "too many connections."  Any chance this will get fixed soon?  It's really hard to debug when your error logs fill with hundreds of lines of useless info.

		if(!$this->db->isConnected()){
			$this->db->selectDB();
			$this->dbc = $this->db->dbc;
		}
		$this->resource = $this->dbc->query($this->text);
		if($this->resource===false){
			$this->error=$this->dbc->connect_error;
			if(isset($this->log)){
				$err=$this->log->writeLog($this->text."\n".$this->error."\n".$this->implode_r("\n",debug_backtrace()),'log',$tag);
			}else{
				echo $this->text."\n".$this->error."\n".$this->implode_r("\n",debug_backtrace()),'log -- '.$tag;
				die;
			}
		}elseif(strpos($this->text,'insert into')!==false){
			$this->result=$this->dbc->insert_id;
		}elseif(strpos($this->text,'delete')!==false or strpos($this->text,'update')!==false){
			$this->result=$this->resource;
		}else{
			$this->fetch_all();					
		}
		$this->dbc->close();
 [2016-11-21 12:11 UTC] aik dot bold at gmail dot com
Happens for me as well on PHP 5.4, PHP 5.5, PHP 5.6. Maybe even on PHP 7.0.
 [2017-01-04 20:29 UTC] johnnyecon at gmail dot com
Same here.
In my phpunit tests I connect to mysql using mysqli_connect on setUp().
All is ok when the first test runs mysqli_real_escape_string.
But when it is not the first test running then I get the below:

mysqli_real_escape_string(): Couldn't fetch mysqli

I am running PHP7.0 on PHPUnit 5.6.1
 [2017-04-26 13:40 UTC] fjanisze@php.net
-Status: Open +Status: Analyzed
 [2017-04-26 13:40 UTC] fjanisze@php.net
Hello everybody, 

the source of all this problem in in $dbc->stat triggering a COM_STATISTICS command to the server which will update affected_rows to -1. This is expected since no rows were influenced by COM_STATISTICS so make no sense to keep the old value 1 (or whatever other value we have stored). 

Being said that, we're thinking about a removal of the $dbc->stat function which will remove the trigger of the command to the server, instead $dbc->stat will read the plain value from the object, this shall fix this problem.
 [2018-01-05 14:00 UTC] steffenbalje at gmail dot com
I can confirm that this happens in php 7.0.22 as well.
 [2018-10-11 22:12 UTC] gcognault at free dot fr
I can confirm that this happens in php 7.2.11 as well.
 [2018-10-18 07:50 UTC] konrad dot br at brynda dot org
I can confirm that this happens in php 7.2.11 as well.
(mysqli->info: "Rows matched: 1  Changed: 1  Warnings: 0")
 [2018-11-21 10:44 UTC] kamilcodes at gmail dot com
This is still an issue in PHP 7.2.2

I have spent days trying to figure out why the code I inherited works on the server but not on my local machine. "mysqli_affected_rows" was the culprit as this is what the previous devs used quite often. 

Is there anyone working on the fix? Is this issue being addressed at all? I would love to contribute but I do not have the skills, unfortunately.
 [2019-06-21 15:52 UTC] derick@php.net
Automatic comment on behalf of github@derickrethans.nl
Revision: http://git.php.net/?p=php-src.git;a=commit;h=579562176b71820ad49d43b2c841642fef12fe57
Log: Fixed bug #67348: Reading $dbc-&gt;stat modifies $dbc-&gt;affected_rows
 [2019-06-21 15:52 UTC] derick@php.net
-Status: Analyzed +Status: Closed
 [2019-06-21 15:53 UTC] derick@php.net
-Assigned To: +Assigned To: derick
 [2019-06-21 15:53 UTC] derick@php.net
This is going to be in 7.4.0alpha2 and later, and the fix is to remove the stat property. The stat() method to obtain the same information is still available.
 [2019-06-21 18:21 UTC] andrey@php.net
Direct removal of a property, part of API, without deprecation. What's going on here?!?
 [2019-06-21 20:46 UTC] derick@php.net
There have been 5 years since the report of this bug, and nothing happening. This bug involves the MySQLi extension *destroying* data when reading this undocumented property (https://www.php.net/manual/en/class.mysqli.php) or doing a var_dump() on a MySQLi object. If you can fix this data trashing bug in another way, then feel free to attempt this.
 [2019-06-21 20:50 UTC] nikic@php.net
It's worth noting that the mysqli::$stat property was undocumented -- per documentation only mysqli::stat() exists, and of course that remains available.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 11:01:29 2024 UTC