Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ PHP NEWS
. Implemented partial function application RFC. (Arnaud)
. Fixed bug GH-22263 (reset typed property default on every unserialize
failure path). (David Carlier)
. Fixed bug GH-18985 (Wrong line numbers for match with constant arms).
(ilutov)

- DOM:
. Fixed bug GH-22825 (DOMElement::setAttribute() fails silently when the DTD
Expand Down Expand Up @@ -65,6 +67,8 @@ PHP NEWS
TransmitFile) for faster stream copying. (Jakub Zelenka, David Carlier)
. Fixed bug GH-22841 (php_stream_copy_to_stream_ex() drops progress
notifications when using the copy fast path). (David Carlier)
. Fixed bug GH-15836 (Use-after-free when a user stream filter accesses
$this->stream during the close flush). (iliaal)

16 Jul 2026, PHP 8.6.0alpha2

Expand Down Expand Up @@ -218,7 +222,7 @@ PHP NEWS
. Fix OSS-Fuzz #429429090 (Failed assertion on unset() with uninitialized
container). (ilutov)
. Fixed GH-20564 (Don't call autoloaders with pending exception). (ilutov)
. Fix deprecation now showing when accessing null key of an array with JIT.
. Fix deprecation not showing when accessing null key of an array with JIT.
(alexandre-daubois)
. Fixed bug GH-20174 (Assertion failure in
ReflectionProperty::skipLazyInitialization after failed LazyProxy
Expand Down
2 changes: 1 addition & 1 deletion UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ PHP 8.6 UPGRADE NOTES
requests, implementing custom server-side session storage, and controlling
session cache behavior.
RFC: https://wiki.php.net/rfc/tls_session_resumption
. Added TLS external PSK support for streams with new strem context options:
. Added TLS external PSK support for streams with new stream context options:
psk_client_cb and psk_server_cb. This allows setting and receiving PSK.

- Phar:
Expand Down
5 changes: 4 additions & 1 deletion Zend/Optimizer/zend_optimizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,10 @@ static void zend_optimize(zend_op_array *op_array,
}

if (ctx->debug_level & ZEND_DUMP_BEFORE_OPTIMIZER) {
zend_dump_op_array(op_array, ZEND_DUMP_LIVE_RANGES, "before optimizer", NULL);
uint32_t additional_dump_flags = (ctx->debug_level & ZEND_DUMP_LINE_NUMBERS_PASSTHRU)
? ZEND_DUMP_LINE_NUMBERS
: 0;
zend_dump_op_array(op_array, ZEND_DUMP_LIVE_RANGES|additional_dump_flags, "before optimizer", NULL);
}

/* pass 1 (Simple local optimizations)
Expand Down
1 change: 1 addition & 0 deletions Zend/Optimizer/zend_optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
#define ZEND_DUMP_DFA_SSA (1<<27)
#define ZEND_DUMP_DFA_SSA_VARS (1<<28)
#define ZEND_DUMP_SCCP (1<<29)
#define ZEND_DUMP_LINE_NUMBERS_PASSTHRU (1<<30)

typedef struct _zend_script {
zend_string *filename;
Expand Down
44 changes: 33 additions & 11 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -7125,6 +7125,8 @@ static void zend_compile_match(znode *result, zend_ast *ast)
zend_ast *arm_ast = arms->child[i];
zend_ast *body_ast = arm_ast->child[1];

CG(zend_lineno) = zend_ast_get_lineno(arm_ast);

if (arm_ast->child[0] != NULL) {
zend_ast_list *conds = zend_ast_get_list(arm_ast->child[0]);

Expand Down Expand Up @@ -10728,6 +10730,8 @@ static void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
zend_compile_expr(&left_node, left_ast);
zend_compile_expr(&right_node, right_ast);

CG(zend_lineno) = ast->lineno;

if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
if (zend_try_ct_eval_binary_op(&result->u.constant, opcode,
&left_node.u.constant, &right_node.u.constant)
Expand Down Expand Up @@ -12335,9 +12339,6 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */

static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */
{
/* CG(zend_lineno) = ast->lineno; */
CG(zend_lineno) = zend_ast_get_lineno(ast);

if (CG(memoize_mode) != ZEND_MEMOIZE_NONE) {
zend_compile_memoized_expr(result, ast, BP_VAR_R);
return;
Expand Down Expand Up @@ -12479,6 +12480,9 @@ static void zend_compile_expr(znode *result, zend_ast *ast)
{
zend_check_stack_limit();

uint32_t prev_lineno = CG(zend_lineno);
CG(zend_lineno) = zend_ast_get_lineno(ast);

uint32_t checkpoint = zend_short_circuiting_checkpoint();
zend_compile_expr_inner(result, ast);
zend_short_circuiting_commit(checkpoint, result, ast);
Expand All @@ -12488,12 +12492,12 @@ static void zend_compile_expr(znode *result, zend_ast *ast)
ZEND_ASSERT(result->op_type != IS_VAR);
}
#endif

CG(zend_lineno) = prev_lineno;
}

static zend_op *zend_compile_var_inner(znode *result, zend_ast *ast, uint32_t type, bool by_ref)
{
CG(zend_lineno) = zend_ast_get_lineno(ast);

if (CG(memoize_mode) != ZEND_MEMOIZE_NONE) {
switch (ast->kind) {
case ZEND_AST_CALL:
Expand Down Expand Up @@ -12554,6 +12558,9 @@ static zend_op *zend_compile_var(znode *result, zend_ast *ast, uint32_t type, bo
{
zend_check_stack_limit();

uint32_t prev_lineno = CG(zend_lineno);
CG(zend_lineno) = zend_ast_get_lineno(ast);

uint32_t checkpoint = zend_short_circuiting_checkpoint();
zend_op *opcode = zend_compile_var_inner(result, ast, type, by_ref);
zend_short_circuiting_commit(checkpoint, result, ast);
Expand All @@ -12567,32 +12574,47 @@ static zend_op *zend_compile_var(znode *result, zend_ast *ast, uint32_t type, bo
ZEND_ASSERT(result->op_type != IS_VAR);
}
#endif

CG(zend_lineno) = prev_lineno;

return opcode;
}

static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
{
zend_check_stack_limit();

uint32_t prev_lineno = CG(zend_lineno);
CG(zend_lineno) = zend_ast_get_lineno(ast);

zend_op *opline;
switch (ast->kind) {
case ZEND_AST_VAR:
return zend_compile_simple_var(result, ast, type, true);
opline = zend_compile_simple_var(result, ast, type, true);
break;
case ZEND_AST_DIM:
return zend_delayed_compile_dim(result, ast, type, by_ref);
opline = zend_delayed_compile_dim(result, ast, type, by_ref);
break;
case ZEND_AST_PROP:
case ZEND_AST_NULLSAFE_PROP:
{
zend_op *opline = zend_delayed_compile_prop(result, ast, type);
opline = zend_delayed_compile_prop(result, ast, type);
if (by_ref) {
opline->extended_value |= ZEND_FETCH_REF;
}
return opline;
break;
}
case ZEND_AST_STATIC_PROP:
return zend_compile_static_prop(result, ast, type, by_ref, true);
opline = zend_compile_static_prop(result, ast, type, by_ref, true);
break;
default:
return zend_compile_var(result, ast, type, false);
opline = zend_compile_var(result, ast, type, false);
break;
}

CG(zend_lineno) = prev_lineno;

return opline;
}
/* }}} */

Expand Down
36 changes: 8 additions & 28 deletions ext/ftp/ftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,14 +308,9 @@ bool ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const cha

case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE: {
php_pollfd p;
int i;
int i, events = (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT;

p.fd = ftp->fd;
p.events = (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT;
p.revents = 0;

i = php_poll2(&p, 1, 300);
i = php_pollfd_for_ms(ftp->fd, events, 300);

retry = i > 0;
}
Expand Down Expand Up @@ -1388,14 +1383,9 @@ static int single_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t size) {

case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_CONNECT: {
php_pollfd p;
int i;

p.fd = fd;
p.events = POLLOUT;
p.revents = 0;
int i, events = POLLOUT;

i = php_poll2(&p, 1, 300);
i = php_pollfd_for_ms(fd, events, 300);

retry = i > 0;
}
Expand Down Expand Up @@ -1521,14 +1511,9 @@ static int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len)

case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_CONNECT: {
php_pollfd p;
int i;
int i, events = POLLIN|POLLPRI;

p.fd = fd;
p.events = POLLIN|POLLPRI;
p.revents = 0;

i = php_poll2(&p, 1, 300);
i = php_pollfd_for_ms(fd, events, 300);

retry = i > 0;
}
Expand Down Expand Up @@ -1825,14 +1810,9 @@ static databuf_t* data_accept(databuf_t *data, ftpbuf_t *ftp)

case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE: {
php_pollfd p;
int i;

p.fd = data->fd;
p.events = (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT;
p.revents = 0;
int i, events = (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT;

i = php_poll2(&p, 1, 300);
i = php_pollfd_for_ms(data->fd, events, 300);

retry = i > 0;
}
Expand Down
16 changes: 8 additions & 8 deletions ext/opcache/ZendAccelerator.c
Original file line number Diff line number Diff line change
Expand Up @@ -1943,10 +1943,10 @@ static zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int
/* ext/phar has to load phar's metadata into memory */
if (persistent_script->is_phar) {
php_stream_statbuf ssb;
char *fname = emalloc(sizeof("phar://") + ZSTR_LEN(persistent_script->script.filename));

memcpy(fname, "phar://", sizeof("phar://") - 1);
memcpy(fname + sizeof("phar://") - 1, ZSTR_VAL(persistent_script->script.filename), ZSTR_LEN(persistent_script->script.filename) + 1);
char *fname = zend_cstr_concat(
"phar://", sizeof("phar://") - 1,
ZSTR_VAL(persistent_script->script.filename),
ZSTR_LEN(persistent_script->script.filename));
php_stream_stat_path(fname, &ssb);
efree(fname);
}
Expand Down Expand Up @@ -2457,10 +2457,10 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
/* ext/phar has to load phar's metadata into memory */
if (persistent_script->is_phar) {
php_stream_statbuf ssb;
char *fname = emalloc(sizeof("phar://") + ZSTR_LEN(persistent_script->script.filename));

memcpy(fname, "phar://", sizeof("phar://") - 1);
memcpy(fname + sizeof("phar://") - 1, ZSTR_VAL(persistent_script->script.filename), ZSTR_LEN(persistent_script->script.filename) + 1);
char *fname = zend_cstr_concat(
"phar://", sizeof("phar://") - 1,
ZSTR_VAL(persistent_script->script.filename),
ZSTR_LEN(persistent_script->script.filename));
php_stream_stat_path(fname, &ssb);
efree(fname);
}
Expand Down
15 changes: 10 additions & 5 deletions ext/opcache/jit/zend_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -3724,6 +3724,16 @@ int zend_jit_check_support(void)
{
int i;

#ifdef ZEND_JIT_USE_APPLE_MAP_JIT
if (!pthread_jit_write_protect_supported_np()) {
zend_accel_error(ACCEL_LOG_WARNING,
"Apple Silicon ZTS JIT requires pthread_jit_write_protect_np() support. JIT disabled.");
JIT_G(enabled) = 0;
JIT_G(on) = 0;
return FAILURE;
}
#endif

if (zend_execute_ex != execute_ex) {
if (zend_dtrace_enabled) {
zend_error(E_WARNING, "JIT is incompatible with DTrace. JIT disabled.");
Expand Down Expand Up @@ -3792,11 +3802,6 @@ void zend_jit_startup(void *buf, size_t size, bool reattached)
"Unable to share JIT buffer across fork using minherit(): %s (%d)",
strerror(error), error);
}
if (!pthread_jit_write_protect_supported_np()) {
munmap(buf, size);
zend_accel_error_noreturn(ACCEL_LOG_FATAL,
"Apple Silicon ZTS JIT requires pthread_jit_write_protect_np() support");
}
#endif

dasm_buf = buf;
Expand Down
3 changes: 2 additions & 1 deletion ext/opcache/shared_alloc_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ static int create_segments(size_t requested_size, zend_shared_segment_posix ***s
* only then amd64/i386/arm64 and perharps risc64*
* archs are on interest here.
*/
size_t i, shared_segment_sizes = 0, shared_segment_lg_index = 0;
size_t shared_segment_lg_index = 0;
size_t shared_segment_sindexes[3] = {0};
const size_t entries = sizeof(shared_segment_sindexes) / sizeof(shared_segment_sindexes[0]);
int i, shared_segment_sizes;

shared_segment_sizes = getpagesizes(shared_segment_sindexes, entries);

Expand Down
35 changes: 35 additions & 0 deletions ext/opcache/tests/gh18985.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--TEST--
GH-18985: Wrong lineno for multiline expressions
--EXTENSIONS--
opcache
--INI--
opcache.enable_cli=1
opcache.opt_debug_level=0x40010000
--FILE--
<?php

echo match(15) {
13 => "A",
15 => "B",
default => "C",
};

?>
--EXPECTF--
$_main:
; (lines=9, args=0, vars=0, tmps=%s)
; (before optimizer)
; %sgh18985.php:1-10
; return [] RANGE[0..0]
L0003 0000 MATCH int(15) 13: 0001, 15: 0003, default: 0005
L0004 0001 T1 = QM_ASSIGN string("A")
L0004 0002 JMP 0007
L0005 0003 T1 = QM_ASSIGN string("B")
L0005 0004 JMP 0007
L0006 0005 T1 = QM_ASSIGN string("C")
L0006 0006 JMP 0007
L0003 0007 ECHO T1
L0010 0008 RETURN int(1)
LIVE RANGES:
1: 0006 - 0007 (tmp/var)
B
5 changes: 4 additions & 1 deletion ext/opcache/tests/jit/gh14267_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ opcache.jit_buffer_size=32M
opcache
--FILE--
<?php
ini_set('opcache.jit', 'tracing');
// Skip when JIT was completely disabled at runtime.
if (($status = opcache_get_status()) === false || $status['jit']['enabled']) {
ini_set('opcache.jit', 'tracing');
}
?>
===DONE===
--EXPECT--
Expand Down
7 changes: 5 additions & 2 deletions ext/opcache/tests/jit/gh16393.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ opcache.jit=1215
opcache.jit_buffer_size=64M
--FILE--
<?php
ini_set('opcache.jit', 'tracing');
// Skip when JIT was completely disabled at runtime.
if (($status = opcache_get_status()) === false || $status['jit']['enabled']) {
ini_set('opcache.jit', 'tracing');
}
class Test {
}
$appendProp2 = (function() {
})->bindTo($test, Test::class);
$appendProp2();
?>
--EXPECTF--
Warning: Undefined variable $test in %sgh16393.php on line 6
Warning: Undefined variable $test in %sgh16393.php on line 9
4 changes: 2 additions & 2 deletions ext/opcache/tests/jit/shift_right_004.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ Warning: Undefined array key 0 in %sshift_right_004.php on line 7

Deprecated: Implicit conversion from float %f to int loses precision in %sshift_right_004.php on line 8

Warning: A non-numeric value encountered in %sshift_right_004.php on line 7
Warning: A non-numeric value encountered in %sshift_right_004.php on line 6

Warning: A non-numeric value encountered in %sshift_right_004.php on line 7
Warning: A non-numeric value encountered in %sshift_right_004.php on line 6

Fatal error: Uncaught ArithmeticError: Bit shift by negative number in %sshift_right_004.php:8
Stack trace:
Expand Down
4 changes: 2 additions & 2 deletions ext/opcache/tests/jit/switch_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ foo();
?>
DONE
--EXPECTF--
Warning: Undefined variable $y in %sswitch_001.php on line 4
Warning: Undefined variable $y in %sswitch_001.php on line 3

Warning: Undefined variable $y in %sswitch_001.php on line 5
Warning: Undefined variable $y in %sswitch_001.php on line 3
DONE
Loading