Skip to content

Commit 70f7e7d

Browse files
committed
JIT: Fix memory leak
Fixes oss-fuzz #44920
1 parent ac8a53c commit 70f7e7d

File tree

4 files changed

+70
-4
lines changed

4 files changed

+70
-4
lines changed

ext/opcache/jit/zend_jit_disasm_x86.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ static int zend_jit_disasm_init(void)
461461
REGISTER_HELPER(zend_jit_post_inc_typed_ref);
462462
REGISTER_HELPER(zend_jit_post_dec_typed_ref);
463463
REGISTER_HELPER(zend_jit_assign_op_to_typed_ref);
464+
REGISTER_HELPER(zend_jit_assign_op_to_typed_ref_tmp);
464465
REGISTER_HELPER(zend_jit_only_vars_by_reference);
465466
REGISTER_HELPER(zend_jit_invalid_array_access);
466467
REGISTER_HELPER(zend_jit_invalid_property_read);

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,6 +2259,20 @@ static void ZEND_FASTCALL zend_jit_assign_op_to_typed_ref(zend_reference *ref, z
22592259
}
22602260
}
22612261

2262+
static void ZEND_FASTCALL zend_jit_assign_op_to_typed_ref_tmp(zend_reference *ref, zval *val, binary_op_type binary_op)
2263+
{
2264+
zval z_copy;
2265+
2266+
binary_op(&z_copy, &ref->val, val);
2267+
if (EXPECTED(zend_verify_ref_assignable_zval(ref, &z_copy, ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data))))) {
2268+
zval_ptr_dtor(&ref->val);
2269+
ZVAL_COPY_VALUE(&ref->val, &z_copy);
2270+
} else {
2271+
zval_ptr_dtor(&z_copy);
2272+
}
2273+
zval_ptr_dtor_nogc(val);
2274+
}
2275+
22622276
static void ZEND_FASTCALL zend_jit_only_vars_by_reference(zval *arg)
22632277
{
22642278
ZVAL_NEW_REF(arg, arg);

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6776,7 +6776,12 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3
67766776
| PUSH_ADDR binary_op, r0
67776777
|.endif
67786778
| SET_EX_OPLINE opline, r0
6779-
| EXT_CALL zend_jit_assign_op_to_typed_ref, r0
6779+
if (((opline+1)->op1_type & (IS_TMP_VAR|IS_VAR))
6780+
&& (op1_data_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
6781+
| EXT_CALL zend_jit_assign_op_to_typed_ref_tmp, r0
6782+
} else {
6783+
| EXT_CALL zend_jit_assign_op_to_typed_ref, r0
6784+
}
67806785
|.if not(X64)
67816786
| add r4, 12
67826787
|.endif
@@ -6900,7 +6905,12 @@ static int zend_jit_assign_op(dasm_State **Dst, const zend_op *opline, uint32_t
69006905
| PUSH_ADDR binary_op, r0
69016906
|.endif
69026907
| SET_EX_OPLINE opline, r0
6903-
| EXT_CALL zend_jit_assign_op_to_typed_ref, r0
6908+
if ((opline->op2_type & (IS_TMP_VAR|IS_VAR))
6909+
&& (op2_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
6910+
| EXT_CALL zend_jit_assign_op_to_typed_ref_tmp, r0
6911+
} else {
6912+
| EXT_CALL zend_jit_assign_op_to_typed_ref, r0
6913+
}
69046914
|.if not(X64)
69056915
| add r4, 12
69066916
|.endif
@@ -13974,7 +13984,12 @@ static int zend_jit_assign_obj_op(dasm_State **Dst,
1397413984
| sub r4, 12
1397513985
| PUSH_ADDR binary_op, r0
1397613986
|.endif
13977-
| EXT_CALL zend_jit_assign_op_to_typed_ref, r0
13987+
if (((opline+1)->op1_type & (IS_TMP_VAR|IS_VAR))
13988+
&& (val_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
13989+
| EXT_CALL zend_jit_assign_op_to_typed_ref_tmp, r0
13990+
} else {
13991+
| EXT_CALL zend_jit_assign_op_to_typed_ref, r0
13992+
}
1397813993
|.if not(X64)
1397913994
| add r4, 12
1398013995
|.endif
@@ -14044,7 +14059,12 @@ static int zend_jit_assign_obj_op(dasm_State **Dst,
1404414059
| sub r4, 12
1404514060
| PUSH_ADDR binary_op, r0
1404614061
|.endif
14047-
| EXT_CALL zend_jit_assign_op_to_typed_ref, r0
14062+
if (((opline+1)->op1_type & (IS_TMP_VAR|IS_VAR))
14063+
&& (val_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
14064+
| EXT_CALL zend_jit_assign_op_to_typed_ref_tmp, r0
14065+
} else {
14066+
| EXT_CALL zend_jit_assign_op_to_typed_ref, r0
14067+
}
1404814068
|.if not(X64)
1404914069
| add r4, 12
1405014070
|.endif
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
JIT ASSIGN_OBJ_OP: memory leak
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.file_update_protection=0
7+
opcache.jit_buffer_size=1M
8+
--FILE--
9+
<?php
10+
class A {
11+
public string $prop = "222";
12+
}
13+
14+
class B {
15+
public function __toString() {
16+
global $a;
17+
$a->prop .= $a->prop . "leak";
18+
return "test";
19+
}
20+
}
21+
22+
$a = new A;
23+
$prop = &$a->prop;
24+
$a->prop = new B;
25+
var_dump($a);
26+
?>
27+
--EXPECT--
28+
object(A)#1 (1) {
29+
["prop"]=>
30+
&string(4) "test"
31+
}

0 commit comments

Comments
 (0)