Merge branch 'master' into assert

* master: (59 commits)
  Improved ASSIGN_DIM handler
  Don't inline slow path
  Revert a part committted by mistake
  Fixed compilation warnings
  Fixed a bug that header value is not terminated by '\0' when accessed through getenv().
  better name
  Improve fix for #69038
  Update NEWs
  Fixed bug #69108 ("Segmentation fault" when (de)serializing SplObjectStorage)
  Added specialized versions of DO_FCALL handler:   DO_ICALL - for internal functions   DO_UCALL - for user functions   DO_FCALL_BY_NAME - plain, most probably user, funcstions (not methods)
  Use cache_slot offsets instead of indexes (simplify run-time instructions)
  Split INIT_FCALL_BY_NAME inti INIT_FCALL_BY_NAME(CONST+STRING) and INIT_DYNAMIC_CALL(CONST-STRING|TMPVAR|CV)
  Support list($a, $b) = $a
  Avoid unnecassary check
  Make zend_array_destroy() to free the corresponding zend_array
  Eliminate check on the fast path
  Make current() and key() receive argument by value.
  Use Firebird default home folder, replace Interbase with Firebird
  Updated NEWS
  updated NEWS
  ...

Conflicts:
	Zend/zend_vm_execute.h
	Zend/zend_vm_opcodes.c
	Zend/zend_vm_opcodes.h
This commit is contained in:
Dmitry Stogov 2015-02-26 11:26:03 +03:00
commit 021fd94ed1
70 changed files with 2612 additions and 1567 deletions

1
NEWS
View File

@ -34,6 +34,7 @@
. Implemented FR #55467 (phpinfo: PHP Variables with $ and single quotes). (Kalle)
. Fixed bug #55415 (php_info produces invalid anchor names). (Kalle, Johannes)
. Added ?? operator. (Andrea)
. Added <=> operator. (Andrea)
. Added \u{xxxxx} Unicode Codepoint Escape Syntax. (Andrea)
. Fixed oversight where define() did not support arrays yet const syntax did. (Andrea, Dmitry)
. Use "integer" and "float" instead of "long" and "double" in ZPP, type hint and conversion error messages. (Andrea)

View File

@ -398,6 +398,8 @@ Other
. Added \u{xxxxxx} Unicode Codepoint Escape Syntax for double-quoted strings
and heredocs.
. define() now supports arrays as constant values, fixing an oversight where define() did not support arrays yet const syntax did.
. Added the comparison operator (<=>), aka the spaceship operator.
(RFC: https://wiki.php.net/rfc/combined-comparison-operator)
========================================
3. Changes in SAPI modules

View File

@ -0,0 +1,18 @@
--TEST--
Bug #69092-2 (Declare Encoding Compile Check Wrong) - multibyte off
--INI--
zend.multibyte=0
--FILE--
<?php
echo "Hi";
function foo() {
declare(encoding="UTF-8");
}
echo "Bye"
?>
--EXPECTF--
Warning: declare(encoding=...) ignored because Zend multibyte feature is turned off by settings in %s on line %d
Fatal error: Encoding declaration pragma must be the very first statement in the script in %s on line %d

22
Zend/tests/bug69092.phpt Normal file
View File

@ -0,0 +1,22 @@
--TEST--
Bug #69092 (Declare Encoding Compile Check Wrong)
--SKIPIF--
<?php
if (!extension_loaded("mbstring")) {
die("skip Requires mbstring extension");
}
?>
--INI--
zend.multibyte=On
--FILE--
<?php
echo "Hi";
function foo() {
declare(encoding="utf-8");
}
echo "Bye"
?>
--EXPECTF--
Fatal error: Encoding declaration pragma must be the very first statement in the script in %s on line %d

11
Zend/tests/gc_034.phpt Normal file
View File

@ -0,0 +1,11 @@
--TEST--
GC 034: GC in request shutdown and resource list destroy
--FILE--
<?php
/* run with valgrind */
$a = array(fopen(__FILE__, 'r'));
$a[] = &$a;
?>
==DONE==
--EXPECT--
==DONE==

View File

@ -0,0 +1,56 @@
--TEST--
Test variable occuring on both LHS and RHS of list()
--FILE--
<?php
$a = [1, 2, 3];
list($a, $b, $c) = $a;
var_dump($a, $b, $c);
$b = [1, 2, 3];
list($a, $b, $c) = $b;
var_dump($a, $b, $c);
$c = [1, 2, 3];
list($a, $b, $c) = $c;
var_dump($a, $b, $c);
$a = [[1, 2], 3];
list(list($a, $b), $c) = $a;
var_dump($a, $b, $c);
$b = [[1, 2], 3];
list(list($a, $b), $c) = $b;
var_dump($a, $b, $c);
$b = [1, [2, 3]];
list($a, list($b, $c)) = $b;
var_dump($a, $b, $c);
$c = [1, [2, 3]];
list($a, list($b, $c)) = $c;
var_dump($a, $b, $c);
?>
--EXPECT--
int(1)
int(2)
int(3)
int(1)
int(2)
int(3)
int(1)
int(2)
int(3)
int(1)
int(2)
int(3)
int(1)
int(2)
int(3)
int(1)
int(2)
int(3)
int(1)
int(2)
int(3)

View File

@ -494,22 +494,28 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals) /* {{
static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{{ */
{
ZEND_TSRMLS_CACHE_UPDATE();
zend_startup_constants();
zend_copy_constants(EG(zend_constants), GLOBAL_CONSTANTS_TABLE);
zend_init_rsrc_plist();
zend_init_exception_op();
EG(lambda_count) = 0;
ZVAL_UNDEF(&EG(user_error_handler));
ZVAL_UNDEF(&EG(user_exception_handler));
EG(in_autoload) = NULL;
EG(current_execute_data) = NULL;
EG(current_module) = NULL;
EG(exit_status) = 0;
executor_globals->lambda_count = 0;
ZVAL_UNDEF(&executor_globals->user_error_handler);
ZVAL_UNDEF(&executor_globals->user_exception_handler);
executor_globals->in_autoload = NULL;
executor_globals->current_execute_data = NULL;
executor_globals->current_module = NULL;
executor_globals->exit_status = 0;
#if XPFPA_HAVE_CW
EG(saved_fpu_cw) = 0;
executor_globals->saved_fpu_cw = 0;
#endif
EG(saved_fpu_cw_ptr) = NULL;
EG(active) = 0;
executor_globals->saved_fpu_cw_ptr = NULL;
executor_globals->active = 0;
executor_globals->bailout = NULL;
executor_globals->error_handling = EH_NORMAL;
executor_globals->exception_class = NULL;
executor_globals->exception = NULL;
executor_globals->objects_store.object_buckets = NULL;
}
/* }}} */
@ -690,9 +696,8 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) /
ini_scanner_globals_ctor(&ini_scanner_globals);
php_scanner_globals_ctor(&language_scanner_globals);
zend_set_default_compile_time_values();
ZVAL_UNDEF(&EG(user_error_handler));
ZVAL_UNDEF(&EG(user_exception_handler));
#endif
EG(error_reporting) = E_ALL & ~E_NOTICE;
zend_interned_strings_init();
zend_startup_builtin_functions();
@ -921,14 +926,14 @@ ZEND_API void zend_deactivate(void) /* {{{ */
shutdown_compiler();
} zend_end_try();
zend_destroy_rsrc_list(&EG(regular_list));
#if ZEND_DEBUG
if (GC_G(gc_enabled) && !CG(unclean_shutdown)) {
gc_collect_cycles();
}
#endif
zend_destroy_rsrc_list(&EG(regular_list));
#if GC_BENCH
fprintf(stderr, "GC Statistics\n");
fprintf(stderr, "-------------\n");

View File

@ -3915,7 +3915,7 @@ ZEND_API zend_string *zend_resolve_method_name(zend_class_entry *ce, zend_functi
zend_string *name;
if (f->common.type != ZEND_USER_FUNCTION ||
*(f->op_array.refcount) < 2 ||
(f->op_array.refcount && *(f->op_array.refcount) < 2) ||
!f->common.scope ||
!f->common.scope->trait_aliases) {
return f->common.function_name;

View File

@ -890,7 +890,6 @@ static void zend_ast_export_zval(smart_str *str, zval *zv, int priority, int ind
static void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent)
{
zval *zv;
zend_ast_decl *decl;
int p, pl, pr;
const char *op;

View File

@ -1227,7 +1227,7 @@ ZEND_FUNCTION(get_class_methods)
zend_binary_strcasecmp(key->val, key->len, mptr->common.function_name->val, len) == 0) {
if (mptr->type == ZEND_USER_FUNCTION &&
*mptr->op_array.refcount > 1 &&
(!mptr->op_array.refcount || *mptr->op_array.refcount > 1) &&
!same_name(key, mptr->common.function_name)) {
ZVAL_STR_COPY(&method_name, zend_find_alias_name(mptr->common.scope, key));
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
@ -1936,7 +1936,9 @@ ZEND_FUNCTION(create_function)
zend_error(E_ERROR, "Unexpected inconsistency in create_function()");
RETURN_FALSE;
}
(*func->refcount)++;
if (func->refcount) {
(*func->refcount)++;
}
static_variables = func->static_variables;
func->static_variables = NULL;
zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1);
@ -2256,6 +2258,9 @@ ZEND_FUNCTION(debug_print_backtrace)
skip->prev_execute_data->func &&
ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
skip->prev_execute_data->opline->opcode != ZEND_DO_ICALL &&
skip->prev_execute_data->opline->opcode != ZEND_DO_UCALL &&
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
skip = skip->prev_execute_data;
}
@ -2451,6 +2456,9 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
skip->prev_execute_data->func &&
ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
skip->prev_execute_data->opline->opcode != ZEND_DO_ICALL &&
skip->prev_execute_data->opline->opcode != ZEND_DO_UCALL &&
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
skip = skip->prev_execute_data;
}

View File

