- Previous version is tagged PRE_METHOD_CALL_SEPERATE_FIX_PATCH.
- I need to check this fix on a server so if it doesn't work I will revert
- it.
function_call:
- T_STRING '(' { do_extended_fcall_begin(CLS_C); $2.u.opline_num = do_begin_function_call(&$1 CLS_CC); }
+ T_STRING '(' { $2.u.opline_num = do_begin_function_call(&$1 CLS_CC); }
function_call_parameter_list
')' { do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num CLS_CC); do_extended_fcall_end(CLS_C); }
- | r_cvar '(' { do_extended_fcall_begin(CLS_C); do_begin_dynamic_function_call(&$1 CLS_CC); }
+ | cvar '(' { do_begin_dynamic_function_call(&$1 CLS_CC); }
function_call_parameter_list
')' { do_end_function_call(&$1, &$$, &$4, 0, 1 CLS_CC); do_extended_fcall_end(CLS_C);}
| T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { do_extended_fcall_begin(CLS_C); do_begin_class_member_function_call(&$1, &$3 CLS_CC); }
}
+zend_bool is_method_call(CLS_D)
+{
+ zend_llist *fetch_list_ptr;
+ zend_llist_element *cur;
+ zend_op *cur_opline;
+
+ zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
+
+ cur = fetch_list_ptr->head;
+ /* There is always at least one node in the list */
+ while (cur->next) {
+ cur = cur->next;
+ }
+ cur_opline = (zend_op *)cur->data;
+ if (cur_opline->opcode == ZEND_FETCH_OBJ_R) {
+ return 1;
+ }
+ return 0;
+}
+
+
void do_init_string(znode *result CLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
}
break;
}
+ do_extended_fcall_begin(CLS_C);
return 0;
}
void do_begin_dynamic_function_call(znode *function_name CLS_DC)
{
unsigned char *ptr = NULL;
- int last_op_number = get_next_op_number(CG(active_op_array))-1;
- zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
-
- if ((last_op_number >= 1) && (last_op->opcode == ZEND_EXT_FCALL_BEGIN) && ((last_op-1)->opcode == ZEND_FETCH_OBJ_R)) {
- zend_op tmp;
+ int last_op_number;
+ zend_op *last_op;
- tmp = *last_op;
- *last_op = *(last_op-1);
- *(last_op-1) = tmp;
- last_op->opcode = ZEND_INIT_FCALL_BY_NAME;
- last_op->extended_value = ZEND_MEMBER_FUNC_CALL;
- } else if (last_op_number>=0 && last_op->opcode == ZEND_FETCH_OBJ_R) {
+ if (function_name->op_type != IS_CONST && is_method_call(CLS_C)) {
+ do_end_variable_parse(BP_VAR_W, 0 CLS_CC);
+ last_op_number = get_next_op_number(CG(active_op_array))-1;
+ last_op = &CG(active_op_array)->opcodes[last_op_number];
last_op->opcode = ZEND_INIT_FCALL_BY_NAME;
last_op->extended_value = ZEND_MEMBER_FUNC_CALL;
} else {
- zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
-
+ zend_op *opline;
+
+ do_end_variable_parse(BP_VAR_R, 0 CLS_CC);
+
+ opline = get_next_op(CG(active_op_array) CLS_CC);
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
opline->op2 = *function_name;
opline->extended_value = 0;
SET_UNUSED(opline->op1);
}
zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
+ do_extended_fcall_begin(CLS_C);
}
static void zend_extension_fcall_begin_handler(zend_extension *extension, zend_op_array *op_array);
static void zend_extension_fcall_end_handler(zend_extension *extension, zend_op_array *op_array);
-
+/*
#define SEPARATE_ON_READ_OBJECT(obj, _type) \
if ((obj) && ((_type) == BP_VAR_R) && ((*(obj))->type == IS_OBJECT)) { \
SEPARATE_ZVAL_IF_NOT_REF((obj)); \
(*(obj))->is_ref = 1; \
}
+*/
#define RETURN_VALUE_USED(opline) (!((opline)->result.u.EA.type & EXT_TYPE_UNUSED))
zval_dtor(varname);
}
Ts[result->u.var].var.ptr_ptr = retval;
- SEPARATE_ON_READ_OBJECT(retval, type);
+// SEPARATE_ON_READ_OBJECT(retval, type);
SELECTIVE_PZVAL_LOCK(*retval, result);
}
} else {
*retval = zend_fetch_dimension_address_inner(container->value.ht, op2, Ts, type ELS_CC);
}
- SEPARATE_ON_READ_OBJECT(*retval, type);
+ //SEPARATE_ON_READ_OBJECT(*retval, type);
SELECTIVE_PZVAL_LOCK(**retval, result);
break;
case IS_NULL:
zendi_zval_copy_ctor(*container);
}
*retval = zend_fetch_property_address_inner(container->value.obj.properties, op2, Ts, type ELS_CC);
- SEPARATE_ON_READ_OBJECT(*retval, type);
+ //SEPARATE_ON_READ_OBJECT(*retval, type);
SELECTIVE_PZVAL_LOCK(**retval, result);
}
if (!object.ptr || object.ptr->type != IS_OBJECT) {
zend_error(E_ERROR, "Call to a member function on a non-object");
}
+ if (!object.ptr->is_ref && object.ptr->refcount > 1) {
+ zend_error(E_ERROR, "Bug: Problem in method call\n");
+ }
+ object.ptr->is_ref=1;
object.ptr->refcount++; /* For $this pointer */
active_function_table = &(object.ptr->value.obj.ce->function_table);
}