summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-08-10 10:08:31 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-08-10 10:11:56 +0200
commit2d087210ebb8adc06dcaca37b9d2dcb93ea2156c (patch)
tree5ad469d9a3774af6260e0d0dd6d9a6907a603ebb
parentfa9bd812fcab6dfd6d9b506cb3cb04dfa75d239d (diff)
downloadphp-git-2d087210ebb8adc06dcaca37b9d2dcb93ea2156c.tar.gz
Fixed bug #79947
Move the FREE_OP for op_data out of the zend_binary_assign_op_dim_slow() slow path, so it can be used by the other error path as well. This makes ASSIGN_DIM_OP structurally more similar to ASSIGN_DIM.
-rw-r--r--NEWS2
-rw-r--r--Zend/tests/bug79947.phpt13
-rw-r--r--Zend/zend_execute.c4
-rw-r--r--Zend/zend_vm_def.h1
-rw-r--r--Zend/zend_vm_execute.h8
5 files changed, 24 insertions, 4 deletions
diff --git a/NEWS b/NEWS
index 0428e1710c..81f9b29251 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,8 @@ PHP NEWS
. Fixed bug #79919 (Stack use-after-scope in define()). (cmb)
. Fixed bug #79934 (CRLF-only line in heredoc causes parsing error).
(Pieter van den Ham)
+ . Fixed bug #79947 (Memory leak on invalid offset type in compound
+ assignment). (Nikita)
- Gettext:
. Fixed bug #70574 (Tests fail due to relying on Linux fallback behavior for
diff --git a/Zend/tests/bug79947.phpt b/Zend/tests/bug79947.phpt
new file mode 100644
index 0000000000..18d2d75a9d
--- /dev/null
+++ b/Zend/tests/bug79947.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Bug #79947: Memory leak on invalid offset type in compound assignment
+--FILE--
+<?php
+$array = [];
+$key = [];
+$array[$key] += [$key];
+var_dump($array);
+?>
+--EXPECTF--
+Warning: Illegal offset type in %s on line %d
+array(0) {
+}
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 59c151fe66..c5b502501e 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -2051,8 +2051,6 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_new_element_for_s
static ZEND_COLD void zend_binary_assign_op_dim_slow(zval *container, zval *dim OPLINE_DC EXECUTE_DATA_DC)
{
- zend_free_op free_op_data1;
-
if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
if (opline->op2_type == IS_UNUSED) {
zend_use_new_element_for_string();
@@ -2063,8 +2061,6 @@ static ZEND_COLD void zend_binary_assign_op_dim_slow(zval *container, zval *dim
} else if (EXPECTED(!Z_ISERROR_P(container))) {
zend_use_scalar_as_array();
}
- get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
- FREE_OP(free_op_data1);
}
static zend_never_inline zend_uchar slow_index_convert(HashTable *ht, const zval *dim, zend_value *value EXECUTE_DATA_DC)
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 827548504c..a5a2070b43 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1272,6 +1272,7 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
} else {
zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
ZEND_VM_C_LABEL(assign_dim_op_ret_null):
+ FREE_UNFETCHED_OP_DATA();
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index ae30886c90..6aa34bbd10 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -22205,6 +22205,7 @@ assign_dim_op_new_array:
} else {
zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
assign_dim_op_ret_null:
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
@@ -24494,6 +24495,7 @@ assign_dim_op_new_array:
} else {
zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
assign_dim_op_ret_null:
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
@@ -26898,6 +26900,7 @@ assign_dim_op_new_array:
} else {
zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
assign_dim_op_ret_null:
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
@@ -28172,6 +28175,7 @@ assign_dim_op_new_array:
} else {
zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
assign_dim_op_ret_null:
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
@@ -39120,6 +39124,7 @@ assign_dim_op_new_array:
} else {
zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
assign_dim_op_ret_null:
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
@@ -42619,6 +42624,7 @@ assign_dim_op_new_array:
} else {
zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
assign_dim_op_ret_null:
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
@@ -45599,6 +45605,7 @@ assign_dim_op_new_array:
} else {
zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
assign_dim_op_ret_null:
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
@@ -47701,6 +47708,7 @@ assign_dim_op_new_array:
} else {
zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
assign_dim_op_ret_null:
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}