@ -63,6 +63,9 @@ ZEND_METHOD(Closure, __invoke) /* {{{ */
/* destruct the function also, then - we have allocated it in get_method */
zend_string_release(func->internal_function.function_name);
efree(func);
#if ZEND_DEBUG
execute_data->func = NULL;
#endif
}
/* }}} */
@ -499,7 +502,9 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
zend_hash_apply_with_arguments(static_variables, zval_copy_static_var, 1, closure->func.op_array.static_variables);
}
closure->func.op_array.run_time_cache = NULL;
(*closure->func.op_array.refcount)++;
if (closure->func.op_array.refcount) {
(*closure->func.op_array.refcount)++;
}
} else {
/* verify that we aren't binding internal function to a wrong scope */
if(func->common.scope != NULL) {

View File

@ -52,15 +52,16 @@
static inline void zend_alloc_cache_slot(uint32_t literal) {
zend_op_array *op_array = CG(active_op_array);
Z_CACHE_SLOT(op_array->literals[literal]) = op_array->last_cache_slot++;
Z_CACHE_SLOT(op_array->literals[literal]) = op_array->cache_size;
op_array->cache_size += sizeof(void*);
}
#define POLYMORPHIC_CACHE_SLOT_SIZE 2
static inline void zend_alloc_polymorphic_cache_slot(uint32_t literal) {
zend_op_array *op_array = CG(active_op_array);
Z_CACHE_SLOT(op_array->literals[literal]) = op_array->last_cache_slot;
op_array->last_cache_slot += POLYMORPHIC_CACHE_SLOT_SIZE;
Z_CACHE_SLOT(op_array->literals[literal]) = op_array->cache_size;
op_array->cache_size += POLYMORPHIC_CACHE_SLOT_SIZE * sizeof(void*);
}
ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type);
@ -863,9 +864,13 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
if (function->type == ZEND_USER_FUNCTION) {
zend_op_array *op_array = &function->op_array;
(*op_array->refcount)++;
if (op_array->refcount) {
(*op_array->refcount)++;
}
if (op_array->static_variables) {
op_array->static_variables = zend_array_dup(op_array->static_variables);
if (!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
GC_REFCOUNT(op_array->static_variables)++;
}
}
op_array->run_time_cache = NULL;
} else if (function->type == ZEND_INTERNAL_FUNCTION) {
@ -908,7 +913,9 @@ ZEND_API int do_bind_function(const zend_op_array *op_array, const zend_op *opli
}
return FAILURE;
} else {
(*function->op_array.refcount)++;
if (function->op_array.refcount) {
(*function->op_array.refcount)++;
}
function->op_array.static_variables = NULL; /* NULL out the unbound function */
return SUCCESS;
}
@ -2310,6 +2317,50 @@ zend_bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast) /* {{{ *
}
/* }}} */
/* Detects if list($a, $b, $c) contains variable with given name */
zend_bool zend_list_has_assign_to(zend_ast *list_ast, zend_string *name) /* {{{ */
{
zend_ast_list *list = zend_ast_get_list(list_ast);
uint32_t i;
for (i = 0; i < list->children; i++) {
zend_ast *var_ast = list->child[i];
if (!var_ast) {
continue;
}
/* Recursively check nested list()s */
if (var_ast->kind == ZEND_AST_LIST && zend_list_has_assign_to(var_ast, name)) {
return 1;
}
if (var_ast->kind == ZEND_AST_VAR && var_ast->child[0]->kind == ZEND_AST_ZVAL) {
zend_string *var_name = zval_get_string(zend_ast_get_zval(var_ast->child[0]));
zend_bool result = zend_string_equals(var_name, name);
zend_string_release(var_name);
if (result) {
return 1;
}
}
}
return 0;
}
/* }}} */
/* Detects patterns like list($a, $b, $c) = $a */
zend_bool zend_list_has_assign_to_self(zend_ast *list_ast, zend_ast *expr_ast) /* {{{ */
{
/* Only check simple variables on the RHS, as only CVs cause issues with this. */
if (expr_ast->kind == ZEND_AST_VAR && expr_ast->child[0]->kind == ZEND_AST_ZVAL) {
zend_string *name = zval_get_string(zend_ast_get_zval(expr_ast->child[0]));
zend_bool result = zend_list_has_assign_to(list_ast, name);
zend_string_release(name);
return result;
}
return 0;
}
/* }}} */
void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
{
zend_ast *var_ast = ast->child[0];
@ -2359,7 +2410,13 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
zend_emit_op_data(&expr_node);
return;
case ZEND_AST_LIST:
zend_compile_expr(&expr_node, expr_ast);
if (zend_list_has_assign_to_self(var_ast, expr_ast)) {
/* list($a, $b) = $a should evaluate the right $a first */
zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0);
} else {
zend_compile_expr(&expr_node, expr_ast);
}
zend_compile_list_assign(result, var_ast, &expr_node);
return;
EMPTY_SWITCH_DEFAULT_CASE();
@ -2560,6 +2617,31 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */
}
/* }}} */
ZEND_API zend_uchar zend_get_call_op(zend_uchar init_op, zend_function *fbc) /* {{{ */
{
if (fbc) {
if (fbc->type == ZEND_INTERNAL_FUNCTION) {
if (!zend_execute_internal &&
!fbc->common.scope &&
!(fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED|ZEND_ACC_HAS_TYPE_HINTS))) {
return ZEND_DO_ICALL;
}
} else {
if (zend_execute_ex == execute_ex &&
!(fbc->common.fn_flags & ZEND_ACC_GENERATOR)) {
return ZEND_DO_UCALL;
}
}
} else if (zend_execute_ex == execute_ex &&
!zend_execute_internal &&
(init_op == ZEND_INIT_FCALL_BY_NAME ||
init_op == ZEND_INIT_NS_FCALL_BY_NAME)) {
return ZEND_DO_FCALL_BY_NAME;
}
return ZEND_DO_FCALL;
}
/* }}} */
void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc) /* {{{ */
{
zend_op *opline;
@ -2579,7 +2661,7 @@ void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *
}
call_flags = (opline->opcode == ZEND_NEW ? ZEND_CALL_CTOR : 0);
opline = zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
opline = zend_emit_op(result, zend_get_call_op(opline->opcode, fbc), NULL, NULL);
opline->op1.num = call_flags;
zend_do_extended_fcall_end();
@ -2616,16 +2698,17 @@ void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast) /
void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */
{
zend_op *opline = get_next_op(CG(active_op_array));
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
SET_UNUSED(opline->op1);
if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) {
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_func_name_literal(CG(active_op_array),
Z_STR(name_node->u.constant));
zend_alloc_cache_slot(opline->op2.constant);
} else {
opline->opcode = ZEND_INIT_DYNAMIC_CALL;
SET_NODE(opline->op2, name_node);
}
SET_UNUSED(opline->op1);
zend_compile_call_common(result, args_ast, NULL);
}
@ -3146,6 +3229,12 @@ static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_
zend_hash_init(CG(active_op_array)->static_variables, 8, NULL, ZVAL_PTR_DTOR, 0);
}
if (GC_REFCOUNT(CG(active_op_array)->static_variables) > 1) {
if (!(GC_FLAGS(CG(active_op_array)->static_variables) & IS_ARRAY_IMMUTABLE)) {
GC_REFCOUNT(CG(active_op_array)->static_variables)--;
}
CG(active_op_array)->static_variables = zend_array_dup(CG(active_op_array)->static_variables);
}
zend_hash_update(CG(active_op_array)->static_variables, Z_STR(var_node.u.constant), value);
opline = zend_emit_op(&result, by_ref ? ZEND_FETCH_W : ZEND_FETCH_R, &var_node, NULL);
@ -3846,16 +3935,26 @@ void zend_compile_declare(zend_ast *ast) /* {{{ */
ZVAL_COPY_VALUE(&CG(declarables).ticks, &value_zv);
zval_dtor(&value_zv);
} else if (zend_string_equals_literal_ci(name, "encoding")) {
uint32_t i = 0;
zend_bool valid = 0;
/* Encoding declaration was already handled during parsing. Here we
* only check that it is the first statement in the file. */
uint32_t num = CG(active_op_array)->last;
while (num > 0 &&
(CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
--num;
}
zend_ast_list *file_ast = zend_ast_get_list(CG(ast));
if (num > 0) {
/* Check to see if this declare is preceeded only by declare statements */
while (valid == 0 && i < file_ast->children) {
if (file_ast->child[i] == ast) {
valid = 1;
} else if (file_ast->child[i] == NULL) {
/* Empty statements are not allowed prior to a declare */
break;
} else if (file_ast->child[i]->kind != ZEND_AST_DECLARE) {
/* declares can only be preceeded by other declares */
break;
}
i++;
}
if (valid != 1) {
zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be "
"the very first statement in the script");
}

View File

@ -352,7 +352,7 @@ struct _zend_op_array {
int last_literal;
zval *literals;
int last_cache_slot;
int cache_size;
void **run_time_cache;
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
@ -718,6 +718,7 @@ ZEND_API zend_bool zend_is_compiling(void);
ZEND_API char *zend_make_compiled_string_description(const char *name);
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers);
uint32_t zend_get_class_fetch_type(zend_string *name);
ZEND_API zend_uchar zend_get_call_op(zend_uchar init_op, zend_function *fbc);
typedef zend_bool (*zend_auto_global_callback)(zend_string *name);
typedef struct _zend_auto_global {

View File

@ -511,22 +511,19 @@ static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *v
}
/* this should modify object only if it's empty */
static inline int make_real_object(zval **object_ptr)
static inline int make_real_object(zval *object)
{
zval *object = *object_ptr;
ZVAL_DEREF(object);
if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE)
|| (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) {
if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE)) {
/* nothing to destroy */
} else if (EXPECTED((Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) {
zval_ptr_dtor_nogc(object);
object_init(object);
zend_error(E_WARNING, "Creating default object from empty value");
} else {
return 0;
}
object_init(object);
zend_error(E_WARNING, "Creating default object from empty value");
}
*object_ptr = object;
return 1;
}
@ -933,7 +930,7 @@ static zend_always_inline void zend_assign_to_object(zval *retval, zval *object,
zend_object *zobj = Z_OBJ_P(object);
zval *property;
if (EXPECTED(prop_offset != ZEND_DYNAMIC_PROPERTY_OFFSET)) {
if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
property = OBJ_PROP(zobj, prop_offset);
if (Z_TYPE_P(property) != IS_UNDEF) {
fast_assign:
@ -1166,6 +1163,12 @@ static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_d
} else if (EXPECTED(fetch_type == ZEND_FETCH_STATIC)) {
ZEND_ASSERT(EX(func)->op_array.static_variables != NULL);
ht = EX(func)->op_array.static_variables;
if (GC_REFCOUNT(ht) > 1) {
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
GC_REFCOUNT(ht)--;
}
EX(func)->op_array.static_variables = ht = zend_array_dup(ht);
}
} else {
ZEND_ASSERT(fetch_type == ZEND_FETCH_LOCAL);
if (!EX(symbol_table)) {
@ -1572,7 +1575,7 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
zend_object *zobj = Z_OBJ_P(container);
zval *retval;
if (EXPECTED(prop_offset != ZEND_DYNAMIC_PROPERTY_OFFSET)) {
if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
retval = OBJ_PROP(zobj, prop_offset);
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
ZVAL_INDIRECT(result, retval);
@ -1688,7 +1691,6 @@ ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table) /* {{{
{
if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
zend_array_destroy(symbol_table);
efree_size(symbol_table, sizeof(zend_array));
} else {
/* clean before putting into the cache, since clean
could call dtors, which could use cached hash */
@ -1737,7 +1739,7 @@ void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
* +----------------------------------------+
*/
static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, int check_this) /* {{{ */
{
uint32_t first_extra_arg, num_args;
ZEND_ASSERT(EX(func) == (zend_function*)op_array);
@ -1793,13 +1795,14 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
} while (var != end);
}
if (op_array->this_var != (uint32_t)-1 && EXPECTED(Z_OBJ(EX(This)))) {
if (check_this && op_array->this_var != (uint32_t)-1 && EXPECTED(Z_OBJ(EX(This)))) {
ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
GC_REFCOUNT(Z_OBJ(EX(This)))++;
}
if (UNEXPECTED(!op_array->run_time_cache)) {
op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*));
op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
memset(op_array->run_time_cache, 0, op_array->cache_size);
}
EX_LOAD_RUN_TIME_CACHE(op_array);
EX_LOAD_LITERALS(op_array);
@ -1824,7 +1827,8 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu
}
if (!op_array->run_time_cache) {
op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
op_array->run_time_cache = emalloc(op_array->cache_size);
memset(op_array->run_time_cache, 0, op_array->cache_size);
}
EX_LOAD_RUN_TIME_CACHE(op_array);
EX_LOAD_LITERALS(op_array);
@ -1901,10 +1905,11 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
if (!op_array->run_time_cache) {
if (op_array->function_name) {
op_array->run_time_cache = zend_arena_calloc(&CG(arena), op_array->last_cache_slot, sizeof(void*));
op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
} else {
op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
op_array->run_time_cache = emalloc(op_array->cache_size);
}
memset(op_array->run_time_cache, 0, op_array->cache_size);
}
EX_LOAD_RUN_TIME_CACHE(op_array);
EX_LOAD_LITERALS(op_array);
@ -1958,7 +1963,7 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data
EX(symbol_table) = NULL;
i_init_func_execute_data(execute_data, op_array, return_value);
i_init_func_execute_data(execute_data, op_array, return_value, 1);
return execute_data;
}
@ -2014,7 +2019,7 @@ static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call,
static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, uint32_t passed_args, uint32_t additional_args) /* {{{ */
{
if (EXPECTED(EG(vm_stack_end) - EG(vm_stack_top) > additional_args)) {
if (EXPECTED((uint32_t)(EG(vm_stack_end) - EG(vm_stack_top)) > additional_args)) {
EG(vm_stack_top) += additional_args;
} else {
*call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args);

View File

@ -256,21 +256,25 @@ ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS);
ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table);
void zend_free_compiled_variables(zend_execute_data *execute_data);
#define CACHE_ADDR(num) \
((void**)((char*)EX_RUN_TIME_CACHE() + (num)))
#define CACHED_PTR(num) \
EX_RUN_TIME_CACHE()[(num)]
((void**)((char*)EX_RUN_TIME_CACHE() + (num)))[0]
#define CACHE_PTR(num, ptr) do { \
EX_RUN_TIME_CACHE()[(num)] = (ptr); \
((void**)((char*)EX_RUN_TIME_CACHE() + (num)))[0] = (ptr); \
} while (0)
#define CACHED_POLYMORPHIC_PTR(num, ce) \
((EX_RUN_TIME_CACHE()[(num)] == (ce)) ? \
EX_RUN_TIME_CACHE()[(num) + 1] : \
((((void**)((char*)EX_RUN_TIME_CACHE() + (num)))[0] == (void*)(ce)) ? \
((void**)((char*)EX_RUN_TIME_CACHE() + (num)))[1] : \
NULL)
#define CACHE_POLYMORPHIC_PTR(num, ce, ptr) do { \
EX_RUN_TIME_CACHE()[(num)] = (ce); \
EX_RUN_TIME_CACHE()[(num) + 1] = (ptr); \
void **slot = (void**)((char*)EX_RUN_TIME_CACHE() + (num)); \
slot[0] = (ce); \
slot[1] = (ptr); \
} while (0)
#define CACHED_PTR_EX(slot) \

View File

@ -595,8 +595,9 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas
if (Z_REFCOUNTED_P(p)) Z_SET_REFCOUNT_P(p, refcount);
} else if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
zval tmp;
SEPARATE_ZVAL_NOREF(p);
if (inline_change) {
SEPARATE_ZVAL_NOREF(p);
}
zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope);
if (inline_change) {
zend_ast_destroy_and_free(Z_ASTVAL_P(p));
@ -690,7 +691,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
EG(current_execute_data) = &dummy_execute_data;
} else if (EG(current_execute_data)->func &&
ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
EG(current_execute_data)->opline->opcode != ZEND_DO_FCALL) {
EG(current_execute_data)->opline->opcode != ZEND_DO_FCALL &&
EG(current_execute_data)->opline->opcode != ZEND_DO_ICALL &&
EG(current_execute_data)->opline->opcode != ZEND_DO_UCALL &&
EG(current_execute_data)->opline->opcode != ZEND_DO_FCALL_BY_NAME) {
/* Insert fake frame in case of include or magic calls */
dummy_execute_data = *EG(current_execute_data);
dummy_execute_data.prev_execute_data = EG(current_execute_data);

View File

@ -236,7 +236,9 @@ ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array
zend_op_array *op_array_copy = (zend_op_array*)emalloc(sizeof(zend_op_array));
*op_array_copy = *op_array;
(*op_array->refcount)++;
if (op_array->refcount) {
(*op_array->refcount)++;
}
op_array->run_time_cache = NULL;
if (op_array->static_variables) {
ALLOC_HASHTABLE(op_array_copy->static_variables);

View File

@ -1113,7 +1113,7 @@ ZEND_API void zend_array_destroy(HashTable *ht)
/* In some rare cases destructors of regular arrays may be changed */
if (UNEXPECTED(ht->pDestructor != ZVAL_PTR_DTOR)) {
zend_hash_destroy(ht);
return;
goto free_ht;
}
p = ht->arData;
@ -1122,9 +1122,7 @@ ZEND_API void zend_array_destroy(HashTable *ht)
if (ht->u.flags & HASH_FLAG_PACKED) {
do {
if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
}
i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
} while (++p != end);
} else {
do {
@ -1139,9 +1137,11 @@ ZEND_API void zend_array_destroy(HashTable *ht)
zend_hash_iterators_remove(ht);
SET_INCONSISTENT(HT_DESTROYED);
} else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
return;
goto free_ht;
}
pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
free_ht:
FREE_HASHTABLE(ht);
}
ZEND_API void zend_hash_clean(HashTable *ht)

View File

@ -934,7 +934,9 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
/* destruct the function also, then - we have allocated it in get_method */
efree_size(func, sizeof(zend_internal_function));
#if ZEND_DEBUG
execute_data->func = NULL;
#endif
}
/* }}} */
@ -1155,7 +1157,9 @@ ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{
/* destruct the function also, then - we have allocated it in get_method */
efree_size(func, sizeof(zend_internal_function));
#if ZEND_DEBUG
execute_data->func = NULL;
#endif
}
/* }}} */

View File

