summaryrefslogtreecommitdiff
path: root/Zend/zend_vm_execute.h
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_vm_execute.h')
-rw-r--r--Zend/zend_vm_execute.h2007
1 files changed, 1568 insertions, 439 deletions
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index c60cef5c88..4328aac4ce 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -108,11 +108,18 @@ static int ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *tmp = &EX_T(EX(opline)->result.u.var).tmp_var;
- tmp->value.str.val = emalloc(1);
- tmp->value.str.val[0] = 0;
- tmp->value.str.len = 0;
+ if (EX(opline)->extended_value == IS_UNICODE) {
+ tmp->value.ustr.val = eumalloc(1);
+ tmp->value.ustr.val[0] = 0;
+ tmp->value.ustr.len = 0;
+ tmp->type = IS_UNICODE;
+ } else {
+ tmp->value.str.val = emalloc(1);
+ tmp->value.str.val[0] = 0;
+ tmp->value.str.len = 0;
+ tmp->type = EX(opline)->extended_value;
+ }
tmp->refcount = 1;
- tmp->type = IS_STRING;
tmp->is_ref = 0;
ZEND_VM_NEXT_OPCODE();
}
@@ -127,7 +134,8 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
zend_bool should_change_scope;
if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
+ /* FIXME: output identifiers properly */
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %v::%v()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
@@ -159,7 +167,8 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
severity = E_ERROR;
severity_word = "cannot";
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name, severity_word);
+ /* FIXME: output identifiers properly */
+ zend_error(severity, "Non-static method %v::%v() %s be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name, severity_word);
}
}
if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
@@ -207,7 +216,7 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
EX(function_state).function_symbol_table = *(EG(symtable_cache_ptr)--);
} else {
ALLOC_HASHTABLE(EX(function_state).function_symbol_table);
- zend_hash_init(EX(function_state).function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(EX(function_state).function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
/*printf("Cache miss! Initialized %x\n", function_state.function_symbol_table);*/
}
calling_symbol_table = EG(active_symbol_table);
@@ -327,8 +336,8 @@ static int ZEND_CATCH_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
- zend_hash_update(EG(active_symbol_table), opline->op2.u.constant.value.str.val,
- opline->op2.u.constant.value.str.len+1, &EG(exception), sizeof(zval *), (void **) NULL);
+ zend_u_hash_update(EG(active_symbol_table), Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
+ Z_UNILEN(opline->op2.u.constant)+1, &EG(exception), sizeof(zval *), (void **) NULL);
EG(exception) = NULL;
ZEND_VM_NEXT_OPCODE();
}
@@ -346,9 +355,9 @@ static int ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC);
if(ptr && ptr->op_array) {
- zend_error(E_WARNING, "Missing argument %ld for %s%s%s(), called in %s on line %d and defined", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
+ zend_error(E_WARNING, "Missing argument %ld for %v%s%v(), called in %s on line %d and defined", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
} else {
- zend_error(E_WARNING, "Missing argument %ld for %s%s%s()", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C));
+ zend_error(E_WARNING, "Missing argument %ld for %v%s%v()", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C));
}
if (opline->result.op_type == IS_VAR) {
PZVAL_UNLOCK_FREE(*EX_T(opline->result.u.var).var.ptr_ptr);
@@ -383,7 +392,7 @@ static int ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
} else {
class_type = "abstract class";
}
- zend_error_noreturn(E_ERROR, "Cannot instantiate %s %s", class_type, EX_T(opline->op1.u.var).class_entry->name);
+ zend_error_noreturn(E_ERROR, "Cannot instantiate %s %v", class_type, EX_T(opline->op1.u.var).class_entry->name);
}
ALLOC_ZVAL(object_zval);
object_init_ex(object_zval, EX_T(opline->op1.u.var).class_entry);
@@ -432,7 +441,7 @@ static int ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name, EX(op_array)->function_name);
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %v::%v()", EG(scope)->name, EX(op_array)->function_name);
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
@@ -499,7 +508,7 @@ static int ZEND_ADD_INTERFACE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_class_entry *iface = EX_T(opline->op2.u.var).class_entry;
if (!(iface->ce_flags & ZEND_ACC_INTERFACE)) {
- zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
+ zend_error_noreturn(E_ERROR, "%v cannot implement %v - it is not an interface", ce->name, iface->name);
}
ce->interfaces[opline->extended_value] = iface;
@@ -591,7 +600,8 @@ static int ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
break;
case IS_STRING:
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ case IS_UNICODE:
+ EX_T(opline->result.u.var).class_entry = zend_u_fetch_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), opline->extended_value TSRMLS_CC);
break;
default:
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
@@ -612,21 +622,20 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
ce = EX_T(opline->op1.u.var).class_entry;
if(IS_CONST != IS_UNUSED) {
char *function_name_strval;
- int function_name_strlen;
+ unsigned int function_name_strlen;
zend_bool is_const = (IS_CONST == IS_CONST);
if (is_const) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name_strval = Z_UNIVAL(opline->op2.u.constant);
+ function_name_strlen = Z_UNILEN(opline->op2.u.constant);
} else {
function_name = &opline->op2.u.constant;
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen);
}
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
@@ -660,29 +669,28 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function;
- char *function_name_strval, *lcname;
- int function_name_strlen;
+ void *function_name_strval, *lcname;
+ unsigned int function_name_strlen, lcname_len;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
if (IS_CONST == IS_CONST) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name = &opline->op2.u.constant;
} else {
function_name = &opline->op2.u.constant;
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
}
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
+ lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_STRVAL_P(function_name), function_name_strlen, 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
efree(lcname);
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
}
efree(lcname);
@@ -787,7 +795,8 @@ static int ZEND_FETCH_CLASS_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
break;
case IS_STRING:
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ case IS_UNICODE:
+ EX_T(opline->result.u.var).class_entry = zend_u_fetch_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), opline->extended_value TSRMLS_CC);
break;
default:
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
@@ -809,21 +818,20 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
ce = EX_T(opline->op1.u.var).class_entry;
if(IS_TMP_VAR != IS_UNUSED) {
char *function_name_strval;
- int function_name_strlen;
+ unsigned int function_name_strlen;
zend_bool is_const = (IS_TMP_VAR == IS_CONST);
zend_free_op free_op2;
if (is_const) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name_strval = Z_UNIVAL(opline->op2.u.constant);
+ function_name_strlen = Z_UNILEN(opline->op2.u.constant);
} else {
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen);
}
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
@@ -857,29 +865,28 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function;
- char *function_name_strval, *lcname;
- int function_name_strlen;
+ void *function_name_strval, *lcname;
+ unsigned int function_name_strlen, lcname_len;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
if (IS_TMP_VAR == IS_CONST) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name = &opline->op2.u.constant;
} else {
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
}
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
+ lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_STRVAL_P(function_name), function_name_strlen, 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
efree(lcname);
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
}
efree(lcname);
@@ -941,7 +948,8 @@ static int ZEND_FETCH_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
break;
case IS_STRING:
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ case IS_UNICODE:
+ EX_T(opline->result.u.var).class_entry = zend_u_fetch_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), opline->extended_value TSRMLS_CC);
break;
default:
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
@@ -963,21 +971,20 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
ce = EX_T(opline->op1.u.var).class_entry;
if(IS_VAR != IS_UNUSED) {
char *function_name_strval;
- int function_name_strlen;
+ unsigned int function_name_strlen;
zend_bool is_const = (IS_VAR == IS_CONST);
zend_free_op free_op2;
if (is_const) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name_strval = Z_UNIVAL(opline->op2.u.constant);
+ function_name_strlen = Z_UNILEN(opline->op2.u.constant);
} else {
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen);
}
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
@@ -1011,29 +1018,28 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function;
- char *function_name_strval, *lcname;
- int function_name_strlen;
+ void *function_name_strval, *lcname;
+ unsigned int function_name_strlen, lcname_len;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
if (IS_VAR == IS_CONST) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name = &opline->op2.u.constant;
} else {
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
}
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
+ lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_STRVAL_P(function_name), function_name_strlen, 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
efree(lcname);
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
}
efree(lcname);
@@ -1095,7 +1101,8 @@ static int ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
break;
case IS_STRING:
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ case IS_UNICODE:
+ EX_T(opline->result.u.var).class_entry = zend_u_fetch_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), opline->extended_value TSRMLS_CC);
break;
default:
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
@@ -1116,21 +1123,20 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_
ce = EX_T(opline->op1.u.var).class_entry;
if(IS_UNUSED != IS_UNUSED) {
char *function_name_strval;
- int function_name_strlen;
+ unsigned int function_name_strlen;
zend_bool is_const = (IS_UNUSED == IS_CONST);
if (is_const) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name_strval = Z_UNIVAL(opline->op2.u.constant);
+ function_name_strlen = Z_UNILEN(opline->op2.u.constant);
} else {
function_name = NULL;
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen);
}
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
@@ -1178,7 +1184,8 @@ static int ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
break;
case IS_STRING:
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ case IS_UNICODE:
+ EX_T(opline->result.u.var).class_entry = zend_u_fetch_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), opline->extended_value TSRMLS_CC);
break;
default:
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
@@ -1199,21 +1206,20 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ce = EX_T(opline->op1.u.var).class_entry;
if(IS_CV != IS_UNUSED) {
char *function_name_strval;
- int function_name_strlen;
+ unsigned int function_name_strlen;
zend_bool is_const = (IS_CV == IS_CONST);
if (is_const) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name_strval = Z_UNIVAL(opline->op2.u.constant);
+ function_name_strlen = Z_UNILEN(opline->op2.u.constant);
} else {
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen);
}
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
@@ -1247,29 +1253,28 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function;
- char *function_name_strval, *lcname;
- int function_name_strlen;
+ void *function_name_strval, *lcname;
+ unsigned int function_name_strlen, lcname_len;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
if (IS_CV == IS_CONST) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name = &opline->op2.u.constant;
} else {
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
}
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
+ lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_STRVAL_P(function_name), function_name_strlen, 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
efree(lcname);
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
}
efree(lcname);
@@ -1342,11 +1347,27 @@ static int ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval *z = &opline->op1.u.constant;
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
- zend_std_cast_object_tostring(z, &z_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
- zend_print_variable(z);
+ UErrorCode status = U_ZERO_ERROR;
+ /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+ if (opline->extended_value &&
+ strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+ ucnv_getName(ZEND_U_CONVERTER(UG(script_encoding_conv)), &status))) {
+ zval z_conv;
+ zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_U_CONVERTER(UG(script_encoding_conv)), &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+ z_conv.type = IS_BINARY;
+ if (U_SUCCESS(status)) {
+ zend_print_variable(&z_conv);
+ } else {
+ zend_error(E_WARNING, "Could not convert inline HTML for output");
+ }
+ zval_dtor(&z_conv);
+ } else {
+ zend_print_variable(z);
+ }
}
ZEND_VM_NEXT_OPCODE();
@@ -1387,23 +1408,23 @@ static int zend_fetch_var_address_helper_SPEC_CONST(int type, ZEND_OPCODE_HANDLE
ZEND_VM_NEXT_OPCODE();
}
*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_u_hash_update(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
@@ -1411,6 +1432,10 @@ static int zend_fetch_var_address_helper_SPEC_CONST(int type, ZEND_OPCODE_HANDLE
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
+ if (IS_CONST != IS_TMP_VAR) {
+
+ }
+ break;
case ZEND_FETCH_LOCAL:
break;
@@ -1577,8 +1602,9 @@ static int ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
- if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
- zend_error_noreturn(E_ERROR, "Unknown function: %s()\n", fname->value.str.val);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(fname), Z_UNIVAL_P(fname), Z_UNILEN_P(fname)+1, (void **) &EX(function_state).function)==FAILURE) {
+ /* FIXME: output identifiers properly */
+ zend_error_noreturn(E_ERROR, "Unknown function: %R()\n", Z_TYPE_P(fname), Z_UNIVAL_P(fname));
}
EX(object) = NULL;
EX(calling_scope) = EX(function_state).function->common.scope;
@@ -1638,9 +1664,9 @@ return_by_value:
INIT_PZVAL_COPY(ret, retval_ptr);
dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", Z_OBJCE_P(retval_ptr)->name);
}
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(retval_ptr)->name);
ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC);
*EG(return_value_ptr_ptr) = ret;
if (!dup) {
@@ -1753,7 +1779,7 @@ static int ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (!clone_call) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", ce->name);
EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr);
EX_T(opline->result.u.var).var.ptr->refcount++;
}
@@ -1763,13 +1789,13 @@ static int ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (ce != EG(scope)) {
- zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to private %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(clone->common.scope, EG(scope))) {
- zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@@ -1816,13 +1842,27 @@ static int ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(result, &var_copy, &use_copy);
+ zend_make_string_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ break;
+ }
+ case IS_UNICODE: {
+ zval var_copy;
+ int use_copy;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
if (use_copy) {
zval_dtor(result);
*result = var_copy;
}
break;
}
+ case IS_BINARY:
+ convert_to_binary(result);
+ break;
case IS_ARRAY:
convert_to_array(result);
break;
@@ -1845,7 +1885,14 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval tmp_inc_filename;
zend_bool failure_retval=0;
- if (inc_filename->type!=IS_STRING) {
+ if (UG(unicode) && opline->op2.u.constant.value.lval == ZEND_EVAL) {
+ if (inc_filename->type != IS_UNICODE) {
+ tmp_inc_filename = *inc_filename;
+ zval_copy_ctor(&tmp_inc_filename);
+ convert_to_unicode(&tmp_inc_filename);
+ inc_filename = &tmp_inc_filename;
+ }
+ } else if (inc_filename->type!=IS_STRING) {
tmp_inc_filename = *inc_filename;
zval_copy_ctor(&tmp_inc_filename);
convert_to_string(&tmp_inc_filename);
@@ -1962,10 +2009,10 @@ static int ZEND_UNSET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
varname = &opline->op1.u.constant;
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -1973,17 +2020,17 @@ static int ZEND_UNSET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1) == SUCCESS) {
+ if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) {
zend_execute_data *ex = execute_data;
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1);
do {
int i;
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
+ ex->op_array->vars[i].name_len == Z_UNILEN_P(varname) &&
+ !memcmp(ex->op_array->vars[i].name, Z_UNIVAL_P(varname), Z_TYPE_P(varname)==IS_UNICODE?UBYTES(Z_UNILEN_P(varname)):Z_UNILEN_P(varname))) {
ex->CVs[i] = NULL;
break;
}
@@ -2059,7 +2106,7 @@ static int ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
if (!EG(exception)) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
+ zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %v did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
@@ -2094,8 +2141,11 @@ static int ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *str_key;
uint str_key_len;
ulong int_key;
- if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
- && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ zend_uchar key_type;
+
+ key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
+ if (key_type != HASH_KEY_NON_EXISTANT &&
+ zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
break;
}
zend_hash_move_forward(fe_ht);
@@ -2129,10 +2179,10 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_bool isset = 1;
HashTable *target_symbol_table;
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -2143,7 +2193,7 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) {
isset = 0;
}
}
@@ -2219,6 +2269,41 @@ static int ZEND_TICKS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_U_NORMALIZE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_op *opline = EX(opline);
+
+ zval *string = &opline->op1.u.constant;
+ zval *result = &EX_T(opline->result.u.var).tmp_var;
+
+ *result = *string;
+ if (!0) {
+ zendi_zval_copy_ctor(*result);
+ }
+
+ if (UG(unicode)) {
+ zval var_copy;
+ int use_copy;
+ UChar *norm;
+ int32_t norm_len;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ Z_USTRVAL_P(result), Z_USTRLEN_P(result), 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(result));
+ } else if (norm != Z_USTRVAL_P(result)) {
+ efree(Z_USTRVAL_P(result));
+ ZVAL_UNICODEL(result, norm, norm_len, 0);
+ }
+ }
+
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
@@ -2502,10 +2587,12 @@ static int ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
}
*/
- if (!zend_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
- opline->op2.u.constant.value.str.val,
- opline->op2.u.constant.value.str.val);
+ if (!zend_get_constant(Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+ zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
+ Z_TYPE(opline->op2.u.constant),
+ Z_UNIVAL(opline->op2.u.constant),
+ Z_TYPE(opline->op2.u.constant),
+ Z_UNIVAL(opline->op2.u.constant));
EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
}
@@ -2514,12 +2601,12 @@ static int ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ce = EX_T(opline->op1.u.var).class_entry;
- if (zend_hash_find(&ce->constants_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
+ if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EX_T(opline->result.u.var).tmp_var = **value;
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
} else {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", opline->op2.u.constant.value.str.val);
+ zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
}
ZEND_VM_NEXT_OPCODE();
@@ -2578,7 +2665,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -2925,7 +3014,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -3272,7 +3363,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -3353,7 +3446,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -3699,7 +3794,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -3757,11 +3854,27 @@ static int ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval *z = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
- zend_std_cast_object_tostring(z, &z_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
- zend_print_variable(z);
+ UErrorCode status = U_ZERO_ERROR;
+ /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+ if (opline->extended_value &&
+ strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+ ucnv_getName(ZEND_U_CONVERTER(UG(script_encoding_conv)), &status))) {
+ zval z_conv;
+ zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_U_CONVERTER(UG(script_encoding_conv)), &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+ z_conv.type = IS_BINARY;
+ if (U_SUCCESS(status)) {
+ zend_print_variable(&z_conv);
+ } else {
+ zend_error(E_WARNING, "Could not convert inline HTML for output");
+ }
+ zval_dtor(&z_conv);
+ } else {
+ zend_print_variable(z);
+ }
}
zval_dtor(free_op1.var);
@@ -3803,23 +3916,23 @@ static int zend_fetch_var_address_helper_SPEC_TMP(int type, ZEND_OPCODE_HANDLER_
ZEND_VM_NEXT_OPCODE();
}
*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_u_hash_update(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
@@ -3827,6 +3940,10 @@ static int zend_fetch_var_address_helper_SPEC_TMP(int type, ZEND_OPCODE_HANDLER_
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
+ if (IS_TMP_VAR != IS_TMP_VAR) {
+ zval_dtor(free_op1.var);
+ }
+ break;
case ZEND_FETCH_LOCAL:
zval_dtor(free_op1.var);
break;
@@ -4048,9 +4165,9 @@ return_by_value:
INIT_PZVAL_COPY(ret, retval_ptr);
dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", Z_OBJCE_P(retval_ptr)->name);
}
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(retval_ptr)->name);
ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC);
*EG(return_value_ptr_ptr) = ret;
if (!dup) {
@@ -4170,7 +4287,7 @@ static int ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (!clone_call) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", ce->name);
EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr);
EX_T(opline->result.u.var).var.ptr->refcount++;
}
@@ -4180,13 +4297,13 @@ static int ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (ce != EG(scope)) {
- zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to private %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(clone->common.scope, EG(scope))) {
- zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@@ -4233,13 +4350,27 @@ static int ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(result, &var_copy, &use_copy);
+ zend_make_string_zval(result, &var_copy, &use_copy);
if (use_copy) {
zval_dtor(result);
*result = var_copy;
}
break;
}
+ case IS_UNICODE: {
+ zval var_copy;
+ int use_copy;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ break;
+ }
+ case IS_BINARY:
+ convert_to_binary(result);
+ break;
case IS_ARRAY:
convert_to_array(result);
break;
@@ -4262,7 +4393,14 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval tmp_inc_filename;
zend_bool failure_retval=0;
- if (inc_filename->type!=IS_STRING) {
+ if (UG(unicode) && opline->op2.u.constant.value.lval == ZEND_EVAL) {
+ if (inc_filename->type != IS_UNICODE) {
+ tmp_inc_filename = *inc_filename;
+ zval_copy_ctor(&tmp_inc_filename);
+ convert_to_unicode(&tmp_inc_filename);
+ inc_filename = &tmp_inc_filename;
+ }
+ } else if (inc_filename->type!=IS_STRING) {
tmp_inc_filename = *inc_filename;
zval_copy_ctor(&tmp_inc_filename);
convert_to_string(&tmp_inc_filename);
@@ -4379,10 +4517,10 @@ static int ZEND_UNSET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
varname = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -4390,17 +4528,17 @@ static int ZEND_UNSET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1) == SUCCESS) {
+ if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) {
zend_execute_data *ex = execute_data;
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1);
do {
int i;
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
+ ex->op_array->vars[i].name_len == Z_UNILEN_P(varname) &&
+ !memcmp(ex->op_array->vars[i].name, Z_UNIVAL_P(varname), Z_TYPE_P(varname)==IS_UNICODE?UBYTES(Z_UNILEN_P(varname)):Z_UNILEN_P(varname))) {
ex->CVs[i] = NULL;
break;
}
@@ -4476,7 +4614,7 @@ static int ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
if (!EG(exception)) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
+ zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %v did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
@@ -4511,8 +4649,11 @@ static int ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *str_key;
uint str_key_len;
ulong int_key;
- if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
- && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ zend_uchar key_type;
+
+ key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
+ if (key_type != HASH_KEY_NON_EXISTANT &&
+ zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
break;
}
zend_hash_move_forward(fe_ht);
@@ -4546,10 +4687,10 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_bool isset = 1;
HashTable *target_symbol_table;
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -4560,7 +4701,7 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) {
isset = 0;
}
}
@@ -4656,6 +4797,41 @@ static int ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_U_NORMALIZE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_op *opline = EX(opline);
+ zend_free_op free_op1;
+ zval *string = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *result = &EX_T(opline->result.u.var).tmp_var;
+
+ *result = *string;
+ if (!1) {
+ zendi_zval_copy_ctor(*result);
+ }
+
+ if (UG(unicode)) {
+ zval var_copy;
+ int use_copy;
+ UChar *norm;
+ int32_t norm_len;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ Z_USTRVAL_P(result), Z_USTRLEN_P(result), 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(result));
+ } else if (norm != Z_USTRVAL_P(result)) {
+ efree(Z_USTRVAL_P(result));
+ ZVAL_UNICODEL(result, norm, norm_len, 0);
+ }
+ }
+
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
@@ -4919,8 +5095,8 @@ static int ZEND_ADD_CHAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_free_op free_op1;
add_char_to_string(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant);
+ _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
+ &opline->op2.u.constant);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
ZEND_VM_NEXT_OPCODE();
}
@@ -4931,8 +5107,8 @@ static int ZEND_ADD_STRING_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_free_op free_op1;
add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant);
+ _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
+ &opline->op2.u.constant);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
ZEND_VM_NEXT_OPCODE();
}
@@ -4944,17 +5120,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = &opline->op2.u.constant;
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -4968,10 +5146,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -5082,7 +5260,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -5352,13 +5532,16 @@ static int ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(var, &var_copy, &use_copy);
+ if (opline->extended_value == IS_UNICODE) {
+ zend_make_unicode_zval(var, &var_copy, &use_copy);
+ } else {
+ zend_make_printable_zval(var, &var_copy, &use_copy);
+ }
if (use_copy) {
var = &var_copy;
}
- add_string_to_string( &EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- var);
+ add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
+ _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), var);
if (use_copy) {
zval_dtor(var);
}
@@ -5380,17 +5563,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -5404,10 +5589,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -5520,7 +5705,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -5790,13 +5977,16 @@ static int ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(var, &var_copy, &use_copy);
+ if (opline->extended_value == IS_UNICODE) {
+ zend_make_unicode_zval(var, &var_copy, &use_copy);
+ } else {
+ zend_make_printable_zval(var, &var_copy, &use_copy);
+ }
if (use_copy) {
var = &var_copy;
}
- add_string_to_string( &EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- var);
+ add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
+ _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), var);
if (use_copy) {
zval_dtor(var);
}
@@ -5818,17 +6008,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -5842,10 +6034,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -5958,7 +6150,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -6039,7 +6233,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_AR
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -6309,13 +6505,16 @@ static int ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(var, &var_copy, &use_copy);
+ if (opline->extended_value == IS_UNICODE) {
+ zend_make_unicode_zval(var, &var_copy, &use_copy);
+ } else {
+ zend_make_printable_zval(var, &var_copy, &use_copy);
+ }
if (use_copy) {
var = &var_copy;
}
- add_string_to_string( &EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- var);
+ add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
+ _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), var);
if (use_copy) {
zval_dtor(var);
}
@@ -6336,17 +6535,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -6360,10 +6561,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -6474,7 +6675,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -6694,11 +6897,27 @@ static int ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval *z = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
- zend_std_cast_object_tostring(z, &z_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
- zend_print_variable(z);
+ UErrorCode status = U_ZERO_ERROR;
+ /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+ if (opline->extended_value &&
+ strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+ ucnv_getName(ZEND_U_CONVERTER(UG(script_encoding_conv)), &status))) {
+ zval z_conv;
+ zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_U_CONVERTER(UG(script_encoding_conv)), &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+ z_conv.type = IS_BINARY;
+ if (U_SUCCESS(status)) {
+ zend_print_variable(&z_conv);
+ } else {
+ zend_error(E_WARNING, "Could not convert inline HTML for output");
+ }
+ zval_dtor(&z_conv);
+ } else {
+ zend_print_variable(z);
+ }
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
@@ -6740,23 +6959,23 @@ static int zend_fetch_var_address_helper_SPEC_VAR(int type, ZEND_OPCODE_HANDLER_
ZEND_VM_NEXT_OPCODE();
}
*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_u_hash_update(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
@@ -6764,6 +6983,10 @@ static int zend_fetch_var_address_helper_SPEC_VAR(int type, ZEND_OPCODE_HANDLER_
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
+ if (IS_VAR != IS_TMP_VAR) {
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
+ break;
case ZEND_FETCH_LOCAL:
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
break;
@@ -6979,9 +7202,9 @@ return_by_value:
INIT_PZVAL_COPY(ret, retval_ptr);
dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", Z_OBJCE_P(retval_ptr)->name);
}
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(retval_ptr)->name);
ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC);
*EG(return_value_ptr_ptr) = ret;
if (!dup) {
@@ -7190,7 +7413,7 @@ static int ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (!clone_call) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", ce->name);
EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr);
EX_T(opline->result.u.var).var.ptr->refcount++;
}
@@ -7200,13 +7423,13 @@ static int ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (ce != EG(scope)) {
- zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to private %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(clone->common.scope, EG(scope))) {
- zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@@ -7253,13 +7476,27 @@ static int ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(result, &var_copy, &use_copy);
+ zend_make_string_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ break;
+ }
+ case IS_UNICODE: {
+ zval var_copy;
+ int use_copy;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
if (use_copy) {
zval_dtor(result);
*result = var_copy;
}
break;
}
+ case IS_BINARY:
+ convert_to_binary(result);
+ break;
case IS_ARRAY:
convert_to_array(result);
break;
@@ -7282,7 +7519,14 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval tmp_inc_filename;
zend_bool failure_retval=0;
- if (inc_filename->type!=IS_STRING) {
+ if (UG(unicode) && opline->op2.u.constant.value.lval == ZEND_EVAL) {
+ if (inc_filename->type != IS_UNICODE) {
+ tmp_inc_filename = *inc_filename;
+ zval_copy_ctor(&tmp_inc_filename);
+ convert_to_unicode(&tmp_inc_filename);
+ inc_filename = &tmp_inc_filename;
+ }
+ } else if (inc_filename->type!=IS_STRING) {
tmp_inc_filename = *inc_filename;
zval_copy_ctor(&tmp_inc_filename);
convert_to_string(&tmp_inc_filename);
@@ -7399,10 +7643,10 @@ static int ZEND_UNSET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
varname = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -7410,17 +7654,17 @@ static int ZEND_UNSET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1) == SUCCESS) {
+ if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) {
zend_execute_data *ex = execute_data;
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1);
do {
int i;
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
+ ex->op_array->vars[i].name_len == Z_UNILEN_P(varname) &&
+ !memcmp(ex->op_array->vars[i].name, Z_UNIVAL_P(varname), Z_TYPE_P(varname)==IS_UNICODE?UBYTES(Z_UNILEN_P(varname)):Z_UNILEN_P(varname))) {
ex->CVs[i] = NULL;
break;
}
@@ -7496,7 +7740,7 @@ static int ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
}
if (!EG(exception)) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
+ zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %v did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
@@ -7531,8 +7775,11 @@ static int ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *str_key;
uint str_key_len;
ulong int_key;
- if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
- && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ zend_uchar key_type;
+
+ key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
+ if (key_type != HASH_KEY_NON_EXISTANT &&
+ zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
break;
}
zend_hash_move_forward(fe_ht);
@@ -7594,11 +7841,16 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
zend_hash_move_forward(fe_ht);
- } while (key_type != HASH_KEY_IS_STRING || zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS);
+ } while (key_type == HASH_KEY_NON_EXISTANT || zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS);
if (use_key) {
- zend_unmangle_property_name(str_key, &class_name, &prop_name);
- str_key_len = strlen(prop_name);
- str_key = estrndup(prop_name, str_key_len);
+ zend_u_unmangle_property_name(key_type == HASH_KEY_IS_UNICODE?IS_UNICODE:IS_STRING, str_key, &class_name, &prop_name);
+ if (key_type == HASH_KEY_IS_UNICODE) {
+ str_key_len = u_strlen((UChar*)prop_name);
+ str_key = (char*)eustrndup((UChar*)prop_name, str_key_len);
+ } else {
+ str_key_len = strlen(prop_name);
+ str_key = estrndup(prop_name, str_key_len);
+ }
str_key_len++;
}
break;
@@ -7688,6 +7940,16 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
key->value.str.len = str_key_len-1;
key->type = IS_STRING;
break;
+ case HASH_KEY_IS_BINARY:
+ key->value.str.val = str_key;
+ key->value.str.len = str_key_len-1;
+ key->type = IS_BINARY;
+ break;
+ case HASH_KEY_IS_UNICODE:
+ key->value.ustr.val = (UChar*)str_key;
+ key->value.ustr.len = str_key_len-1;
+ key->type = IS_UNICODE;
+ break;
case HASH_KEY_IS_LONG:
key->value.lval = int_key;
key->type = IS_LONG;
@@ -7709,10 +7971,10 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_bool isset = 1;
HashTable *target_symbol_table;
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -7723,7 +7985,7 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) {
isset = 0;
}
}
@@ -7804,6 +8066,41 @@ static int ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_U_NORMALIZE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_op *opline = EX(opline);
+ zend_free_op free_op1;
+ zval *string = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *result = &EX_T(opline->result.u.var).tmp_var;
+
+ *result = *string;
+ if (!0) {
+ zendi_zval_copy_ctor(*result);
+ }
+
+ if (UG(unicode)) {
+ zval var_copy;
+ int use_copy;
+ UChar *norm;
+ int32_t norm_len;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ Z_USTRVAL_P(result), Z_USTRLEN_P(result), 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(result));
+ } else if (norm != Z_USTRVAL_P(result)) {
+ efree(Z_USTRVAL_P(result));
+ ZVAL_UNICODEL(result, norm, norm_len, 0);
+ }
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_ADD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
@@ -8799,17 +9096,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = &opline->op2.u.constant;
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -8823,10 +9122,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -8938,7 +9237,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -8996,10 +9297,31 @@ static int ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -9007,8 +9329,8 @@ static int ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -9016,7 +9338,11 @@ static int ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -9122,10 +9448,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST(int prop_dim,
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -9168,7 +9518,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST(int prop_dim,
} else {
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -9180,12 +9532,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST(int prop_dim,
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -10220,17 +10577,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -10244,10 +10603,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -10361,7 +10720,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -10419,10 +10780,31 @@ static int ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -10430,8 +10812,8 @@ static int ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -10439,7 +10821,11 @@ static int ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -10545,10 +10931,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(int prop_dim, ZE
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -10591,7 +11001,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(int prop_dim, ZE
} else {
zval_dtor(free_op2.var);
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -10603,12 +11015,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(int prop_dim, ZE
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -11681,17 +12098,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -11705,10 +12124,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -11822,7 +12241,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -11880,10 +12301,31 @@ static int ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -11891,8 +12333,8 @@ static int ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -11900,7 +12342,11 @@ static int ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -12006,10 +12452,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(int prop_dim, ZE
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -12052,7 +12522,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(int prop_dim, ZE
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -12064,12 +12536,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(int prop_dim, ZE
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -12487,7 +12964,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_AR
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -13546,17 +14025,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -13570,10 +14051,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -13685,7 +14166,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -13743,10 +14226,31 @@ static int ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -13754,8 +14258,8 @@ static int ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -13763,7 +14267,11 @@ static int ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -13869,10 +14377,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(int prop_dim, ZEN
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -13915,7 +14447,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(int prop_dim, ZEN
} else {
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -13927,12 +14461,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(int prop_dim, ZEN
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -13991,7 +14530,7 @@ static int ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (!clone_call) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", ce->name);
EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr);
EX_T(opline->result.u.var).var.ptr->refcount++;
}
@@ -14001,13 +14540,13 @@ static int ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (ce != EG(scope)) {
- zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to private %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(clone->common.scope, EG(scope))) {
- zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@@ -14693,17 +15232,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
char *function_name_strval;
int function_name_strlen;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = &opline->op2.u.constant;
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -14717,10 +15258,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -14765,10 +15306,12 @@ static int ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
}
*/
- if (!zend_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
- opline->op2.u.constant.value.str.val,
- opline->op2.u.constant.value.str.val);
+ if (!zend_get_constant(Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+ zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
+ Z_TYPE(opline->op2.u.constant),
+ Z_UNIVAL(opline->op2.u.constant),
+ Z_TYPE(opline->op2.u.constant),
+ Z_UNIVAL(opline->op2.u.constant));
EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
}
@@ -14777,12 +15320,12 @@ static int ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
ce = EX_T(opline->op1.u.var).class_entry;
- if (zend_hash_find(&ce->constants_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
+ if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EX_T(opline->result.u.var).tmp_var = **value;
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
} else {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", opline->op2.u.constant.value.str.val);
+ zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
}
ZEND_VM_NEXT_OPCODE();
@@ -14841,7 +15384,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -14899,10 +15444,31 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -14910,8 +15476,8 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -14919,7 +15485,11 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -15023,10 +15593,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CONST(int prop_di
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -15069,7 +15663,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CONST(int prop_di
} else {
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -15081,12 +15677,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CONST(int prop_di
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -15773,17 +16374,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -15797,10 +16400,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -15881,7 +16484,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -15939,10 +16544,31 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -15950,8 +16576,8 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -15959,7 +16585,11 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -16063,10 +16693,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP(int prop_dim,
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -16109,7 +16763,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP(int prop_dim,
} else {
zval_dtor(free_op2.var);
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -16121,12 +16777,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP(int prop_dim,
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -16813,17 +17474,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -16837,10 +17500,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -16921,7 +17584,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -16979,10 +17644,31 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -16990,8 +17676,8 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -16999,7 +17685,11 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -17103,10 +17793,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR(int prop_dim,
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -17149,7 +17863,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR(int prop_dim,
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -17161,12 +17877,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR(int prop_dim,
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -17540,7 +18261,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -18217,17 +18940,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
char *function_name_strval;
int function_name_strlen;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -18241,10 +18966,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -18324,7 +19049,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -18382,10 +19109,31 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -18393,8 +19141,8 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -18402,7 +19150,11 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -18506,10 +19258,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV(int prop_dim,
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -18552,7 +19328,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV(int prop_dim,
} else {
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -18564,12 +19342,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV(int prop_dim,
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -18793,11 +19576,27 @@ static int ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval *z = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
- zend_std_cast_object_tostring(z, &z_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
- zend_print_variable(z);
+ UErrorCode status = U_ZERO_ERROR;
+ /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+ if (opline->extended_value &&
+ strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+ ucnv_getName(ZEND_U_CONVERTER(UG(script_encoding_conv)), &status))) {
+ zval z_conv;
+ zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_U_CONVERTER(UG(script_encoding_conv)), &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+ z_conv.type = IS_BINARY;
+ if (U_SUCCESS(status)) {
+ zend_print_variable(&z_conv);
+ } else {
+ zend_error(E_WARNING, "Could not convert inline HTML for output");
+ }
+ zval_dtor(&z_conv);
+ } else {
+ zend_print_variable(z);
+ }
}
ZEND_VM_NEXT_OPCODE();
@@ -18838,23 +19637,23 @@ static int zend_fetch_var_address_helper_SPEC_CV(int type, ZEND_OPCODE_HANDLER_A
ZEND_VM_NEXT_OPCODE();
}
*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_u_hash_update(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
@@ -18862,6 +19661,10 @@ static int zend_fetch_var_address_helper_SPEC_CV(int type, ZEND_OPCODE_HANDLER_A
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
+ if (IS_CV != IS_TMP_VAR) {
+
+ }
+ break;
case ZEND_FETCH_LOCAL:
break;
@@ -19072,9 +19875,9 @@ return_by_value:
INIT_PZVAL_COPY(ret, retval_ptr);
dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", Z_OBJCE_P(retval_ptr)->name);
}
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(retval_ptr)->name);
ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC);
*EG(return_value_ptr_ptr) = ret;
if (!dup) {
@@ -19275,7 +20078,7 @@ static int ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (!clone_call) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", ce->name);
EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr);
EX_T(opline->result.u.var).var.ptr->refcount++;
}
@@ -19285,13 +20088,13 @@ static int ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (ce != EG(scope)) {
- zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to private %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(clone->common.scope, EG(scope))) {
- zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@@ -19338,13 +20141,27 @@ static int ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(result, &var_copy, &use_copy);
+ zend_make_string_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ break;
+ }
+ case IS_UNICODE: {
+ zval var_copy;
+ int use_copy;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
if (use_copy) {
zval_dtor(result);
*result = var_copy;
}
break;
}
+ case IS_BINARY:
+ convert_to_binary(result);
+ break;
case IS_ARRAY:
convert_to_array(result);
break;
@@ -19367,7 +20184,14 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval tmp_inc_filename;
zend_bool failure_retval=0;
- if (inc_filename->type!=IS_STRING) {
+ if (UG(unicode) && opline->op2.u.constant.value.lval == ZEND_EVAL) {
+ if (inc_filename->type != IS_UNICODE) {
+ tmp_inc_filename = *inc_filename;
+ zval_copy_ctor(&tmp_inc_filename);
+ convert_to_unicode(&tmp_inc_filename);
+ inc_filename = &tmp_inc_filename;
+ }
+ } else if (inc_filename->type!=IS_STRING) {
tmp_inc_filename = *inc_filename;
zval_copy_ctor(&tmp_inc_filename);
convert_to_string(&tmp_inc_filename);
@@ -19484,10 +20308,10 @@ static int ZEND_UNSET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
varname = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -19495,17 +20319,17 @@ static int ZEND_UNSET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1) == SUCCESS) {
+ if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) {
zend_execute_data *ex = execute_data;
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1);
do {
int i;
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
+ ex->op_array->vars[i].name_len == Z_UNILEN_P(varname) &&
+ !memcmp(ex->op_array->vars[i].name, Z_UNIVAL_P(varname), Z_TYPE_P(varname)==IS_UNICODE?UBYTES(Z_UNILEN_P(varname)):Z_UNILEN_P(varname))) {
ex->CVs[i] = NULL;
break;
}
@@ -19581,7 +20405,7 @@ static int ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
if (!EG(exception)) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
+ zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %v did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
@@ -19616,8 +20440,11 @@ static int ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *str_key;
uint str_key_len;
ulong int_key;
- if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
- && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ zend_uchar key_type;
+
+ key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
+ if (key_type != HASH_KEY_NON_EXISTANT &&
+ zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
break;
}
zend_hash_move_forward(fe_ht);
@@ -19651,10 +20478,10 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_bool isset = 1;
HashTable *target_symbol_table;
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -19665,7 +20492,7 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) {
isset = 0;
}
}
@@ -19745,6 +20572,41 @@ static int ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_U_NORMALIZE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_op *opline = EX(opline);
+
+ zval *string = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *result = &EX_T(opline->result.u.var).tmp_var;
+
+ *result = *string;
+ if (!0) {
+ zendi_zval_copy_ctor(*result);
+ }
+
+ if (UG(unicode)) {
+ zval var_copy;
+ int use_copy;
+ UChar *norm;
+ int32_t norm_len;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ Z_USTRVAL_P(result), Z_USTRLEN_P(result), 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(result));
+ } else if (norm != Z_USTRVAL_P(result)) {
+ efree(Z_USTRVAL_P(result));
+ ZVAL_UNICODEL(result, norm, norm_len, 0);
+ }
+ }
+
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
@@ -20737,17 +21599,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = &opline->op2.u.constant;
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -20761,10 +21625,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -20875,7 +21739,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -20933,10 +21799,31 @@ static int ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -20944,8 +21831,8 @@ static int ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -20953,7 +21840,11 @@ static int ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -21057,10 +21948,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(int prop_dim, Z
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -21103,7 +22018,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(int prop_dim, Z
} else {
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -21115,12 +22032,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(int prop_dim, Z
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -22150,17 +23072,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -22174,10 +23098,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -22290,7 +23214,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -22348,10 +23274,31 @@ static int ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -22359,8 +23306,8 @@ static int ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -22368,7 +23315,11 @@ static int ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -22472,10 +23423,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(int prop_dim, ZEN
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -22518,7 +23493,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(int prop_dim, ZEN
} else {
zval_dtor(free_op2.var);
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -22530,12 +23507,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(int prop_dim, ZEN
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -23602,17 +24584,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -23626,10 +24610,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -23742,7 +24726,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -23800,10 +24786,31 @@ static int ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -23811,8 +24818,8 @@ static int ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -23820,7 +24827,11 @@ static int ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -23924,10 +24935,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int prop_dim, ZEN
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -23970,7 +25005,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int prop_dim, ZEN
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -23982,12 +25019,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int prop_dim, ZEN
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -24402,7 +25444,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -25457,17 +26501,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -25481,10 +26527,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -25595,7 +26641,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -25653,10 +26701,31 @@ static int ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -25664,8 +26733,8 @@ static int ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -25673,7 +26742,11 @@ static int ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -25777,10 +26850,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(int prop_dim, ZEND
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -25823,7 +26920,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(int prop_dim, ZEND
} else {
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -25835,12 +26934,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(int prop_dim, ZEND
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -29661,6 +30765,31 @@ void zend_init_opcodes_handlers()
ZEND_USER_OPCODE_SPEC_HANDLER,
ZEND_USER_OPCODE_SPEC_HANDLER,
ZEND_USER_OPCODE_SPEC_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CONST_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CONST_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CONST_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CONST_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CONST_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_TMP_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_TMP_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_TMP_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_TMP_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_TMP_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_VAR_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_VAR_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_VAR_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_VAR_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CV_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CV_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CV_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CV_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CV_HANDLER,
ZEND_NULL_HANDLER
};
zend_opcode_handlers = (opcode_handler_t*)labels;