Req #69213 [Nab]: consecutivly issued fseek don't work properly when together over PHP_MAX_INT
| From: | ab@php.net | Date: | Thu, 12 Mar 2015 10:28:06 +0000 |
| Subject: | Req #69213 [Nab]: consecutivly issued fseek don't work properly when together over PHP_MAX_INT | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-191347@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=69213&edit=1
ID: 69213
Updated by: ab@php.net
Reported by: johnregphpbug at stefanie dot de
Summary: consecutivly issued fseek don't work properly when
together over PHP_MAX_INT
Status: Not a bug
Type: Feature/Change Request
Package: Filesystem function related
Operating System: Win 7 Home Premium SP1
PHP Version: Irrelevant
Block user comment: N
Private report: N
New Comment:
Your experience with PERL seems to be ok, so you've found a practical solution. Though PERL
seems to be using 64 bit APIs. Note that with 32 bit APIs there's no chance to process files
bigger than INT_MAX bytes.
Btw. I wasn't asking you to switch your environment to master, but only to check whether the
master x64 snap works correct on your snippet. The PHP code can be easily modified to use pure
fseek() instead of my_fseek(), and running it on the console were good enough. If you had time, of
course :)
Thanks.
Previous Comments:
------------------------------------------------------------------------
[2015-03-12 02:41:50] johnregphpbug at stefanie dot de
Hi!
When I seek to the end (42+GByte) using perl it gives me the right end tag </osm>.
I just tried the php code again: I have two more counter-vars in my code here - the code looks even
worse then :) , so I can be sure that the my_fseek function does count correctly, but doesn't
give that end tag.
When I seek to PHP_INT_MAX (2147483647) less 1000 and then read 2000 bytes I get the same result as
with perl.
When I seek to twice PHP_INT_MAX the my_fseek version already returns different text than the
perl-script. There are node-tags with increasing id-numbers in the big file, and those are higher
than at the PHP_INT_MAX position in the file, but already lower than in the (correct) perl output.
The output I see when I seek to 40GByte-position indicates that it comes from a position under
PHP_INT_MAX: The id-numbers are lower than at PHP_INT_MAX.
As I only need to read such a big file only once a month or less, so I could preprocess it a bit and
then put it in a database, I'm using perl now for that specific task. Switching everything
(xampp, apache, php, mysql-interface) to 64 bit or to perl for only this would be too much.
If I would be better in programming, I could map which position of the file php gives back when
seeking far over PHP_INT_MAX. I'm not that good. - But if I happen to find out I will post the
results here.
Thank you very much for the feedback. I appreciate that very much.
Greetings John
------------------------------------------------------------------------
[2015-03-11 07:59:09] ab@php.net
Typo: in 32 bit runtime, offset is "signed long".
------------------------------------------------------------------------
[2015-03-11 07:58:08] ab@php.net
Hi, thanks for following. Just looking at your php code - it's horrible :) Even if it seems to
work, I'd rather call it bug itself. In the C run time, the 32 bit offset is an unsigned long.
Tho manual is clearly states offset to expect an integer, not a double. Are you sure the data you
seek() to is correct? Some unpleasant surprise is to expect, I'd highly discourage you from
using this in production.
About how to try snap - the easiest is just to get a zipball and try on console. If you wish to use
it with some webserver - IIS and Apache will sure work. For Apache, if your XAMPP is a vc11-x64
build - maybe yes, otherwise get an appropriate build from apachelounge.com, but in both cases use
php7_module directive in the httpd.conf
Thanks.
------------------------------------------------------------------------
[2015-03-10 15:39:15] johnregphpbug at stefanie dot de
I will try to install a 64 bit version.
The manual is just not really clear at this.
1. The answers on I got on stackoverflow can't be entirly correct, and other people have come
accross the restriction, too:
2. Reading over the PHP_MAX_INT treshhold is possible. But the workaround found at least in one
user-comment on the manual of fseek and another old bugreport that shows a workaround for the
workaround don't work as expected.
I'm very sure there is a bug in that php-version. Of course it might really just be
undocumented behaviour outside the defintions. (But then it should throw an error; which it
doesn't.)
(Can I just download a 64 bit build from the snapshots and put in my xampp installation instead of
old php version?)
If you find time, you might want to test the workaround I tried:
<?php
$testdata = '';
// C:\xampp\todrivei\germany-latest.osm 42.651.795.559 , 42651795559 file size from last year
$filenameandpath = 'C:\xampp\todrivei\germany-latest.osm';
$seekto = 42651795559 - 2000;;
// PHP_INT_MAX: 2147483647;
function my_fseek($fp,$pos,$first=0) {
if($first) fseek($fp,0,SEEK_SET);
$pos=floatval($pos);
// within limits, use normal fseek
if($pos<=PHP_INT_MAX) {
fseek($fp,$pos,SEEK_CUR);
}
// out of limits, use recursive fseek
else {
fseek($fp,PHP_INT_MAX,SEEK_CUR);
$pos -= PHP_INT_MAX;
$tempchar = fread($fp,1); // ."\n\r";
$pos -= 1;
my_fseek($fp,$pos);
}
}
$testdata = 'PHP_INT_MAX: '.PHP_INT_MAX."\n\r";
$testdata .= 'seekto: ' . $seekto."\n\r";
$handle = fopen($filenameandpath,'r');
my_fseek($handle, floatval($seekto),1);
$testdata .= fread($handle,62000);
fclose($handle);
echo $testdata;
?>
I can even try to seek over the file size (like I set seekto to 400GByte) and fread still returns
data of the file.
------------------------------------------------------------------------
[2015-03-10 14:40:19] ab@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to
report
a bug at http://bugs.php.net/how-to-report.php
Thanks for the report.
PHP before 7 on Windows doesn't support large file operations. All the APIs used are 32 bit
APIs. Same for integers. Und anyway much less in the 32 bit build, no matter what bitness the OS
has.
Instead, it'd be really appreciable you to take some latest snapshot http://windows.php.net/downloads/snaps/master/
to test the functionality you've described. It is the highest time for that now :) Though note
that you'll need a 64 bit build for LFS.
Thanks.
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=69213
--
Edit this bug report at https://bugs.php.net/bug.php?id=69213&edit=1