[go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SplFileObject::__toString() reads next line #9883

Closed
cmb69 opened this issue Nov 3, 2022 · 1 comment
Closed

SplFileObject::__toString() reads next line #9883

cmb69 opened this issue Nov 3, 2022 · 1 comment

Comments

@cmb69
Copy link
Member
cmb69 commented Nov 3, 2022

Description

The following code:

<?php
$file_stream = new SplFileObject(__FILE__, 'rb');

echo $file_stream; // line 4
echo $file_stream; // line 5
echo $file_stream; // line 6
echo $file_stream; // line 7
echo $file_stream; // line 8
echo $file_stream; // line 9

Resulted in this output:

<?php

$file_stream = new SplFileObject(__FILE__, 'rb');

echo $file_stream; // line 4
echo $file_stream; // line 5

But I expected this output instead:

<?php
<?php
<?php
<?php
<?php
<?php

See https://3v4l.org/gF4tm.

The issue is due to the erroneous fix of bug 77024, where ::__toString() is now an alias of ::fgets() what appears to be strange.

This issue has been discovered by @derickr.

PHP Version

PHP 8.0

Operating System

any

Girgias added a commit to Girgias/php-src that referenced this issue Nov 9, 2022
We need to overwrite the __toString magic method for SplFileObject, similarly to how DirectoryIterator overwrites it
Moreover, the custom cast handler is useless as we define __toString methods, so use the standard one instead.
@hormus
Copy link
hormus commented Nov 12, 2022

hi @cmb69 nice bug, I prefer unexpected terminology. Since the READ_CSV flag exists, the SplFileObject::current() method returns array or string or otherwise false. The SplFileObject class uses the alias __tostring (). Magic method __tostring() It is worth noting that prior to PHP 5.2.0 the __toString method was only called when combined directly with echo() or print(). As of PHP 5.2.0, it is called in any string context (e.g. in printf() with the% s modifier) ​​but not in other context types (e.g. with the% d modifier). Starting with PHP 5.2.0, converting objects without the __toString method to string would cause E_RECOVERABLE_ERROR. The first unexpected action is the magic method tostring() instead uses alias SplFileObject:: tostring(), the second unexpected action is SplFileObject::current() which does not return array although the bitmask for example 10 (e.g. READ_AHEAD | READ_CSV) uses READ_CSV. The third expected action is the modification of (alias of magic method __tostring()) SplFileObject::__tostring() if the bitmask uses READ_CSV accepts the input array and converts it to string

Pseudo code check:

<?php
$file = new SplFileObject(__FILE__, "rb");
echo 'string with key ' . $file->key();
echo $file->current(); // Bug, if SplFileObject::__tostring() alias of SplFileObject::fgets() next key
//$file->rewind(); // if SplFileObject::__tostring() alias of SplFileObject::fgets() or if SplFileObject::__tostring() alias of SplFileObject::current() for magic method __tostring() e.g. echo $file; now is array
$file->setFlags(SplFileObject::READ_CSV);
if(!is_array($file->current())) {
echo 'Not array' . "\r\n";
}
$flag_read_csv = 8 & $file->getFlags();
echo $file; // bug Magic method __tostring() and current(), is string
$file->setFlags(SplFileObject::READ_AHEAD | SplFileObject::READ_CSV);
$flag_read_csv2 = 8 & $file->getFlags();
$file->setFlags(0);
//$file->rewind(); // If SplFileObject::__current() don't update SplFileObject::__current()
if(is_array($file->current())) {
echo 'bug' . "\r\n";
}
var_dump('use flag READ_CSV:', $flag_read_csv, $flag_read_csv2);
?>

Output for 5.2.0 - 5.2.17, 5.3.0 - 5.3.29, 5.4.0 - 5.4.45, 5.5.0 - 5.5.38, 5.6.0 - 5.6.40, 7.0.0 - 7.0.33, 7.1.0 - 7.1.33, 7.2.0 - 7.2.18, 7.3.0 - 7.3.5 (if SplFileObject::__tostring() alias of SplFileObject::current():

string with key 0<?php
Not array
<?php
string(18) "use flag READ_CSV:"
int(8)
int(8)

Expected result:

string with key 0<?php
<?php
string(18) "use flag READ_CSV:"
int(8)
int(8)

Girgias added a commit to Girgias/php-src that referenced this issue Nov 21, 2022
We need to overwrite the __toString magic method for SplFileObject, similarly to how DirectoryIterator overwrites it
Moreover, the custom cast handler is useless as we define __toString methods, so use the standard one instead.
Girgias added a commit that referenced this issue Nov 22, 2022
* PHP-8.1:
  Fix GH-9883  SplFileObject::__toString() reads next line
Girgias added a commit that referenced this issue Nov 22, 2022
* PHP-8.2:
  Fix GH-9883  SplFileObject::__toString() reads next line
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants
@cmb69 @hormus and others