We were using atoi, which is only for integers. When the size does not
fit in an integer this breaks. Use ZEND_STRTOUL instead. Also make sure
invalid data isn't accidentally parsed into a file size.
Closes GH-15035.
* PHP-8.3:
NEWS for GH-14814
ext/standard/tests: strings/wordwrap_memory_limit_32bit.phpt has two outputs
ext/standard/tests: 32bit wordwrap tests aren't just for Windows
* PHP-8.2:
NEWS for GH-14814
ext/standard/tests: strings/wordwrap_memory_limit_32bit.phpt has two outputs
ext/standard/tests: 32bit wordwrap tests aren't just for Windows
It turns out that on a 32-bit system, this test can produce either the
"usual" expected output from the 64-bit test, OR the 32-bit-only
integer overflow message. We copy the dual expected outputs from
chunk_split_variation1_32bit.phpt to handle both cases.
This fixes an earlier commit that split the two tests based only on
the size of an int (32-bit versus 64-bit). The CI reveals that, at
least on a debug/zts build, the "64-bit" memory limit error (and not
the integer overflow error) is still produced.
The test in strings/wordwrap_memory_limit.phpt has a counterpart in
strings/wordwrap_memory_limit_win32.phpt. The two are conditional on
both the OS name and the size of an int (32- versus 64-bits).
A Gentoo Linux user has however reported that the 64-bit test fails on
a 32-bit system, with precisely the error message that the "win32"
test is expecting. I don't have any 32-bit hardware to test myself,
but I think it's reasonable to conclude that the OS name is not an
essential part of the test: it's simply 32- versus 64-bit.
This commit drops the conditionals for the OS name. Now one test will
be run on 32-bit systems, and the other on 64-bit systems, regardless
of the OS name.
Bug: https://bugs.gentoo.org/935382
In strings/chunk_split_variation1_32bit.phpt, we have a test that is
expected to fail on x32 with a possible integer overflow error. The
message reports the exact number of bytes -- a number big enough to
overflow an int on x32 -- stemming from a memory allocation in
chunk_split().
This number appears unpredictable, and is not the point of the test.
We replace it with %d to make the test independent of the allocation
details.
* zend_compile: Rename `string_placeholder_count` to `placeholder_count` in `zend_compile_func_sprintf()`
This is intended to make the diff of a follow-up commit smaller.
* zend_compile: Add support for `%d` to `sprintf()` optimization
This extends the existing `sprintf()` optimization by support for the `%d`
placeholder, which effectively equivalent to an `(int)` cast followed by a
`(string)` cast.
For a synthetic test using:
<?php
$a = 'foo';
$b = 42;
for ($i = 0; $i < 100_000_000; $i++) {
sprintf("%s-%d", $a, $b);
}
This optimization yields a 1.3× performance improvement:
$ hyperfine 'sapi/cli/php -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php' \
'/tmp/unoptimized -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php'
Benchmark 1: sapi/cli/php -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php
Time (mean ± σ): 3.296 s ± 0.094 s [User: 3.287 s, System: 0.005 s]
Range (min … max): 3.213 s … 3.527 s 10 runs
Benchmark 2: /tmp/unoptimized -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php
Time (mean ± σ): 4.300 s ± 0.025 s [User: 4.290 s, System: 0.007 s]
Range (min … max): 4.266 s … 4.334 s 10 runs
Summary
sapi/cli/php -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php ran
1.30 ± 0.04 times faster than /tmp/unoptimized -d zend_extension=php-src/modules/opcache.so -d opcache.enable_cli=1 test.php
* Fix sprintf_rope_optimization_003.phpt test expecation for 32-bit integers
* zend_compile: Indent switch-case labels in zend_compile_func_sprintf()
* Add GMP test to sprintf() rope optimization
* Add `%s` test case to sprintf() GMP test