Skip to content

Commit cd67e83

Browse files
committed
Merge remote-tracking branch 'php/master' into perf/zts_thread_alloc
# Conflicts: # ext/reflection/php_reflection.c
2 parents 58b487f + e2c975d commit cd67e83

25 files changed

Lines changed: 724 additions & 124 deletions

.github/actions/apt-x64/action.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ runs:
6363
snmp-mibs-downloader \
6464
freetds-dev \
6565
unixodbc-dev \
66+
libsqliteodbc \
6667
llvm \
6768
clang \
6869
dovecot-core \

NEWS

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3-
?? ??? ????, PHP 8.6.0alpha2
3+
?? ??? ????, PHP 8.6.0alpha3
4+
5+
- Reflection:
6+
. Fixed bug GH-22681 (Reflection*::__toString() truncates on null bytes).
7+
(DanielEScherzer)
8+
9+
16 Jul 2026, PHP 8.6.0alpha2
410

511
- Core:
612
. Sync Boost.Context assembly with 1.91.0. (kn1g78)
@@ -93,6 +99,8 @@ PHP NEWS
9399
- Reflection:
94100
. Fixed bug GH-22683 (Reflection(Class)Constant::__toString() should not warn
95101
on NAN conversions). (Khaled Alam)
102+
. Fixed bug GH-22681 (Reflection*::__toString() truncates on null bytes).
103+
(DanielEScherzer)
96104

97105
- Session:
98106
. Fixed bug GH-21314 (Different session garbage collector behavior between
@@ -103,6 +111,8 @@ PHP NEWS
103111
do_request() parameters). (David Carlier)
104112
. Fixed xsd:hexBinary decoding to reject odd-length values instead of
105113
silently truncating the last nibble. (Weilin Du)
114+
. Made SOAP encoding errors report the affected type or failing operation
115+
instead of the generic "Violation of encoding rules" message. (Weilin Du)
106116

107117
- Standard:
108118
. Fixed sleep() and usleep() to reject values that overflow the underlying

UPGRADING

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ PHP 8.6 UPGRADE NOTES
147147
. WSDL/XML Schema parsing now rejects out-of-range integer values for
148148
occurrence constraints and integer restriction facets. Negative minOccurs
149149
and maxOccurs values are rejected as well.
150+
. SOAP encoding errors now report the affected type or failing operation in
151+
the error message instead of the generic "Encoding: Violation of encoding
152+
rules" message. Code that compares the exact message may need to be
153+
updated.
150154

151155
- Sodium:
152156
. The password-hashing functions sodium_crypto_pwhash(),

ext/bz2/bz2_filter.c