@ -55,7 +55,6 @@ ZEND_API void zend_object_std_dtor(zend_object *object)
if (object->properties) {
zend_array_destroy(object->properties);
FREE_HASHTABLE(object->properties);
}
count = object->ce->default_properties_count;
for (i = 0; i < count; i++) {

View File

@ -91,7 +91,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->literals = NULL;
op_array->run_time_cache = NULL;
op_array->last_cache_slot = 0;
op_array->cache_size = 0;
memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
@ -130,7 +130,8 @@ ZEND_API void zend_function_dtor(zval *zv)
ZEND_API void zend_cleanup_op_array_data(zend_op_array *op_array)
{
if (op_array->static_variables) {
if (op_array->static_variables &&
!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
zend_hash_clean(op_array->static_variables);
}
}
@ -317,16 +318,18 @@ ZEND_API void destroy_op_array(zend_op_array *op_array)
zval *end;
uint32_t i;
if (op_array->static_variables) {
zend_hash_destroy(op_array->static_variables);
FREE_HASHTABLE(op_array->static_variables);
if (op_array->static_variables &&
!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
if (--GC_REFCOUNT(op_array->static_variables) == 0) {
zend_array_destroy(op_array->static_variables);
}
}
if (op_array->run_time_cache && !op_array->function_name) {
efree(op_array->run_time_cache);
}
if (--(*op_array->refcount)>0) {
if (!op_array->refcount || --(*op_array->refcount)>0) {
return;
}

View File

@ -2870,6 +2870,38 @@ ZEND_API const char* zend_memnrstr_ex(const char *haystack, const char *needle,
}
/* }}} */
#if !ZEND_DVAL_TO_LVAL_CAST_OK
# if SIZEOF_ZEND_LONG == 4
ZEND_API zend_long zend_dval_to_lval_slow(double d)
{
double two_pow_32 = pow(2., 32.),
dmod;
dmod = fmod(d, two_pow_32);
if (dmod < 0) {
/* we're going to make this number positive; call ceil()
* to simulate rounding towards 0 of the negative number */
dmod = ceil(dmod);// + two_pow_32;
}
return (zend_long)(zend_ulong)dmod;
}
#else
ZEND_API zend_long zend_dval_to_lval_slow(double d)
{
double two_pow_64 = pow(2., 64.),
dmod;
dmod = fmod(d, two_pow_64);
if (dmod < 0) {
/* no need to call ceil; original double must have had no
* fractional part, hence dmod does not have one either */
dmod += two_pow_64;
}
return (zend_long)(zend_ulong)dmod;
}
#endif
#endif
/*
* Local variables:
* tab-width: 4

View File

@ -108,41 +108,15 @@ static zend_always_inline zend_long zend_dval_to_lval(double d)
return 0;
}
}
#elif SIZEOF_ZEND_LONG == 4
static zend_always_inline zend_long zend_dval_to_lval(double d)
{
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
return 0;
} else if (!ZEND_DOUBLE_FITS_LONG(d)) {
double two_pow_32 = pow(2., 32.),
dmod;
dmod = fmod(d, two_pow_32);
if (dmod < 0) {
/* we're going to make this number positive; call ceil()
* to simulate rounding towards 0 of the negative number */
dmod = ceil(dmod) + two_pow_32;
}
return (zend_long)(zend_ulong)dmod;
}
return (zend_long)d;
}
#else
ZEND_API zend_long zend_dval_to_lval_slow(double d);
static zend_always_inline zend_long zend_dval_to_lval(double d)
{
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
return 0;
} else if (!ZEND_DOUBLE_FITS_LONG(d)) {
double two_pow_64 = pow(2., 64.),
dmod;
dmod = fmod(d, two_pow_64);
if (dmod < 0) {
/* no need to call ceil; original double must have had no
* fractional part, hence dmod does not have one either */
dmod += two_pow_64;
}
return (zend_long)(zend_ulong)dmod;
return zend_dval_to_lval_slow(d);
}
return (zend_long)d;
}

View File

@ -345,6 +345,9 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
#define IS_STR_CONSTANT (1<<3) /* constant index */
#define IS_STR_CONSTANT_UNQUALIFIED (1<<4) /* the same as IS_CONSTANT_UNQUALIFIED */
/* array flags */
#define IS_ARRAY_IMMUTABLE (1<<1) /* the same as IS_TYPE_IMMUTABLE */
/* object flags (zval.value->gc.u.flags) */
#define IS_OBJ_APPLY_COUNT 0x07
#define IS_OBJ_DESTRUCTOR_CALLED (1<<3)

View File

