diff options
-rw-r--r-- | Zend/tests/bug69568.phpt | 25 | ||||
-rw-r--r-- | Zend/tests/parent_class_name_without_parent.phpt | 21 | ||||
-rw-r--r-- | Zend/zend_API.c | 17 | ||||
-rw-r--r-- | Zend/zend_API.h | 1 | ||||
-rw-r--r-- | Zend/zend_closures.c | 34 | ||||
-rw-r--r-- | Zend/zend_closures.h | 2 | ||||
-rw-r--r-- | Zend/zend_compile.c | 30 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 91 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 250 | ||||
-rw-r--r-- | ext/pdo/pdo_stmt.c | 56 | ||||
-rw-r--r-- | ext/pdo/php_pdo_driver.h | 3 | ||||
-rw-r--r-- | ext/pdo_dblib/dblib_stmt.c | 9 | ||||
-rw-r--r-- | ext/pdo_firebird/firebird_statement.c | 4 | ||||
-rw-r--r-- | ext/pdo_mysql/mysql_statement.c | 7 | ||||
-rw-r--r-- | ext/pdo_oci/oci_statement.c | 3 | ||||
-rw-r--r-- | ext/pdo_odbc/odbc_stmt.c | 3 | ||||
-rw-r--r-- | ext/pdo_pgsql/pgsql_statement.c | 7 | ||||
-rw-r--r-- | ext/pdo_sqlite/sqlite_statement.c | 5 | ||||
-rw-r--r-- | ext/reflection/php_reflection.c | 6 | ||||
-rw-r--r-- | ext/simplexml/simplexml.c | 110 | ||||
-rw-r--r-- | ext/standard/formatted_print.c | 22 | ||||
-rw-r--r-- | ext/standard/string.c | 22 |
22 files changed, 400 insertions, 328 deletions
diff --git a/Zend/tests/bug69568.phpt b/Zend/tests/bug69568.phpt new file mode 100644 index 0000000000..18ec941d0b --- /dev/null +++ b/Zend/tests/bug69568.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #69568: call a private function in closure failed +--FILE-- +<?php +class A { + + private static function testprivate() { + return 1; + } + public static function test() { + return function() { + return self::testprivate(); + }; + } +} + +class B extends A { +} + +$fn = B::test(); +echo $fn(); + +?> +--EXPECT-- +1 diff --git a/Zend/tests/parent_class_name_without_parent.phpt b/Zend/tests/parent_class_name_without_parent.phpt new file mode 100644 index 0000000000..0e67173f87 --- /dev/null +++ b/Zend/tests/parent_class_name_without_parent.phpt @@ -0,0 +1,21 @@ +--TEST-- +Getting parent class name when there is no parent generates an error +--FILE-- +<?php + +trait T { + public function f() { + var_dump(parent::class); + } +} + +class C { + use T; +} + +(new C)->f(); + +?> +--EXPECTF-- +Fatal error: Cannot use "parent" when current class scope has no parent in %s on line 5 + diff --git a/Zend/zend_API.c b/Zend/zend_API.c index e55ec45af6..7f8587ab4f 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3828,6 +3828,23 @@ ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char } /* }}} */ +ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zval *value) /* {{{ */ +{ + zval property; + zend_class_entry *old_scope = EG(scope); + + EG(scope) = scope; + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, Z_OBJCE_P(object)->name->val); + } + ZVAL_STR(&property, name); + Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL); + + EG(scope) = old_scope; +} +/* }}} */ + ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value) /* {{{ */ { zval property; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index e0860a45f4..f61091ae72 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -329,6 +329,7 @@ ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char ZEND_API int zend_update_class_constants(zend_class_entry *class_type); +ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zval *value); ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value); ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, size_t name_length); ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value); diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 952e4ed1e0..97f0cbf57a 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -35,9 +35,10 @@ zend_error(E_EXCEPTION | E_ERROR, "Closure object cannot have properties") typedef struct _zend_closure { - zend_object std; - zend_function func; - zval this_ptr; + zend_object std; + zend_function func; + zval this_ptr; + zend_class_entry *called_scope; } zend_closure; /* non-static since it needs to be referenced */ @@ -129,7 +130,7 @@ ZEND_METHOD(Closure, bind) { zval *newthis, *zclosure, *scope_arg = NULL; zend_closure *closure; - zend_class_entry *ce; + zend_class_entry *ce, *called_scope; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) { RETURN_NULL(); @@ -161,7 +162,13 @@ ZEND_METHOD(Closure, bind) ce = closure->func.common.scope; } - zend_create_closure(return_value, &closure->func, ce, newthis); + if (newthis) { + called_scope = Z_OBJCE_P(newthis); + } else { + called_scope = ce; + } + + zend_create_closure(return_value, &closure->func, ce, called_scope, newthis); } /* }}} */ @@ -296,7 +303,8 @@ static zend_object *zend_closure_clone(zval *zobject) /* {{{ */ zend_closure *closure = (zend_closure *)Z_OBJ_P(zobject); zval result; - zend_create_closure(&result, &closure->func, closure->func.common.scope, &closure->this_ptr); + zend_create_closure(&result, &closure->func, + closure->func.common.scope, closure->called_scope, &closure->this_ptr); return Z_OBJ(result); } /* }}} */ @@ -311,17 +319,14 @@ int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function closure = (zend_closure *)Z_OBJ_P(obj); *fptr_ptr = &closure->func; + *ce_ptr = closure->called_scope; - if (Z_TYPE(closure->this_ptr) != IS_UNDEF) { - if (obj_ptr) { + if (obj_ptr) { + if (Z_TYPE(closure->this_ptr) != IS_UNDEF) { *obj_ptr = Z_OBJ(closure->this_ptr); - } - *ce_ptr = Z_OBJCE(closure->this_ptr); - } else { - if (obj_ptr) { + } else { *obj_ptr = NULL; } - *ce_ptr = closure->func.common.scope; } return SUCCESS; } @@ -457,7 +462,7 @@ void zend_register_closure_ce(void) /* {{{ */ } /* }}} */ -ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_entry *scope, zval *this_ptr) /* {{{ */ +ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_entry *scope, zend_class_entry *called_scope, zval *this_ptr) /* {{{ */ { zend_closure *closure; @@ -512,6 +517,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent * If the closure is unscoped, it has no bound object. * The the closure is scoped, it's either static or it's bound */ closure->func.common.scope = scope; + closure->called_scope = called_scope; if (scope) { closure->func.common.fn_flags |= ZEND_ACC_PUBLIC; if (this_ptr && Z_TYPE_P(this_ptr) == IS_OBJECT && (closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0) { diff --git a/Zend/zend_closures.h b/Zend/zend_closures.h index 9862bc07cf..8d0963ec17 100644 --- a/Zend/zend_closures.h +++ b/Zend/zend_closures.h @@ -28,7 +28,7 @@ void zend_register_closure_ce(void); extern ZEND_API zend_class_entry *zend_ce_closure; -ZEND_API void zend_create_closure(zval *res, zend_function *op_array, zend_class_entry *scope, zval *this_ptr); +ZEND_API void zend_create_closure(zval *res, zend_function *op_array, zend_class_entry *scope, zend_class_entry *called_scope, zval *this_ptr); ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *obj); ZEND_API const zend_function *zend_get_closure_method_def(zval *obj); ZEND_API zval* zend_get_closure_this_ptr(zval *obj); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c92a25a705..2e05b35966 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6349,16 +6349,8 @@ void zend_compile_resolve_class_name(znode *result, zend_ast *ast) /* {{{ */ switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: if (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) { - zval class_str_zv; - zend_ast *class_str_ast, *class_const_ast; - - ZVAL_STRING(&class_str_zv, "class"); - class_str_ast = zend_ast_create_zval(&class_str_zv); - class_const_ast = zend_ast_create(ZEND_AST_CLASS_CONST, name_ast, class_str_ast); - - zend_compile_expr(result, class_const_ast); - - zval_ptr_dtor(&class_str_zv); + zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL); + opline->extended_value = fetch_type; } else { result->op_type = IS_CONST; ZVAL_STR_COPY(&result->u.constant, CG(active_class_entry)->name); @@ -6367,17 +6359,8 @@ void zend_compile_resolve_class_name(znode *result, zend_ast *ast) /* {{{ */ case ZEND_FETCH_CLASS_STATIC: case ZEND_FETCH_CLASS_PARENT: { - zval class_str_zv; - zend_ast *class_str_ast, *class_const_ast; - - ZVAL_STRING(&class_str_zv, "class"); - class_str_ast = zend_ast_create_zval(&class_str_zv); - class_const_ast = zend_ast_create( - ZEND_AST_CLASS_CONST, name_ast, class_str_ast); - - zend_compile_expr(result, class_const_ast); - - zval_ptr_dtor(&class_str_zv); + zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL); + opline->extended_value = fetch_type; } break; case ZEND_FETCH_CLASS_DEFAULT: @@ -6518,6 +6501,8 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */ void zend_compile_magic_const(znode *result, zend_ast *ast) /* {{{ */ { + zend_op *opline; + if (zend_try_ct_eval_magic_const(&result->u.constant, ast)) { result->op_type = IS_CONST; return; @@ -6527,7 +6512,8 @@ void zend_compile_magic_const(znode *result, zend_ast *ast) /* {{{ */ CG(active_class_entry) && (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != 0); - zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL); + opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL); + opline->extended_value = ZEND_FETCH_CLASS_SELF; } /* }}} */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 282844df10..e00ee07d84 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5076,9 +5076,6 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value); } ZVAL_DUP(EX_VAR(opline->result.var), value); - } else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) { - /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ - ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); } else { zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); } @@ -7304,9 +7301,11 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED) if (UNEXPECTED((Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC) || (EX(func)->common.fn_flags & ZEND_ACC_STATIC))) { - zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(called_scope), NULL); + zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), + EG(scope), EX(called_scope), NULL); } else { - zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(scope), Z_OBJ(EX(This)) ? &EX(This) : NULL); + zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), + EG(scope), EX(called_scope), Z_OBJ(EX(This)) ? &EX(This) : NULL); } CHECK_EXCEPTION(); @@ -7773,44 +7772,31 @@ ZEND_VM_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMP|VAR|CV, ANY) { USE_OPLINE zval *value; - int result; + int result = 0; zend_free_op free_op1; SAVE_OPLINE(); value = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); - switch (opline->extended_value) { - case IS_NULL: - case IS_LONG: - case IS_DOUBLE: - case IS_STRING: - case IS_ARRAY: - result = (Z_TYPE_P(value) == opline->extended_value); - break; - case _IS_BOOL: - result = (Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE); - break; - case IS_OBJECT: - if (Z_TYPE_P(value) == opline->extended_value) { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !memcmp(ce->name->val, "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1)) { - result = 0; - } else { - result = 1; - } - } else { - result = 0; + if (EXPECTED(Z_TYPE_P(value) == opline->extended_value)) { + if (UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { + zend_class_entry *ce = Z_OBJCE_P(value); + + if (UNEXPECTED(ce->name->len != sizeof("__PHP_Incomplete_Class") - 1) || + EXPECTED(memcmp(ce->name->val, "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1) != 0)) { + result = 1; } - break; - case IS_RESOURCE: - if (Z_TYPE_P(value) == opline->extended_value) { - const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value)); - result = (type_name != NULL); - } else { - result = 0; + } else if (UNEXPECTED(Z_TYPE_P(value) == IS_RESOURCE)) { + const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value)); + + if (EXPECTED(type_name != NULL)) { + result = 1; } - break; - EMPTY_SWITCH_DEFAULT_CASE() + } else { + result = 1; + } + } else if (UNEXPECTED(opline->extended_value == _IS_BOOL) && + EXPECTED(Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE)) { + result = 1; } FREE_OP1(); ZEND_VM_SMART_BRANCH(result, 1); @@ -7857,12 +7843,35 @@ ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, ANY) ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, ANY, ANY) { + uint32_t fetch_type; USE_OPLINE - if (EG(scope) && EG(scope)->name) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->name); - } else { - ZVAL_EMPTY_STRING(EX_VAR(opline->result.var)); + SAVE_OPLINE(); + fetch_type = opline->extended_value; + + if (UNEXPECTED(EG(scope) == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use \"%s\" when no class scope is active", + fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : + fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); + HANDLE_EXCEPTION(); + } + + switch (fetch_type) { + case ZEND_FETCH_CLASS_SELF: + ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->name); + break; + case ZEND_FETCH_CLASS_PARENT: + if (UNEXPECTED(EG(scope)->parent == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, + "Cannot use \"parent\" when current class scope has no parent"); + HANDLE_EXCEPTION(); + } + ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->parent->name); + break; + case ZEND_FETCH_CLASS_STATIC: + ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(called_scope)->name); + break; + EMPTY_SWITCH_DEFAULT_CASE() } ZEND_VM_NEXT_OPCODE(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 89e95a4463..85075af2a6 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1790,12 +1790,35 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSERT_CHECK_SPEC_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { + uint32_t fetch_type; USE_OPLINE - if (EG(scope) && EG(scope)->name) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->name); - } else { - ZVAL_EMPTY_STRING(EX_VAR(opline->result.var)); + SAVE_OPLINE(); + fetch_type = opline->extended_value; + + if (UNEXPECTED(EG(scope) == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Cannot use \"%s\" when no class scope is active", + fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : + fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); + HANDLE_EXCEPTION(); + } + + switch (fetch_type) { + case ZEND_FETCH_CLASS_SELF: + ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->name); + break; + case ZEND_FETCH_CLASS_PARENT: + if (UNEXPECTED(EG(scope)->parent == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, + "Cannot use \"parent\" when current class scope has no parent"); + HANDLE_EXCEPTION(); + } + ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->parent->name); + break; + case ZEND_FETCH_CLASS_STATIC: + ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(called_scope)->name); + break; + EMPTY_SWITCH_DEFAULT_CASE() } ZEND_VM_NEXT_OPCODE(); } @@ -4199,44 +4222,31 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CONST_HANDLER( { USE_OPLINE zval *value; - int result; + int result = 0; SAVE_OPLINE(); value = EX_CONSTANT(opline->op1); - switch (opline->extended_value) { - case IS_NULL: - case IS_LONG: - case IS_DOUBLE: - case IS_STRING: - case IS_ARRAY: - result = (Z_TYPE_P(value) == opline->extended_value); - break; - case _IS_BOOL: - result = (Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE); - break; - case IS_OBJECT: - if (Z_TYPE_P(value) == opline->extended_value) { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !memcmp(ce->name->val, "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1)) { - result = 0; - } else { - result = 1; - } - } else { - result = 0; + if (EXPECTED(Z_TYPE_P(value) == opline->extended_value)) { + if (UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { + zend_class_entry *ce = Z_OBJCE_P(value); + + if (UNEXPECTED(ce->name->len != sizeof("__PHP_Incomplete_Class") - 1) || + EXPECTED(memcmp(ce->name->val, "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1) != 0)) { + result = 1; } - break; - case IS_RESOURCE: - if (Z_TYPE_P(value) == opline->extended_value) { - const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value)); - result = (type_name != NULL); - } else { - result = 0; + } else if (UNEXPECTED(Z_TYPE_P(value) == IS_RESOURCE)) { + const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value)); + + if (EXPECTED(type_name != NULL)) { + result = 1; } - break; - EMPTY_SWITCH_DEFAULT_CASE() + } else { + result = 1; + } + } else if (UNEXPECTED(opline->extended_value == _IS_BOOL) && + EXPECTED(Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE)) { + result = 1; } ZEND_VM_SMART_BRANCH(result, 1); @@ -5832,9 +5842,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONS CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value); } ZVAL_DUP(EX_VAR(opline->result.var), value); - } else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) { - /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ - ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); } else { zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); } @@ -7983,9 +7990,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_C if (UNEXPECTED((Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC) || (EX(func)->common.fn_flags & ZEND_ACC_STATIC))) { - zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(called_scope), NULL); + zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), + EG(scope), EX(called_scope), NULL); } else { - zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(scope), Z_OBJ(EX(This)) ? &EX(This) : NULL); + zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), + EG(scope), EX(called_scope), Z_OBJ(EX(This)) ? &EX(This) : NULL); } CHECK_EXCEPTION(); @@ -12262,44 +12271,31 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TMP_HANDLER(ZE { USE_OPLINE zval *value; - int result; + int result = 0; zend_free_op free_op1; SAVE_OPLINE(); value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); - switch (opline->extended_value) { - case IS_NULL: - case IS_LONG: - case IS_DOUBLE: - case IS_STRING: - case IS_ARRAY: - result = (Z_TYPE_P(value) == opline->extended_value); - break; - case _IS_BOOL: - result = (Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE); - break; - case IS_OBJECT: - if (Z_TYPE_P(value) == opline->extended_value) { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !memcmp(ce->name->val, "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1)) { - result = 0; - } else { - result = 1; - } - } else { - result = 0; + if (EXPECTED(Z_TYPE_P(value) == opline->extended_value)) { + if (UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { + zend_class_entry *ce = Z_OBJCE_P(value); + + if (UNEXPECTED(ce->name->len != sizeof("__PHP_Incomplete_Class") - 1) || + EXPECTED(memcmp(ce->name->val, "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1) != 0)) { + result = 1; } - break; - case IS_RESOURCE: - if (Z_TYPE_P(value) == opline->extended_value) { - const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value)); - result = (type_name != NULL); - } else { - result = 0; + } else if (UNEXPECTED(Z_TYPE_P(value) == IS_RESOURCE)) { + const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value)); + + if (EXPECTED(type_name != NULL)) { + result = 1; } - break; - EMPTY_SWITCH_DEFAULT_CASE() + } else { + result = 1; + } + } else if (UNEXPECTED(opline->extended_value == _IS_BOOL) && + EXPECTED(Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE)) { + result = 1; } zval_ptr_dtor_nogc(free_op1); ZEND_VM_SMART_BRANCH(result, 1); @@ -16017,44 +16013,31 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_VAR_HANDLER(ZE { USE_OPLINE zval *value; - int result; + int result = 0; zend_free_op free_op1; SAVE_OPLINE(); value = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1); - switch (opline->extended_value) { - case IS_NULL: - case IS_LONG: - case IS_DOUBLE: - case IS_STRING: - case IS_ARRAY: - result = (Z_TYPE_P(value) == opline->extended_value); - break; - case _IS_BOOL: - result = (Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE); - break; - case IS_OBJECT: - if (Z_TYPE_P(value) == opline->extended_value) { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !memcmp(ce->name->val, "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1)) { - result = 0; - } else { - result = 1; - } - } else { - result = 0; + if (EXPECTED(Z_TYPE_P(value) == opline->extended_value)) { + if (UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { + zend_class_entry *ce = Z_OBJCE_P(value); + + if (UNEXPECTED(ce->name->len != sizeof("__PHP_Incomplete_Class") - 1) || + EXPECTED(memcmp(ce->name->val, "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1) != 0)) { + result = 1; } - break; - case IS_RESOURCE: - if (Z_TYPE_P(value) == opline->extended_value) { - const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value)); - result = (type_name != NULL); - } else { - result = 0; + } else if (UNEXPECTED(Z_TYPE_P(value) == IS_RESOURCE)) { + const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value)); + + if (EXPECTED(type_name != NULL)) { + result = 1; } - break; - EMPTY_SWITCH_DEFAULT_CASE() + } else { + result = 1; + } + } else if (UNEXPECTED(opline->extended_value == _IS_BOOL) && + EXPECTED(Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE)) { + result = 1; } zval_ptr_dtor_nogc(free_op1); ZEND_VM_SMART_BRANCH(result, 1); @@ -17447,9 +17430,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value); } ZVAL_DUP(EX_VAR(opline->result.var), value); - } else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) { - /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ - ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); } else { zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); } @@ -23819,9 +23799,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value); } ZVAL_DUP(EX_VAR(opline->result.var), value); - } else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) { - /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ - ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); } else { zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); } @@ -29701,44 +29678,31 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEN { USE_OPLINE zval *value; - int result; + int result = 0; SAVE_OPLINE(); value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var); - switch (opline->extended_value) { - case IS_NULL: - case IS_LONG: - case IS_DOUBLE: - case IS_STRING: - case IS_ARRAY: - result = (Z_TYPE_P(value) == opline->extended_value); - break; - case _IS_BOOL: - result = (Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE); - break; - case IS_OBJECT: - if (Z_TYPE_P(value) == opline->extended_value) { - zend_class_entry *ce = Z_OBJCE_P(value); - if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1 - && !memcmp(ce->name->val, "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1)) { - result = 0; - } else { - result = 1; - } - } else { - result = 0; + if (EXPECTED(Z_TYPE_P(value) == opline->extended_value)) { + if (UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { + zend_class_entry *ce = Z_OBJCE_P(value); + + if (UNEXPECTED(ce->name->len != sizeof("__PHP_Incomplete_Class") - 1) || + EXPECTED(memcmp(ce->name->val, "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1) != 0)) { + result = 1; } - break; - case IS_RESOURCE: - if (Z_TYPE_P(value) == opline->extended_value) { - const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value)); - result = (type_name != NULL); - } else { - result = 0; + } else if (UNEXPECTED(Z_TYPE_P(value) == IS_RESOURCE)) { + const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value)); + + if (EXPECTED(type_name != NULL)) { + result = 1; } - break; - EMPTY_SWITCH_DEFAULT_CASE() + } else { + result = 1; + } + } else if (UNEXPECTED(opline->extended_value == _IS_BOOL) && + EXPECTED(Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE)) { + result = 1; } ZEND_VM_SMART_BRANCH(result, 1); diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 3387da0f2d..6383abb925 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -209,7 +209,7 @@ int pdo_stmt_describe_columns(pdo_stmt_t *stmt) /* {{{ */ /* if we are applying case conversions on column names, do so now */ if (stmt->dbh->native_case != stmt->dbh->desired_case && stmt->dbh->desired_case != PDO_CASE_NATURAL) { - char *s = stmt->columns[col].name; + char *s = stmt->columns[col].name->val; switch (stmt->dbh->desired_case) { case PDO_CASE_UPPER: @@ -243,8 +243,8 @@ int pdo_stmt_describe_columns(pdo_stmt_t *stmt) /* {{{ */ if (stmt->bound_columns) { struct pdo_bound_param_data *param; - if ((param = zend_hash_str_find_ptr(stmt->bound_columns, - stmt->columns[col].name, stmt->columns[col].namelen)) != NULL) { + if ((param = zend_hash_find_ptr(stmt->bound_columns, + stmt->columns[col].name)) != NULL) { param->paramno = col; } } @@ -345,7 +345,8 @@ static int really_register_bound_param(struct pdo_bound_param_data *param, pdo_s int i; for (i = 0; i < stmt->column_count; i++) { - if (strncmp(stmt->columns[i].name, param->name->val, param->name->len + 1) == 0) { + if (stmt->columns[i].name->len == param->name->len && + strncmp(stmt->columns[i].name->val, param->name->val, param->name->len + 1) == 0) { param->paramno = i; break; } @@ -1025,7 +1026,7 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, enum pdo_ switch (how) { case PDO_FETCH_ASSOC: - add_assoc_zval(return_value, stmt->columns[i].name, &val); + zend_symtable_update(Z_ARRVAL_P(return_value), stmt->columns[i].name, &val); break; case PDO_FETCH_KEY_PAIR: @@ -1046,19 +1047,18 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, enum pdo_ case PDO_FETCH_USE_DEFAULT: case PDO_FETCH_BOTH: - add_assoc_zval(return_value, stmt->columns[i].name, &val); + zend_symtable_update(Z_ARRVAL_P(return_value), stmt->columns[i].name, &val); if (Z_REFCOUNTED(val)) { Z_ADDREF(val); } - add_next_index_zval(return_value, &val); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &val); break; case PDO_FETCH_NAMED: /* already have an item with this name? */ { zval *curr_val; - if ((curr_val = zend_hash_str_find(Z_ARRVAL_P(return_value), stmt->columns[i].name, - strlen(stmt->columns[i].name)))) { + if ((curr_val = zend_hash_find(Z_ARRVAL_P(return_value), stmt->columns[i].name))) { zval arr; if (Z_TYPE_P(curr_val) != IS_ARRAY) { /* a little bit of black magic here: @@ -1077,33 +1077,33 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, enum pdo_ ZVAL_COPY_VALUE(&cur, curr_val); ZVAL_COPY_VALUE(curr_val, &arr); - add_next_index_zval(&arr, &cur); + zend_hash_next_index_insert_new(Z_ARRVAL(arr), &cur); } else { ZVAL_COPY_VALUE(&arr, curr_val); } - add_next_index_zval(&arr, &val); + zend_hash_next_index_insert_new(Z_ARRVAL(arr), &val); } else { - add_assoc_zval(return_value, stmt->columns[i].name, &val); + zend_hash_update(Z_ARRVAL_P(return_value), stmt->columns[i].name, &val); } } break; case PDO_FETCH_NUM: - add_next_index_zval(return_value, &val); + zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &val); break; case PDO_FETCH_OBJ: case PDO_FETCH_INTO: - zend_update_property(NULL, return_value, - stmt->columns[i].name, stmt->columns[i].namelen, + zend_update_property_ex(NULL, return_value, + stmt->columns[i].name, &val); zval_ptr_dtor(&val); break; case PDO_FETCH_CLASS: if ((flags & PDO_FETCH_SERIALIZE) == 0 || idx) { - zend_update_property(ce, return_value, - stmt->columns[i].name, stmt->columns[i].namelen, + zend_update_property_ex(ce, return_value, + stmt->columns[i].name, &val); zval_ptr_dtor(&val); } else { @@ -1194,16 +1194,16 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, enum pdo_ if (return_all) { if ((flags & PDO_FETCH_UNIQUE) == PDO_FETCH_UNIQUE) { - add_assoc_zval(return_all, Z_STRVAL(grp_val), return_value); + zend_symtable_update(Z_ARRVAL_P(return_all), Z_STR(grp_val), return_value); } else { zval grp; if ((pgrp = zend_symtable_find(Z_ARRVAL_P(return_all), Z_STR(grp_val))) == NULL) { array_init(&grp); - add_assoc_zval(return_all, Z_STRVAL(grp_val), &grp); + zend_symtable_update(Z_ARRVAL_P(return_all), Z_STR(grp_val), &grp); } else { ZVAL_COPY_VALUE(&grp, pgrp); } - add_next_index_zval(&grp, return_value); + zend_hash_next_index_insert(Z_ARRVAL(grp), return_value); } zval_dtor(&grp_val); } @@ -1518,7 +1518,7 @@ static PHP_METHOD(PDOStatement, fetchAll) } else { array_init(return_value); do { - add_next_index_zval(return_value, &data); + zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &data); } while (do_fetch(stmt, 1, &data, how | flags, PDO_FETCH_ORI_NEXT, 0, 0)); } } @@ -1824,7 +1824,7 @@ static PHP_METHOD(PDOStatement, getColumnMeta) /* add stock items */ col = &stmt->columns[colno]; - add_assoc_string(return_value, "name", col->name); + add_assoc_str(return_value, "name", zend_string_copy(col->name)); add_assoc_long(return_value, "len", col->maxlen); /* FIXME: unsigned ? */ add_assoc_long(return_value, "precision", col->precision); if (col->param_type != PDO_PARAM_ZVAL) { @@ -2027,7 +2027,7 @@ static int pdo_stmt_do_next_rowset(pdo_stmt_t *stmt) struct pdo_column_data *cols = stmt->columns; for (i = 0; i < stmt->column_count; i++) { - efree(cols[i].name); + zend_string_release(cols[i].name); } efree(stmt->columns); stmt->columns = NULL; @@ -2329,7 +2329,7 @@ PDO_API void php_pdo_free_statement(pdo_stmt_t *stmt) for (i = 0; i < stmt->column_count; i++) { if (cols[i].name) { - efree(cols[i].name); + zend_string_release(cols[i].name); cols[i].name = NULL; } } @@ -2506,7 +2506,8 @@ static zval *row_prop_read(zval *object, zval *member, int type, void **cache_sl /* TODO: replace this with a hash of available column names to column * numbers */ for (colno = 0; colno < stmt->column_count; colno++) { - if (strcmp(stmt->columns[colno].name, Z_STRVAL_P(member)) == 0) { + if (stmt->columns[colno].name->len == Z_STRLEN_P(member) && + strncmp(stmt->columns[colno].name->val, Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0) { fetch_value(stmt, rv, colno, NULL); //??? //Z_SET_REFCOUNT_P(rv, 0); @@ -2565,7 +2566,8 @@ static int row_prop_exists(zval *object, zval *member, int check_empty, void **c /* TODO: replace this with a hash of available column names to column * numbers */ for (colno = 0; colno < stmt->column_count; colno++) { - if (strcmp(stmt->columns[colno].name, Z_STRVAL_P(member)) == 0) { + if (stmt->columns[colno].name->len == Z_STRLEN_P(member) && + strncmp(stmt->columns[colno].name->val, Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0) { return 1; } } @@ -2606,7 +2608,7 @@ static HashTable *row_get_properties(zval *object) zval val; fetch_value(stmt, &val, i, NULL); - zend_hash_str_update(stmt->std.properties, stmt->columns[i].name, stmt->columns[i].namelen, &val); + zend_hash_update(stmt->std.properties, stmt->columns[i].name, &val); } return stmt->std.properties; diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index 407d1baa82..efa21a4e14 100644 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -527,11 +527,10 @@ static inline pdo_dbh_object_t *php_pdo_dbh_fetch_object(zend_object *obj) { /* describes a column */ struct pdo_column_data { - char *name; + zend_string *name; size_t maxlen; zend_ulong precision; enum pdo_param_type param_type; - size_t namelen; /* don't touch this unless your name is dbdo */ void *dbdo_data; diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c index 4da5f71531..97776548b2 100644 --- a/ext/pdo_dblib/dblib_stmt.c +++ b/ext/pdo_dblib/dblib_stmt.c @@ -191,16 +191,17 @@ static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno) { pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data; pdo_dblib_db_handle *H = S->H; + struct pdo_column_data *col; + zend_string *str; if(colno >= stmt->column_count || colno < 0) { return FAILURE; } - struct pdo_column_data *col = &stmt->columns[colno]; - - col->name = estrdup(dbcolname(H->link, colno+1)); + col = &stmt->columns[colno]; + str = dbcolname(H->link, colno+1); + col->name = zend_string_init(str, strlen(str), 0); col->maxlen = dbcollen(H->link, colno+1); - col->namelen = strlen(col->name); col->param_type = PDO_PARAM_STR; return 1; diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 50901841c8..337ce3fb66 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -197,8 +197,8 @@ static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */ : (var->aliasname_length); col->precision = -var->sqlscale; col->maxlen = var->sqllen; - col->namelen = colname_len; - col->name = cp = emalloc(colname_len + 1); + col->name = zend_string_alloc(colname_len, 0); + cp = col->name->val; if (colname_len > var->aliasname_length) { memmove(cp, var->relname, var->relname_length); cp += var->relname_length; diff --git a/ext/pdo_mysql/mysql_statement.c b/ext/pdo_mysql/mysql_statement.c index 56728ed92d..551960560e 100644 --- a/ext/pdo_mysql/mysql_statement.c +++ b/ext/pdo_mysql/mysql_statement.c @@ -696,14 +696,11 @@ static int pdo_mysql_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */ PDO_DBG_RETURN(1); } for (i = 0; i < stmt->column_count; i++) { - int namelen; if (S->H->fetch_table_names) { - namelen = spprintf(&cols[i].name, 0, "%s.%s", S->fields[i].table, S->fields[i].name); - cols[i].namelen = namelen; + cols[i].name = strpprintf(0, "%s.%s", S->fields[i].table, S->fields[i].name); } else { - cols[i].namelen = S->fields[i].name_length; - cols[i].name = estrndup(S->fields[i].name, S->fields[i].name_length); + cols[i].name = zend_string_init(S->fields[i].name, S->fields[i].name_length, 0); } cols[i].precision = S->fields[i].decimals; diff --git a/ext/pdo_oci/oci_statement.c b/ext/pdo_oci/oci_statement.c index e47fba513b..9efb371f6d 100644 --- a/ext/pdo_oci/oci_statement.c +++ b/ext/pdo_oci/oci_statement.c @@ -525,8 +525,7 @@ static int oci_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */ col->precision = scale; col->maxlen = data_size; - col->namelen = namelen; - col->name = estrndup((char *)colname, namelen); + col->name = zend_string_init((char *)colname, namelen, 0); S->cols[colno].dtype = dtype; diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c index 5d4ff3af96..6421cb6701 100644 --- a/ext/pdo_odbc/odbc_stmt.c +++ b/ext/pdo_odbc/odbc_stmt.c @@ -594,8 +594,7 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno) colsize = displaysize; col->maxlen = S->cols[colno].datalen = colsize; - col->namelen = colnamelen; - col->name = estrdup(S->cols[colno].colname); + col->name = zend_string_init(S->cols[colno].colname, colnamelen, 0); S->cols[colno].is_unicode = pdo_odbc_sqltype_is_unicode(S, S->cols[colno].coltype); /* returning data as a string */ diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index 435781ecf1..60553b36ce 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -438,13 +438,14 @@ static int pgsql_stmt_describe(pdo_stmt_t *stmt, int colno) pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; struct pdo_column_data *cols = stmt->columns; struct pdo_bound_param_data *param; + char *str; if (!S->result) { return 0; } - cols[colno].name = estrdup(PQfname(S->result, colno)); - cols[colno].namelen = strlen(cols[colno].name); + str = PQfname(S->result, colno); + cols[colno].name = zend_string_init(str, strlen(str), 0); cols[colno].maxlen = PQfsize(S->result, colno); cols[colno].precision = PQfmod(S->result, colno); S->cols[colno].pgsql_type = PQftype(S->result, colno); @@ -459,7 +460,7 @@ static int pgsql_stmt_describe(pdo_stmt_t *stmt, int colno) /* did the user bind the column as a LOB ? */ if (stmt->bound_columns && ( (param = zend_hash_index_find_ptr(stmt->bound_columns, colno)) != NULL || - (param = zend_hash_str_find_ptr(stmt->bound_columns, cols[colno].name, cols[colno].namelen)) != NULL)) { + (param = zend_hash_find_ptr(stmt->bound_columns, cols[colno].name)) != NULL)) { if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) { cols[colno].param_type = PDO_PARAM_LOB; diff --git a/ext/pdo_sqlite/sqlite_statement.c b/ext/pdo_sqlite/sqlite_statement.c index 29300c198a..f42ad05329 100644 --- a/ext/pdo_sqlite/sqlite_statement.c +++ b/ext/pdo_sqlite/sqlite_statement.c @@ -233,6 +233,7 @@ static int pdo_sqlite_stmt_fetch(pdo_stmt_t *stmt, static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno) { pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data; + char *str; if(colno >= sqlite3_column_count(S->stmt)) { /* error invalid column */ @@ -240,8 +241,8 @@ static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno) return 0; } - stmt->columns[colno].name = estrdup(sqlite3_column_name(S->stmt, colno)); - stmt->columns[colno].namelen = strlen(stmt->columns[colno].name); + str = sqlite3_column_name(S->stmt, colno); + stmt->columns[colno].name = zend_string_init(str, strlen(str), 0); stmt->columns[colno].maxlen = 0xffffffff; stmt->columns[colno].precision = 0; diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 76159479f2..f7dd5531d0 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1717,7 +1717,7 @@ ZEND_METHOD(reflection_function, getClosure) } GET_REFLECTION_OBJECT_PTR(fptr); - zend_create_closure(return_value, fptr, NULL, NULL); + zend_create_closure(return_value, fptr, NULL, NULL, NULL); } /* }}} */ @@ -2827,7 +2827,7 @@ ZEND_METHOD(reflection_method, getClosure) GET_REFLECTION_OBJECT_PTR(mptr); if (mptr->common.fn_flags & ZEND_ACC_STATIC) { - zend_create_closure(return_value, mptr, mptr->common.scope, NULL); + zend_create_closure(return_value, mptr, mptr->common.scope, mptr->common.scope, NULL); } else { if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) { return; @@ -2844,7 +2844,7 @@ ZEND_METHOD(reflection_method, getClosure) { RETURN_ZVAL(obj, 1, 0); } else { - zend_create_closure(return_value, mptr, mptr->common.scope, obj); + zend_create_closure(return_value, mptr, mptr->common.scope, Z_OBJCE_P(obj), obj); } } } diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index d2ed7da008..7a9775b752 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -64,7 +64,7 @@ static void php_sxe_iterator_rewind(zend_object_iterator *iter); /* {{{ _node_as_zval() */ -static void _node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE_ITER itertype, char *name, const xmlChar *nsprefix, int isprefix) +static void _node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE_ITER itertype, char *name, const char *nsprefix, int isprefix) { php_sxe_object *subnode; @@ -73,10 +73,10 @@ static void _node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE subnode->document->refcount++; subnode->iter.type = itertype; if (name) { - subnode->iter.name = xmlStrdup((xmlChar *)name); + subnode->iter.name = (xmlChar*)estrdup(name); } if (nsprefix && *nsprefix) { - subnode->iter.nsprefix = xmlStrdup(nsprefix); + subnode->iter.nsprefix = (xmlChar*)estrdup(nsprefix); subnode->iter.isprefix = isprefix; } @@ -978,7 +978,7 @@ static inline zend_string *sxe_xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr li /* {{{ _get_base_node_value() */ -static void _get_base_node_value(php_sxe_object *sxe_ref, xmlNodePtr node, zval *value, xmlChar *nsprefix, int isprefix) +static void _get_base_node_value(php_sxe_object *sxe_ref, xmlNodePtr node, zval *value, char *nsprefix, int isprefix) { php_sxe_object *subnode; xmlChar *contents; @@ -994,7 +994,7 @@ static void _get_base_node_value(php_sxe_object *sxe_ref, xmlNodePtr node, zval subnode->document = sxe_ref->document; subnode->document->refcount++; if (nsprefix && *nsprefix) { - subnode->iter.nsprefix = xmlStrdup((xmlChar *)nsprefix); + subnode->iter.nsprefix = (xmlChar*)estrdup(nsprefix); subnode->iter.isprefix = isprefix; } php_libxml_increment_node_ptr((php_libxml_node_object *)subnode, node, NULL); @@ -1007,26 +1007,24 @@ static void _get_base_node_value(php_sxe_object *sxe_ref, xmlNodePtr node, zval static void sxe_properties_add(HashTable *rv, char *name, int namelen, zval *value) /* {{{ */ { + zend_string *key; zval *data_ptr; zval newptr; - if ((data_ptr = zend_hash_str_find(rv, name, namelen)) != NULL) { + key = zend_string_init(name, namelen, 0); + if ((data_ptr = zend_hash_find(rv, key)) != NULL) { if (Z_TYPE_P(data_ptr) == IS_ARRAY) { - zend_hash_next_index_insert(Z_ARRVAL_P(data_ptr), value); + zend_hash_next_index_insert_new(Z_ARRVAL_P(data_ptr), value); } else { array_init(&newptr); - - if (Z_REFCOUNTED_P(data_ptr)) { - Z_ADDREF_P(data_ptr); - } - zend_hash_next_index_insert(Z_ARRVAL(newptr), data_ptr); - zend_hash_next_index_insert(Z_ARRVAL(newptr), value); - - zend_hash_str_update(rv, name, namelen, &newptr); + zend_hash_next_index_insert_new(Z_ARRVAL(newptr), data_ptr); + zend_hash_next_index_insert_new(Z_ARRVAL(newptr), value); + ZVAL_ARR(data_ptr, Z_ARR(newptr)); } } else { - zend_hash_str_update(rv, name, namelen, value); + zend_hash_add_new(rv, key, value); } + zend_string_release(key); } /* }}} */ @@ -1499,9 +1497,14 @@ SXE_METHOD(asXML) static inline void sxe_add_namespace_name(zval *return_value, xmlNsPtr ns) /* {{{ */ { char *prefix = SXE_NS_PREFIX(ns); - if (zend_hash_str_exists(Z_ARRVAL_P(return_value), prefix, strlen(prefix)) == 0) { - add_assoc_string(return_value, prefix, (char*)ns->href); + zend_string *key = zend_string_init(prefix, strlen(prefix), 0); + zval zv; + + if (!zend_hash_exists(Z_ARRVAL_P(return_value), key)) { + ZVAL_STRING(&zv, (char*)ns->href); + zend_hash_add_new(Z_ARRVAL_P(return_value), key, &zv); } + zend_string_release(key); } /* }}} */ @@ -2061,10 +2064,10 @@ sxe_object_clone(zval *object) clone->iter.isprefix = sxe->iter.isprefix; if (sxe->iter.name != NULL) { - clone->iter.name = xmlStrdup((xmlChar *)sxe->iter.name); + clone->iter.name = (xmlChar*)estrdup((char*)sxe->iter.name); } if (sxe->iter.nsprefix != NULL) { - clone->iter.nsprefix = xmlStrdup((xmlChar *)sxe->iter.nsprefix); + clone->iter.nsprefix = (xmlChar*)estrdup((char*)sxe->iter.nsprefix); } clone->iter.type = sxe->iter.type; @@ -2093,11 +2096,11 @@ static void sxe_object_dtor(zend_object *object) } if (sxe->iter.name) { - xmlFree(sxe->iter.name); + efree(sxe->iter.name); sxe->iter.name = NULL; } if (sxe->iter.nsprefix) { - xmlFree(sxe->iter.nsprefix); + efree(sxe->iter.nsprefix); sxe->iter.nsprefix = NULL; } if (!Z_ISUNDEF(sxe->tmp)) { @@ -2136,17 +2139,21 @@ static zend_function* php_sxe_find_fptr_count(zend_class_entry *ce) { zend_function *fptr_count = NULL; zend_class_entry *parent = ce; + int inherited = 0; while (parent) { if (parent == sxe_class_entry) { break; } parent = parent->parent; + inherited = 1; } - fptr_count = zend_hash_str_find_ptr(&ce->function_table, "count", sizeof("count") - 1); - if (fptr_count->common.scope == parent) { - fptr_count = NULL; + if (inherited) { + fptr_count = zend_hash_str_find_ptr(&ce->function_table, "count", sizeof("count") - 1); + if (fptr_count->common.scope == parent) { + fptr_count = NULL; + } } return fptr_count; @@ -2218,7 +2225,7 @@ PHP_FUNCTION(simplexml_load_file) fptr_count = php_sxe_find_fptr_count(ce); } sxe = php_sxe_object_new(ce, fptr_count); - sxe->iter.nsprefix = ns_len ? xmlStrdup((xmlChar *)ns) : NULL; + sxe->iter.nsprefix = ns_len ? (xmlChar*)estrdup(ns) : NULL; sxe->iter.isprefix = isprefix; php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp); php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL); @@ -2259,7 +2266,7 @@ PHP_FUNCTION(simplexml_load_string) fptr_count = php_sxe_find_fptr_count(ce); } sxe = php_sxe_object_new(ce, fptr_count); - sxe->iter.nsprefix = ns_len ? xmlStrdup((xmlChar *)ns) : NULL; + sxe->iter.nsprefix = ns_len ? (xmlChar*)estrdup(ns) : NULL; sxe->iter.isprefix = isprefix; php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp); php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL); @@ -2291,7 +2298,7 @@ SXE_METHOD(__construct) return; } - sxe->iter.nsprefix = ns_len ? xmlStrdup((xmlChar *)ns) : NULL; + sxe->iter.nsprefix = ns_len ? (xmlChar*)estrdup(ns) : NULL; sxe->iter.isprefix = isprefix; php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp); php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL); @@ -2312,22 +2319,45 @@ static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, i { xmlChar *prefix = sxe->iter.nsprefix; int isprefix = sxe->iter.isprefix; - int test_elem = sxe->iter.type == SXE_ITER_ELEMENT && sxe->iter.name; - int test_attr = sxe->iter.type == SXE_ITER_ATTRLIST && sxe->iter.name; - while (node) { - SKIP_TEXT(node); - if (sxe->iter.type != SXE_ITER_ATTRLIST && node->type == XML_ELEMENT_NODE) { - if ((!test_elem || !xmlStrcmp(node->name, sxe->iter.name)) && match_ns(sxe, node, prefix, isprefix)) { - break; + if (sxe->iter.type == SXE_ITER_ATTRLIST) { + if (sxe->iter.name) { + while (node) { + if (node->type == XML_ATTRIBUTE_NODE) { + if (!xmlStrcmp(node->name, sxe->iter.name) && match_ns(sxe, node, prefix, isprefix)) { + break; + } + } + node = node->next; } - } else if (node->type == XML_ATTRIBUTE_NODE) { - if ((!test_attr || !xmlStrcmp(node->name, sxe->iter.name)) && match_ns(sxe, node, prefix, isprefix)) { - break; + } else { + while (node) { + if (node->type == XML_ATTRIBUTE_NODE) { + if (match_ns(sxe, node, prefix, isprefix)) { + break; + } + } + node = node->next; } } -next_iter: - node = node->next; + } else if (sxe->iter.type == SXE_ITER_ELEMENT && sxe->iter.name) { + while (node) { + if (node->type == XML_ELEMENT_NODE) { + if (!xmlStrcmp(node->name, sxe->iter.name) && match_ns(sxe, node, prefix, isprefix)) { + break; + } + } + node = node->next; + } + } else { + while (node) { + if (node->type == XML_ELEMENT_NODE) { + if (match_ns(sxe, node, prefix, isprefix)) { + break; + } + } + node = node->next; + } } if (node && use_data) { diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c index 4c0eeeebb9..1c381cdb00 100644 --- a/ext/standard/formatted_print.c +++ b/ext/standard/formatted_print.c @@ -383,7 +383,7 @@ php_sprintf_getnumber(char *buffer, size_t *pos) * */ static zend_string * -php_formatted_print(int param_count, int use_array, int format_offset) +php_formatted_print(zend_execute_data *execute_data, int use_array, int format_offset) { zval *newargs = NULL; zval *args, *z_format; @@ -395,9 +395,15 @@ php_formatted_print(int param_count, int use_array, int format_offset) int always_sign; size_t format_len; - if (zend_parse_parameters(param_count, "+", &args, &argc) == FAILURE) { +#ifndef FAST_ZPP + if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) { return NULL; } +#else + ZEND_PARSE_PARAMETERS_START(1, -1) + Z_PARAM_VARIADIC('+', args, argc) + ZEND_PARSE_PARAMETERS_END_EX(return NULL); +#endif /* verify the number of args */ if ((use_array && argc != (2 + format_offset)) @@ -670,7 +676,7 @@ PHP_FUNCTION(user_sprintf) { zend_string *result; - if ((result=php_formatted_print(ZEND_NUM_ARGS(), 0, 0))==NULL) { + if ((result=php_formatted_print(execute_data, 0, 0))==NULL) { RETURN_FALSE; } RETVAL_STR(result); @@ -683,7 +689,7 @@ PHP_FUNCTION(vsprintf) { zend_string *result; - if ((result=php_formatted_print(ZEND_NUM_ARGS(), 1, 0))==NULL) { + if ((result=php_formatted_print(execute_data, 1, 0))==NULL) { RETURN_FALSE; } RETVAL_STR(result); @@ -697,7 +703,7 @@ PHP_FUNCTION(user_printf) zend_string *result; size_t rlen; - if ((result=php_formatted_print(ZEND_NUM_ARGS(), 0, 0))==NULL) { + if ((result=php_formatted_print(execute_data, 0, 0))==NULL) { RETURN_FALSE; } rlen = PHPWRITE(result->val, result->len); @@ -713,7 +719,7 @@ PHP_FUNCTION(vprintf) zend_string *result; size_t rlen; - if ((result=php_formatted_print(ZEND_NUM_ARGS(), 1, 0))==NULL) { + if ((result=php_formatted_print(execute_data, 1, 0))==NULL) { RETURN_FALSE; } rlen = PHPWRITE(result->val, result->len); @@ -740,7 +746,7 @@ PHP_FUNCTION(fprintf) php_stream_from_zval(stream, arg1); - if ((result=php_formatted_print(ZEND_NUM_ARGS(), 0, 1))==NULL) { + if ((result=php_formatted_print(execute_data, 0, 1))==NULL) { RETURN_FALSE; } @@ -769,7 +775,7 @@ PHP_FUNCTION(vfprintf) php_stream_from_zval(stream, arg1); - if ((result=php_formatted_print(ZEND_NUM_ARGS(), 1, 1))==NULL) { + if ((result=php_formatted_print(execute_data, 1, 1))==NULL) { RETURN_FALSE; } diff --git a/ext/standard/string.c b/ext/standard/string.c index 686fa19536..ee66e8a2af 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1082,18 +1082,22 @@ PHPAPI void php_explode(const zend_string *delim, zend_string *str, zval *return char *p1 = str->val; char *endp = str->val + str->len; char *p2 = (char *) php_memnstr(str->val, delim->val, delim->len, endp); + zval tmp; if (p2 == NULL) { - add_next_index_str(return_value, zend_string_copy(str)); + ZVAL_STR_COPY(&tmp, str); + zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); } else { do { - add_next_index_stringl(return_value, p1, p2 - p1); + ZVAL_STRINGL(&tmp, p1, p2 - p1); + zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); p1 = p2 + delim->len; p2 = (char *) php_memnstr(p1, delim->val, delim->len, endp); } while (p2 != NULL && --limit > 1); if (p1 <= endp) { - add_next_index_stringl(return_value, p1, endp - p1); + ZVAL_STRINGL(&tmp, p1, endp - p1); + zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); } } } @@ -1107,6 +1111,7 @@ PHPAPI void php_explode_negative_limit(const zend_string *delim, zend_string *st char *p1 = str->val; char *endp = str->val + str->len; char *p2 = (char *) php_memnstr(str->val, delim->val, delim->len, endp); + zval tmp; if (p2 == NULL) { /* @@ -1131,8 +1136,8 @@ PHPAPI void php_explode_negative_limit(const zend_string *delim, zend_string *st to_return = limit + found; /* limit is at least -1 therefore no need of bounds checking : i will be always less than found */ for (i = 0; i < to_return; i++) { /* this checks also for to_return > 0 */ - add_next_index_stringl(return_value, positions[i], - (positions[i+1] - delim->len) - positions[i]); + ZVAL_STRINGL(&tmp, positions[i], (positions[i+1] - delim->len) - positions[i]); + zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); } efree(positions); } @@ -1146,6 +1151,7 @@ PHP_FUNCTION(explode) { zend_string *str, *delim; zend_long limit = ZEND_LONG_MAX; /* No limit */ + zval tmp; #ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &delim, &str, &limit) == FAILURE) { @@ -1169,7 +1175,8 @@ PHP_FUNCTION(explode) if (str->len == 0) { if (limit >= 0) { - add_next_index_str(return_value, STR_EMPTY_ALLOC()); + ZVAL_EMPTY_STRING(&tmp); + zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp); } return; } @@ -1179,7 +1186,8 @@ PHP_FUNCTION(explode) } else if (limit < 0) { php_explode_negative_limit(delim, str, return_value, limit); } else { - add_index_stringl(return_value, 0, str->val, str->len); + ZVAL_STR_COPY(&tmp, str); + zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp); } } /* }}} */ |