Skip to content

Commit a60a9b4

Browse files
committed
Fix memory leak
Fixes oss-fuzz #44222
1 parent 54c952f commit a60a9b4

File tree

5 files changed

+217
-95
lines changed

5 files changed

+217
-95
lines changed

Zend/tests/nullsafe_operator/040.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Memory leak in JMP_NULL
3+
--FILE--
4+
<?php
5+
function &returns_ref($unused) {
6+
global $foo;
7+
return $foo;
8+
}
9+
10+
function &returns_ref2() {
11+
return returns_ref(returns_ref(null)?->null);
12+
}
13+
14+
$foo2 = &returns_ref2();
15+
$foo2 = 'foo';
16+
var_dump($foo);
17+
?>
18+
--EXPECT--
19+
string(3) "foo"

Zend/zend_vm_def.h

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7422,39 +7422,44 @@ ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR)
74227422
ZEND_VM_NEXT_OPCODE();
74237423
}
74247424

7425-
ZEND_VM_HOT_NOCONST_HANDLER(198, ZEND_JMP_NULL, CONST|TMPVARCV, JMP_ADDR)
7425+
ZEND_VM_HOT_NOCONST_HANDLER(198, ZEND_JMP_NULL, CONST|TMP|VAR|CV, JMP_ADDR)
74267426
{
74277427
USE_OPLINE
7428-
zval *val;
7428+
zval *val, *result;
74297429

74307430
val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
7431-
if (OP1_TYPE != IS_CONST) {
7432-
ZVAL_DEREF(val);
7433-
}
7434-
7435-
if (Z_TYPE_INFO_P(val) > IS_NULL) {
7436-
ZEND_VM_NEXT_OPCODE();
7437-
} else {
7438-
zval *result = EX_VAR(opline->result.var);
74397431

7440-
if (EXPECTED(opline->extended_value == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) {
7441-
ZVAL_NULL(result);
7442-
if (UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
7443-
SAVE_OPLINE();
7444-
ZVAL_UNDEFINED_OP1();
7445-
if (UNEXPECTED(EG(exception) != NULL)) {
7446-
HANDLE_EXCEPTION();
7432+
if (Z_TYPE_P(val) > IS_NULL) {
7433+
do {
7434+
if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) && Z_TYPE_P(val) == IS_REFERENCE) {
7435+
val = Z_REFVAL_P(val);
7436+
if (Z_TYPE_P(val) <= IS_NULL) {
7437+
FREE_OP1();
7438+
break;
74477439
}
74487440
}
7449-
} else if (opline->extended_value == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) {
7450-
ZVAL_FALSE(result);
7451-
} else {
7452-
ZEND_ASSERT(opline->extended_value == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY);
7453-
ZVAL_TRUE(result);
7454-
}
7441+
ZEND_VM_NEXT_OPCODE();
7442+
} while (0);
7443+
}
74557444

7456-
ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
7445+
result = EX_VAR(opline->result.var);
7446+
if (EXPECTED(opline->extended_value == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) {
7447+
ZVAL_NULL(result);
7448+
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(val) == IS_UNDEF)) {
7449+
SAVE_OPLINE();
7450+
ZVAL_UNDEFINED_OP1();
7451+
if (UNEXPECTED(EG(exception) != NULL)) {
7452+
HANDLE_EXCEPTION();
7453+
}
7454+
}
7455+
} else if (opline->extended_value == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) {
7456+
ZVAL_FALSE(result);
7457+
} else {
7458+
ZEND_ASSERT(opline->extended_value == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY);
7459+
ZVAL_TRUE(result);
74577460
}
7461+
7462+
ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
74587463
}
74597464

74607465
ZEND_VM_HOT_HANDLER(31, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)

0 commit comments

Comments
 (0)