@ -46,7 +46,6 @@ ZEND_API void _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC)
GC_TYPE(arr) = IS_NULL;
GC_REMOVE_FROM_BUFFER(arr);
zend_array_destroy(arr);
efree_size(arr, sizeof(zend_array));
break;
}
case IS_CONSTANT_AST: {
@ -102,7 +101,6 @@ ZEND_API void _zval_dtor_func_for_ptr(zend_refcounted *p ZEND_FILE_LINE_DC)
GC_TYPE(arr) = IS_NULL;
GC_REMOVE_FROM_BUFFER(arr);
zend_array_destroy(arr);
efree_size(arr, sizeof(zend_array));
break;
}
case IS_CONSTANT_AST: {

View File

@ -366,7 +366,8 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (UNEXPECTED(!make_real_object(&object))) {
ZVAL_DEREF(object);
if (UNEXPECTED(!make_real_object(object))) {
zend_error(E_WARNING, "Attempt to assign property of non-object");
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
@ -377,7 +378,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|
/* here we are sure we are dealing with an object */
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
ZVAL_DEREF(zptr);
SEPARATE_ZVAL_NOREF(zptr);
@ -391,7 +392,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|
zval rv;
if (Z_OBJ_HT_P(object)->read_property &&
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
zval rv;
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
@ -404,7 +405,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|
ZVAL_DEREF(z);
SEPARATE_ZVAL_NOREF(z);
binary_op(z, z, value);
Z_OBJ_HT_P(object)->write_property(object, property, z, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
Z_OBJ_HT_P(object)->write_property(object, property, z, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), z);
}
@ -765,7 +766,8 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|C
do {
if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (UNEXPECTED(!make_real_object(&object))) {
ZVAL_DEREF(object);
if (UNEXPECTED(!make_real_object(object))) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(retval);
@ -777,7 +779,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|C
/* here we are sure we are dealing with an object */
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
ZVAL_DEREF(zptr);
SEPARATE_ZVAL_NOREF(zptr);
@ -790,7 +792,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|C
zval rv;
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
zval rv;
@ -807,7 +809,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|C
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(retval, z);
}
Z_OBJ_HT_P(object)->write_property(object, property, z, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
Z_OBJ_HT_P(object)->write_property(object, property, z, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
zval_ptr_dtor(z);
} else {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
@ -854,7 +856,8 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|
do {
if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (UNEXPECTED(!make_real_object(&object))) {
ZVAL_DEREF(object);
if (UNEXPECTED(!make_real_object(object))) {
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
ZVAL_NULL(retval);
break;
@ -864,7 +867,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|
/* here we are sure we are dealing with an object */
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
ZVAL_DEREF(zptr);
ZVAL_COPY_VALUE(retval, zptr);
@ -874,7 +877,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|
} else {
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
zval rv;
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
zval z_copy;
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
@ -890,7 +893,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|
ZVAL_DUP(&z_copy, z);
incdec_op(&z_copy);
if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
zval_ptr_dtor(&z_copy);
zval_ptr_dtor(z);
} else {
@ -1131,7 +1134,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
if (OP1_TYPE == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + 1);
retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
/* check if static properties were destoyed */
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
@ -1438,9 +1441,9 @@ ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP2_TYPE == IS_CONST &&
EXPECTED(zobj->ce == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(offset) + sizeof(void*));
if (EXPECTED(prop_offset != ZEND_DYNAMIC_PROPERTY_OFFSET)) {
if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
retval = OBJ_PROP(zobj, prop_offset);
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
@ -1460,7 +1463,7 @@ ZEND_VM_C_LABEL(fetch_obj_r_no_object):
zend_error(E_NOTICE, "Trying to get property of non-object");
ZVAL_NULL(EX_VAR(opline->result.var));
} else {
retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
if (retval != EX_VAR(opline->result.var)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
@ -1489,7 +1492,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMPVAR|CV)
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
FREE_OP2();
if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@ -1513,7 +1516,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
FREE_OP2();
if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@ -1553,9 +1556,9 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP2_TYPE == IS_CONST &&
EXPECTED(zobj->ce == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(offset) + sizeof(void*));
if (EXPECTED(prop_offset != ZEND_DYNAMIC_PROPERTY_OFFSET)) {
if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
retval = OBJ_PROP(zobj, prop_offset);
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
@ -1575,7 +1578,7 @@ ZEND_VM_C_LABEL(fetch_obj_is_no_object):
ZVAL_NULL(EX_VAR(opline->result.var));
} else {
retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
if (retval != EX_VAR(opline->result.var)) {
ZVAL_COPY(EX_VAR(opline->result.var), retval);
@ -1609,7 +1612,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMPV
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
FREE_OP2();
if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@ -1635,7 +1638,7 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
FREE_OP2();
if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@ -1696,7 +1699,7 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
}
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, OP1_TYPE, property_name, OP2_TYPE, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property_name)) : NULL));
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, OP1_TYPE, property_name, OP2_TYPE, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL));
FREE_OP2();
FREE_OP1_VAR_PTR();
/* assign_obj has two opcodes! */
@ -1711,7 +1714,6 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|CV)
zend_free_op free_op1;
zval *object_ptr;
zend_free_op free_op2, free_op_data1;
zval rv;
zval *value;
zval *variable_ptr;
zval *dim;
@ -1726,12 +1728,20 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|CV)
ZEND_VM_C_LABEL(try_assign_dim):
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
ZEND_VM_C_LABEL(try_assign_dim_array):
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
zend_fetch_dimension_address_W(&rv, object_ptr, dim, OP2_TYPE);
FREE_OP2();
if (OP2_TYPE == IS_UNUSED) {
SEPARATE_ARRAY(object_ptr);
variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval));
if (UNEXPECTED(variable_ptr == NULL)) {
zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
variable_ptr = &EG(error_zval);
}
} else {
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
SEPARATE_ARRAY(object_ptr);
variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, OP2_TYPE, BP_VAR_W);
FREE_OP2();
}
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
variable_ptr = Z_INDIRECT(rv);
if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
FREE_OP(free_op_data1);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@ -1752,21 +1762,41 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
FREE_OP2();
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
zend_long offset;
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
zend_long offset;
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
FREE_OP2();
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
FREE_OP(free_op_data1);
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
FREE_OP2();
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
FREE_OP(free_op_data1);
} else {
zval_ptr_dtor_nogc(object_ptr);
ZEND_VM_C_LABEL(assign_dim_convert_to_array):
ZVAL_NEW_ARR(object_ptr);
zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
ZEND_VM_C_GOTO(try_assign_dim_array);
}
} else if (EXPECTED(Z_ISREF_P(object_ptr))) {
object_ptr = Z_REFVAL_P(object_ptr);
ZEND_VM_C_GOTO(try_assign_dim);
} else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
if (UNEXPECTED(object_ptr == &EG(error_zval))) {
ZEND_VM_C_GOTO(assign_dim_clean);
}
ZEND_VM_C_GOTO(assign_dim_convert_to_array);
} else {
ZEND_VM_C_GOTO(try_assign_dim_array);
zend_error(E_WARNING, "Cannot use a scalar value as an array");
ZEND_VM_C_LABEL(assign_dim_clean):
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
FREE_OP2();
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
FREE_OP(free_op_data1);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
}
FREE_OP1_VAR_PTR();
/* assign_dim has two opcodes! */
@ -2347,13 +2377,17 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMPVAR|UNUSED|CV, CONST|TMPVAR|CV)
if (opline->opcode == ZEND_INIT_FCALL ||
opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
opline->opcode == ZEND_INIT_DYNAMIC_CALL ||
opline->opcode == ZEND_INIT_METHOD_CALL ||
opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
opline->opcode == ZEND_INIT_USER_CALL ||
opline->opcode == ZEND_NEW
) {
nesting++;
} else if (opline->opcode == ZEND_DO_FCALL) {
} else if (opline->opcode == ZEND_DO_FCALL ||
opline->opcode == ZEND_DO_ICALL ||
opline->opcode == ZEND_DO_UCALL ||
opline->opcode == ZEND_DO_FCALL_BY_NAME) {
nesting--;
}
} while (nesting);
@ -2534,150 +2568,154 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMPVAR|CV)
ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST)
{
USE_OPLINE
zend_function *fbc;
zval *function_name, *func;
if (OP2_TYPE == IS_CONST && Z_TYPE_P(EX_CONSTANT(opline->op2)) == IS_STRING) {
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
} else {
function_name = (zval*)(EX_CONSTANT(opline->op2)+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
} else {
fbc = Z_FUNC_P(func);
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
}
}
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
fbc, opline->extended_value, NULL, NULL, EX(call));
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
fbc, opline->extended_value, NULL, NULL, EX(call));
/*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
}
/*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
} else {
zend_string *lcname;
zend_free_op free_op2;
zend_class_entry *called_scope;
zend_object *object;
ZEND_VM_HANDLER(128, ZEND_INIT_DYNAMIC_CALL, ANY, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_function *fbc;
zval *function_name, *func;
zend_string *lcname;
zend_free_op free_op2;
zend_class_entry *called_scope;
zend_object *object;
SAVE_OPLINE();
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
SAVE_OPLINE();
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
ZEND_VM_C_LABEL(try_function_name):
if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
if (Z_STRVAL_P(function_name)[0] == '\\') {
lcname = zend_string_alloc(Z_STRLEN_P(function_name) - 1, 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name) + 1, Z_STRLEN_P(function_name) - 1);
} else {
lcname = zend_string_tolower(Z_STR_P(function_name));
}
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
}
zend_string_release(lcname);
if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
if (Z_STRVAL_P(function_name)[0] == '\\') {
lcname = zend_string_alloc(Z_STRLEN_P(function_name) - 1, 0);
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name) + 1, Z_STRLEN_P(function_name) - 1);
} else {
lcname = zend_string_tolower(Z_STR_P(function_name));
}
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
}
zend_string_release(lcname);
FREE_OP2();
fbc = Z_FUNC_P(func);
called_scope = NULL;
object = NULL;
} else if (OP2_TYPE != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object) == SUCCESS) {
if (object) {
GC_REFCOUNT(object)++;
}
if (OP2_TYPE == IS_VAR && (fbc->common.fn_flags & ZEND_ACC_CLOSURE)) {
/* Delay closure destruction until its invocation */
fbc->common.prototype = (zend_function*)Z_OBJ_P(free_op2);
} else if (OP2_TYPE == IS_CV) {
FREE_OP2();
}
} else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
zval *obj;
zval *method;
obj = zend_hash_index_find(Z_ARRVAL_P(function_name), 0);
method = zend_hash_index_find(Z_ARRVAL_P(function_name), 1);
fbc = Z_FUNC_P(func);
called_scope = NULL;
if (!obj || !method) {
zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1");
}
ZVAL_DEREF(obj);
if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) {
zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
}
ZVAL_DEREF(method);
if (Z_TYPE_P(method) != IS_STRING) {
zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
}
if (Z_TYPE_P(obj) == IS_STRING) {
object = NULL;
} else if (OP2_TYPE != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object) == SUCCESS) {
if (object) {
GC_REFCOUNT(object)++;
}
if (OP2_TYPE == IS_VAR && (fbc->common.fn_flags & ZEND_ACC_CLOSURE)) {
/* Delay closure destruction until its invocation */
fbc->common.prototype = (zend_function*)Z_OBJ_P(free_op2);
} else if (OP2_TYPE == IS_CV) {
FREE_OP2();
}
} else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
zval *obj;
zval *method;
obj = zend_hash_index_find(Z_ARRVAL_P(function_name), 0);
method = zend_hash_index_find(Z_ARRVAL_P(function_name), 1);
if (!obj || !method) {
zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1");
called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0);
if (UNEXPECTED(called_scope == NULL)) {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZVAL_DEREF(obj);
if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) {
zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
if (called_scope->get_static_method) {
fbc = called_scope->get_static_method(called_scope, Z_STR_P(method));
} else {
fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL);
}
ZVAL_DEREF(method);
if (Z_TYPE_P(method) != IS_STRING) {
zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
}
if (Z_TYPE_P(obj) == IS_STRING) {
object = NULL;
called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0);
if (UNEXPECTED(called_scope == NULL)) {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
if (called_scope->get_static_method) {
fbc = called_scope->get_static_method(called_scope, Z_STR_P(method));
} else {
fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL);
}
if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
}
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
zend_error(E_STRICT,
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
zend_error(E_STRICT,
"Non-static method %s::%s() should not be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
} else {
zend_error_noreturn(
E_ERROR,
"Non-static method %s::%s() cannot be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
}
}
} else {
called_scope = Z_OBJCE_P(obj);
object = Z_OBJ_P(obj);
fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL);
if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method));
}
if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
object = NULL;
} else {
GC_REFCOUNT(object)++; /* For $this pointer */
zend_error_noreturn(
E_ERROR,
"Non-static method %s::%s() cannot be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
}
}
FREE_OP2();
} else if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(function_name) == IS_REFERENCE) {
function_name = Z_REFVAL_P(function_name);
ZEND_VM_C_GOTO(try_function_name);
} else {
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
zend_error_noreturn(E_ERROR, "Function name must be a string");
ZEND_VM_CONTINUE(); /* Never reached */
}
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
fbc, opline->extended_value, called_scope, object, EX(call));
called_scope = Z_OBJCE_P(obj);
object = Z_OBJ_P(obj);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL);
if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method));
}
if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
object = NULL;
} else {
GC_REFCOUNT(object)++; /* For $this pointer */
}
}
FREE_OP2();
} else if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(function_name) == IS_REFERENCE) {
function_name = Z_REFVAL_P(function_name);
ZEND_VM_C_GOTO(try_function_name);
} else {
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
zend_error_noreturn(E_ERROR, "Function name must be a string");
ZEND_VM_CONTINUE(); /* Never reached */
}
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
fbc, opline->extended_value, called_scope, object, EX(call));
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV)
@ -2791,6 +2829,185 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY)
{
USE_OPLINE
zend_execute_data *call = EX(call);
zend_function *fbc = call->func;
zval *ret;
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
LOAD_OPLINE();
call->called_scope = EX(called_scope);
Z_OBJ(call->This) = Z_OBJ(EX(This));
call->prev_execute_data = execute_data;
EG(current_execute_data) = call;
ret = EX_VAR(opline->result.var);
ZVAL_NULL(ret);
Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
fbc->internal_function.handler(call, ret);
ZEND_ASSERT(
!call->func ||
!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
EG(current_execute_data) = call->prev_execute_data;
zend_vm_stack_free_args(call);
zend_vm_stack_free_call_frame(call);
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(EX_VAR(opline->result.var));
}
if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL);
if (RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(EX_VAR(opline->result.var));
}
HANDLE_EXCEPTION();
}
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY)
{
USE_OPLINE
zend_execute_data *call = EX(call);
zend_function *fbc = call->func;
zval *ret;
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
LOAD_OPLINE();
EG(scope) = NULL;
ret = NULL;
call->symbol_table = NULL;
if (RETURN_VALUE_USED(opline)) {
ret = EX_VAR(opline->result.var);
ZVAL_NULL(ret);
Z_VAR_FLAGS_P(ret) = 0;
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret, 0);
ZEND_VM_ENTER();
}
ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY)
{
USE_OPLINE
zend_execute_data *call = EX(call);
zend_function *fbc = call->func;
zval *ret;
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
LOAD_OPLINE();
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
EG(scope) = NULL;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
if (RETURN_VALUE_USED(opline)) {
zend_generator_create_zval(call, &fbc->op_array, EX_VAR(opline->result.var));
} else {
zend_vm_stack_free_args(call);
}
zend_vm_stack_free_call_frame(call);
} else {
ret = NULL;
call->symbol_table = NULL;
if (RETURN_VALUE_USED(opline)) {
ret = EX_VAR(opline->result.var);
ZVAL_NULL(ret);
Z_VAR_FLAGS_P(ret) = 0;
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret, 0);
ZEND_VM_ENTER();
}
EG(scope) = EX(func)->op_array.scope;
} else {
ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
fbc->common.scope ? fbc->common.scope->name->val : "",
fbc->common.scope ? "::" : "",
fbc->common.function_name->val);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
}
call->called_scope = EX(called_scope);
Z_OBJ(call->This) = Z_OBJ(EX(This));
call->prev_execute_data = execute_data;
EG(current_execute_data) = call;
if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
uint32_t i;
uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
zval *p = ZEND_CALL_ARG(call, 1);
for (i = 0; i < num_args; ++i) {
zend_verify_internal_arg_type(fbc, i + 1, p);
p++;
}
if (UNEXPECTED(EG(exception) != NULL)) {
EG(current_execute_data) = call->prev_execute_data;
zend_vm_stack_free_args(call);
zend_vm_stack_free_call_frame(call);
zend_throw_exception_internal(NULL);
HANDLE_EXCEPTION();
}
}
ret = EX_VAR(opline->result.var);
ZVAL_NULL(ret);
Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
fbc->internal_function.handler(call, ret);
ZEND_ASSERT(
!call->func ||
!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
EG(current_execute_data) = call->prev_execute_data;
zend_vm_stack_free_args(call);
zend_vm_stack_free_call_frame(call);
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(EX_VAR(opline->result.var));
}
}
if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL);
if (RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(EX_VAR(opline->result.var));
}
HANDLE_EXCEPTION();
}
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
{
USE_OPLINE
@ -2838,7 +3055,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret);
i_init_func_execute_data(call, &fbc->op_array, ret, 1);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
@ -2849,7 +3066,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
}
} else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) {
int should_change_scope = 0;
zval *ret;
if (fbc->common.scope) {
should_change_scope = 1;
@ -4654,7 +4870,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
}
}
if (Z_OBJ_HT_P(container)->unset_property) {
Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
} else {
zend_error(E_NOTICE, "Trying to unset property of non-object");
}
@ -5316,7 +5532,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
if (OP1_TYPE == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + 1);
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
/* check if static properties were destoyed */
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
@ -5523,7 +5739,7 @@ ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|
ZEND_VM_C_LABEL(isset_no_object):
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((OP2_TYPE == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
if ((opline->extended_value & ZEND_ISSET) == 0) {
result = !result;
}
@ -5960,11 +6176,15 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
do {
switch (opline->opcode) {
case ZEND_DO_FCALL:
case ZEND_DO_ICALL:
case ZEND_DO_UCALL:
case ZEND_DO_FCALL_BY_NAME:
level++;
break;
case ZEND_INIT_FCALL:
case ZEND_INIT_FCALL_BY_NAME:
case ZEND_INIT_NS_FCALL_BY_NAME:
case ZEND_INIT_DYNAMIC_CALL:
case ZEND_INIT_USER_CALL:
case ZEND_INIT_METHOD_CALL:
case ZEND_INIT_STATIC_METHOD_CALL:
@ -6005,11 +6225,15 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
do {
switch (opline->opcode) {
case ZEND_DO_FCALL:
case ZEND_DO_ICALL:
case ZEND_DO_UCALL:
case ZEND_DO_FCALL_BY_NAME:
level++;
break;
case ZEND_INIT_FCALL:
case ZEND_INIT_FCALL_BY_NAME:
case ZEND_INIT_NS_FCALL_BY_NAME:
case ZEND_INIT_DYNAMIC_CALL:
case ZEND_INIT_USER_CALL:
case ZEND_INIT_METHOD_CALL:
case ZEND_INIT_STATIC_METHOD_CALL:
@ -6609,7 +6833,7 @@ ZEND_VM_HANDLER(122, ZEND_DEFINED, CONST, ANY)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(128, ZEND_ASSERT_CHECK, ANY, ANY)
ZEND_VM_HANDLER(137, ZEND_ASSERT_CHECK, ANY, ANY)
{
USE_OPLINE

File diff suppressed because it is too large Load Diff

View File

@ -967,7 +967,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
out($f,"#undef LOAD_OPLINE\n");
out($f,"#undef SAVE_OPLINE\n");
out($f,"#define OPLINE opline\n");
out($f,"#define DCL_OPLINE zend_op *opline;\n");
out($f,"#define DCL_OPLINE const zend_op *opline;\n");
out($f,"#define USE_OPLINE\n");
out($f,"#define LOAD_OPLINE() opline = EX(opline)\n");
out($f,"#define SAVE_OPLINE() EX(opline) = opline\n");
@ -993,7 +993,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name,
out($f,"#undef LOAD_OPLINE\n");
out($f,"#undef SAVE_OPLINE\n");
out($f,"#define OPLINE opline\n");
out($f,"#define DCL_OPLINE zend_op *opline;\n");
out($f,"#define DCL_OPLINE const zend_op *opline;\n");
out($f,"#define USE_OPLINE\n");
out($f,"#define LOAD_OPLINE() opline = EX(opline)\n");
out($f,"#define SAVE_OPLINE() EX(opline) = opline\n");

View File

@ -150,16 +150,16 @@ const char *zend_vm_opcodes_map[171] = {
"ZEND_FE_RESET_RW",
"ZEND_FE_FETCH_RW",
"ZEND_FE_FREE",
"ZEND_ASSERT_CHECK",
NULL,
NULL,
NULL,
"ZEND_INIT_DYNAMIC_CALL",
"ZEND_DO_ICALL",
"ZEND_DO_UCALL",
"ZEND_DO_FCALL_BY_NAME",
"ZEND_PRE_INC_OBJ",
"ZEND_PRE_DEC_OBJ",
"ZEND_POST_INC_OBJ",
"ZEND_POST_DEC_OBJ",
"ZEND_ASSIGN_OBJ",
NULL,
"ZEND_ASSERT_CHECK",
"ZEND_INSTANCEOF",
"ZEND_DECLARE_CLASS",
"ZEND_DECLARE_INHERITED_CLASS",

View File

@ -152,12 +152,16 @@ END_EXTERN_C()
#define ZEND_FE_RESET_RW 125
#define ZEND_FE_FETCH_RW 126
#define ZEND_FE_FREE 127
#define ZEND_ASSERT_CHECK 128
#define ZEND_INIT_DYNAMIC_CALL 128
#define ZEND_DO_ICALL 129
#define ZEND_DO_UCALL 130
#define ZEND_DO_FCALL_BY_NAME 131
#define ZEND_PRE_INC_OBJ 132
#define ZEND_PRE_DEC_OBJ 133
#define ZEND_POST_INC_OBJ 134
#define ZEND_POST_DEC_OBJ 135
#define ZEND_ASSIGN_OBJ 136
#define ZEND_ASSERT_CHECK 137
#define ZEND_INSTANCEOF 138
#define ZEND_DECLARE_CLASS 139
#define ZEND_DECLARE_INHERITED_CLASS 140

View File

@ -844,6 +844,11 @@ PHP_MINIT_FUNCTION(curl)
REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS4);
REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS5);
#if LIBCURL_VERSION_NUM >= 0x071200 /* Available since 7.18.0 */
REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS4A);
REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS5_HOSTNAME);
#endif
/* Curl Share constants */
REGISTER_CURL_CONSTANT(CURLSHOPT_NONE);
REGISTER_CURL_CONSTANT(CURLSHOPT_SHARE);
@ -1239,7 +1244,7 @@ PHP_MINIT_FUNCTION(curl)
gcry_control(GCRYCTL_SET_THREAD_CBS, &php_curl_gnutls_tsl);
#endif
if (curl_global_init(CURL_GLOBAL_SSL) != CURLE_OK) {
if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) {
return FAILURE;
}

View File

@ -809,6 +809,16 @@ PHP_RSHUTDOWN_FUNCTION(date)
#define DATE_FORMAT_ISO8601 "Y-m-d\\TH:i:sO"
/*
* RFC3339, Appendix A: http://www.ietf.org/rfc/rfc3339.txt
* ISO 8601 also requires (in section 5.3.1.3) that a decimal fraction
* be proceeded by a "0" if less than unity. Annex B.2 of ISO 8601
* gives examples where the decimal fractions are not preceded by a "0".
* This grammar assumes section 5.3.1.3 is correct and that Annex B.2 is
* in error.
*/
#define DATE_FORMAT_RFC3339_EXTENDED "Y-m-d\\TH:i:s.vP"
/*
* This comes from various sources that like to contradict. I'm going with the
* format here because of:
@ -849,12 +859,15 @@ PHP_MINIT_FUNCTION(date)
*/
REGISTER_STRING_CONSTANT("DATE_COOKIE", DATE_FORMAT_COOKIE, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("DATE_ISO8601", DATE_FORMAT_ISO8601, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("DATE_RFC822", DATE_FORMAT_RFC822, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("DATE_RFC850", DATE_FORMAT_RFC850, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("DATE_RFC1036", DATE_FORMAT_RFC1036, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("DATE_RFC1123", DATE_FORMAT_RFC1123, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("DATE_RFC2822", DATE_FORMAT_RFC2822, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("DATE_RFC3339", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("DATE_RFC3339", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("DATE_RFC3339_EXTENDED", DATE_FORMAT_RFC3339_EXTENDED, CONST_CS | CONST_PERSISTENT);
/*
* RSS 2.0 Specification: http://blogs.law.harvard.edu/tech/rss
* "All date-times in RSS conform to the Date and Time Specification of RFC 822,
@ -1145,6 +1158,7 @@ static zend_string *date_format(char *format, size_t format_len, timelib_time *t
case 'i': length = slprintf(buffer, 32, "%02d", (int) t->i); break;
case 's': length = slprintf(buffer, 32, "%02d", (int) t->s); break;
case 'u': length = slprintf(buffer, 32, "%06d", (int) floor(t->f * 1000000 + 0.5)); break;
case 'v': length = slprintf(buffer, 32, "%03d", (int) floor(t->f * 1000 + 0.5)); break;
/* timezone */
case 'I': length = slprintf(buffer, 32, "%d", localtime ? offset->is_dst : 0); break;
@ -1981,17 +1995,18 @@ static void date_register_classes(void) /* {{{ */
#define REGISTER_DATE_CLASS_CONST_STRING(const_name, value) \
zend_declare_class_constant_stringl(date_ce_date, const_name, sizeof(const_name)-1, value, sizeof(value)-1);
REGISTER_DATE_CLASS_CONST_STRING("ATOM", DATE_FORMAT_RFC3339);
REGISTER_DATE_CLASS_CONST_STRING("COOKIE", DATE_FORMAT_COOKIE);
REGISTER_DATE_CLASS_CONST_STRING("ISO8601", DATE_FORMAT_ISO8601);
REGISTER_DATE_CLASS_CONST_STRING("RFC822", DATE_FORMAT_RFC822);
REGISTER_DATE_CLASS_CONST_STRING("RFC850", DATE_FORMAT_RFC850);
REGISTER_DATE_CLASS_CONST_STRING("RFC1036", DATE_FORMAT_RFC1036);
REGISTER_DATE_CLASS_CONST_STRING("RFC1123", DATE_FORMAT_RFC1123);
REGISTER_DATE_CLASS_CONST_STRING("RFC2822", DATE_FORMAT_RFC2822);
REGISTER_DATE_CLASS_CONST_STRING("RFC3339", DATE_FORMAT_RFC3339);
REGISTER_DATE_CLASS_CONST_STRING("RSS", DATE_FORMAT_RFC1123);
REGISTER_DATE_CLASS_CONST_STRING("W3C", DATE_FORMAT_RFC3339);
REGISTER_DATE_CLASS_CONST_STRING("ATOM", DATE_FORMAT_RFC3339);
REGISTER_DATE_CLASS_CONST_STRING("COOKIE", DATE_FORMAT_COOKIE);
REGISTER_DATE_CLASS_CONST_STRING("ISO8601", DATE_FORMAT_ISO8601);
REGISTER_DATE_CLASS_CONST_STRING("RFC822", DATE_FORMAT_RFC822);
REGISTER_DATE_CLASS_CONST_STRING("RFC850", DATE_FORMAT_RFC850);
REGISTER_DATE_CLASS_CONST_STRING("RFC1036", DATE_FORMAT_RFC1036);
REGISTER_DATE_CLASS_CONST_STRING("RFC1123", DATE_FORMAT_RFC1123);
REGISTER_DATE_CLASS_CONST_STRING("RFC2822", DATE_FORMAT_RFC2822);
REGISTER_DATE_CLASS_CONST_STRING("RFC3339", DATE_FORMAT_RFC3339);
REGISTER_DATE_CLASS_CONST_STRING("RFC3339_EXTENDED", DATE_FORMAT_RFC3339_EXTENDED);
REGISTER_DATE_CLASS_CONST_STRING("RSS", DATE_FORMAT_RFC1123);
REGISTER_DATE_CLASS_CONST_STRING("W3C", DATE_FORMAT_RFC3339);
INIT_CLASS_ENTRY(ce_immutable, "DateTimeImmutable", date_funcs_immutable);
ce_immutable.create_object = date_object_new_date;

View File

@ -156,7 +156,7 @@ array(18) {
}
}
..and get names of all its class constants
array(11) {
array(12) {
["ATOM"]=>
string(13) "Y-m-d\TH:i:sP"
["COOKIE"]=>
@ -175,6 +175,8 @@ array(11) {
string(16) "D, d M Y H:i:s O"
["RFC3339"]=>
string(13) "Y-m-d\TH:i:sP"
["RFC3339_EXTENDED"]=>
string(15) "Y-m-d\TH:i:s.vP"
["RSS"]=>
string(16) "D, d M Y H:i:s O"
["W3C"]=>

View File

@ -0,0 +1,17 @@
--TEST--
Bug #69089 (Add support for RFC3339 extended to DateTime::format)
--CREDITS--
Mariano Iglesias <mariano@cricava.com>
--FILE--
<?php
date_default_timezone_set('America/Buenos_Aires');
$date = new DateTime('2009-09-28 09:45:31.918312');
var_dump($date->format(DateTime::RFC3339_EXTENDED));
var_dump($date->format('u'));
var_dump($date->format('v'));
--EXPECT--
string(29) "2009-09-28T09:45:31.918-03:00"
string(6) "918312"
string(3) "918"

View File

@ -1,11 +1,11 @@
PHP_ARG_WITH(interbase,for InterBase support,
[ --with-interbase[=DIR] Include InterBase support. DIR is the InterBase base
install directory [/usr/interbase]])
PHP_ARG_WITH(interbase,for Firebird support,
[ --with-interbase[=DIR] Include Firebird support. DIR is the Firebird base
install directory [/opt/firebird]])
if test "$PHP_INTERBASE" != "no"; then
if test "$PHP_INTERBASE" = "yes"; then
IBASE_INCDIR=/usr/interbase/include
IBASE_LIBDIR=/usr/interbase/lib
IBASE_INCDIR=/opt/firebird/include
IBASE_LIBDIR=/opt/firebird/lib
else
IBASE_INCDIR=$PHP_INTERBASE/include
IBASE_LIBDIR=$PHP_INTERBASE/$PHP_LIBDIR
@ -23,7 +23,7 @@ if test "$PHP_INTERBASE" != "no"; then
[
IBASE_LIBNAME=ib_util
], [
AC_MSG_ERROR([libgds, libib_util or libfbclient not found! Check config.log for more information.])
AC_MSG_ERROR([libfbclient, libgds or libib_util not found! Check config.log for more information.])
], [
-L$IBASE_LIBDIR
])

View File

@ -94,23 +94,24 @@ static inline void php_json_pretty_print_indent(smart_str *buf, int options) /*
/* }}} */
static inline int php_json_is_valid_double(double d) /* {{{ */
{
return !zend_isinf(d) && !zend_isnan(d);
}
/* }}} */
static inline void php_json_encode_double(smart_str *buf, double d, int options) /* {{{ */
{
if (!zend_isinf(d) && !zend_isnan(d)) {
size_t len;
char num[PHP_JSON_DOUBLE_MAX_LENGTH];
php_gcvt(d, EG(precision), '.', 'e', &num[0]);
len = strlen(num);
if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && len < PHP_JSON_DOUBLE_MAX_LENGTH - 2) {
num[len++] = '.';
num[len++] = '0';
num[len] = '\0';
}
smart_str_appendl(buf, num, len);
} else {
JSON_G(error_code) = PHP_JSON_ERROR_INF_OR_NAN;
smart_str_appendc(buf, '0');
size_t len;
char num[PHP_JSON_DOUBLE_MAX_LENGTH];
php_gcvt(d, EG(precision), '.', 'e', &num[0]);
len = strlen(num);
if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && len < PHP_JSON_DOUBLE_MAX_LENGTH - 2) {
num[len++] = '.';
num[len++] = '0';
num[len] = '\0';
}
smart_str_appendl(buf, num, len);
}
/* }}} */
@ -293,10 +294,11 @@ static void php_json_escape_string(smart_str *buf, char *s, size_t len, int opti
if ((type = is_numeric_string(s, len, &p, &d, 0)) != 0) {
if (type == IS_LONG) {
smart_str_append_long(buf, p);
} else if (type == IS_DOUBLE) {
return;
} else if (type == IS_DOUBLE && php_json_is_valid_double(d)) {
php_json_encode_double(buf, d, options);
return;
}
return;
}
}
@ -506,7 +508,12 @@ again:
break;
case IS_DOUBLE:
php_json_encode_double(buf, Z_DVAL_P(val), options);
if (php_json_is_valid_double(Z_DVAL_P(val))) {
php_json_encode_double(buf, Z_DVAL_P(val), options);
} else {
JSON_G(error_code) = PHP_JSON_ERROR_INF_OR_NAN;
smart_str_appendc(buf, '0');
}
break;
case IS_STRING:

View File

@ -0,0 +1,14 @@
--TEST--
Bug #64695 JSON_NUMERIC_CHECK has issues with strings that are numbers plus the letter e
--SKIPIF--
<?php if (!extension_loaded("json")) print "skip"; ?>
--FILE--
<?php
$t = array('test' => '123343e871700');
var_dump(json_encode($t, JSON_NUMERIC_CHECK));
echo "Done\n";
?>
--EXPECT--
string(24) "{"test":"123343e871700"}"
Done

View File

@ -9,4 +9,4 @@ declare(encoding="ISO-8859-1");
echo "ok\n";
?>
--EXPECTF--
ok
ok

View File

@ -10,4 +10,4 @@ declare(encoding="ISO-8859-15") {
}
?>
--EXPECTF--
ok
Fatal error: Encoding declaration pragma must be the very first statement in the script in %s on line %d

View File

@ -0,0 +1,16 @@
--TEST--
zend multibyte (15)
--INI--
zend.multibyte=1
--FILE--
<?php
declare(encoding="ISO-8859-15") {
echo "ok\n";
}
declare(encoding="UTF-8") {
echo "ok\n";
}
?>
--EXPECTF--
ok
ok

View File

@ -0,0 +1,14 @@
--TEST--
zend multibyte (16)
--INI--
zend.multibyte=1
--FILE--
<?php
declare(encoding="ISO-8859-15") {
echo "ok\n";
}
echo "ok\n";
?>
--EXPECTF--
ok
ok

View File

@ -1830,6 +1830,9 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
case ZEND_ASSIGN:
case ZEND_ASSIGN_REF:
case ZEND_DO_FCALL:
case ZEND_DO_ICALL:
case ZEND_DO_UCALL:
case ZEND_DO_FCALL_BY_NAME:
if (ZEND_RESULT_TYPE(opline) == IS_VAR) {
ZEND_RESULT_TYPE(opline) |= EXT_TYPE_UNUSED;
}

View File

@ -117,7 +117,7 @@ static void optimizer_literal_class_info(literal_info *info,
void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx)
{
zend_op *opline, *end;
int i, j, n, *map, cache_slots;
int i, j, n, *map, cache_size;
zval zv, *pos;
literal_info *info;
int l_null = -1;
@ -139,9 +139,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 1);
break;
case ZEND_INIT_FCALL_BY_NAME:
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 2);
}
LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 2);
break;
case ZEND_INIT_NS_FCALL_BY_NAME:
LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 3);
@ -320,7 +318,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
#endif
/* Merge equal constants */
j = 0; cache_slots = 0;
j = 0; cache_size = 0;
zend_hash_init(&hash, op_array->last_literal, NULL, NULL, 0);
map = (int*)zend_arena_alloc(&ctx->arena, op_array->last_literal * sizeof(int));
memset(map, 0, op_array->last_literal * sizeof(int));
@ -441,8 +439,8 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
info[j] = info[i];
}
if (LITERAL_NUM_SLOTS(info[i].flags)) {
Z_CACHE_SLOT(op_array->literals[j]) = cache_slots;
cache_slots += LITERAL_NUM_SLOTS(info[i].flags);
Z_CACHE_SLOT(op_array->literals[j]) = cache_size;
cache_size += LITERAL_NUM_SLOTS(info[i].flags) * sizeof(void*);
}
j++;
n = LITERAL_NUM_RELATED(info[i].flags);
@ -467,7 +465,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
}
zend_hash_destroy(&hash);
op_array->last_literal = j;
op_array->last_cache_slot = cache_slots;
op_array->cache_size = cache_size;
/* Update opcodes to use new literals table */
opline = op_array->opcodes;

View File

@ -66,6 +66,7 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
}
/* break missing intentionally */
case ZEND_NEW:
case ZEND_INIT_DYNAMIC_CALL:
case ZEND_INIT_METHOD_CALL:
case ZEND_INIT_STATIC_METHOD_CALL:
case ZEND_INIT_FCALL:
@ -74,6 +75,9 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
call++;
break;
case ZEND_DO_FCALL:
case ZEND_DO_ICALL:
case ZEND_DO_UCALL:
case ZEND_DO_FCALL_BY_NAME:
call--;
if (call_stack[call].func && call_stack[call].opline) {
zend_op *fcall = call_stack[call].opline;
@ -84,6 +88,7 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
literal_dtor(&ZEND_OP2_LITERAL(fcall));
fcall->op2.constant = fcall->op2.constant + 1;
opline->opcode = zend_get_call_op(ZEND_INIT_FCALL, call_stack[call].func);
} else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
fcall->opcode = ZEND_INIT_FCALL;
fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func);
@ -91,6 +96,7 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
literal_dtor(&op_array->literals[fcall->op2.constant]);
literal_dtor(&op_array->literals[fcall->op2.constant + 2]);
fcall->op2.constant = fcall->op2.constant + 1;
opline->opcode = zend_get_call_op(ZEND_INIT_FCALL, call_stack[call].func);
} else {
ZEND_ASSERT(0);
}

View File

@ -341,7 +341,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
}
break;
case ZEND_DO_FCALL: {
case ZEND_DO_ICALL: {
zend_op *send1_opline = opline - 1;
zend_op *send2_opline = NULL;
zend_op *init_opline = NULL;

View File

@ -129,7 +129,8 @@ void zend_optimizer_update_op1_const(zend_op_array *op_array,
case ZEND_NEW:
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline)));
Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->last_cache_slot++;
Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->cache_size;
op_array->cache_size += sizeof(void*);
zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
zend_optimizer_add_literal(op_array, val);
zend_string_hash_val(Z_STR(op_array->literals[opline->op1.constant+1]));
@ -154,7 +155,8 @@ void zend_optimizer_update_op2_const(zend_op_array *op_array,
zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
zend_string_hash_val(Z_STR(ZEND_OP2_LITERAL(opline)));
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot++;
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->cache_size;
op_array->cache_size += sizeof(void*);
return;
}
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
@ -175,7 +177,16 @@ void zend_optimizer_update_op2_const(zend_op_array *op_array,
case ZEND_ADD_INTERFACE:
case ZEND_ADD_TRAIT:
case ZEND_INSTANCEOF:
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot++;
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->cache_size;
op_array->cache_size += sizeof(void*);
zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
zend_optimizer_add_literal(op_array, val);
zend_string_hash_val(Z_STR(op_array->literals[opline->op2.constant+1]));
break;
case ZEND_INIT_DYNAMIC_CALL:
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->cache_size;
op_array->cache_size += sizeof(void*);
zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
zend_optimizer_add_literal(op_array, val);
zend_string_hash_val(Z_STR(op_array->literals[opline->op2.constant+1]));
@ -200,8 +211,8 @@ void zend_optimizer_update_op2_const(zend_op_array *op_array,
case ZEND_POST_INC_OBJ:
case ZEND_POST_DEC_OBJ:
case ZEND_ISSET_ISEMPTY_PROP_OBJ:
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot;
op_array->last_cache_slot += 2;
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->cache_size;
op_array->cache_size += 2 * sizeof(void*);
break;
case ZEND_ASSIGN_ADD:
case ZEND_ASSIGN_SUB:
@ -215,8 +226,8 @@ void zend_optimizer_update_op2_const(zend_op_array *op_array,
case ZEND_ASSIGN_BW_AND:
case ZEND_ASSIGN_BW_XOR:
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot;
op_array->last_cache_slot += 2;
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->cache_size;
op_array->cache_size += 2 * sizeof(void*);
}
break;
case ZEND_OP_DATA:
@ -309,15 +320,26 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
* and allows its reuse. The number of ZEND_CASE instructions
* usually terminated by ZEND_FREE that finally kills the value.
*/
case ZEND_FREE:
case ZEND_CASE: {
zend_op *m, *n;
int brk = op_array->last_brk_cont;
zend_bool in_switch = 0;
while (brk--) {
if (op_array->brk_cont_array[brk].start <= (opline - op_array->opcodes) &&
op_array->brk_cont_array[brk].brk > (opline - op_array->opcodes)) {
in_switch = 1;
break;
}
}
if (!in_switch) {
ZEND_ASSERT(opline->opcode == ZEND_FREE);
MAKE_NOP(opline);
zval_dtor(val);
return 1;
}
m = opline;
n = op_array->opcodes + op_array->brk_cont_array[brk].brk + 1;
while (m < n) {
@ -340,10 +362,6 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
zval_dtor(val);
return 1;
}
case ZEND_FREE:
MAKE_NOP(opline);
zval_dtor(val);
return 1;
default:
break;
}

View File

@ -1163,7 +1163,13 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr
memory_used = zend_accel_script_persist_calc(new_persistent_script, key, key_length);
/* Allocate shared memory */
#ifdef __SSE2__
/* Align to 64-byte boundary */
ZCG(mem) = zend_shared_alloc(memory_used + 64);
ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
#else
ZCG(mem) = zend_shared_alloc(memory_used);
#endif
if (!ZCG(mem)) {
zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
zend_shared_alloc_unlock();
@ -1830,6 +1836,11 @@ static void accel_activate(void)
return;
}
if (!ZCG(function_table).nTableSize) {
zend_hash_init(&ZCG(function_table), zend_hash_num_elements(CG(function_table)), NULL, ZEND_FUNCTION_DTOR, 1);
zend_accel_copy_internal_functions();
}
SHM_UNPROTECT();
/* PHP-5.4 and above return "double", but we use 1 sec precision */
ZCG(auto_globals_mask) = 0;
@ -1973,7 +1984,11 @@ static int accel_clean_non_persistent_function(zval *zv)
return ZEND_HASH_APPLY_STOP;
} else {
if (function->op_array.static_variables) {
accel_fast_hash_destroy(function->op_array.static_variables);
if (!(GC_FLAGS(function->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
if (--GC_REFCOUNT(function->op_array.static_variables) == 0) {
accel_fast_hash_destroy(function->op_array.static_variables);
}
}
function->op_array.static_variables = NULL;
}
return ZEND_HASH_APPLY_REMOVE;
@ -2025,7 +2040,11 @@ static void zend_accel_fast_shutdown(void)
break;
} else {
if (func->op_array.static_variables) {
accel_fast_hash_destroy(func->op_array.static_variables);
if (!(GC_FLAGS(func->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
if (--GC_REFCOUNT(func->op_array.static_variables) == 0) {
accel_fast_hash_destroy(func->op_array.static_variables);
}
}
}
zend_accel_fast_del_bucket(EG(function_table), _idx-1, _p);
}
@ -2043,7 +2062,11 @@ static void zend_accel_fast_shutdown(void)
ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
if (func->type == ZEND_USER_FUNCTION) {
if (func->op_array.static_variables) {
accel_fast_hash_destroy(func->op_array.static_variables);
if (!(GC_FLAGS(func->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
if (--GC_REFCOUNT(func->op_array.static_variables) == 0) {
accel_fast_hash_destroy(func->op_array.static_variables);
}
}
func->op_array.static_variables = NULL;
}
}
@ -2239,8 +2262,6 @@ static void accel_globals_ctor(zend_accel_globals *accel_globals)
ZEND_TSRMLS_CACHE_UPDATE();
#endif
memset(accel_globals, 0, sizeof(zend_accel_globals));
zend_hash_init(&accel_globals->function_table, zend_hash_num_elements(CG(function_table)), NULL, ZEND_FUNCTION_DTOR, 1);
zend_accel_copy_internal_functions();
}
static void accel_globals_internal_func_dtor(zval *zv)
@ -2250,8 +2271,10 @@ static void accel_globals_internal_func_dtor(zval *zv)
static void accel_globals_dtor(zend_accel_globals *accel_globals)
{
accel_globals->function_table.pDestructor = accel_globals_internal_func_dtor;
zend_hash_destroy(&accel_globals->function_table);
if (accel_globals->function_table.nTableSize) {
accel_globals->function_table.pDestructor = accel_globals_internal_func_dtor;
zend_hash_destroy(&accel_globals->function_table);
}
}
static int accel_startup(zend_extension *extension)
@ -2404,11 +2427,6 @@ static int accel_startup(zend_extension *extension)
zend_accel_blacklist_load(&accel_blacklist, ZCG(accel_directives.user_blacklist_filename));
}
#if 0
/* FIXME: We probably don't need it here */
zend_accel_copy_internal_functions();
#endif
return SUCCESS;
}

View File

@ -49,8 +49,17 @@ function c($b = "bad") {
}
var_dump(c());
function d() {
switch (PHP_OS) {
default: return "bad";
case PHP_OS: return "okey";
}
}
var_dump(d());
?>
--EXPECT--
string(4) "okey"
string(4) "okey"
string(4) "okey"
string(4) "okey"

View File

@ -25,10 +25,6 @@
#include "zend_persist.h"
#include "zend_shared_alloc.h"
#define ZEND_PROTECTED_REFCOUNT (1<<30)
static uint32_t zend_accel_refcount = ZEND_PROTECTED_REFCOUNT;
#if SIZEOF_SIZE_T <= SIZEOF_ZEND_LONG
/* If sizeof(void*) == sizeof(ulong) we can use zend_hash index functions */
# define accel_xlat_set(old, new) zend_hash_index_update_ptr(&ZCG(bind_hash), (zend_ulong)(zend_uintptr_t)(old), (new))
@ -55,8 +51,11 @@ static void zend_accel_destroy_zend_function(zval *zv)
if (function->type == ZEND_USER_FUNCTION) {
if (function->op_array.static_variables) {
FREE_HASHTABLE(function->op_array.static_variables);
if (!(GC_FLAGS(function->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
if (--GC_REFCOUNT(function->op_array.static_variables) == 0) {
FREE_HASHTABLE(function->op_array.static_variables);
}
}
function->op_array.static_variables = NULL;
}
}
@ -366,31 +365,11 @@ static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
}
}
/* protects reference count, creates copy of statics */
static zend_always_inline void zend_prepare_function_for_execution(zend_op_array *op_array)
{
/* protect reference count */
op_array->refcount = &zend_accel_refcount;
(*op_array->refcount) = ZEND_PROTECTED_REFCOUNT;
/* copy statics */
if (UNEXPECTED(op_array->static_variables)) {
HashTable *shared_statics = op_array->static_variables;
ALLOC_HASHTABLE(op_array->static_variables);
GC_REFCOUNT(op_array->static_variables) = 1;
GC_TYPE(op_array->static_variables) = IS_ARRAY;
zend_hash_clone_zval(op_array->static_variables, shared_statics, 0);
}
}
static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce)
{
uint idx;
Bucket *p, *q;
zend_ulong nIndex;
zend_class_entry *new_ce;
zend_function *new_prototype;
zend_op_array *new_entry;
ht->nTableSize = source->nTableSize;
@ -432,31 +411,11 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class
ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val)));
new_entry = (zend_op_array*)Z_PTR(q->val);
/* Copy constructor */
/* we use refcount to show that op_array is referenced from several places */
if (new_entry->refcount != NULL) {
accel_xlat_set(Z_PTR(p->val), new_entry);
}
zend_prepare_function_for_execution(new_entry);
if (old_ce == new_entry->scope) {
new_entry->scope = ce;
} else {
if ((new_ce = accel_xlat_get(new_entry->scope)) != NULL) {
new_entry->scope = new_ce;
} else {
zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name->val, new_entry->function_name->val);
}
}
new_entry->scope = ARENA_REALLOC(new_entry->scope);
/* update prototype */
if (new_entry->prototype) {
if ((new_prototype = accel_xlat_get(new_entry->prototype)) != NULL) {
new_entry->prototype = new_prototype;
} else {
zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s, function %s", ce->name->val, new_entry->function_name->val);
}
new_entry->prototype = ARENA_REALLOC(new_entry->prototype);
}
}
}
@ -466,7 +425,6 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla
uint idx;
Bucket *p, *q;
zend_ulong nIndex;
zend_class_entry *new_ce;
zend_property_info *prop_info;
ht->nTableSize = source->nTableSize;
@ -517,24 +475,14 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla
prop_info->doc_comment = NULL;
}
}
if (prop_info->ce == old_ce) {
prop_info->ce = ce;
} else if ((new_ce = accel_xlat_get(prop_info->ce)) != NULL) {
prop_info->ce = new_ce;
} else {
zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s, property %s", ce->name->val, prop_info->name->val);
}
prop_info->ce = ARENA_REALLOC(prop_info->ce);
}
}
#define zend_update_inherited_handler(handler) \
{ \
if (ce->handler != NULL) { \
if ((new_func = accel_xlat_get(ce->handler)) != NULL) { \
ce->handler = new_func; \
} else { \
zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME " class loading error, class %s", ce->name->val); \
} \
ce->handler = ARENA_REALLOC(ce->handler); \
} \
}
@ -543,17 +491,10 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
{
zend_class_entry *ce = *pce;
zend_class_entry *old_ce = ce;
zend_class_entry *new_ce;
zend_function *new_func;
*pce = ce = ARENA_REALLOC(old_ce);
ce->refcount = 1;
if (old_ce->refcount != 1) {
/* this class is not used as a parent for any other classes */
accel_xlat_set(old_ce, ce);
}
if (old_ce->default_properties_table) {
int i;
@ -603,11 +544,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
}
if (ce->parent) {
if ((new_ce = accel_xlat_get(ce->parent)) != NULL) {
ce->parent = new_ce;
} else {
zend_error(E_ERROR, ACCELERATOR_PRODUCT_NAME" class loading error, class %s", ce->name->val);
}
ce->parent = ARENA_REALLOC(ce->parent);
}
zend_update_inherited_handler(constructor);
@ -718,21 +655,14 @@ static void zend_accel_function_hash_copy(HashTable *target, HashTable *source)
for (idx = 0; idx < source->nNumUsed; idx++) {
p = source->arData + idx;
if (Z_TYPE(p->val) == IS_UNDEF) continue;
if (p->key) {
t = zend_hash_add(target, p->key, &p->val);
if (UNEXPECTED(t == NULL)) {
if (p->key->len > 0 && p->key->val[0] == 0) {
/* Mangled key */
t = zend_hash_update(target, p->key, &p->val);
} else {
t = zend_hash_find(target, p->key);
goto failure;
}
}
} else {
t = zend_hash_index_add(target, p->h, &p->val);
if (UNEXPECTED(t == NULL)) {
t = zend_hash_index_find(target, p->h);
ZEND_ASSERT(p->key);
t = zend_hash_add(target, p->key, &p->val);
if (UNEXPECTED(t == NULL)) {
if (p->key->len > 0 && p->key->val[0] == 0) {
/* Mangled key */
t = zend_hash_update(target, p->key, &p->val);
} else {
t = zend_hash_find(target, p->key);
goto failure;
}
}
@ -767,26 +697,18 @@ static void zend_accel_function_hash_copy_from_shm(HashTable *target, HashTable
for (idx = 0; idx < source->nNumUsed; idx++) {
p = source->arData + idx;
if (Z_TYPE(p->val) == IS_UNDEF) continue;
if (p->key) {
t = zend_hash_add(target, p->key, &p->val);
if (UNEXPECTED(t == NULL)) {
if (p->key->len > 0 && p->key->val[0] == 0) {
/* Mangled key */
t = zend_hash_update(target, p->key, &p->val);
} else {
t = zend_hash_find(target, p->key);
goto failure;
}
}
} else {
t = zend_hash_index_add(target, p->h, &p->val);
if (UNEXPECTED(t == NULL)) {
t = zend_hash_index_find(target, p->h);
ZEND_ASSERT(p->key);
t = zend_hash_add(target, p->key, &p->val);
if (UNEXPECTED(t == NULL)) {
if (p->key->len > 0 && p->key->val[0] == 0) {
/* Mangled key */
t = zend_hash_update(target, p->key, &p->val);
} else {
t = zend_hash_find(target, p->key);
goto failure;
}
}
Z_PTR_P(t) = ARENA_REALLOC(Z_PTR(p->val));
zend_prepare_function_for_execution((zend_op_array*)Z_PTR_P(t));
}
target->nInternalPointer = target->nNumOfElements ? 0 : INVALID_IDX;
return;
@ -818,24 +740,15 @@ static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, uni
for (idx = 0; idx < source->nNumUsed; idx++) {
p = source->arData + idx;
if (Z_TYPE(p->val) == IS_UNDEF) continue;
if (p->key) {
t = zend_hash_add(target, p->key, &p->val);
if (UNEXPECTED(t == NULL)) {
if (p->key->len > 0 && p->key->val[0] == 0) {
/* Mangled key - ignore and wait for runtime */
continue;
} else if (!ZCG(accel_directives).ignore_dups) {
t = zend_hash_find(target, p->key);
goto failure;
}
}
} else {
t = zend_hash_index_add(target, p->h, &p->val);
if (UNEXPECTED(t == NULL)) {
if (!ZCG(accel_directives).ignore_dups) {
t = zend_hash_index_find(target,p->h);
goto failure;
}
ZEND_ASSERT(p->key);
t = zend_hash_add(target, p->key, &p->val);
if (UNEXPECTED(t == NULL)) {
if (p->key->len > 0 && p->key->val[0] == 0) {
/* Mangled key - ignore and wait for runtime */
continue;
} else if (!ZCG(accel_directives).ignore_dups) {
t = zend_hash_find(target, p->key);
goto failure;
}
}
if (pCopyConstructor) {
@ -853,6 +766,34 @@ failure:
zend_error(E_ERROR, "Cannot redeclare class %s", ce1->name->val);
}
#ifdef __SSE2__
#include <mmintrin.h>
#include <emmintrin.h>
static zend_always_inline void fast_memcpy(void *dest, const void *src, size_t size)
{
__m128i *dqdest = (__m128i*)dest;
const __m128i *dqsrc = (const __m128i*)src;
const __m128i *end = (const __m128i*)((const char*)src + size);
do {
_mm_prefetch(dqsrc + 4, _MM_HINT_NTA);
_mm_prefetch(dqsrc + 6, _MM_HINT_NTA);
__m128i xmm0 = _mm_load_si128(dqsrc + 0);
__m128i xmm1 = _mm_load_si128(dqsrc + 1);
__m128i xmm2 = _mm_load_si128(dqsrc + 2);
__m128i xmm3 = _mm_load_si128(dqsrc + 3);
dqsrc += 4;
_mm_stream_si128(dqdest + 0, xmm0);
_mm_stream_si128(dqdest + 1, xmm1);
_mm_stream_si128(dqdest + 2, xmm2);
_mm_stream_si128(dqdest + 3, xmm3);
dqdest += 4;
} while (dqsrc != end);
}
#endif
zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory)
{
zend_op_array *op_array;
@ -866,8 +807,15 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script,
ZCG(current_persistent_script) = persistent_script;
ZCG(arena_mem) = NULL;
if (EXPECTED(persistent_script->arena_size)) {
#ifdef __SSE2__
/* Target address must be aligned to 64-byte boundary */
ZCG(arena_mem) = zend_arena_alloc(&CG(arena), persistent_script->arena_size + 64);
ZCG(arena_mem) = (void*)(((zend_uintptr_t)ZCG(arena_mem) + 63L) & ~63L);
fast_memcpy(ZCG(arena_mem), persistent_script->arena_mem, persistent_script->arena_size);
#else
ZCG(arena_mem) = zend_arena_alloc(&CG(arena), persistent_script->arena_size);
memcpy(ZCG(arena_mem), persistent_script->arena_mem, persistent_script->arena_size);
#endif
}
/* Copy all the necessary stuff from shared memory to regular memory, and protect the shared script */
@ -880,8 +828,6 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script,
zend_accel_function_hash_copy_from_shm(CG(function_table), &persistent_script->function_table);
}
zend_prepare_function_for_execution(op_array);
/* Register __COMPILER_HALT_OFFSET__ constant */
if (persistent_script->compiler_halt_offset != 0 &&
persistent_script->full_path) {

View File

@ -204,6 +204,7 @@ static void zend_persist_zval(zval *z)
/* make immutable array */
Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE;
Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
}
}
@ -229,6 +230,63 @@ static void zend_persist_zval(zval *z)
}
}
static void zend_persist_zval_static(zval *z)
{
zend_uchar flags;
void *new_ptr;
switch (Z_TYPE_P(z)) {
case IS_STRING:
case IS_CONSTANT:
flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
zend_accel_store_interned_string(Z_STR_P(z));
Z_GC_FLAGS_P(z) |= flags;
Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
break;
case IS_ARRAY:
new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
if (new_ptr) {
Z_ARR_P(z) = new_ptr;
Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
} else {
if (Z_IMMUTABLE_P(z)) {
Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array));
zend_hash_persist_immutable(Z_ARRVAL_P(z));
} else {
GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
/* make immutable array */
Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE;
Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
}
}
break;
case IS_REFERENCE:
new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z));
if (new_ptr) {
Z_REF_P(z) = new_ptr;
} else {
zend_accel_store(Z_REF_P(z), sizeof(zend_reference));
zend_persist_zval(Z_REFVAL_P(z));
}
break;
case IS_CONSTANT_AST:
new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
if (new_ptr) {
Z_AST_P(z) = new_ptr;
} else {
zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_IMMUTABLE;
GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
}
break;
}
}
static void zend_persist_zval_const(zval *z)
{
zend_uchar flags;
@ -258,6 +316,7 @@ static void zend_persist_zval_const(zval *z)
/* make immutable array */
Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE;
Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
}
}
@ -293,7 +352,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
return;
}
if (--(*op_array->refcount) == 0) {
if (op_array->refcount && --(*op_array->refcount) == 0) {
efree(op_array->refcount);
}
op_array->refcount = NULL;
@ -313,8 +372,18 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
}
if (op_array->static_variables) {
zend_hash_persist(op_array->static_variables, zend_persist_zval);
zend_accel_store(op_array->static_variables, sizeof(HashTable));
HashTable *stored = zend_shared_alloc_get_xlat_entry(op_array->static_variables);
if (stored) {
op_array->static_variables = stored;
} else {
zend_hash_persist(op_array->static_variables, zend_persist_zval_static);
zend_accel_store(op_array->static_variables, sizeof(HashTable));
/* make immutable array */
GC_REFCOUNT(op_array->static_variables) = 2;
GC_TYPE_INFO(op_array->static_variables) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << 8);
op_array->static_variables->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
}
}
if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) {
@ -495,8 +564,6 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
if (op_array->scope && op_array->prototype) {
if ((persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->prototype))) {
op_array->prototype = (union _zend_function*)persist_ptr;
/* we use refcount to show that op_array is referenced from several places */
op_array->prototype->op_array.refcount++;
}
} else {
op_array->prototype = NULL;
@ -661,63 +728,47 @@ static int zend_update_parent_ce(zval *zv)
if (ce->parent) {
ce->parent = zend_shared_alloc_get_xlat_entry(ce->parent);
/* We use refcount to show if the class is used as a parent */
ce->parent->refcount++;
}
/* update methods */
if (ce->constructor) {
ce->constructor = zend_shared_alloc_get_xlat_entry(ce->constructor);
/* we use refcount to show that op_array is referenced from several places */
ce->constructor->op_array.refcount++;
}
if (ce->destructor) {
ce->destructor = zend_shared_alloc_get_xlat_entry(ce->destructor);
ce->destructor->op_array.refcount++;
}
if (ce->clone) {
ce->clone = zend_shared_alloc_get_xlat_entry(ce->clone);
ce->clone->op_array.refcount++;
}
if (ce->__get) {
ce->__get = zend_shared_alloc_get_xlat_entry(ce->__get);
ce->__get->op_array.refcount++;
}
if (ce->__set) {
ce->__set = zend_shared_alloc_get_xlat_entry(ce->__set);
ce->__set->op_array.refcount++;
}
if (ce->__call) {
ce->__call = zend_shared_alloc_get_xlat_entry(ce->__call);
ce->__call->op_array.refcount++;
}
if (ce->serialize_func) {
ce->serialize_func = zend_shared_alloc_get_xlat_entry(ce->serialize_func);
ce->serialize_func->op_array.refcount++;
}
if (ce->unserialize_func) {
ce->unserialize_func = zend_shared_alloc_get_xlat_entry(ce->unserialize_func);
ce->unserialize_func->op_array.refcount++;
}
if (ce->__isset) {
ce->__isset = zend_shared_alloc_get_xlat_entry(ce->__isset);
ce->__isset->op_array.refcount++;
}
if (ce->__unset) {
ce->__unset = zend_shared_alloc_get_xlat_entry(ce->__unset);
ce->__unset->op_array.refcount++;
}
if (ce->__tostring) {
ce->__tostring = zend_shared_alloc_get_xlat_entry(ce->__tostring);
ce->__tostring->op_array.refcount++;
}
if (ce->__callstatic) {
ce->__callstatic = zend_shared_alloc_get_xlat_entry(ce->__callstatic);
ce->__callstatic->op_array.refcount++;
}
if (ce->__debugInfo) {
ce->__debugInfo = zend_shared_alloc_get_xlat_entry(ce->__debugInfo);
ce->__debugInfo->op_array.refcount++;
}
zend_hash_apply(&ce->properties_info, (apply_func_t) zend_update_property_info_ce);
return 0;
@ -739,6 +790,11 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
*key = zend_accel_memdup(*key, key_length + 1);
zend_accel_store_string(script->full_path);
#ifdef __SSE2__
/* Align to 64-byte boundary */
ZCG(mem) = (void*)(((zend_uintptr_t)ZCG(mem) + 63L) & ~63L);
#endif
script->arena_mem = ZCG(arena_mem) = ZCG(mem);
ZCG(mem) = (void*)((char*)ZCG(mem) + script->arena_size);

View File

@ -150,8 +150,13 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array)
}
if (op_array->static_variables) {
ADD_DUP_SIZE(op_array->static_variables, sizeof(HashTable));
zend_hash_persist_calc(op_array->static_variables, zend_persist_zval_calc);
if (!zend_shared_alloc_get_xlat_entry(op_array->static_variables)) {
HashTable *old = op_array->static_variables;
ADD_DUP_SIZE(op_array->static_variables, sizeof(HashTable));
zend_hash_persist_calc(op_array->static_variables, zend_persist_zval_calc);
zend_shared_alloc_register_xlat_entry(old, op_array->static_variables);
}
}
if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) {
@ -356,10 +361,20 @@ uint zend_accel_script_persist_calc(zend_persistent_script *new_persistent_scrip
ADD_DUP_SIZE(key, key_length + 1);
ADD_STRING(new_persistent_script->full_path);
#ifdef __SSE2__
/* Align size to 64-byte boundary */
new_persistent_script->size = (new_persistent_script->size + 63) & ~63;
#endif
zend_accel_persist_class_table_calc(&new_persistent_script->class_table);
zend_hash_persist_calc(&new_persistent_script->function_table, zend_persist_op_array_calc);
zend_persist_op_array_calc_ex(&new_persistent_script->main_op_array);
#ifdef __SSE2__
/* Align size to 64-byte boundary */
new_persistent_script->arena_size = (new_persistent_script->arena_size + 63) & ~63;
#endif
new_persistent_script->size += new_persistent_script->arena_size;
ZCG(current_persistent_script) = NULL;

View File

@ -91,7 +91,7 @@ typedef struct _handler_entry {
typedef struct _zend_shared_memory_state {
int *positions; /* current positions for each segment */
int shared_free; /* amount of free shared memory */
size_t shared_free; /* amount of free shared memory */
} zend_shared_memory_state;
typedef struct _zend_smm_shared_globals {

View File

@ -1852,6 +1852,12 @@ ZEND_METHOD(reflection_function, getStaticVariables)
/* Return an empty array in case no static variables exist */
array_init(return_value);
if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) {
if (GC_REFCOUNT(fptr->op_array.static_variables) > 1) {
if (!(GC_FLAGS(fptr->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
GC_REFCOUNT(fptr->op_array.static_variables)--;
}
fptr->op_array.static_variables = zend_array_dup(fptr->op_array.static_variables);
}
zend_hash_apply_with_argument(fptr->op_array.static_variables, (apply_func_arg_t) zval_update_constant_inline_change, fptr->common.scope);
zend_hash_copy(Z_ARRVAL_P(return_value), fptr->op_array.static_variables, zval_add_ref);
}

View File

@ -192,18 +192,21 @@ static inline void spl_filesystem_object_get_file_name(spl_filesystem_object *in
{
char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
if (!intern->file_name) {
switch (intern->type) {
switch (intern->type) {
case SPL_FS_INFO:
case SPL_FS_FILE:
php_error_docref(NULL, E_ERROR, "Object not initialized");
if (!intern->file_name) {
php_error_docref(NULL, E_ERROR, "Object not initialized");
}
break;
case SPL_FS_DIR:
if (intern->file_name) {
efree(intern->file_name);
}
intern->file_name_len = (int)spprintf(&intern->file_name, 0, "%s%c%s",
spl_filesystem_object_get_path(intern, NULL),
slash, intern->u.dir.entry.d_name);
break;
}
}
} /* }}} */

View File

@ -770,6 +770,7 @@ SPL_METHOD(SplObjectStorage, serialize)
/* members */
smart_str_appendl(&buf, "m:", 2);
ZVAL_ARR(&members, zend_array_dup(zend_std_get_properties(getThis())));
zend_hash_str_del(Z_ARRVAL(members), "\x00gcdata", sizeof("\x00gcdata") - 1);
php_var_serialize(&buf, &members, &var_hash); /* finishes the string */
zval_ptr_dtor(&members);

View File

@ -0,0 +1,42 @@
--TEST--
Bug #68557 (SplFileInfo::getPathname() may be broken)
--FILE--
<?php
mkdir(__DIR__ . DIRECTORY_SEPARATOR . 'tmp');
touch(__DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'a');
touch(__DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'b');
$d = new DirectoryIterator(__DIR__ . DIRECTORY_SEPARATOR . 'tmp');
$d->seek(0);
$path0 = $d->current()->getPathname();
$d->seek(1);
$path1 = $d->current()->getPathname();
$d->seek(2);
$path2 = $d->current()->getPathname();
$d->seek(0);
var_dump($path0 === $d->current()->getPathname());
$d->seek(1);
var_dump($path1 === $d->current()->getPathname());
$d->seek(2);
var_dump($path2 === $d->current()->getPathname());
$d->seek(0);
var_dump($path0 === $d->current()->getPathname());
?>
--CLEAN--
<?php
unlink(__DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'a');
unlink(__DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'b');
rmdir(__DIR__ . DIRECTORY_SEPARATOR . 'tmp');
?>
--EXPECTF--
bool(true)
bool(true)
bool(true)
bool(true)

View File

@ -0,0 +1,22 @@
--TEST--
Bug #69108 ("Segmentation fault" when (de)serializing SplObjectStorage)
--INI--
zend.enable_gc=1
--FILE--
<?php
$a = array();
$b = new SplObjectStorage();
for ($i = 10000; $i > 0; $i--) {
$object = new StdClass();
$a[] = $object;
$b->attach($object);
}
$c = serialize(array($a, $b));
$d = unserialize($c);
unset($d);
echo "ok";
?>
--EXPECT--
ok

View File

@ -925,12 +925,12 @@ PHP_FUNCTION(current)
zval *entry;
#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "H", &array) == FAILURE) {
return;
}
#else
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
Z_PARAM_ARRAY_OR_OBJECT_HT(array)
ZEND_PARSE_PARAMETERS_END();
#endif
@ -953,12 +953,12 @@ PHP_FUNCTION(key)
HashTable *array;
#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "H", &array) == FAILURE) {
return;
}
#else
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
Z_PARAM_ARRAY_OR_OBJECT_HT(array)
ZEND_PARSE_PARAMETERS_END();
#endif

View File

@ -289,11 +289,11 @@ ZEND_BEGIN_ARG_INFO(arginfo_reset, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_current, 0)
ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, arg)
ZEND_ARG_INFO(0, arg)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_key, 0)
ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, arg)
ZEND_ARG_INFO(0, arg)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_min, 0, 0, 1)

View File

@ -311,8 +311,7 @@ PHP_MINIT_FUNCTION(browscap) /* {{{ */
char *browscap = INI_STR("browscap");
#ifdef ZTS
ts_allocate_id(&browscap_globals_id, sizeof(browser_data),
(ts_allocate_ctor) browscap_globals_ctor, NULL);
ts_allocate_id(&browscap_globals_id, sizeof(browser_data), (ts_allocate_ctor) browscap_globals_ctor, NULL);
#endif
/* ctor call not really needed for non-ZTS */

View File

@ -359,11 +359,7 @@ PHP_FUNCTION(flock)
/* flock_values contains all possible actions if (operation & 4) we won't block on the lock */
act = flock_values[act - 1] | (operation & PHP_LOCK_NB ? LOCK_NB : 0);
if (php_stream_lock(stream, act)) {
#ifdef PHP_WIN32
if (operation && errno == ERROR_INVALID_BLOCK && wouldblock) {
#else
if (operation && errno == EWOULDBLOCK && wouldblock) {
#endif
ZVAL_LONG(wouldblock, 1);
}
RETURN_FALSE;

View File

@ -125,8 +125,12 @@ PHPAPI int php_flock(int fd, int operation)
DWORD low = 1, high = 0;
OVERLAPPED offset =
{0, 0, 0, 0, NULL};
if (hdl < 0)
DWORD err;
if (hdl < 0) {
_set_errno(EBADF);
return -1; /* error in file descriptor */
}
/* bug for bug compatible with Unix */
UnlockFileEx(hdl, 0, low, high, &offset);
switch (operation & ~LOCK_NB) { /* translate to LockFileEx() op */
@ -146,12 +150,14 @@ PHPAPI int php_flock(int fd, int operation)
default: /* default */
break;
}
/* Under Win32 MT library, errno is not a variable but a function call,
* which cannot be assigned to.
*/
#if !defined(PHP_WIN32)
errno = EINVAL; /* bad call */
#endif
err = GetLastError();
if (ERROR_LOCK_VIOLATION == err || ERROR_SHARING_VIOLATION == err) {
_set_errno(EWOULDBLOCK);
} else {
_set_errno(EINVAL); /* bad call */
}
return -1;
}
/* }}} */

View File

@ -459,9 +459,13 @@ array(5) {
-- Testing variation: when array is unset --
Notice: Undefined variable: unset_array in %s on line %d
Warning: current() expects parameter 1 to be array, null given in %s on line %d
NULL
Notice: Undefined variable: unset_array in %s on line %d
Warning: key() expects parameter 1 to be array, null given in %s on line %d
NULL

View File

@ -1919,8 +1919,6 @@ static size_t php_output_wrapper(const char *str, size_t str_length)
static void core_globals_ctor(php_core_globals *core_globals)
{
memset(core_globals, 0, sizeof(*core_globals));
php_startup_ticks();
}
/* }}} */
#endif
@ -2034,11 +2032,6 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
int retval = SUCCESS, module_number=0; /* for REGISTER_INI_ENTRIES() */
char *php_os;
zend_module_entry *module;
#ifdef ZTS
zend_executor_globals *executor_globals;
void ***tsrm_ls;
php_core_globals *core_globals;
#endif
#if defined(PHP_WIN32) || (defined(NETWARE) && defined(USE_WINSOCK))
WORD wVersionRequested = MAKEWORD(2, 0);
@ -2057,11 +2050,11 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
_CrtSetReportMode(_CRT_ASSERT, 0);
#endif
#else
php_os=PHP_OS;
php_os = PHP_OS;
#endif
#ifdef ZTS
tsrm_ls = ts_resource(0);
(void)ts_resource(0);
#endif
#ifdef PHP_WIN32
@ -2081,6 +2074,17 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
php_output_startup();
#ifdef ZTS
ts_allocate_id(&core_globals_id, sizeof(php_core_globals), (ts_allocate_ctor) core_globals_ctor, (ts_allocate_dtor) core_globals_dtor);
php_startup_ticks();
#ifdef PHP_WIN32
ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor) php_win32_core_globals_ctor, (ts_allocate_dtor) php_win32_core_globals_dtor);
#endif
#else
php_startup_ticks();
#endif
gc_globals_ctor();
zuf.error_function = php_error_cb;
zuf.printf_function = php_printf;
zuf.write_function = php_output_wrapper;
@ -2098,18 +2102,6 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
zuf.resolve_path_function = php_resolve_path_for_zend;
zend_startup(&zuf, NULL);
#ifdef ZTS
executor_globals = ts_resource(executor_globals_id);
ts_allocate_id(&core_globals_id, sizeof(php_core_globals), (ts_allocate_ctor) core_globals_ctor, (ts_allocate_dtor) core_globals_dtor);
core_globals = ts_resource(core_globals_id);
#ifdef PHP_WIN32
ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor) php_win32_core_globals_ctor, (ts_allocate_dtor) php_win32_core_globals_dtor);
#endif
#else
php_startup_ticks();
#endif
gc_globals_ctor();
#ifdef PHP_WIN32
{
OSVERSIONINFOEX *osvi = &EG(windows_version_info);
@ -2122,24 +2114,6 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
}
}
#endif
EG(bailout) = NULL;
EG(error_reporting) = E_ALL & ~E_NOTICE;
PG(header_is_being_sent) = 0;
SG(request_info).headers_only = 0;
SG(request_info).argv0 = NULL;
SG(request_info).argc=0;
SG(request_info).argv=(char **)NULL;
PG(connection_status) = PHP_CONNECTION_NORMAL;
PG(during_request_startup) = 0;
PG(last_error_message) = NULL;
PG(last_error_file) = NULL;
PG(last_error_lineno) = 0;
EG(error_handling) = EH_NORMAL;
EG(exception_class) = NULL;
PG(disable_functions) = NULL;
PG(disable_classes) = NULL;
EG(exception) = NULL;
EG(objects_store).object_buckets = NULL;
#if HAVE_SETLOCALE
setlocale(LC_CTYPE, "");

