|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
Patch __CLASS__-in-traits.002.patch for Scripting Engine problem Bug #55214Patch version 2011-07-24 18:28 UTC Return to Bug #55214 | Download this patchThis patch renders other patches obsolete Obsolete patches: Patch Revisions:Developer: gron@php.net
Index: Zend/zend_compile.c
===================================================================
--- Zend/zend_compile.c (revision 313649)
+++ Zend/zend_compile.c (working copy)
@@ -3482,11 +3482,13 @@
/* {{{ Originates from php_runkit_function_copy_ctor
Duplicate structures in an op_array where necessary to make an outright duplicate */
-static void zend_traits_duplicate_function(zend_function *fe, char *newname TSRMLS_DC)
+static void zend_traits_duplicate_function(zend_function *fe, zend_class_entry *target_ce, char *newname TSRMLS_DC)
{
zend_literal *literals_copy;
zend_compiled_variable *dupvars;
zend_op *opcode_copy;
+ zval class_name_zv;
+ int class_name_literal;
int i;
if (fe->op_array.static_variables) {
@@ -3498,24 +3500,34 @@
fe->op_array.static_variables = tmpHash;
}
+
+ /* TODO: Verify that this size is a global thing, do not see why but is used
+ like this elsewhere */
+ literals_copy = (zend_literal*)emalloc(CG(context).literals_size * sizeof(zend_literal));
+
+ for (i = 0; i < fe->op_array.last_literal; i++) {
+ literals_copy[i] = fe->op_array.literals[i];
+ zval_copy_ctor(&literals_copy[i].constant);
+ }
+ fe->op_array.literals = literals_copy;
+
fe->op_array.refcount = emalloc(sizeof(zend_uint));
*(fe->op_array.refcount) = 1;
- if (fe->op_array.vars) {
- i = fe->op_array.last_var;
- dupvars = safe_emalloc(fe->op_array.last_var, sizeof(zend_compiled_variable), 0);
- while (i > 0) {
- i--;
- dupvars[i].name = estrndup(fe->op_array.vars[i].name, fe->op_array.vars[i].name_len);
- dupvars[i].name_len = fe->op_array.vars[i].name_len;
- dupvars[i].hash_value = fe->op_array.vars[i].hash_value;
- }
- fe->op_array.vars = dupvars;
- }
- else {
- fe->op_array.vars = NULL;
- }
+ if (fe->op_array.vars) {
+ i = fe->op_array.last_var;
+ dupvars = safe_emalloc(fe->op_array.last_var, sizeof(zend_compiled_variable), 0);
+ while (i > 0) {
+ i--;
+ dupvars[i].name = estrndup(fe->op_array.vars[i].name, fe->op_array.vars[i].name_len);
+ dupvars[i].name_len = fe->op_array.vars[i].name_len;
+ dupvars[i].hash_value = fe->op_array.vars[i].hash_value;
+ }
+ fe->op_array.vars = dupvars;
+ } else {
+ fe->op_array.vars = NULL;
+ }
opcode_copy = safe_emalloc(sizeof(zend_op), fe->op_array.last, 0);
for(i = 0; i < fe->op_array.last; i++) {
@@ -3525,6 +3537,16 @@
opcode_copy[i].op1.jmp_addr < fe->op_array.opcodes + fe->op_array.last) {
opcode_copy[i].op1.jmp_addr = opcode_copy + (fe->op_array.opcodes[i].op1.jmp_addr - fe->op_array.opcodes);
}
+ } else {
+ // if __CLASS__ i.e. T_CLASS_C was used, we need to fix it up here
+ if (target_ce
+ && Z_TYPE_P(opcode_copy[i].op1.zv) == IS_NULL
+ && Z_LVAL_P(opcode_copy[i].op1.zv) == ZEND_ACC_TRAIT) {
+ INIT_ZVAL(class_name_zv);
+ ZVAL_STRINGL(&class_name_zv, target_ce->name, target_ce->name_length, 0);
+ class_name_literal = zend_add_literal(&fe->op_array, &class_name_zv TSRMLS_CC);
+ opcode_copy[i].op1.zv = &fe->op_array.literals[class_name_literal].constant;
+ }
}
if (opcode_copy[i].op2_type != IS_CONST) {
@@ -3532,6 +3554,16 @@
opcode_copy[i].op2.jmp_addr < fe->op_array.opcodes + fe->op_array.last) {
opcode_copy[i].op2.jmp_addr = opcode_copy + (fe->op_array.opcodes[i].op2.jmp_addr - fe->op_array.opcodes);
}
+ } else {
+ // if __CLASS__ i.e. T_CLASS_C was used, we need to fix it up here
+ if (target_ce
+ && Z_TYPE_P(opcode_copy[i].op2.zv) == IS_NULL
+ && Z_LVAL_P(opcode_copy[i].op2.zv) == ZEND_ACC_TRAIT) {
+ INIT_ZVAL(class_name_zv);
+ ZVAL_STRINGL(&class_name_zv, target_ce->name, target_ce->name_length, 0);
+ class_name_literal = zend_add_literal(&fe->op_array, &class_name_zv TSRMLS_CC);
+ opcode_copy[i].op2.zv = &fe->op_array.literals[class_name_literal].constant;
+ }
}
}
fe->op_array.opcodes = opcode_copy;
@@ -3559,14 +3591,6 @@
fe->op_array.brk_cont_array = (zend_brk_cont_element*)estrndup((char*)fe->op_array.brk_cont_array, sizeof(zend_brk_cont_element) * fe->op_array.last_brk_cont);
- /* TODO: check whether there is something similar and whether that is ok */
- literals_copy = (zend_literal*)emalloc(fe->op_array.last_literal * sizeof(zend_literal));
-
- for (i = 0; i < fe->op_array.last_literal; i++) {
- literals_copy[i] = fe->op_array.literals[i];
- zval_copy_ctor(&literals_copy[i].constant);
- }
- fe->op_array.literals = literals_copy;
}
/* }}}} */
@@ -3619,7 +3643,7 @@
ce->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
}
fn_copy = *fn;
- zend_traits_duplicate_function(&fn_copy, estrdup(fn->common.function_name) TSRMLS_CC);
+ zend_traits_duplicate_function(&fn_copy, ce, estrdup(fn->common.function_name) TSRMLS_CC);
if (zend_hash_quick_update(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, &fn_copy, sizeof(zend_function), (void**)&fn_copy_p)==FAILURE) {
zend_error(E_COMPILE_ERROR, "Trait method %s has not been applied, because failure occured during updating class method table", hash_key->arKey);
@@ -3641,6 +3665,7 @@
static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
{
HashTable* target;
+ zend_class_entry *target_ce;
zend_trait_alias** aliases;
HashTable* exclude_table;
char* lcname;
@@ -3648,8 +3673,10 @@
zend_function fn_copy;
void* dummy;
size_t i = 0;
- target = va_arg(args, HashTable*);
- aliases = va_arg(args, zend_trait_alias**);
+
+ target = va_arg(args, HashTable*);
+ target_ce = va_arg(args, zend_class_entry*);
+ aliases = va_arg(args, zend_trait_alias**);
exclude_table = va_arg(args, HashTable*);
fnname_len = strlen(fn->common.function_name);
@@ -3663,7 +3690,7 @@
&& aliases[i]->trait_method->mname_len == fnname_len
&& (zend_binary_strcasecmp(aliases[i]->trait_method->method_name, aliases[i]->trait_method->mname_len, fn->common.function_name, fnname_len) == 0)) {
fn_copy = *fn;
- zend_traits_duplicate_function(&fn_copy, estrndup(aliases[i]->alias, aliases[i]->alias_len) TSRMLS_CC);
+ zend_traits_duplicate_function(&fn_copy, NULL, estrndup(aliases[i]->alias, aliases[i]->alias_len) TSRMLS_CC);
/* if it is 0, no modifieres has been changed */
if (aliases[i]->modifiers) {
@@ -3690,7 +3717,7 @@
if (exclude_table == NULL || zend_hash_find(exclude_table, lcname, fnname_len, &dummy) == FAILURE) {
/* is not in hashtable, thus, function is not to be excluded */
fn_copy = *fn;
- zend_traits_duplicate_function(&fn_copy, estrndup(fn->common.function_name, fnname_len) TSRMLS_CC);
+ zend_traits_duplicate_function(&fn_copy, NULL, estrndup(fn->common.function_name, fnname_len) TSRMLS_CC);
/* apply aliases which are not qualified by a class name, or which have not
* alias name, just setting visibility */
@@ -3725,9 +3752,9 @@
/* }}} */
/* Copies function table entries to target function table with applied aliasing */
-static void zend_traits_copy_trait_function_table(HashTable *target, HashTable *source, zend_trait_alias** aliases, HashTable* exclude_table TSRMLS_DC) /* {{{ */
+static void zend_traits_copy_trait_function_table(HashTable *target, zend_class_entry *target_ce, HashTable *source, zend_trait_alias** aliases, HashTable* exclude_table TSRMLS_DC) /* {{{ */
{
- zend_hash_apply_with_arguments(source TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, target, aliases, exclude_table);
+ zend_hash_apply_with_arguments(source TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 4, target, target_ce, aliases, exclude_table);
}
/* }}} */
@@ -3825,10 +3852,10 @@
zend_traits_compile_exclude_table(&exclude_table, ce->trait_precedences, ce->traits[i]);
/* copies functions, applies defined aliasing, and excludes unused trait methods */
- zend_traits_copy_trait_function_table(function_tables[i], &ce->traits[i]->function_table, ce->trait_aliases, &exclude_table TSRMLS_CC);
+ zend_traits_copy_trait_function_table(function_tables[i], ce, &ce->traits[i]->function_table, ce->trait_aliases, &exclude_table TSRMLS_CC);
zend_hash_graceful_destroy(&exclude_table);
} else {
- zend_traits_copy_trait_function_table(function_tables[i], &ce->traits[i]->function_table, ce->trait_aliases, NULL TSRMLS_CC);
+ zend_traits_copy_trait_function_table(function_tables[i], ce, &ce->traits[i]->function_table, ce->trait_aliases, NULL TSRMLS_CC);
}
}
Index: Zend/zend_language_scanner.l
===================================================================
--- Zend/zend_language_scanner.l (revision 313649)
+++ Zend/zend_language_scanner.l (working copy)
@@ -1529,16 +1529,25 @@
<ST_IN_SCRIPTING>"__CLASS__" {
char *class_name = NULL;
- if (CG(active_class_entry)) {
- class_name = CG(active_class_entry)->name;
- }
+ if (ZEND_ACC_TRAIT == (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT)) {
+ // This is a hack, we abuse IS_NULL to indicate an invalid value
+ // if __CLASS__ is encountered in a trait, however, we also not that we
+ // should fix it up when we copy the method into an actual class
+ zendlval->value.lval = ZEND_ACC_TRAIT;
+ zendlval->type = IS_NULL;
+ } else {
+ if (CG(active_class_entry)) {
+ class_name = CG(active_class_entry)->name;
+ }
- if (!class_name) {
- class_name = "";
+ if (!class_name) {
+ class_name = "";
+ }
+
+ zendlval->value.str.len = strlen(class_name);
+ zendlval->value.str.val = estrndup(class_name, zendlval->value.str.len);
+ zendlval->type = IS_STRING;
}
- zendlval->value.str.len = strlen(class_name);
- zendlval->value.str.val = estrndup(class_name, zendlval->value.str.len);
- zendlval->type = IS_STRING;
return T_CLASS_C;
}
|
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 21:00:01 2025 UTC |