[php-src] master: Merge branch 'PHP-8.5' into PHP-8.6

From: Date: Fri, 02 Oct 2026 14:24:32 +0000
Subject: [php-src] master: Merge branch 'PHP-8.5' into PHP-8.6
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-141881@lists.php.net to get a copy of this message
Author: Arnaud Le Blanc (arnaud-lb) Date: 2026-10-02T16:24:08+02:00 Commit: https://github.com/php/php-src/commit/38b2036e6f70de1000cd9177c113f7e5195eae47 Raw diff: https://github.com/php/php-src/commit/38b2036e6f70de1000cd9177c113f7e5195eae47.diff Merge branch 'PHP-8.5' into PHP-8.6 * PHP-8.5: Fix GH-24063: SCCP merges 0.0 and -0.0 into a single constant (#24064) Changed paths: A ext/opcache/tests/opt/gh24063.phpt M NEWS M Zend/Optimizer/sccp.c Diff: diff --git a/NEWS b/NEWS index 191a241cb246..f9ce88ceec19 100644 --- a/NEWS +++ b/NEWS @@ -61,6 +61,8 @@ PHP NEWS child's shadowing public property). (Ilia Alshanetsky) . Fix multiple incorrect DCE due to unsound escape analysis. (ndossche, arnaud-lb) + . Fixed bug GH-24063 (OPcache optimizer folds $cond ? -0.0 : 0.0 into a + single -0.0 constant). (lazerg) - OpenSSL: . Fixed stream_socket_enable_crypto() leaving the socket non-blocking diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index 72ba6d98888e..01ba8e6ba676 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -1951,6 +1951,28 @@ static void sccp_mark_feasible_successors( scdf_mark_edge_feasible(scdf, block_num, block->successors[s]); } +/* Unlike zend_is_identical(), this does not treat 0.0 and -0.0 as the same value. + * Returns int to be usable as compare_func_t. */ +static int sccp_values_differ(const void *p1, const void *p2) +{ + const zval *a = p1; + const zval *b = p2; + + if (Z_TYPE_P(a) != Z_TYPE_P(b)) { + return 1; + } + if (Z_TYPE_P(a) == IS_DOUBLE) { + return memcmp(&Z_DVAL_P(a), &Z_DVAL_P(b), sizeof(double)) != 0; + } + if (Z_TYPE_P(a) == IS_ARRAY) { + return Z_ARRVAL_P(a) != Z_ARRVAL_P(b) + && zend_hash_compare(Z_ARRVAL_P(a), Z_ARRVAL_P(b), sccp_values_differ, 1) != 0; + } + ZEND_ASSERT(IS_PARTIAL_ARRAY(a) || IS_PARTIAL_OBJECT(a) + || ((1 << Z_TYPE_P(a)) & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_BOOL|MAY_BE_LONG|MAY_BE_STRING))); + return !zend_is_identical(a, b); +} + static void join_hash_tables(HashTable *ret, const HashTable *ht1, const HashTable *ht2) { zend_ulong index; @@ -1963,7 +1985,7 @@ static void join_hash_tables(HashTable *ret, const HashTable *ht1, const HashTab } else { val2 = zend_hash_index_find(ht2, index); } - if (val2 && zend_is_identical(val1, val2)) { + if (val2 && !sccp_values_differ(val1, val2)) { if (key) { val1 = zend_hash_add_new(ret, key, val1); } else { @@ -2031,7 +2053,7 @@ static void join_phi_values(zval *a, const zval *b, bool escape) { zval_ptr_dtor_nogc(a); MAKE_BOT(a); } - } else if (!zend_is_identical(a, b)) { + } else if (sccp_values_differ(a, b)) { if (join_partial_arrays(a, b) == FAILURE) { zval_ptr_dtor_nogc(a); MAKE_BOT(a); diff --git a/ext/opcache/tests/opt/gh24063.phpt b/ext/opcache/tests/opt/gh24063.phpt new file mode 100644 index 000000000000..36f3ddbdca13 --- /dev/null +++ b/ext/opcache/tests/opt/gh24063.phpt @@ -0,0 +1,46 @@ +--TEST-- +GH-24063 (SCCP merges 0.0 and -0.0 into a single constant) +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- +<?php + +function scalar(float $n): float +{ + $r = $n < 0 ? -0.0 : 0.0; + return $r; +} + +function arr(float $n): array +{ + $r = $n < 0 ? [-0.0] : [0.0]; + return $r; +} + +function partial(float $n, $x): float +{ + $a = ['x' => $x]; + if ($n < 0) { + $a['k'] = -0.0; + } else { + $a['k'] = 0.0; + } + return $a['k']; +} + +var_dump(scalar(1.0), scalar(-1.0)); +var_dump(arr(1.0)[0], arr(-1.0)[0]); +var_dump(partial(1.0, 1), partial(-1.0, 1)); + +?> +--EXPECT-- +float(0) +float(-0) +float(0) +float(-0) +float(0) +float(-0)

« previous php.cvs (#141881) next »