|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2009-02-10 21:30 UTC] basant dot kukreja at gmail dot com
Description:
------------
Php crashes for a simple script like the below (in Reproduce code).
On debugging, I figured out that ZEND_JMPZNZ is not handled correctly.
Reproduce code:
---------------
<?php
$besim_hosts = array('abcd');
print "count of hosts = " . count($besim_hosts);
for ($i = 0; $i < count($besim_hosts); $i++)
{
print "host = " . $besim_hosts[$i];
}
?>
Expected result:
----------------
php should run fine.
Actual result:
--------------
Crashes
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 11:00:02 2025 UTC |
There are 3 issues which I found * First ZEND_JMPZNZ jmp address is not fixed properly. If you look at the snip of the opcodes 39 JMPZNZ 53 OP1[ IS_TMP_VAR ~1 ] OP2[ , ->48 ] 40* POST_INC RES[ IS_TMP_VAR ~1 ] OP1[ IS_CV !7 ] 41* FREE OP1[ IS_TMP_VAR ~1 ] 42* JMP OP1[ ->36 ] 24 43* FETCH_CONSTANT RES[ IS_TMP_VAR ~1 ] OP1[ IS_UNUSED ] OP2[ IS_CONST (24567152) 'i' ] ... 27 48 RETURN OP1[ IS_CONST (0) 1 ] 49* ZEND_HANDLE_EXCEPTION JMPZNZ will jump to 53 which doesn't exist and php crashes arbitrarily. My suggested fix, fixes the extended_value. Php jumps to undefined location by ZEND_JMPZNZ_SPEC_TMP_HANDLER. zend_vm_execute.h static int ZEND_JMPZNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { ... if (retval) { #if DEBUG_ZEND>=2 printf("Conditional jmp on true to %d\n", opline->extended_value); #endif ZEND_VM_JMP(&EX(op_array)->opcodes[opline->extended_value]); } else { ... } Issue 2 : * optimization_level should be defined as zend_ulong otherwise php crashes during initialization for 64 bit. Issue 3 : * Simple compilation issue. Here is the suggested patch : --- ../../../../unchanged/pecl/optimizer/./optimize.c 2009-01-13 12:22:42.000000000 -0800 +++ ./optimize.c 2009-02-10 18:03:40.002346000 -0800 @@ -3775,6 +3775,9 @@ if (p->start[p->len - 1].opcode == ZEND_CATCH) { p->start[p->len - 1].extended_value = p->jmp_ext->start - start; } + else if (p->start[p->len - 1].opcode == ZEND_JMPZNZ) { + p->start[p->len - 1].extended_value = p->jmp_ext->start - start; + } } } p = p->next; --- ../../../../unchanged/pecl/optimizer/./php_optimizer.c 2008-12-20 00:18:29.000000000 -0800 +++ ./php_optimizer.c 2009-02-10 18:05:07.367382000 -0800 @@ -79,6 +79,7 @@ static zend_bool optimizer_ini_bool_decode(zend_uint value_length, char* value) { if ((value_length == 2 && strcasecmp("on", value) == 0) || + (value_length == 1 && strcasecmp("1", value) == 0) || (value_length == 3 && strcasecmp("yes", value) == 0) || (value_length == 4 && strcasecmp("true", value) == 0)) { return 1; @@ -190,7 +191,7 @@ zend_ini_entry* apc_enabled = NULL; if (zend_hash_find(EG(ini_directives), "apc.enabled", sizeof("apc.enabled"), (void**)&apc_enabled) == SUCCESS) { - if (optimizer_ini_bool_decode(apc_enabled.value_length, apc_enabled.value)) { + if (optimizer_ini_bool_decode(apc_enabled->value_length, apc_enabled->value)) { compile_f_reg = OPTIMIZER_COMPILE_APC_REG; } } else { --- ../../../../unchanged/pecl/optimizer/./php_optimizer.h 2008-12-20 00:10:46.000000000 -0800 +++ ./php_optimizer.h 2009-02-10 17:03:48.700971000 -0800 @@ -107,7 +107,7 @@ char* optimize_out_funcs; zend_uint optimize_out_funcs_l; - zend_uint optimization_level; /* An arbitrary level that specifies what will happen in the optimizer */ + zend_ulong optimization_level; /* An arbitrary level that specifies what will happen in the optimizer */ zend_uint peephole_passes; /* The number of passes to be done by the peephole optimizer */ zend_bool optimize_for_speed; /* true if the optimizer should favor execution time speed over memory conservation */ /* We will try to optimize for both as much as possible but when a decission for one over the other needs to be made this will help decide it */