mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
Fixed bug #52614 (Memory leak when writing on uninitialized variable returned from method call)
This commit is contained in:
parent
45960c9030
commit
2188f26c45
2
NEWS
2
NEWS
@ -117,6 +117,8 @@
|
||||
- Fixed a NULL pointer dereference when processing invalid XML-RPC
|
||||
requests (Fixes CVE-2010-0397, bug #51288). (Raphael Geissert)
|
||||
|
||||
- Fixed bug #52614 (Memory leak when writing on uninitialized variable returned
|
||||
from method call). (Dmitry)
|
||||
- Fixed bug #51338 (URL-Rewriter is still enabled if use_only_cookies is
|
||||
on). (Ilia, j dot jeising at gmail dot com)
|
||||
- Fixed bug #51269 (zlib.output_compression Overwrites Vary Header). (Adam)
|
||||
|
83
Zend/tests/bug52614.phpt
Normal file
83
Zend/tests/bug52614.phpt
Normal file
@ -0,0 +1,83 @@
|
||||
--TEST--
|
||||
Bug #52614 (Memory leak when writing on uninitialized variable returned from method call)
|
||||
--FILE--
|
||||
<?php
|
||||
class foo {
|
||||
public $a1;
|
||||
public $a2 = array();
|
||||
public $a3;
|
||||
public $o1;
|
||||
public $o2;
|
||||
|
||||
public function f1() {
|
||||
return $this->a1;
|
||||
}
|
||||
|
||||
public function f2() {
|
||||
return $this->a2;
|
||||
}
|
||||
|
||||
public function f3() {
|
||||
$this->a3 = array();
|
||||
return $this->a3;
|
||||
}
|
||||
|
||||
public function f4() {
|
||||
return $this->o1;
|
||||
}
|
||||
|
||||
public function f5() {
|
||||
$this->o2 = new stdClass;
|
||||
return $this->o2;
|
||||
}
|
||||
|
||||
public function &f6() {
|
||||
return $this->a1;
|
||||
}
|
||||
|
||||
public function f7(&$x) {
|
||||
$x = 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$foo = new foo;
|
||||
|
||||
$foo->f1()[0] = 1;
|
||||
var_dump($foo->a1);
|
||||
|
||||
$foo->f2()[0] = 1;
|
||||
var_dump($foo->a2);
|
||||
|
||||
$foo->f3()[0] = 1;
|
||||
var_dump($foo->a3);
|
||||
|
||||
$foo->f4()->a = 1;
|
||||
var_dump($foo->o1);
|
||||
|
||||
$foo->f5()->a = 1;
|
||||
var_dump($foo->o2);
|
||||
|
||||
$foo->a1[0] = 1;
|
||||
$foo->f7($foo->f6()[0]);
|
||||
var_dump($foo->a1[0]);
|
||||
$foo->f1()[0]++;
|
||||
var_dump($foo->a1[0]);
|
||||
$foo->f6()[0]++;
|
||||
var_dump($foo->a1[0]);
|
||||
--EXPECTF--
|
||||
NULL
|
||||
array(0) {
|
||||
}
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Strict Standards: Creating default object from empty value in %sbug52614.php on line 52
|
||||
NULL
|
||||
object(stdClass)#%d (1) {
|
||||
["a"]=>
|
||||
int(1)
|
||||
}
|
||||
int(2)
|
||||
int(2)
|
||||
int(3)
|
@ -550,6 +550,14 @@ int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unq
|
||||
op.constant = zend_add_literal(CG(active_op_array), &_c); \
|
||||
} while (0)
|
||||
|
||||
static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
|
||||
{
|
||||
zend_uint type = variable->EA;
|
||||
|
||||
return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
@ -781,6 +789,18 @@ void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS
|
||||
zend_op opline;
|
||||
zend_llist *fetch_list_ptr;
|
||||
|
||||
zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
|
||||
|
||||
if (zend_is_function_or_method_call(parent)) {
|
||||
init_op(&opline TSRMLS_CC);
|
||||
opline.opcode = ZEND_SEPARATE;
|
||||
SET_NODE(opline.op1, parent);
|
||||
SET_UNUSED(opline.op2);
|
||||
opline.result_type = IS_VAR;
|
||||
opline.result.var = opline.op1.var;
|
||||
zend_llist_add_element(fetch_list_ptr, &opline);
|
||||
}
|
||||
|
||||
init_op(&opline TSRMLS_CC);
|
||||
opline.opcode = ZEND_FETCH_DIM_W; /* the backpatching routine assumes W */
|
||||
opline.result_type = IS_VAR;
|
||||
@ -802,7 +822,6 @@ void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS
|
||||
|
||||
GET_NODE(result, opline.result);
|
||||
|
||||
zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
|
||||
zend_llist_add_element(fetch_list_ptr, &opline);
|
||||
}
|
||||
/* }}} */
|
||||
@ -985,14 +1004,6 @@ void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) /* {
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
|
||||
{
|
||||
zend_uint type = variable->EA;
|
||||
|
||||
return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_op *opline;
|
||||
@ -1307,6 +1318,14 @@ void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS
|
||||
|
||||
while (le) {
|
||||
opline_ptr = (zend_op *)le->data;
|
||||
if (opline_ptr->opcode == ZEND_SEPARATE) {
|
||||
if (type != BP_VAR_R && type != BP_VAR_IS) {
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
memcpy(opline, opline_ptr, sizeof(zend_op));
|
||||
}
|
||||
le = le->next;
|
||||
continue;
|
||||
}
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
memcpy(opline, opline_ptr, sizeof(zend_op));
|
||||
if (opline->op1_type == IS_VAR &&
|
||||
@ -4865,6 +4884,16 @@ void zend_do_fetch_property(znode *result, znode *object, const znode *property
|
||||
}
|
||||
}
|
||||
|
||||
if (zend_is_function_or_method_call(object)) {
|
||||
init_op(&opline TSRMLS_CC);
|
||||
opline.opcode = ZEND_SEPARATE;
|
||||
SET_NODE(opline.op1, object);
|
||||
SET_UNUSED(opline.op2);
|
||||
opline.result_type = IS_VAR;
|
||||
opline.result.var = opline.op1.var;
|
||||
zend_llist_add_element(fetch_list_ptr, &opline);
|
||||
}
|
||||
|
||||
init_op(&opline TSRMLS_CC);
|
||||
opline.opcode = ZEND_FETCH_OBJ_W; /* the backpatching routine assumes W */
|
||||
opline.result_type = IS_VAR;
|
||||
@ -5745,7 +5774,11 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token
|
||||
if (fetch->opcode == ZEND_FETCH_DIM_W && fetch->op2_type == IS_UNUSED) {
|
||||
zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
|
||||
}
|
||||
fetch->opcode -= 3; /* FETCH_W -> FETCH_R */
|
||||
if (fetch->opcode == ZEND_SEPARATE) {
|
||||
MAKE_NOP(fetch);
|
||||
} else {
|
||||
fetch->opcode -= 3; /* FETCH_W -> FETCH_R */
|
||||
}
|
||||
}
|
||||
/* prevent double SWITCH_FREE */
|
||||
zend_stack_top(&CG(foreach_copy_stack), (void **) &foreach_copy);
|
||||
|
@ -932,7 +932,7 @@ variable_property:
|
||||
|
||||
array_method_dereference:
|
||||
array_method_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
|
||||
| method '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
|
||||
| method '[' dim_offset ']' { $1.EA = ZEND_PARSED_METHOD_CALL; fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
method:
|
||||
@ -942,7 +942,7 @@ method:
|
||||
;
|
||||
|
||||
method_or_not:
|
||||
method { $$ = $1; zend_do_push_object(&$$ TSRMLS_CC); $$.EA = ZEND_PARSED_METHOD_CALL; }
|
||||
method { $$ = $1; $$.EA = ZEND_PARSED_METHOD_CALL; zend_do_push_object(&$$ TSRMLS_CC); }
|
||||
| array_method_dereference { $$ = $1; zend_do_push_object(&$$ TSRMLS_CC); }
|
||||
| /* empty */ { $$.EA = ZEND_PARSED_MEMBER; }
|
||||
;
|
||||
@ -964,7 +964,7 @@ variable_class_name:
|
||||
|
||||
array_function_dereference:
|
||||
array_function_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
|
||||
| function_call { zend_do_begin_variable_parse(TSRMLS_C); $$.EA = ZEND_PARSED_FUNCTION_CALL; }
|
||||
| function_call { zend_do_begin_variable_parse(TSRMLS_C); $1.EA = ZEND_PARSED_FUNCTION_CALL; }
|
||||
'[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$4 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
|
@ -4998,4 +4998,25 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr, *new_zv;
|
||||
|
||||
SAVE_OPLINE();
|
||||
var_ptr = EX_T(opline->op1.var).var.ptr;
|
||||
if (Z_TYPE_P(var_ptr) != IS_OBJECT &&
|
||||
!PZVAL_IS_REF(var_ptr) &&
|
||||
Z_REFCOUNT_P(var_ptr) > 1) {
|
||||
|
||||
Z_DELREF_P(var_ptr);
|
||||
ALLOC_ZVAL(new_zv);
|
||||
INIT_PZVAL_COPY(new_zv, var_ptr);
|
||||
var_ptr = new_zv;
|
||||
zval_copy_ctor(var_ptr);
|
||||
EX_T(opline->op1.var).var.ptr = var_ptr;
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)
|
||||
|
@ -18807,6 +18807,27 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *var_ptr, *new_zv;
|
||||
|
||||
SAVE_OPLINE();
|
||||
var_ptr = EX_T(opline->op1.var).var.ptr;
|
||||
if (Z_TYPE_P(var_ptr) != IS_OBJECT &&
|
||||
!PZVAL_IS_REF(var_ptr) &&
|
||||
Z_REFCOUNT_P(var_ptr) > 1) {
|
||||
|
||||
Z_DELREF_P(var_ptr);
|
||||
ALLOC_ZVAL(new_zv);
|
||||
INIT_PZVAL_COPY(new_zv, var_ptr);
|
||||
var_ptr = new_zv;
|
||||
zval_copy_ctor(var_ptr);
|
||||
EX_T(opline->op1.var).var.ptr = var_ptr;
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@ -39488,6 +39509,31 @@ void zend_init_opcodes_handlers(void)
|
||||
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
||||
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
||||
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER
|
||||
};
|
||||
zend_opcode_handlers = (opcode_handler_t*)labels;
|
||||
|
@ -156,3 +156,4 @@
|
||||
#define ZEND_DECLARE_LAMBDA_FUNCTION 153
|
||||
#define ZEND_ADD_TRAIT 154
|
||||
#define ZEND_BIND_TRAITS 155
|
||||
#define ZEND_SEPARATE 156
|
||||
|
Loading…
Reference in New Issue
Block a user