Skip to content

Commit 466c8b0

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix GH-17257: UBSAN warning in ext/opcache/jit/zend_jit_vm_helpers.c Fix GH-17223: Memory leak in libxml encoding handling
2 parents b4c5f4e + f4fb77e commit 466c8b0

File tree

6 files changed

+65
-7
lines changed

6 files changed

+65
-7
lines changed

ext/dom/tests/gh17223.phpt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
GH-17223 (Memory leak in libxml encoding handling)
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
$doc = new DOMDocument("1.0", "Shift-JIS");
8+
@$doc->save("%00");
9+
echo "Done\n";
10+
?>
11+
--EXPECT--
12+
Done

ext/libxml/libxml.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -562,11 +562,11 @@ php_libxml_output_buffer_create_filename(const char *URI,
562562
char *unescaped = NULL;
563563

564564
if (URI == NULL)
565-
return(NULL);
565+
goto err;
566566

567567
if (strstr(URI, "%00")) {
568568
php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes");
569-
return NULL;
569+
goto err;
570570
}
571571

572572
puri = xmlParseURI(URI);
@@ -587,7 +587,7 @@ php_libxml_output_buffer_create_filename(const char *URI,
587587
}
588588

589589
if (context == NULL) {
590-
return(NULL);
590+
goto err;
591591
}
592592

593593
/* Allocate the Output buffer front-end. */
@@ -599,6 +599,11 @@ php_libxml_output_buffer_create_filename(const char *URI,
599599
}
600600

601601
return(ret);
602+
603+
err:
604+
/* Similarly to __xmlOutputBufferCreateFilename we should also close the encoder on failure. */
605+
xmlCharEncCloseFunc(encoder);
606+
return NULL;
602607
}
603608

604609
static void php_libxml_free_error(void *ptr)

ext/opcache/jit/zend_jit_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_counter_helper(ZEND_OPCODE_H
231231
ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_counter_helper(ZEND_OPCODE_HANDLER_ARGS);
232232

233233
void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D);
234+
void ZEND_FASTCALL zend_jit_copy_extra_args_helper_no_skip_recv(EXECUTE_DATA_D);
234235
bool ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D);
235236
void ZEND_FASTCALL zend_jit_undefined_long_key(EXECUTE_DATA_D);
236237
void ZEND_FASTCALL zend_jit_undefined_long_key_ex(zend_long key EXECUTE_DATA_DC);

ext/opcache/jit/zend_jit_ir.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3053,6 +3053,7 @@ static void zend_jit_setup_disasm(void)
30533053
REGISTER_HELPER(zend_jit_undefined_long_key_ex);
30543054
REGISTER_HELPER(zend_jit_undefined_string_key);
30553055
REGISTER_HELPER(zend_jit_copy_extra_args_helper);
3056+
REGISTER_HELPER(zend_jit_copy_extra_args_helper_no_skip_recv);
30563057
REGISTER_HELPER(zend_jit_vm_stack_free_args_helper);
30573058
REGISTER_HELPER(zend_free_extra_named_params);
30583059
REGISTER_HELPER(zend_jit_free_call_frame);
@@ -10292,6 +10293,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
1029210293
}
1029310294
}
1029410295
} else {
10296+
ir_ref helper;
1029510297
if (!trace || (trace->op == ZEND_JIT_TRACE_END
1029610298
&& trace->stop >= ZEND_JIT_TRACE_STOP_INTERPRETER)) {
1029710299
ir_ref ip;
@@ -10305,11 +10307,14 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
1030510307
ip = ir_LOAD_A(ir_ADD_OFFSET(func_ref, offsetof(zend_op_array, opcodes)));
1030610308
}
1030710309
jit_LOAD_IP(jit, ip);
10310+
helper = ir_CONST_FC_FUNC(zend_jit_copy_extra_args_helper);
10311+
} else {
10312+
helper = ir_CONST_FC_FUNC(zend_jit_copy_extra_args_helper_no_skip_recv);
1030810313
}
1030910314
if (GCC_GLOBAL_REGS) {
10310-
ir_CALL(IR_VOID, ir_CONST_FC_FUNC(zend_jit_copy_extra_args_helper));
10315+
ir_CALL(IR_VOID, helper);
1031110316
} else {
10312-
ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_copy_extra_args_helper), jit_FP(jit));
10317+
ir_CALL_1(IR_VOID, helper, jit_FP(jit));
1031310318
}
1031410319
}
1031510320
} else {

ext/opcache/jit/zend_jit_vm_helpers.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_func_helper(EXECUTE_DATA_D)
120120
}
121121
}
122122

123-
void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D)
123+
static void ZEND_FASTCALL zend_jit_copy_extra_args_helper_ex(bool skip_recv EXECUTE_DATA_DC)
124124
{
125125
zend_op_array *op_array = &EX(func)->op_array;
126126

@@ -130,7 +130,7 @@ void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D)
130130
zval *end, *src, *dst;
131131
uint32_t type_flags = 0;
132132

133-
if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
133+
if (skip_recv && EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
134134
/* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
135135
#ifdef HAVE_GCC_GLOBAL_REGS
136136
opline += first_extra_arg;
@@ -166,6 +166,16 @@ void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D)
166166
}
167167
}
168168

169+
void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D)
170+
{
171+
zend_jit_copy_extra_args_helper_ex(true EXECUTE_DATA_CC);
172+
}
173+
174+
void ZEND_FASTCALL zend_jit_copy_extra_args_helper_no_skip_recv(EXECUTE_DATA_D)
175+
{
176+
zend_jit_copy_extra_args_helper_ex(false EXECUTE_DATA_CC);
177+
}
178+
169179
bool ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D)
170180
{
171181
zend_execute_data *call = (zend_execute_data *) opline;

ext/opcache/tests/jit/gh17257.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
GH-17257 (SEGV ext/opcache/jit/zend_jit_vm_helpers.c)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.jit_buffer_size=32M
7+
opcache.jit=1254
8+
opcache.jit_hot_func=1
9+
--FILE--
10+
<?php
11+
function get_const() {
12+
}
13+
function test() {
14+
call_user_func('get_const', 1); // need an extra arg to trigger the issue
15+
}
16+
function main(){
17+
for ($i = 0; $i < 10; $i++) {
18+
test();
19+
}
20+
echo "Done\n";
21+
}
22+
main();
23+
?>
24+
--EXPECT--
25+
Done

0 commit comments

Comments
 (0)