Browse Source

Fixed bugs #34065 and #38623 (throw in foreach/switch causes memory leaks)

PECL_OPENSSL
Dmitry Stogov 20 years ago
parent
commit
cd6537ed6d
  1. 3
      NEWS
  2. 15
      Zend/tests/bug34065.phpt
  3. 16
      Zend/tests/bug38623.phpt
  4. 1
      Zend/zend_compile.c
  5. 1
      Zend/zend_compile.h
  6. 40
      Zend/zend_vm_def.h
  7. 40
      Zend/zend_vm_execute.h

3
NEWS

@ -6,6 +6,8 @@ PHP NEWS
(Dmitry)
- Fixed bug #38844 (curl_easy_strerror() is defined only since cURL 7.12.0).
(Tony)
- Fixed bug #38623 (leaks in a tricky code with switch() and exceptions).
(Dmitry)
- Fixed bug #38574 (missing curl constants and improper constant detection).
(Ilia)
- Fixed bug #37870 (pgo_pgsql tries to de-allocate unused statements).
@ -13,6 +15,7 @@ PHP NEWS
- Fixed bug #36681 (pdo_pgsql driver incorrectly ignored some errors). (Wez,
Ilia)
- Fixed bug #34066 (recursive array_walk causes segfault). (Tony)
- Fixed bug #34065 (throw in foreach causes memory leaks). (Dmitry)
14 Sep 2006, PHP 5.2.0RC4
- Added DSA key generation support to openssl_pkey_new(), FR #38731

15
Zend/tests/bug34065.phpt

@ -0,0 +1,15 @@
--TEST--
Bug #34065 (throw in foreach causes memory leaks)
--FILE--
<?php
$data = file(__FILE__);
try {
foreach ($data as $line) {
throw new Exception("error");
}
} catch (Exception $e) {
echo "ok\n";
}
?>
--EXPECT--
ok

16
Zend/tests/bug38623.phpt

@ -0,0 +1,16 @@
--TEST--
Bug #38623 (leaks in a tricky code with switch() and exceptions)
--FILE--
<?php
try {
switch(strtolower("apache")) {
case "apache":
throw new Exception("test");
break;
}
} catch (Exception $e) {
echo "ok\n";
}
?>
--EXPECT--
ok

1
Zend/zend_compile.c

@ -649,6 +649,7 @@ static inline void do_begin_loop(TSRMLS_D)
parent = CG(active_op_array)->current_brk_cont;
CG(active_op_array)->current_brk_cont = CG(active_op_array)->last_brk_cont;
brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
brk_cont_element->start = get_next_op_number(CG(active_op_array));
brk_cont_element->parent = parent;
}

1
Zend/zend_compile.h

@ -89,6 +89,7 @@ struct _zend_op {
typedef struct _zend_brk_cont_element {
int start;
int cont;
int brk;
int parent;

40
Zend/zend_vm_def.h

@ -3718,7 +3718,8 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
{
zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
int i;
int encapsulating_block=-1;
zend_uint catch_op_num;
int catched = 0;
zval **stack_zval_pp;
zval restored_error_reporting;
@ -3737,7 +3738,8 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
}
if (op_num >= EG(active_op_array)->try_catch_array[i].try_op
&& op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
encapsulating_block = i;
catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
catched = 1;
}
}
@ -3753,6 +3755,28 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
zend_ptr_stack_2_pop(&EG(arg_types_stack), (void**)&EX(object), (void**)&EX(fbc));
}
for (i=0; i<EX(op_array)->last_brk_cont; i++) {
if (EX(op_array)->brk_cont_array[i].start > op_num) {
/* further blocks will not be relevant... */
break;
}
if (op_num < EX(op_array)->brk_cont_array[i].brk) {
if (!catched ||
catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
switch (brk_opline->opcode) {
case ZEND_SWITCH_FREE:
zend_switch_free(brk_opline, EX(Ts) TSRMLS_CC);
break;
case ZEND_FREE:
zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var);
break;
}
}
}
}
/* restore previous error_reporting value */
if (!EG(error_reporting) && EX(old_error_reporting) != NULL && Z_LVAL_P(EX(old_error_reporting)) != 0) {
Z_TYPE(restored_error_reporting) = IS_LONG;
@ -3763,12 +3787,12 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
}
EX(old_error_reporting) = NULL;
if (encapsulating_block == -1) {
ZEND_VM_RETURN_FROM_EXECUTE_LOOP();
} else {
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[EG(active_op_array)->try_catch_array[encapsulating_block].catch_op]);
ZEND_VM_CONTINUE();
}
if (!catched) {
ZEND_VM_RETURN_FROM_EXECUTE_LOOP();
} else {
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
}
}
ZEND_VM_HANDLER(146, ZEND_VERIFY_ABSTRACT_CLASS, ANY, ANY)

40
Zend/zend_vm_execute.h

@ -528,7 +528,8 @@ static int ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
int i;
int encapsulating_block=-1;
zend_uint catch_op_num;
int catched = 0;
zval **stack_zval_pp;
zval restored_error_reporting;
@ -547,7 +548,8 @@ static int ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
if (op_num >= EG(active_op_array)->try_catch_array[i].try_op
&& op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
encapsulating_block = i;
catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
catched = 1;
}
}
@ -563,6 +565,28 @@ static int ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_ptr_stack_2_pop(&EG(arg_types_stack), (void**)&EX(object), (void**)&EX(fbc));
}
for (i=0; i<EX(op_array)->last_brk_cont; i++) {
if (EX(op_array)->brk_cont_array[i].start > op_num) {
/* further blocks will not be relevant... */
break;
}
if (op_num < EX(op_array)->brk_cont_array[i].brk) {
if (!catched ||
catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
switch (brk_opline->opcode) {
case ZEND_SWITCH_FREE:
zend_switch_free(brk_opline, EX(Ts) TSRMLS_CC);
break;
case ZEND_FREE:
zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var);
break;
}
}
}
}
/* restore previous error_reporting value */
if (!EG(error_reporting) && EX(old_error_reporting) != NULL && Z_LVAL_P(EX(old_error_reporting)) != 0) {
Z_TYPE(restored_error_reporting) = IS_LONG;
@ -573,12 +597,12 @@ static int ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
EX(old_error_reporting) = NULL;
if (encapsulating_block == -1) {
ZEND_VM_RETURN_FROM_EXECUTE_LOOP();
} else {
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[EG(active_op_array)->try_catch_array[encapsulating_block].catch_op]);
ZEND_VM_CONTINUE();
}
if (!catched) {
ZEND_VM_RETURN_FROM_EXECUTE_LOOP();
} else {
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
}
}
static int ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)

Loading…
Cancel
Save