Lines changed: 117 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -375,22 +375,8 @@ static const php_stream_filter_ops php_bz2_compress_ops = {
375375

376376
/* }}} */
377377

378-
/* {{{ bzip2.* common factory */
379-
380-
static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *filterparams, bool persistent)
381-
{
382-
const php_stream_filter_ops *fops = NULL;
383-
php_stream_filter_seekable_t write_seekable;
384-
php_bz2_filter_data *data;
385-
int status = BZ_OK;
386-
387-
if (php_stream_filter_parse_write_seek_mode(filterparams, &write_seekable) == FAILURE) {
388-
return NULL;
389-
}
390-
391-
/* Create this filter */
392-
data = pecalloc(1, sizeof(php_bz2_filter_data), persistent);
393-
378+
static php_bz2_filter_data *php_bz2_filter_data_new(bool persistent) {
379+
php_bz2_filter_data *data = pecalloc(1, sizeof(php_bz2_filter_data), persistent);
394380
/* Circular reference */
395381
data->strm.opaque = (void *) data;
396382

@@ -401,86 +387,143 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi
401387
data->strm.next_in = data->inbuf = (char *) pemalloc(data->inbuf_len, persistent);
402388
data->strm.avail_in = 0;
403389
data->strm.next_out = data->outbuf = (char *) pemalloc(data->outbuf_len, persistent);
390+
return data;
391+
}
404392

405-
if (strcasecmp(filtername, "bzip2.decompress") == 0) {
406-
data->small_footprint = 0;
407-
data->expect_concatenated = 0;
408-
409-
if (filterparams) {
410-
zval *tmpzval = NULL;
393+
static php_stream_filter *php_bz2_decompress_filter_create(zval *filter_params, bool persistent) {
394+
php_stream_filter_seekable_t write_seekable = PSFS_SEEKABLE_ALWAYS;
395+
bool small_footprint = false;
396+
bool expect_concatenated = false;
397+
398+
if (filter_params) {
399+
if (UNEXPECTED(
400+
Z_TYPE_P(filter_params) != IS_TRUE
401+
&& Z_TYPE_P(filter_params) != IS_FALSE
402+
&& Z_TYPE_P(filter_params) != IS_ARRAY
403+
&& Z_TYPE_P(filter_params) != IS_OBJECT
404+
)) {
405+
php_error_docref(NULL, E_WARNING,
406+
"Filter parameters for bzip2.decompress filter must be of type array|object|bool, %s given",
407+
zend_zval_type_name(filter_params)
408+
);
409+
return NULL;
410+
}
411411

412-
if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) {
413-
HashTable *ht = HASH_OF(filterparams);
412+
if (Z_TYPE_P(filter_params) == IS_TRUE || Z_TYPE_P(filter_params) == IS_FALSE) {
413+
small_footprint = Z_TYPE_P(filter_params) == IS_TRUE;
414+
} else {
415+
ZEND_ASSERT(Z_TYPE_P(filter_params) == IS_ARRAY || Z_TYPE_P(filter_params) == IS_OBJECT);
414416

415-
if ((tmpzval = zend_hash_str_find_ind(ht, "concatenated", sizeof("concatenated")-1))) {
416-
data->expect_concatenated = zend_is_true(tmpzval);
417-
tmpzval = NULL;
418-
}
417+
const HashTable *filter_params_ht = HASH_OF(filter_params);
418+
/* TODO: convert php_stream_filter_parse_write_seek_mode() to take HashTable */
419+
if (php_stream_filter_parse_write_seek_mode(filter_params, &write_seekable) == FAILURE) {
420+
return NULL;
421+
}
419422

420-
tmpzval = zend_hash_str_find_ind(ht, "small", sizeof("small")-1);
421-
} else {
422-
tmpzval = filterparams;
423+
const zval *concatenated = zend_hash_str_find_ind(filter_params_ht, ZEND_STRL("concatenated"));
424+
if (concatenated) {
425+
expect_concatenated = zend_is_true(concatenated);
423426
}
424427

425-
if (tmpzval) {
426-
data->small_footprint = zend_is_true(tmpzval);
428+
const zval *small = zend_hash_str_find_ind(filter_params_ht, ZEND_STRL("small"));
429+
if (small) {
430+
small_footprint = zend_is_true(small);
427431
}
428432
}
433+
}
429434

430-
data->status = PHP_BZ2_UNINITIALIZED;
431-
fops = &php_bz2_decompress_ops;
432-
} else if (strcasecmp(filtername, "bzip2.compress") == 0) {
433-
int blockSize100k = PHP_BZ2_FILTER_DEFAULT_BLOCKSIZE;
434-
int workFactor = PHP_BZ2_FILTER_DEFAULT_WORKFACTOR;
435-
436-
if (filterparams) {
437-
zval *tmpzval;
438-
439-
if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) {
440-
HashTable *ht = HASH_OF(filterparams);
441-
442-
if ((tmpzval = zend_hash_str_find_ind(ht, "blocks", sizeof("blocks")-1))) {
443-
/* How much memory to allocate (1 - 9) x 100kb */
444-
zend_long blocks = zval_get_long(tmpzval);
445-
if (blocks < 1 || blocks > 9) {
446-
php_error_docref(NULL, E_WARNING, "Invalid parameter given for number of blocks to allocate (" ZEND_LONG_FMT ")", blocks);
447-
} else {
448-
blockSize100k = (int) blocks;
449-
}
450-
}
435+
php_bz2_filter_data *data = php_bz2_filter_data_new(persistent);
436+
/* Save configuration for reset */
437+
data->small_footprint = small_footprint;
438+
data->expect_concatenated = expect_concatenated;
439+
data->status = PHP_BZ2_UNINITIALIZED;
451440

452-
if ((tmpzval = zend_hash_str_find_ind(ht, "work", sizeof("work")-1))) {
453-
/* Work Factor (0 - 250) */
454-
zend_long work = zval_get_long(tmpzval);
455-
if (work < 0 || work > 250) {
456-
php_error_docref(NULL, E_WARNING, "Invalid parameter given for work factor (" ZEND_LONG_FMT ")", work);
457-
} else {
458-
workFactor = (int) work;
459-
}
460-
}
461-
}
441+
return php_stream_filter_alloc(&php_bz2_decompress_ops, data, persistent, PSFS_SEEKABLE_START, write_seekable);
442+
}
443+
444+
static php_stream_filter *php_bz2_compress_filter_create(zval *filter_params, bool persistent) {
445+
php_stream_filter_seekable_t write_seekable = PSFS_SEEKABLE_ALWAYS;
446+
int blockSize100k = PHP_BZ2_FILTER_DEFAULT_BLOCKSIZE;
447+
int workFactor = PHP_BZ2_FILTER_DEFAULT_WORKFACTOR;
448+
449+
if (filter_params) {
450+
if (UNEXPECTED(Z_TYPE_P(filter_params) != IS_ARRAY && Z_TYPE_P(filter_params) != IS_OBJECT)) {
451+
php_error_docref(NULL, E_WARNING,
452+
"Filter parameters for bzip2.compress filter must be of type array|object, %s given",
453+
zend_zval_type_name(filter_params)
454+
);
455+
return NULL;
462456
}
463457

464-
/* Save configuration for reset */
465-
data->blockSize100k = blockSize100k;
466-
data->workFactor = workFactor;
458+
const HashTable *filter_params_ht = HASH_OF(filter_params);
459+
/* TODO: convert php_stream_filter_parse_write_seek_mode() to take HashTable */
460+
if (php_stream_filter_parse_write_seek_mode(filter_params, &write_seekable) == FAILURE) {
461+
return NULL;
462+
}
467463

468-
status = BZ2_bzCompressInit(&(data->strm), blockSize100k, 0, workFactor);
469-
data->is_flushed = 1;
470-
fops = &php_bz2_compress_ops;
471-
} else {
472-
status = BZ_DATA_ERROR;
464+
const zval *blocks_zv = zend_hash_str_find_ind(filter_params_ht, ZEND_STRL("blocks"));
465+
if (blocks_zv) {
466+
ZEND_ASSERT(Z_TYPE_P(blocks_zv) != IS_INDIRECT);
467+
bool failed = false;
468+
/* How much memory to allocate (1 - 9) x 100kb */
469+
zend_long blocks = zval_try_get_long(blocks_zv, &failed);
470+
if (UNEXPECTED(failed)) {
471+
php_error_docref(NULL, E_WARNING, "Number of blocks parameter must be of type int, %s given", zend_zval_type_name(blocks_zv));
472+
return NULL;
473+
} else if (blocks < 1 || blocks > 9) {
474+
php_error_docref(NULL, E_WARNING, "Number of blocks to allocate must be between 1 and 9, " ZEND_LONG_FMT " given", blocks);
475+
return NULL;
476+
} else {
477+
blockSize100k = (int) blocks;
478+
}
479+
}
480+
481+
const zval *work_zv = zend_hash_str_find_ind(filter_params_ht, ZEND_STRL("work"));
482+
if (work_zv) {
483+
ZEND_ASSERT(Z_TYPE_P(work_zv) != IS_INDIRECT);
484+
bool failed = false;
485+
/* Work Factor (0 - 250) */
486+
zend_long work = zval_try_get_long(work_zv, &failed);
487+
if (UNEXPECTED(failed)) {
488+
php_error_docref(NULL, E_WARNING, "Work factor parameter must be of type int, %s given", zend_zval_type_name(work_zv));
489+
return NULL;
490+
} else if (work < 0 || work > 250) {
491+
php_error_docref(NULL, E_WARNING, "Work factor must be between 0 and 250, " ZEND_LONG_FMT " given", work);
492+
return NULL;
493+
} else {
494+
workFactor = (int) work;
495+
}
496+
}
473497
}
474498

475-
if (status != BZ_OK) {
499+
php_bz2_filter_data *data = php_bz2_filter_data_new(persistent);
500+
/* Save configuration for reset */
501+
data->blockSize100k = blockSize100k;
502+
data->workFactor = workFactor;
503+
504+
int status = BZ2_bzCompressInit(&(data->strm), blockSize100k, 0, workFactor);
505+
if (UNEXPECTED(status != BZ_OK)) {
476506
/* Unspecified (probably strm) error, let stream-filter error do its own whining */
477507
pefree(data->strm.next_in, persistent);
478508
pefree(data->strm.next_out, persistent);
479509
pefree(data, persistent);
480510
return NULL;
481511
}
512+
data->is_flushed = true;
513+
514+
return php_stream_filter_alloc(&php_bz2_compress_ops, data, persistent, PSFS_SEEKABLE_START, write_seekable);
515+
}
482516

483-
return php_stream_filter_alloc(fops, data, persistent, PSFS_SEEKABLE_START, write_seekable);
517+
/* {{{ bzip2.* common factory */
518+
static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *filterparams, bool persistent)
519+
{
520+
if (strcasecmp(filtername, "bzip2.decompress") == 0) {
521+
return php_bz2_decompress_filter_create(filterparams, persistent);
522+
} else if (strcasecmp(filtername, "bzip2.compress") == 0) {
523+
return php_bz2_compress_filter_create(filterparams, persistent);
524+
} else {
525+
return NULL;
526+
}
484527
}
485528

486529
const php_stream_filter_factory php_bz2_filter_factory = {

ext/bz2/tests/bug72447.phpt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ fclose($fp);
1616
unlink('testfile');
1717
?>
1818
--EXPECTF--
19-
Warning: stream_filter_append(): Invalid parameter given for number of blocks to allocate (0) in %s%ebug72447.php on line %d
19+
Warning: stream_filter_append(): Number of blocks parameter must be of type int, string given in %s on line %d
20+
21+
Warning: stream_filter_append(): Unable to create or locate filter "bzip2.compress" in %s on line %d
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
--TEST--
2+
bzip2.compress filter param errors
3+
--EXTENSIONS--
4+
bz2
5+
--FILE--
6+
<?php
7+
$fp = fopen('php://stdout', 'w');
8+
9+
$param = 'not an array';
10+
var_dump(stream_filter_append($fp, 'bzip2.compress', STREAM_FILTER_WRITE, $param));
11+
12+
$param = ['blocks' => 'not an int'];
13+
var_dump(stream_filter_append($fp, 'bzip2.compress', STREAM_FILTER_WRITE, $param));
14+
15+
$param = ['blocks' => '15'];
16+
var_dump(stream_filter_append($fp, 'bzip2.compress', STREAM_FILTER_WRITE, $param));
17+
18+
$param = ['blocks' => '0'];
19+
var_dump(stream_filter_append($fp, 'bzip2.compress', STREAM_FILTER_WRITE, $param));
20+
21+
$param = ['work' => 'not an int'];
22+
var_dump(stream_filter_append($fp, 'bzip2.compress', STREAM_FILTER_WRITE, $param));
23+
24+
$param = ['work' => '251'];
25+
var_dump(stream_filter_append($fp, 'bzip2.compress', STREAM_FILTER_WRITE, $param));
26+
27+
$param = ['work' => '-1'];
28+
var_dump(stream_filter_append($fp, 'bzip2.compress', STREAM_FILTER_WRITE, $param));
29+
30+
fclose($fp);
31+
32+
?>
33+
--EXPECTF--
34+
Warning: stream_filter_append(): Filter parameters for bzip2.compress filter must be of type array|object, string given in %s on line %d
35+
36+
Warning: stream_filter_append(): Unable to create or locate filter "bzip2.compress" in %s on line %d
37+
bool(false)
38+
39+
Warning: stream_filter_append(): Number of blocks parameter must be of type int, string given in %s on line %d
40+
41+
Warning: stream_filter_append(): Unable to create or locate filter "bzip2.compress" in %s on line %d
42+
bool(false)
43+
44+
Warning: stream_filter_append(): Number of blocks to allocate must be between 1 and 9, 15 given in %s on line %d
45+
46+
Warning: stream_filter_append(): Unable to create or locate filter "bzip2.compress" in %s on line %d
47+
bool(false)
48+
49+
Warning: stream_filter_append(): Number of blocks to allocate must be between 1 and 9, 0 given in %s on line %d
50+
51+
Warning: stream_filter_append(): Unable to create or locate filter "bzip2.compress" in %s on line %d
52+
bool(false)
53+
54+
Warning: stream_filter_append(): Work factor parameter must be of type int, string given in %s on line %d
55+
56+
Warning: stream_filter_append(): Unable to create or locate filter "bzip2.compress" in %s on line %d
57+
bool(false)
58+
59+
Warning: stream_filter_append(): Work factor must be between 0 and 250, 251 given in %s on line %d
60+
61+
Warning: stream_filter_append(): Unable to create or locate filter "bzip2.compress" in %s on line %d
62+
bool(false)
63+
64+
Warning: stream_filter_append(): Work factor must be between 0 and 250, -1 given in %s on line %d
65+
66+
Warning: stream_filter_append(): Unable to create or locate filter "bzip2.compress" in %s on line %d
67+
bool(false)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
bzip2.decompress filter param errors
3+
--EXTENSIONS--
4+
bz2
5+
--FILE--
6+
<?php
7+
$fp = fopen('php://stdout', 'w');
8+
9+
$param = 'not an array or bool';
10+
var_dump(stream_filter_append($fp, 'bzip2.decompress', STREAM_FILTER_WRITE, $param));
11+
12+
fclose($fp);
13+
14+
?>
15+
--EXPECTF--
16+
Warning: stream_filter_append(): Filter parameters for bzip2.decompress filter must be of type array|object|bool, string given in %s on line %d
17+
18+
Warning: stream_filter_append(): Unable to create or locate filter "bzip2.decompress" in %s on line %d
19+
bool(false)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
bzip2 filter error on unknown filter name
3+
--EXTENSIONS--
4+
bz2
5+
--FILE--
6+
<?php
7+
$fp = fopen('php://stdout', 'w');
8+
9+
var_dump(stream_filter_append($fp, 'bzip2.i_dont_exist', STREAM_FILTER_WRITE));
10+
11+
fclose($fp);
12+
13+
?>
14+
--EXPECTF--
15+
Warning: stream_filter_append(): Unable to create or locate filter "bzip2.i_dont_exist" in %s on line %d
16+
bool(false)

0 commit comments

Comments
 (0)