php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #69906 chr() behavior difference between 32- and 64-bit bulids
Submitted: 2015-06-23 07:22 UTC Modified: 2020-11-04 13:22 UTC
Votes:2
Avg. Score:3.5 ± 0.5
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: ab@php.net Assigned: cmb (profile)
Status: Closed Package: Strings related
PHP Version: * OS: any
Private report: No CVE-ID: None
 [2015-06-23 07:22 UTC] ab@php.net
Description:
------------
When passing an integer that overflows PHP_INT_MAX in 32-bit, the behavior of chr() differs. The documentation currently doesn't define what should happen in this situation, the only statement is that chr() expects an ASCII code. chr() should ensure the input is in the valid range, thus making the behavior consistent between 32- and 64-bit.

Test script:
---------------
Debug\php.exe -r "$a = chr(2632627629); var_dump($a, ord($a));"
string(1) " "
int(0)

x64\Debug\php.exe -r "$a = chr(2632627629); var_dump($a, ord($a));"
string(1) "ยก"
int(173)


Expected result:
----------------
string(1) " "
int(0)

Actual result:
--------------
Different behavior depending on 32- or 64-bit build.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-06-23 07:56 UTC] ab@php.net
-Assigned To: +Assigned To: ab
 [2015-06-23 20:15 UTC] bwoebi@php.net
May I request to not have that changed?

That's technically a BC break, because there's code out there relying on chr() implicitly doing & 0xFF on the passed param.

I think that's rather a doc bug?
 [2015-06-23 21:30 UTC] ab@php.net
-Status: Assigned +Status: Not a bug
 [2015-06-23 21:30 UTC] ab@php.net
Hi Bob,

yeah, i was investigating on this but didn't come to update the ticket. You're right, while it's an issue :) 

I first thought it's an issue on 64-bit, now it looks the issue is on 32-bit (expected should deliver int(173)). Namely - on 32-bit the argument that overflows PHP_INT_MAX will be just truncated to zero (read as 'l' by ZPP or alike). While I saw that there could be a way to fix this on 32-bit, it would be too expensive to be justified. Thus, probably best is to leave it as is, a cast to int should do more or less correct job on this.

So kinda marking this as no bug.

Thanks.
 [2015-06-24 07:06 UTC] jan dot slabon at setasign dot com
Hi Bob, hi Anatol,

I reported that problem while talking to Anatol about another bug by email. We really had such code which got broken by this change.

So technically it is a BC break but I'm not sure if we are the only one trapping into that issue?

We encountered the problem in an Ascii85 encoder which we fixed now by casting to int explicity. So I don't have a problem with this BC break as we've a fix for it:

$r = 0;
for ($j = 0; $j < 5; ++$j) {
    $r = (int)($r * 85 + $chn[$j]);
}

$out .= chr($r >> 24)
      . chr($r >> 16)
      . chr($r >> 8)
      . chr($r);

Anyhow this problem will only arise in special situations and will not be recognized until it happens (in our case PDF documents that uses an Ascii85 filter - very rare), which may lead people to think that the code is fine with PHP 7 while it is not... 

Here are some os projects/packages which current versions are affected:

https://packagist.org/search/?q=fpdi
https://packagist.org/search/?q=mpdf
https://packagist.org/search/?q=pdfparser (depends on https://packagist.org/search/?q=tcpdf which seems to use such structure in its filter class/method, too - which is actually only used by the pdfparser)

Additionally there are some hundreds packages depending on these packages, too.

If you want to stay with this BC break this have to be documentated.

At our end this would force people to update not only to PHP 7 but to the latest library version. So I'm fine with this BC break.
Anyhow it could end in some trouble around these packages and users.

Cheers,
Jan
 [2015-06-24 09:10 UTC] ab@php.net
-Status: Not a bug +Status: Re-Opened -Type: Bug +Type: Documentation Problem -Assigned To: ab +Assigned To:
 [2015-06-24 09:10 UTC] ab@php.net
Jan,

ok, doc bug sounds appropriate. Thanks for more extended info.

Actually it's not a local BC, but might be found somewhere else and is a general behavior change. In PHP5 on 32-bit it would happily allow the internal integer argument to be overflown by that big integral constant, while in PHP7 it'll be always truncated to zero.

Thanks.
 [2015-06-24 12:06 UTC] jan dot slabon at setasign dot com
Anatol,

Do you have some other functions which are also affected by this behavior change?

Thanks!
Jan
 [2015-06-24 12:44 UTC] ab@php.net
Jan,

yeah, quite a behavior difference can be seen here and there. In most cases it's related to the implementation of https://wiki.php.net/rfc/zpp_fail_on_overflow . Additionally, we have an alternative API (aka fast ZPP) which partially replaces the old one where it makes sense, here also a slight difference can be seen. For instance, you can compare rand(0, 2632627629) on x64/x86 in PHP7 and PHP5. But actually any other functions taking integer arguments.

Hereby one should be aware that on Windows it's once more different again, because PHP7 has full 64-bit support cross platform - so it's kinda new land for the users yet. But as mentioned, it's now consistent across platforms. In general, switching to x64 would bring the most correct results probably.

Thanks.
 [2015-06-25 08:01 UTC] kalle@php.net
-PHP Version: 7.0.0alpha1 +PHP Version: *
 [2020-11-04 13:22 UTC] cmb@php.net
-Package: *General Issues +Package: Strings related -Assigned To: +Assigned To: cmb
 [2020-11-04 13:22 UTC] cmb@php.net
The most relevant issue here is that prior to PHP 7.4.0[1], chr()
did not warn about unsupported input.  Any value was silently
accepted and cast to zero unless it could be coerced to int.  That
even happend in strict_type code for all non integer values.

[1] <http://git.php.net/?p=php-src.git;a=commit;h=714d9fc358640069bda5540c2b1136a6241c4c94>
 [2020-11-04 13:24 UTC] phpdocbot@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=doc/en.git;a=commit;h=eaff4ac6338e42ab28f161a95cd7d9e6139891cc
Log: Fix #69906: chr() behavior difference between 32- and 64-bit bulids
 [2020-11-04 13:24 UTC] phpdocbot@php.net
-Status: Re-Opened +Status: Closed
 [2020-11-04 18:20 UTC] phpdocbot@php.net
Automatic comment on behalf of mumumu
Revision: http://git.php.net/?p=doc/ja.git;a=commit;h=45cb6343428f3d417d5e582a9ee03837c3c56e0f
Log: Fix #69906: chr() behavior difference between 32- and 64-bit bulids
 [2020-12-30 11:58 UTC] nikic@php.net
Automatic comment on behalf of mumumu
Revision: http://git.php.net/?p=doc/ja.git;a=commit;h=55971a558baddbdacb5357dc13778b4e9db9f343
Log: Fix #69906: chr() behavior difference between 32- and 64-bit bulids
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Apr 24 11:01:30 2024 UTC