View File

@ -180,6 +180,7 @@ PHPAPI void php_output_deactivate(void)
php_output_handler **handler = NULL;
if ((OG(flags) & PHP_OUTPUT_ACTIVATED)) {
php_output_header();
OG(flags) ^= PHP_OUTPUT_ACTIVATED;
OG(active) = NULL;

View File

@ -1390,10 +1390,12 @@ char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
if ( !off )
return NULL;
if ( *(pReq->m_pHttpHeader + off +
pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
*( pReq->m_pHttpHeader + off +
pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
if ( *(pReq->m_pHttpHeader + off
+ pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
{
*( pReq->m_pHttpHeader + off
+ pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
}
return pReq->m_pHttpHeader + off;
}
@ -1830,12 +1832,21 @@ ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t le
static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
{
int i;
char * pValue;
for( i = 0; i < H_TRANSFER_ENCODING; ++i )
{
if ( pReq->m_pHeaderIndex->m_headerOff[i] )
{
if ( strcmp( name, CGI_HEADERS[i] ) == 0 )
return pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
{
pValue = pReq->m_pHttpHeader
+ pReq->m_pHeaderIndex->m_headerOff[i];
if ( *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) != '\0')
{
*(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) = '\0';
}
return pValue;
}
}
}
if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
@ -1862,7 +1873,15 @@ static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
++p; ++pKey;
}
if (( pKey == pKeyEnd )&& (!*p ))
return pReq->m_pHttpHeader + pCur->valueOff;
{
pValue = pReq->m_pHttpHeader + pCur->valueOff;
if ( *(pValue + pCur->valueLen) != '\0')
{
*(pValue + pCur->valueLen) = '\0';
}
return pValue;
}
++pCur;
}
}

View File

@ -1454,7 +1454,10 @@ next:
PHPDBG_G(last_line) = execute_data->opline->lineno;
/* stupid hack to make zend_do_fcall_common_helper return ZEND_VM_ENTER() instead of recursively calling zend_execute() and eventually segfaulting */
if (execute_data->opline->opcode == ZEND_DO_FCALL && execute_data->func->type == ZEND_USER_FUNCTION) {
if ((execute_data->opline->opcode == ZEND_DO_FCALL ||
execute_data->opline->opcode == ZEND_DO_UCALL ||
execute_data->opline->opcode == ZEND_DO_FCALL_BY_NAME) &&
execute_data->func->type == ZEND_USER_FUNCTION) {
zend_execute_ex = execute_ex;
}
PHPDBG_G(vmret) = execute_data->opline->handler(execute_data);

View File

@ -1,5 +0,0 @@
@if exist ..\ZendEngine2\OBJECTS2_HOWTO (
move ..\Zend ..\ZendEngine1
move ..\ZendEngine2 ..\Zend
echo "PLEASE RESTART VISUAL C++ TO RELOAD THE ZEND PROJECT."
exit 1 )

View File

@ -1,84 +0,0 @@
/*
* Program: Unix compatibility routines
*
* Author: Mark Crispin
* Networks and Distributed Computing
* Computing & Communications
* University of Washington
* Administration Building, AG-44
* Seattle, WA 98195
* Internet: MRC@CAC.Washington.EDU
*
* Date: 14 September 1996
* Last Edited: 14 August 1997
*
* Copyright 1997 by the University of Washington
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appears in all copies and that both the
* above copyright notice and this permission notice appear in supporting
* documentation, and that the name of the University of Washington not be
* used in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. This software is made available
* "as is", and
* THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
* WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
* NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
/* DEDICATION
* This file is dedicated to my dog, Unix, also known as Yun-chan and
* Unix J. Terwilliker Jehosophat Aloysius Monstrosity Animal Beast. Unix
* passed away at the age of 11 1/2 on September 14, 1996, 12:18 PM PDT, after
* a two-month bout with cirrhosis of the liver.
*
* He was a dear friend, and I miss him terribly.
*
* Lift a leg, Yunie. Luv ya forever!!!!
*/
#include "php.h"
#include <windows.h>
#include <io.h>
#include <errno.h>
#include "flock.h"
PHPAPI int flock(int fd, int op)
{
HANDLE hdl = (HANDLE) _get_osfhandle(fd);
DWORD low = 1, high = 0;
OVERLAPPED offset =
{0, 0, 0, 0, NULL};
if (hdl < 0)
return -1; /* error in file descriptor */
/* bug for bug compatible with Unix */
UnlockFileEx(hdl, 0, low, high, &offset);
switch (op & ~LOCK_NB) { /* translate to LockFileEx() op */
case LOCK_EX: /* exclusive */
if (LockFileEx(hdl, LOCKFILE_EXCLUSIVE_LOCK +
((op & LOCK_NB) ? LOCKFILE_FAIL_IMMEDIATELY : 0),
0, low, high, &offset))
return 0;
break;
case LOCK_SH: /* shared */
if (LockFileEx(hdl, ((op & LOCK_NB) ? LOCKFILE_FAIL_IMMEDIATELY : 0),
0, low, high, &offset))
return 0;
break;
case LOCK_UN: /* unlock */
return 0; /* always succeeds */
default: /* default */
break;
}
errno = EINVAL; /* bad call */
return -1;
}

View File

@ -1,11 +0,0 @@
#define fsync _commit
#define ftruncate chsize
/* For flock() emulation */
#define LOCK_SH 1
#define LOCK_EX 2
#define LOCK_NB 4
#define LOCK_UN 8
PHPAPI int flock(int fd, int op);