zend_error_noreturn(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", Z_STRVAL_P(op1));
return NULL;
}
-
- if (ce->ce_flags & ZEND_ACC_ANON_BOUND) {
- return ce;
- }
-
ce->refcount++;
-
if (zend_hash_add_ptr(class_table, Z_STR_P(op2), ce) == NULL) {
ce->refcount--;
-
if (!compile_time) {
/* If we're in compile time, in practice, it's quite possible
* that we'll never reach this class declaration at runtime,
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ce->name->val);
}
- /* Reuse anonymous bound class */
- if (ce->ce_flags & ZEND_ACC_ANON_BOUND) {
- return ce;
- }
-
zend_do_inheritance(ce, parent_ce);
ce->refcount++;
if (zend_hash_add_ptr(class_table, Z_STR_P(op2), ce) == NULL) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ce->name->val);
}
-
return ce;
}
/* }}} */
class_node.op_type = IS_CONST;
ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
} else if (class_ast->kind == ZEND_AST_CLASS) {
+ uint32_t dcl_opnum = get_next_op_number(CG(active_op_array));
zend_class_entry *ce = zend_compile_class_decl(class_ast);
class_node.op_type = IS_CONST;
ZVAL_STR_COPY(&class_node.u.constant, ce->name);
+ /* jump over anon class declaration */
+ opline = &CG(active_op_array)->opcodes[dcl_opnum];
+ if (opline->opcode == ZEND_FETCH_CLASS) {
+ opline++;
+ }
+ opline->op1.opline_num = get_next_op_number(CG(active_op_array));
} else {
zend_compile_class_ref(&class_node, class_ast, 1);
}
}
/* }}} */
-static zend_string *zend_generate_anon_class_name() /* {{{ */
+static zend_string *zend_generate_anon_class_name(void) /* {{{ */
{
// TODO The opline pointer may be reused, this is not safe!
uint32_t next = get_next_op_number(CG(active_op_array));
opline->op2_type = IS_CONST;
LITERAL_STR(opline->op2, lcname);
- if (extends_ast) {
- opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
- opline->extended_value = extends_node.u.op.var;
+ if (decl->flags & ZEND_ACC_ANON_CLASS) {
+ if (extends_ast) {
+ opline->opcode = ZEND_DECLARE_ANON_INHERITED_CLASS;
+ opline->extended_value = extends_node.u.op.var;
+ } else {
+ opline->opcode = ZEND_DECLARE_ANON_CLASS;
+ }
+
+ opline->op1_type = IS_UNUSED;
+
+ zend_hash_update_ptr(CG(class_table), lcname, ce);
} else {
- opline->opcode = ZEND_DECLARE_CLASS;
- }
+ zend_string *key;
- {
- zend_string *key = zend_build_runtime_definition_key(lcname, decl->lex_pos);
+ if (extends_ast) {
+ opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
+ opline->extended_value = extends_node.u.op.var;
+ } else {
+ opline->opcode = ZEND_DECLARE_CLASS;
+ }
+
+ key = zend_build_runtime_definition_key(lcname, decl->lex_pos);
opline->op1_type = IS_CONST;
LITERAL_STR(opline->op1, key);
opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->result.var);
}
switch (opline->opcode) {
+ case ZEND_DECLARE_ANON_INHERITED_CLASS:
+ ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
+ /* break omitted intentionally */
case ZEND_DECLARE_INHERITED_CLASS:
case ZEND_DECLARE_INHERITED_CLASS_DELAYED:
opline->extended_value = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->extended_value);
/* break omitted intentionally */
case ZEND_JMP:
case ZEND_FAST_CALL:
+ case ZEND_DECLARE_ANON_CLASS:
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
break;
case ZEND_JMPZNZ:
SAVE_OPLINE();
Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(&EX(func)->op_array, opline, EG(class_table), 0);
- if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_CLASS) {
- if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_BOUND) {
- while (opline->opcode != ZEND_NEW) {
- opline++;
- }
- ZEND_VM_JMP(opline);
- } else Z_CE_P(EX_VAR(opline->result.var))->ce_flags |= ZEND_ACC_ANON_BOUND;
- }
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
SAVE_OPLINE();
Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0);
- if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_CLASS) {
- if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_BOUND) {
- while (opline->opcode != ZEND_NEW) {
- opline++;
- }
- ZEND_VM_JMP(opline);
- } else Z_CE_P(EX_VAR(opline->result.var))->ce_flags |= ZEND_ACC_ANON_BOUND;
- }
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_NEXT_OPCODE();
}
+ZEND_VM_HANDLER(171, ZEND_DECLARE_ANON_CLASS, ANY, ANY)
+{
+ zend_class_entry *ce;
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(EX_CONSTANT(opline->op2)));
+ Z_CE_P(EX_VAR(opline->result.var)) = ce;
+ ZEND_ASSERT(ce != NULL);
+
+ if (ce->ce_flags & ZEND_ACC_ANON_BOUND) {
+ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op1));
+ }
+
+ if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
+ zend_verify_abstract_class(ce);
+ }
+ ce->ce_flags |= ZEND_ACC_ANON_BOUND;
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(172, ZEND_DECLARE_ANON_INHERITED_CLASS, ANY, ANY)
+{
+ zend_class_entry *ce;
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(EX_CONSTANT(opline->op2)));
+ Z_CE_P(EX_VAR(opline->result.var)) = ce;
+ ZEND_ASSERT(ce != NULL);
+
+ if (ce->ce_flags & ZEND_ACC_ANON_BOUND) {
+ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op1));
+ }
+
+ zend_do_inheritance(ce, Z_CE_P(EX_VAR(opline->extended_value)));
+ ce->ce_flags |= ZEND_ACC_ANON_BOUND;
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
ZEND_VM_HANDLER(141, ZEND_DECLARE_FUNCTION, ANY, ANY)
{
USE_OPLINE
SAVE_OPLINE();
Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(&EX(func)->op_array, opline, EG(class_table), 0);
- if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_CLASS) {
- if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_BOUND) {
- while (opline->opcode != ZEND_NEW) {
- opline++;
- }
- ZEND_VM_JMP(opline);
- } else Z_CE_P(EX_VAR(opline->result.var))->ce_flags |= ZEND_ACC_ANON_BOUND;
- }
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
SAVE_OPLINE();
Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0);
- if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_CLASS) {
- if (Z_CE_P(EX_VAR(opline->result.var))->ce_flags & ZEND_ACC_ANON_BOUND) {
- while (opline->opcode != ZEND_NEW) {
- opline++;
- }
- ZEND_VM_JMP(opline);
- } else Z_CE_P(EX_VAR(opline->result.var))->ce_flags |= ZEND_ACC_ANON_BOUND;
- }
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_NEXT_OPCODE();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_class_entry *ce;
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(EX_CONSTANT(opline->op2)));
+ Z_CE_P(EX_VAR(opline->result.var)) = ce;
+ ZEND_ASSERT(ce != NULL);
+
+ if (ce->ce_flags & ZEND_ACC_ANON_BOUND) {
+ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op1));
+ }
+
+ if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
+ zend_verify_abstract_class(ce);
+ }
+ ce->ce_flags |= ZEND_ACC_ANON_BOUND;
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_class_entry *ce;
+ USE_OPLINE
+
+ SAVE_OPLINE();
+ ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(EX_CONSTANT(opline->op2)));
+ Z_CE_P(EX_VAR(opline->result.var)) = ce;
+ ZEND_ASSERT(ce != NULL);
+
+ if (ce->ce_flags & ZEND_ACC_ANON_BOUND) {
+ ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op1));
+ }
+
+ zend_do_inheritance(ce, Z_CE_P(EX_VAR(opline->extended_value)));
+ ce->ce_flags |= ZEND_ACC_ANON_BOUND;
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_FUNCTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
ZEND_SPACESHIP_SPEC_CV_TMPVAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_SPACESHIP_SPEC_CV_CV_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
+ ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
ZEND_NULL_HANDLER
};
zend_opcode_handlers = labels;
#include <stdio.h>
#include <zend.h>
-const char *zend_vm_opcodes_map[171] = {
+const char *zend_vm_opcodes_map[173] = {
"ZEND_NOP",
"ZEND_ADD",
"ZEND_SUB",
"ZEND_BIND_GLOBAL",
"ZEND_COALESCE",
"ZEND_SPACESHIP",
+ "ZEND_DECLARE_ANON_CLASS",
+ "ZEND_DECLARE_ANON_INHERITED_CLASS",
};
ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) {
#define ZEND_BIND_GLOBAL 168
#define ZEND_COALESCE 169
#define ZEND_SPACESHIP 170
+#define ZEND_DECLARE_ANON_CLASS 171
+#define ZEND_DECLARE_ANON_INHERITED_CLASS 172
#endif
START_BLOCK_OP(opno + 1);
break;
case ZEND_JMP:
+ case ZEND_DECLARE_ANON_CLASS:
+ case ZEND_DECLARE_ANON_INHERITED_CLASS:
START_BLOCK_OP(ZEND_OP1(opline).opline_num);
/* break missing intentionally */
case ZEND_RETURN:
case ZEND_JMP:
cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num];
break;
+ case ZEND_DECLARE_ANON_CLASS:
+ case ZEND_DECLARE_ANON_INHERITED_CLASS:
+ cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num];
+ cur_block->follow_to = &blocks[opno];
+ break;
case ZEND_JMPZNZ:
cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num];
cur_block->ext_to = &blocks[opline->extended_value];
case ZEND_JMP:
case ZEND_GOTO:
case ZEND_FAST_CALL:
+ case ZEND_DECLARE_ANON_CLASS:
+ case ZEND_DECLARE_ANON_INHERITED_CLASS:
ZEND_OP1(opline).opline_num -= shiftlist[ZEND_OP1(opline).opline_num];
break;
case ZEND_JMPZ:
}
if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS ||
+ opline->opcode == ZEND_DECLARE_ANON_INHERITED_CLASS ||
opline->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED) {
currT = VAR_NUM(opline->extended_value) - offset;
if (!valid_T[currT]) {
opline->result.var += sizeof(zval);
}
if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS ||
+ opline->opcode == ZEND_DECLARE_ANON_INHERITED_CLASS ||
opline->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED) {
opline->extended_value += sizeof(zval);
}
case ZEND_JMP:
case ZEND_GOTO:
case ZEND_FAST_CALL:
+ case ZEND_DECLARE_ANON_CLASS:
+ case ZEND_DECLARE_ANON_INHERITED_CLASS:
ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, ZEND_OP1(opline));
break;
case ZEND_JMPZNZ:
case ZEND_JMP:
case ZEND_GOTO:
case ZEND_FAST_CALL:
+ case ZEND_DECLARE_ANON_CLASS:
+ case ZEND_DECLARE_ANON_INHERITED_CLASS:
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, ZEND_OP1(opline));
break;
case ZEND_JMPZNZ:
case ZEND_JMP:
case ZEND_GOTO:
case ZEND_FAST_CALL:
+ case ZEND_DECLARE_ANON_CLASS:
+ case ZEND_DECLARE_ANON_INHERITED_CLASS:
ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes];
break;
case ZEND_JMPZNZ: