/** * Executes the validation * * @param string $value * @return boolean */ PHP_METHOD(Phalcon_Validation_Validator_Json, valid){ zval *value, assoc = {}, valid = {}, json = {}, *constant, ret = {}, option = {}, keys = {}; phalcon_fetch_params(0, 1, 0, &value); ZVAL_TRUE(&valid); ZVAL_TRUE(&assoc); PHALCON_CALL_FUNCTIONW(&json, "json_decode", value, &assoc); if (Z_TYPE(json) == IS_NULL) { if ((constant = zend_get_constant_str(SL("JSON_ERROR_NONE"))) != NULL) { PHALCON_CALL_FUNCTIONW(&ret, "json_last_error"); if (!PHALCON_IS_EQUAL(&ret, constant)) { ZVAL_FALSE(&valid); } } } if (!zend_is_true(&valid)) { RETURN_FALSE; } ZVAL_STRING(&option, "keys"); PHALCON_CALL_METHODW(&keys, getThis(), "getoption", &option); if (Z_TYPE(keys) != IS_NULL) { PHALCON_CALL_FUNCTIONW(&ret, "array_key_exists", &keys, &json); if (!zend_is_true(&ret)) { RETURN_FALSE; } } RETURN_TRUE; }
ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, zend_ulong flags) { zend_constant *c; const char *colon; zend_class_entry *ce = NULL; zend_string *class_name; const char *name = cname->val; size_t name_len = cname->len; /* Skip leading \\ */ if (name[0] == '\\') { name += 1; name_len -= 1; cname = NULL; } if ((colon = zend_memrchr(name, ':', name_len)) && colon > name && (*(colon - 1) == ':')) { int class_name_len = colon - name - 1; size_t const_name_len = name_len - class_name_len - 2; zend_string *constant_name = zend_string_init(colon + 1, const_name_len, 0); char *lcname; zval *ret_constant = NULL; ALLOCA_FLAG(use_heap) class_name = zend_string_init(name, class_name_len, 0); lcname = do_alloca(class_name_len + 1, use_heap); zend_str_tolower_copy(lcname, name, class_name_len); if (!scope) { if (EG(current_execute_data)) { scope = EG(scope); } else { scope = CG(active_class_entry); } } if (class_name_len == sizeof("self")-1 && !memcmp(lcname, "self", sizeof("self")-1)) { if (UNEXPECTED(!scope)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot access self:: when no class scope is active"); return NULL; } ce = scope; } else if (class_name_len == sizeof("parent")-1 && !memcmp(lcname, "parent", sizeof("parent")-1)) { if (UNEXPECTED(!scope)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot access parent:: when no class scope is active"); return NULL; } else if (UNEXPECTED(!scope->parent)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot access parent:: when current class scope has no parent"); return NULL; } else { ce = scope->parent; } } else if (class_name_len == sizeof("static")-1 && !memcmp(lcname, "static", sizeof("static")-1)) { ce = zend_get_called_scope(EG(current_execute_data)); if (UNEXPECTED(!ce)) { zend_error(E_EXCEPTION | E_ERROR, "Cannot access static:: when no class scope is active"); return NULL; } } else { ce = zend_fetch_class(class_name, flags); } free_alloca(lcname, use_heap); if (ce) { ret_constant = zend_hash_find(&ce->constants_table, constant_name); if (ret_constant == NULL) { if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) { zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s::%s'", class_name->val, constant_name->val); zend_string_release(class_name); zend_string_free(constant_name); return NULL; } } else if (Z_ISREF_P(ret_constant)) { ret_constant = Z_REFVAL_P(ret_constant); } } zend_string_release(class_name); zend_string_free(constant_name); if (ret_constant && Z_CONSTANT_P(ret_constant)) { if (UNEXPECTED(zval_update_constant_ex(ret_constant, 1, ce) != SUCCESS)) { return NULL; } } return ret_constant; } /* non-class constant */ if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) { /* compound constant name */ int prefix_len = colon - name; size_t const_name_len = name_len - prefix_len - 1; const char *constant_name = colon + 1; char *lcname; size_t lcname_len; ALLOCA_FLAG(use_heap) lcname_len = prefix_len + 1 + const_name_len; lcname = do_alloca(lcname_len + 1, use_heap); zend_str_tolower_copy(lcname, name, prefix_len); /* Check for namespace constant */ lcname[prefix_len] = '\\'; memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1); if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) == NULL) { /* try lowercase */ zend_str_tolower(lcname + prefix_len + 1, const_name_len); if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) != NULL) { if ((c->flags & CONST_CS) != 0) { c = NULL; } } } free_alloca(lcname, use_heap); if (c) { return &c->value; } /* name requires runtime resolution, need to check non-namespaced name */ if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) { return zend_get_constant_str(constant_name, const_name_len); } return NULL; } if (cname) { return zend_get_constant(cname); } else { return zend_get_constant_str(name, name_len); } }
static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script) { int already_stored = 0; zend_op *persist_ptr; zval *orig_literals = NULL; if (op_array->type != ZEND_USER_FUNCTION) { return; } if (--(*op_array->refcount) == 0) { efree(op_array->refcount); } op_array->refcount = NULL; if (main_persistent_script) { zend_execute_data *orig_execute_data = EG(current_execute_data); zend_execute_data fake_execute_data; zval *offset; memset(&fake_execute_data, 0, sizeof(fake_execute_data)); fake_execute_data.func = (zend_function*)op_array; EG(current_execute_data) = &fake_execute_data; if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) { main_persistent_script->compiler_halt_offset = Z_LVAL_P(offset); } EG(current_execute_data) = orig_execute_data; } if (op_array->static_variables) { zend_hash_persist(op_array->static_variables, zend_persist_zval); zend_accel_store(op_array->static_variables, sizeof(HashTable)); } if (zend_shared_alloc_get_xlat_entry(op_array->opcodes)) { already_stored = 1; } if (op_array->literals) { if (already_stored) { orig_literals = zend_shared_alloc_get_xlat_entry(op_array->literals); ZEND_ASSERT(orig_literals != NULL); op_array->literals = orig_literals; } else { zval *p = zend_accel_memdup(op_array->literals, sizeof(zval) * op_array->last_literal); zval *end = p + op_array->last_literal; orig_literals = op_array->literals; op_array->literals = p; while (p < end) { zend_persist_zval(p); p++; } efree(orig_literals); } } if (already_stored) { persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->opcodes); ZEND_ASSERT(persist_ptr != NULL); op_array->opcodes = persist_ptr; } else { zend_op *new_opcodes = zend_accel_memdup(op_array->opcodes, sizeof(zend_op) * op_array->last); #if ZEND_USE_ABS_CONST_ADDR || ZEND_USE_ABS_JMP_ADDR zend_op *opline = new_opcodes; zend_op *end = new_opcodes + op_array->last; int offset = 0; for (; opline < end ; opline++, offset++) { # if ZEND_USE_ABS_CONST_ADDR if (ZEND_OP1_TYPE(opline) == IS_CONST) { opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals)); } if (ZEND_OP2_TYPE(opline) == IS_CONST) { opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals)); } # endif # if ZEND_USE_ABS_JMP_ADDR if (ZEND_DONE_PASS_TWO(op_array)) { /* fix jumps to point to new array */ switch (opline->opcode) { case ZEND_JMP: case ZEND_GOTO: case ZEND_FAST_CALL: ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes]; break; case ZEND_JMPZNZ: /* relative extended_value don't have to be changed */ /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: case ZEND_COALESCE: case ZEND_NEW: case ZEND_FE_RESET: case ZEND_FE_FETCH: ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes]; break; } } # endif } #endif efree(op_array->opcodes); op_array->opcodes = new_opcodes; if (op_array->run_time_cache) { efree(op_array->run_time_cache); op_array->run_time_cache = NULL; } } if (op_array->function_name && !IS_ACCEL_INTERNED(op_array->function_name)) { zend_string *new_name; if (already_stored) { new_name = zend_shared_alloc_get_xlat_entry(op_array->function_name); ZEND_ASSERT(new_name != NULL); op_array->function_name = new_name; } else { zend_accel_store_string(op_array->function_name); } } if (op_array->filename) { /* do not free! PHP has centralized filename storage, compiler will free it */ zend_accel_memdup_string(op_array->filename); } if (op_array->arg_info) { if (already_stored) { zend_arg_info *new_ptr = zend_shared_alloc_get_xlat_entry(op_array->arg_info); ZEND_ASSERT(new_ptr != NULL); op_array->arg_info = new_ptr; } else { uint32_t i, num_args; num_args = op_array->num_args; if (op_array->fn_flags & ZEND_ACC_VARIADIC) { num_args++; } zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * num_args); for (i = 0; i < num_args; i++) { if (op_array->arg_info[i].name) { zend_accel_store_interned_string(op_array->arg_info[i].name); } if (op_array->arg_info[i].class_name) { zend_accel_store_interned_string(op_array->arg_info[i].class_name); } } } } if (op_array->brk_cont_array) { zend_accel_store(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont); } if (op_array->scope) { op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope); } if (op_array->doc_comment) { if (ZCG(accel_directives).save_comments) { if (already_stored) { op_array->doc_comment = zend_shared_alloc_get_xlat_entry(op_array->doc_comment); ZEND_ASSERT(op_array->doc_comment != NULL); } else { zend_accel_store_string(op_array->doc_comment); } } else { if (!already_stored) { zend_string_release(op_array->doc_comment); } op_array->doc_comment = NULL; } } if (op_array->try_catch_array) { zend_accel_store(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch); } if (op_array->vars) { if (already_stored) { persist_ptr = zend_shared_alloc_get_xlat_entry(op_array->vars); ZEND_ASSERT(persist_ptr != NULL); op_array->vars = (zend_string**)persist_ptr; } else { int i; zend_accel_store(op_array->vars, sizeof(zend_string*) * op_array->last_var); for (i = 0; i < op_array->last_var; i++) { zend_accel_store_interned_string(op_array->vars[i]); } } } /* "prototype" may be undefined if "scope" isn't set */ 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; } }
ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, uint32_t flags) { zend_constant *c; const char *colon; zend_class_entry *ce = NULL; const char *name = ZSTR_VAL(cname); size_t name_len = ZSTR_LEN(cname); /* Skip leading \\ */ if (name[0] == '\\') { name += 1; name_len -= 1; cname = NULL; } if ((colon = zend_memrchr(name, ':', name_len)) && colon > name && (*(colon - 1) == ':')) { int class_name_len = colon - name - 1; size_t const_name_len = name_len - class_name_len - 2; zend_string *constant_name = zend_string_init(colon + 1, const_name_len, 0); zend_string *class_name = zend_string_init(name, class_name_len, 0); zval *ret_constant = NULL; if (zend_string_equals_literal_ci(class_name, "self")) { if (UNEXPECTED(!scope)) { zend_throw_error(NULL, "Cannot access self:: when no class scope is active"); goto failure; } ce = scope; } else if (zend_string_equals_literal_ci(class_name, "parent")) { if (UNEXPECTED(!scope)) { zend_throw_error(NULL, "Cannot access parent:: when no class scope is active"); goto failure; } else if (UNEXPECTED(!scope->parent)) { zend_throw_error(NULL, "Cannot access parent:: when current class scope has no parent"); goto failure; } else { ce = scope->parent; } } else if (zend_string_equals_literal_ci(class_name, "static")) { ce = zend_get_called_scope(EG(current_execute_data)); if (UNEXPECTED(!ce)) { zend_throw_error(NULL, "Cannot access static:: when no class scope is active"); goto failure; } } else { ce = zend_fetch_class(class_name, flags); } if (ce) { zend_class_constant *c = zend_hash_find_ptr(&ce->constants_table, constant_name); if (c == NULL) { if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) { zend_throw_error(NULL, "Undefined class constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name)); goto failure; } ret_constant = NULL; } else { if (!zend_verify_const_access(c, scope)) { zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(class_name), ZSTR_VAL(constant_name)); goto failure; } ret_constant = &c->value; } } if (ret_constant && Z_CONSTANT_P(ret_constant)) { if (Z_TYPE_P(ret_constant) == IS_CONSTANT_AST) { if (IS_CONSTANT_VISITED(ret_constant)) { zend_throw_error(NULL, "Cannot declare self-referencing constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name)); ret_constant = NULL; goto failure; } MARK_CONSTANT_VISITED(ret_constant); } if (UNEXPECTED(zval_update_constant_ex(ret_constant, ce) != SUCCESS)) { RESET_CONSTANT_VISITED(ret_constant); ret_constant = NULL; goto failure; } RESET_CONSTANT_VISITED(ret_constant); } failure: zend_string_release(class_name); zend_string_free(constant_name); return ret_constant; } /* non-class constant */ if ((colon = zend_memrchr(name, '\\', name_len)) != NULL) { /* compound constant name */ int prefix_len = colon - name; size_t const_name_len = name_len - prefix_len - 1; const char *constant_name = colon + 1; char *lcname; size_t lcname_len; ALLOCA_FLAG(use_heap) lcname_len = prefix_len + 1 + const_name_len; lcname = do_alloca(lcname_len + 1, use_heap); zend_str_tolower_copy(lcname, name, prefix_len); /* Check for namespace constant */ lcname[prefix_len] = '\\'; memcpy(lcname + prefix_len + 1, constant_name, const_name_len + 1); if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) == NULL) { /* try lowercase */ zend_str_tolower(lcname + prefix_len + 1, const_name_len); if ((c = zend_hash_str_find_ptr(EG(zend_constants), lcname, lcname_len)) != NULL) { if ((c->flags & CONST_CS) != 0) { c = NULL; } } } free_alloca(lcname, use_heap); if (c) { return &c->value; } /* name requires runtime resolution, need to check non-namespaced name */ if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) { return zend_get_constant_str(constant_name, const_name_len); } return NULL; } if (cname) { return zend_get_constant(cname); } else { return zend_get_constant_str(name, name_len); } }
void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) { int i = 0; zend_op *opline = op_array->opcodes; zend_op *end = opline + op_array->last; zend_bool collect_constants = (ZEND_OPTIMIZER_PASS_15 & ctx->optimization_level)? (op_array == &ctx->script->main_op_array) : 0; while (opline < end) { switch (opline->opcode) { case ZEND_ADD: case ZEND_SUB: case ZEND_MUL: case ZEND_DIV: case ZEND_MOD: case ZEND_POW: case ZEND_SL: case ZEND_SR: case ZEND_CONCAT: case ZEND_FAST_CONCAT: case ZEND_IS_EQUAL: case ZEND_IS_NOT_EQUAL: case ZEND_IS_SMALLER: case ZEND_IS_SMALLER_OR_EQUAL: case ZEND_IS_IDENTICAL: case ZEND_IS_NOT_IDENTICAL: case ZEND_BW_OR: case ZEND_BW_AND: case ZEND_BW_XOR: case ZEND_BOOL_XOR: case ZEND_SPACESHIP: case ZEND_CASE: if (opline->op1_type == IS_CONST && opline->op2_type == IS_CONST) { /* binary operation with constant operands */ zval result; if (zend_optimizer_eval_binary_op(&result, opline->opcode, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) == SUCCESS) { literal_dtor(&ZEND_OP1_LITERAL(opline)); literal_dtor(&ZEND_OP2_LITERAL(opline)); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, opline->result.var, &result)) { MAKE_NOP(opline); } else { opline->opcode = ZEND_QM_ASSIGN; SET_UNUSED(opline->op2); zend_optimizer_update_op1_const(op_array, opline, &result); } } } break; case ZEND_CAST: if (opline->op1_type == IS_CONST) { /* cast of constant operand */ zval result; if (zend_optimizer_eval_cast(&result, opline->extended_value, &ZEND_OP1_LITERAL(opline)) == SUCCESS) { literal_dtor(&ZEND_OP1_LITERAL(opline)); if (zend_optimizer_replace_by_const(op_array, opline + 1, opline->result_type, opline->result.var, &result)) { MAKE_NOP(opline); } else { opline->opcode = ZEND_QM_ASSIGN; opline->extended_value = 0; zend_optimizer_update_op1_const(op_array, opline, &result); } break; } } if (opline->extended_value == _IS_BOOL) { /* T = CAST(X, IS_BOOL) => T = BOOL(X) */ opline->opcode = ZEND_BOOL; opline->extended_value = 0; } break; case ZEND_BW_NOT: case ZEND_BOOL_NOT: if (opline->op1_type == IS_CONST) { /* unary operation on constant operand */ zval result; if (zend_optimizer_eval_unary_op(&result, opline->opcode, &ZEND_OP1_LITERAL(opline)) == SUCCESS) { literal_dtor(&ZEND_OP1_LITERAL(opline)); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, opline->result.var, &result)) { MAKE_NOP(opline); } else { opline->opcode = ZEND_QM_ASSIGN; zend_optimizer_update_op1_const(op_array, opline, &result); } } } break; case ZEND_FETCH_CONSTANT: if (opline->op2_type == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING && Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__") - 1 && memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) { /* substitute __COMPILER_HALT_OFFSET__ constant */ zend_execute_data *orig_execute_data = EG(current_execute_data); zend_execute_data fake_execute_data; zval *offset; memset(&fake_execute_data, 0, sizeof(zend_execute_data)); fake_execute_data.func = (zend_function*)op_array; EG(current_execute_data) = &fake_execute_data; if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) { literal_dtor(&ZEND_OP2_LITERAL(opline)); if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, opline->result.var, offset)) { MAKE_NOP(opline); } else { opline->opcode = ZEND_QM_ASSIGN; opline->extended_value = 0; SET_UNUSED(opline->op2); zend_optimizer_update_op1_const(op_array, opline, offset); } } EG(current_execute_data) = orig_execute_data; break; } if (opline->op2_type == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { /* substitute persistent constants */ zval c; if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP2_LITERAL(opline)), &c, 1)) { if (!ctx->constants || !zend_optimizer_get_collected_constant(ctx->constants, &ZEND_OP2_LITERAL(opline), &c)) { break; } } if (Z_TYPE(c) == IS_CONSTANT_AST) { break; } literal_dtor(&ZEND_OP2_LITERAL(opline)); if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, opline->result.var, &c)) { MAKE_NOP(opline); } else { opline->opcode = ZEND_QM_ASSIGN; opline->extended_value = 0; SET_UNUSED(opline->op2); zend_optimizer_update_op1_const(op_array, opline, &c); } } break; case ZEND_FETCH_CLASS_CONSTANT: if (opline->op2_type == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { zend_class_entry *ce = NULL; if (opline->op1_type == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) { /* for A::B */ if (op_array->scope && !strncasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), ZSTR_VAL(op_array->scope->name), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1)) { ce = op_array->scope; } else { if ((ce = zend_hash_find_ptr(EG(class_table), Z_STR(op_array->literals[opline->op1.constant + 1]))) == NULL || (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->type != MODULE_PERSISTENT) || (ce->type == ZEND_USER_CLASS && ce->info.user.filename != op_array->filename)) { break; } } } else if (op_array->scope && opline->op1_type == IS_UNUSED && (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) { /* for self::B */ ce = op_array->scope; } else if (op_array->scope && opline->op1_type == IS_VAR && (opline - 1)->opcode == ZEND_FETCH_CLASS && ((opline - 1)->op2_type == IS_UNUSED && ((opline - 1)->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) && (opline - 1)->result.var == opline->op1.var) { /* for self::B */ ce = op_array->scope; } if (ce) { zend_class_constant *cc; zval *c, t; if ((cc = zend_hash_find_ptr(&ce->constants_table, Z_STR(ZEND_OP2_LITERAL(opline)))) != NULL && (Z_ACCESS_FLAGS(cc->value) & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) { c = &cc->value; if (Z_TYPE_P(c) == IS_CONSTANT_AST) { zend_ast *ast = Z_ASTVAL_P(c); if (ast->kind != ZEND_AST_CONSTANT || !zend_optimizer_get_persistent_constant(zend_ast_get_constant_name(ast), &t, 1) || Z_TYPE(t) == IS_CONSTANT_AST) { break; } } else { ZVAL_COPY_OR_DUP(&t, c); } if (opline->op1_type == IS_CONST) { literal_dtor(&ZEND_OP1_LITERAL(opline)); } else if (opline->op1_type == IS_VAR) { MAKE_NOP((opline - 1)); } literal_dtor(&ZEND_OP2_LITERAL(opline)); if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, opline->result.var, &t)) { MAKE_NOP(opline); } else { opline->opcode = ZEND_QM_ASSIGN; opline->extended_value = 0; SET_UNUSED(opline->op2); zend_optimizer_update_op1_const(op_array, opline, &t); } } } } break; case ZEND_DO_ICALL: { zend_op *send1_opline = opline - 1; zend_op *send2_opline = NULL; zend_op *init_opline = NULL; while (send1_opline->opcode == ZEND_NOP) { send1_opline--; } if (send1_opline->opcode != ZEND_SEND_VAL || send1_opline->op1_type != IS_CONST) { /* don't colllect constants after unknown function call */ collect_constants = 0; break; } if (send1_opline->op2.num == 2) { send2_opline = send1_opline; send1_opline--; while (send1_opline->opcode == ZEND_NOP) { send1_opline--; } if (send1_opline->opcode != ZEND_SEND_VAL || send1_opline->op1_type != IS_CONST) { /* don't colllect constants after unknown function call */ collect_constants = 0; break; } } init_opline = send1_opline - 1; while (init_opline->opcode == ZEND_NOP) { init_opline--; } if (init_opline->opcode != ZEND_INIT_FCALL || init_opline->op2_type != IS_CONST || Z_TYPE(ZEND_OP2_LITERAL(init_opline)) != IS_STRING) { /* don't colllect constants after unknown function call */ collect_constants = 0; break; } /* define("name", scalar); */ if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("define")-1 && zend_binary_strcasecmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), Z_STRLEN(ZEND_OP2_LITERAL(init_opline)), "define", sizeof("define")-1) == 0) { if (Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING && send2_opline && Z_TYPE(ZEND_OP1_LITERAL(send2_opline)) <= IS_STRING) { if (collect_constants) { zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(send1_opline), &ZEND_OP1_LITERAL(send2_opline)); } if (RESULT_UNUSED(opline) && !zend_memnstr(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), "::", sizeof("::") - 1, Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)) + Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)))) { opline->opcode = ZEND_DECLARE_CONST; opline->op1_type = IS_CONST; opline->op2_type = IS_CONST; opline->result_type = IS_UNUSED; opline->op1.constant = send1_opline->op1.constant; opline->op2.constant = send2_opline->op1.constant; opline->result.num = 0; literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); MAKE_NOP(send1_opline); MAKE_NOP(send2_opline); } break; } } /* pre-evaluate constant functions: constant(x) function_exists(x) is_callable(x) extension_loaded(x) */ if (!send2_opline && Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING) { if ((Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("function_exists")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "function_exists", sizeof("function_exists")-1) && !zend_optimizer_is_disabled_func("function_exists", sizeof("function_exists") - 1)) || (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "is_callable", sizeof("is_callable")) && !zend_optimizer_is_disabled_func("is_callable", sizeof("is_callable") - 1))) { zend_internal_function *func; zend_string *lc_name = zend_string_tolower( Z_STR(ZEND_OP1_LITERAL(send1_opline))); if ((func = zend_hash_find_ptr(EG(function_table), lc_name)) != NULL && func->type == ZEND_INTERNAL_FUNCTION && func->module->type == MODULE_PERSISTENT #ifdef ZEND_WIN32 && func->module->handle == NULL #endif ) { zval t; if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable") - 1 || func->handler != ZEND_FN(display_disabled_function)) { ZVAL_TRUE(&t); } else { ZVAL_FALSE(&t); } literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, opline->result.var, &t)) { MAKE_NOP(opline); } else { opline->opcode = ZEND_QM_ASSIGN; opline->extended_value = 0; SET_UNUSED(opline->op2); zend_optimizer_update_op1_const(op_array, opline, &t); } } zend_string_release_ex(lc_name, 0); break; } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("extension_loaded")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "extension_loaded", sizeof("extension_loaded")-1) && !zend_optimizer_is_disabled_func("extension_loaded", sizeof("extension_loaded") - 1)) { zval t; zend_string *lc_name = zend_string_tolower( Z_STR(ZEND_OP1_LITERAL(send1_opline))); zend_module_entry *m = zend_hash_find_ptr(&module_registry, lc_name); zend_string_release_ex(lc_name, 0); if (!m) { if (PG(enable_dl)) { break; } else { ZVAL_FALSE(&t); } } else { if (m->type == MODULE_PERSISTENT #ifdef ZEND_WIN32 && m->handle == NULL #endif ) { ZVAL_TRUE(&t); } else { break; } } literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, opline->result.var, &t)) { MAKE_NOP(opline); } else { opline->opcode = ZEND_QM_ASSIGN; opline->extended_value = 0; SET_UNUSED(opline->op2); zend_optimizer_update_op1_const(op_array, opline, &t); } break; } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("constant")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "constant", sizeof("constant")-1) && !zend_optimizer_is_disabled_func("constant", sizeof("constant") - 1)) { zval t; if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(send1_opline)), &t, 1)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, opline->result.var, &t)) { MAKE_NOP(opline); } else { opline->opcode = ZEND_QM_ASSIGN; opline->extended_value = 0; SET_UNUSED(opline->op2); zend_optimizer_update_op1_const(op_array, opline, &t); } } break; /* dirname(IS_CONST/IS_STRING) -> IS_CONST/IS_STRING */ } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("dirname")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "dirname", sizeof("dirname") - 1) && !zend_optimizer_is_disabled_func("dirname", sizeof("dirname") - 1) && IS_ABSOLUTE_PATH(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)))) { zend_string *dirname = zend_string_init(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)), 0); ZSTR_LEN(dirname) = zend_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname)); if (IS_ABSOLUTE_PATH(ZSTR_VAL(dirname), ZSTR_LEN(dirname))) { zval t; ZVAL_STR(&t, dirname); literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, opline->result.var, &t)) { MAKE_NOP(opline); } else { opline->opcode = ZEND_QM_ASSIGN; opline->extended_value = 0; SET_UNUSED(opline->op2); zend_optimizer_update_op1_const(op_array, opline, &t); } } else { zend_string_release_ex(dirname, 0); } break; } } /* don't colllect constants after any other function call */ collect_constants = 0; break; } case ZEND_STRLEN: if (opline->op1_type == IS_CONST) { zval t; if (zend_optimizer_eval_strlen(&t, &ZEND_OP1_LITERAL(opline)) == SUCCESS) { literal_dtor(&ZEND_OP1_LITERAL(opline)); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, opline->result.var, &t)) { MAKE_NOP(opline); } else { opline->opcode = ZEND_QM_ASSIGN; zend_optimizer_update_op1_const(op_array, opline, &t); } } } break; case ZEND_DEFINED: { zval c; if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline)), &c, 0)) { break; } ZVAL_TRUE(&c); literal_dtor(&ZEND_OP1_LITERAL(opline)); if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, opline->result.var, &c)) { MAKE_NOP(opline); } else { opline->opcode = ZEND_QM_ASSIGN; zend_optimizer_update_op1_const(op_array, opline, &c); } } break; case ZEND_DECLARE_CONST: if (collect_constants && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING && Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_STRING) { zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)); } break; case ZEND_RETURN: case ZEND_RETURN_BY_REF: case ZEND_GENERATOR_RETURN: case ZEND_EXIT: case ZEND_THROW: case ZEND_CATCH: case ZEND_FAST_CALL: case ZEND_FAST_RET: case ZEND_JMP: case ZEND_JMPZNZ: case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_FE_RESET_R: case ZEND_FE_RESET_RW: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: case ZEND_JMP_SET: case ZEND_COALESCE: case ZEND_ASSERT_CHECK: collect_constants = 0; break; } opline++; i++; } }
/** * Executes the validation * * @param string $file * @param int $minsize * @param int $maxsize * @param array $mimes * @param int $minwidth * @param int $maxwidth * @param int $minheight * @param int $maxheight * @return boolean */ PHP_METHOD(Phalcon_Validation_Validator_File, valid) { zval *value, *minsize = NULL, *maxsize = NULL, *mimes = NULL, *minwidth = NULL, *maxwidth = NULL, *minheight = NULL, *maxheight = NULL; zval file = {}, size = {}, *constant, finfo = {}, pathname = {}, mime = {}, image = {}, imageinfo = {}, width = {}, height = {}, valid = {}; zend_class_entry *imagick_ce; phalcon_fetch_params(0, 1, 7, &value, &minsize, &maxsize, &mimes, &minwidth, &maxwidth, &minheight, &maxheight); if (Z_TYPE_P(value) == IS_STRING) { object_init_ex(&file, spl_ce_SplFileInfo); if (phalcon_has_constructor(&file)) { PHALCON_CALL_METHODW(NULL, &file, "__construct", value); } } else if (Z_TYPE_P(value) == IS_OBJECT && instanceof_function_ex(Z_OBJCE_P(value), spl_ce_SplFileInfo, 0)) { PHALCON_CPY_WRT(&file, value); } if (Z_TYPE(file) <= IS_NULL) { phalcon_update_property_str(getThis(), SL("_type"), SL("TypeUnknow")); RETURN_FALSE; } if (!minsize) { minsize = &PHALCON_GLOBAL(z_null); } if (!maxsize) { maxsize = &PHALCON_GLOBAL(z_null); } if (!mimes) { mimes = &PHALCON_GLOBAL(z_null); } if (!minwidth) { minwidth = &PHALCON_GLOBAL(z_null); } if (!maxwidth) { maxwidth = &PHALCON_GLOBAL(z_null); } if (!minheight) { minheight = &PHALCON_GLOBAL(z_null); } if (!maxheight) { maxheight = &PHALCON_GLOBAL(z_null); } PHALCON_CALL_METHODW(&valid, &file, "isfile"); if (!zend_is_true(&valid)) { phalcon_update_property_str(getThis(), SL("_type"), SL("FileValid")); RETURN_FALSE; } PHALCON_CALL_METHODW(&size, &file, "getsize"); if (!PHALCON_IS_EMPTY(minsize)) { is_smaller_or_equal_function(&valid, minsize, &size); if (!zend_is_true(&valid)) { phalcon_update_property_str(getThis(), SL("_type"), SL("TooSmall")); RETURN_FALSE; } } if (!PHALCON_IS_EMPTY(maxsize)) { is_smaller_or_equal_function(&valid, &size, maxsize); if (!zend_is_true(&valid)) { phalcon_update_property_str(getThis(), SL("_type"), SL("TooLarge")); RETURN_FALSE; } } PHALCON_CALL_METHODW(&pathname, &file, "getpathname"); if (Z_TYPE_P(mimes) == IS_ARRAY) { if ((constant = zend_get_constant_str(SL("FILEINFO_MIME_TYPE"))) == NULL) { PHALCON_THROW_EXCEPTION_STRW(phalcon_validation_exception_ce, "Undefined constant `FILEINFO_MIME_TYPE`"); return; } PHALCON_CALL_FUNCTIONW(&finfo, "finfo_open", constant); if (Z_TYPE(finfo) != IS_RESOURCE) { PHALCON_THROW_EXCEPTION_STRW(phalcon_validation_exception_ce, "Opening fileinfo database failed"); return; } PHALCON_CALL_FUNCTIONW(&mime, "finfo_file", &finfo, &pathname); PHALCON_CALL_FUNCTIONW(NULL, "finfo_close", &finfo); if (!phalcon_fast_in_array(&mime, mimes)) { phalcon_update_property_str(getThis(), SL("_type"), SL("MimeValid")); RETURN_FALSE; } } if (phalcon_class_str_exists(SL("imagick"), 0) != NULL) { imagick_ce = phalcon_fetch_str_class(SL("Imagick"), ZEND_FETCH_CLASS_AUTO); object_init_ex(&image, imagick_ce); PHALCON_CALL_METHODW(NULL, &image, "__construct", &pathname); PHALCON_CALL_METHODW(&width, &image, "getImageWidth"); PHALCON_CALL_METHODW(&height, &image, "getImageHeight"); } else if (phalcon_function_exists_ex(SL("getimagesize")) != FAILURE) { PHALCON_CALL_FUNCTIONW(&imageinfo, "getimagesize", &pathname); if (!phalcon_array_isset_fetch_long(&width, &imageinfo, 0)) { ZVAL_LONG(&width, -1); } if (!phalcon_array_isset_fetch_long(&height, &imageinfo, 1)) { ZVAL_LONG(&height, -1); } } else { ZVAL_LONG(&width, -1); ZVAL_LONG(&height, -1); } if (!PHALCON_IS_EMPTY(minwidth)) { is_smaller_or_equal_function(&valid, minwidth, &width); if (!zend_is_true(&valid)) { phalcon_update_property_str(getThis(), SL("_type"), SL("TooNarrow")); RETURN_FALSE; } } if (!PHALCON_IS_EMPTY(maxwidth)) { is_smaller_or_equal_function(&valid, &width, maxwidth); if (!zend_is_true(&valid)) { phalcon_update_property_str(getThis(), SL("_type"), SL("TooWide")); RETURN_FALSE; } } if (!PHALCON_IS_EMPTY(minheight)) { is_smaller_or_equal_function(&valid, minheight, &height); if (!zend_is_true(&valid)) { phalcon_update_property_str(getThis(), SL("_type"), SL("TooShort")); RETURN_FALSE; } } if (!PHALCON_IS_EMPTY(maxheight)) { is_smaller_or_equal_function(&valid, &height, maxheight); if (!zend_is_true(&valid)) { phalcon_update_property_str(getThis(), SL("_type"), SL("TooLong")); RETURN_FALSE; } } RETURN_TRUE; }
void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) { int i = 0; zend_op *opline = op_array->opcodes; zend_op *end = opline + op_array->last; zend_bool collect_constants = (op_array == &ctx->script->main_op_array); while (opline < end) { switch (opline->opcode) { case ZEND_ADD: case ZEND_SUB: case ZEND_MUL: case ZEND_DIV: case ZEND_MOD: case ZEND_POW: case ZEND_SL: case ZEND_SR: case ZEND_CONCAT: case ZEND_FAST_CONCAT: case ZEND_IS_EQUAL: case ZEND_IS_NOT_EQUAL: case ZEND_IS_SMALLER: case ZEND_IS_SMALLER_OR_EQUAL: case ZEND_IS_IDENTICAL: case ZEND_IS_NOT_IDENTICAL: case ZEND_BW_OR: case ZEND_BW_AND: case ZEND_BW_XOR: case ZEND_BOOL_XOR: if (ZEND_OP1_TYPE(opline) == IS_CONST && ZEND_OP2_TYPE(opline) == IS_CONST) { /* binary operation with constant operands */ binary_op_type binary_op = get_binary_op(opline->opcode); uint32_t tv = ZEND_RESULT(opline).var; /* temporary variable */ zval result; int er; if (opline->opcode == ZEND_DIV && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG && Z_LVAL(ZEND_OP2_LITERAL(opline)) == 0) { /* div by 0 */ break; } er = EG(error_reporting); EG(error_reporting) = 0; /* evaluate constant expression */ if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) != SUCCESS) { EG(error_reporting) = er; break; } EG(error_reporting) = er; if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result)) { literal_dtor(&ZEND_OP1_LITERAL(opline)); literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); } } break; case ZEND_CAST: if (ZEND_OP1_TYPE(opline) == IS_CONST && opline->extended_value != IS_ARRAY && opline->extended_value != IS_OBJECT && opline->extended_value != IS_RESOURCE) { /* cast of constant operand */ zend_uchar type = opline->result_type; uint32_t tv = ZEND_RESULT(opline).var; /* temporary variable */ zval res; res = ZEND_OP1_LITERAL(opline); zval_copy_ctor(&res); switch (opline->extended_value) { case IS_NULL: convert_to_null(&res); break; case _IS_BOOL: convert_to_boolean(&res); break; case IS_LONG: convert_to_long(&res); break; case IS_DOUBLE: convert_to_double(&res); break; case IS_STRING: convert_to_string(&res); break; } if (zend_optimizer_replace_by_const(op_array, opline + 1, type, tv, &res)) { literal_dtor(&ZEND_OP1_LITERAL(opline)); MAKE_NOP(opline); } } else if (opline->extended_value == _IS_BOOL) { /* T = CAST(X, IS_BOOL) => T = BOOL(X) */ opline->opcode = ZEND_BOOL; opline->extended_value = 0; } break; case ZEND_BW_NOT: case ZEND_BOOL_NOT: if (ZEND_OP1_TYPE(opline) == IS_CONST) { /* unary operation on constant operand */ unary_op_type unary_op = get_unary_op(opline->opcode); zval result; uint32_t tv = ZEND_RESULT(opline).var; /* temporary variable */ int er; er = EG(error_reporting); EG(error_reporting) = 0; if (unary_op(&result, &ZEND_OP1_LITERAL(opline)) != SUCCESS) { EG(error_reporting) = er; break; } EG(error_reporting) = er; if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result)) { literal_dtor(&ZEND_OP1_LITERAL(opline)); MAKE_NOP(opline); } } break; #if 0 case ZEND_ADD_STRING: case ZEND_ADD_CHAR: { zend_op *next_op = opline + 1; int requires_conversion = (opline->opcode == ZEND_ADD_CHAR? 1 : 0); size_t final_length = 0; zend_string *str; char *ptr; zend_op *last_op; /* There is always a ZEND_RETURN at the end if (next_op>=end) { break; } */ while (next_op->opcode == ZEND_ADD_STRING || next_op->opcode == ZEND_ADD_CHAR) { if (ZEND_RESULT(opline).var != ZEND_RESULT(next_op).var) { break; } if (next_op->opcode == ZEND_ADD_CHAR) { final_length += 1; } else { /* ZEND_ADD_STRING */ final_length += Z_STRLEN(ZEND_OP2_LITERAL(next_op)); } next_op++; } if (final_length == 0) { break; } last_op = next_op; final_length += (requires_conversion? 1 : Z_STRLEN(ZEND_OP2_LITERAL(opline))); str = zend_string_alloc(final_length, 0); str->len = final_length; ptr = str->val; ptr[final_length] = '\0'; if (requires_conversion) { /* ZEND_ADD_CHAR */ char chval = (char)Z_LVAL(ZEND_OP2_LITERAL(opline)); ZVAL_NEW_STR(&ZEND_OP2_LITERAL(opline), str); ptr[0] = chval; opline->opcode = ZEND_ADD_STRING; ptr++; } else { /* ZEND_ADD_STRING */ memcpy(ptr, Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline))); ptr += Z_STRLEN(ZEND_OP2_LITERAL(opline)); zend_string_release(Z_STR(ZEND_OP2_LITERAL(opline))); ZVAL_NEW_STR(&ZEND_OP2_LITERAL(opline), str); } next_op = opline + 1; while (next_op < last_op) { if (next_op->opcode == ZEND_ADD_STRING) { memcpy(ptr, Z_STRVAL(ZEND_OP2_LITERAL(next_op)), Z_STRLEN(ZEND_OP2_LITERAL(next_op))); ptr += Z_STRLEN(ZEND_OP2_LITERAL(next_op)); literal_dtor(&ZEND_OP2_LITERAL(next_op)); } else { /* ZEND_ADD_CHAR */ *ptr = (char)Z_LVAL(ZEND_OP2_LITERAL(next_op)); ptr++; } MAKE_NOP(next_op); next_op++; } if (!((ZEND_OPTIMIZER_PASS_5|ZEND_OPTIMIZER_PASS_10) & OPTIMIZATION_LEVEL)) { /* NOP removal is disabled => insert JMP over NOPs */ if (last_op-opline >= 3) { /* If we have more than 2 NOPS then JMP over them */ (opline + 1)->opcode = ZEND_JMP; ZEND_OP1(opline + 1).opline_num = last_op - op_array->opcodes; /* that's OK even for ZE2, since opline_num's are resolved in pass 2 later */ } } } break; #endif case ZEND_FETCH_CONSTANT: if (ZEND_OP1_TYPE(opline) == IS_UNUSED && ZEND_OP2_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING && Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__") - 1 && memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) { /* substitute __COMPILER_HALT_OFFSET__ constant */ zend_execute_data *orig_execute_data = EG(current_execute_data); zend_execute_data fake_execute_data; zval *offset; memset(&fake_execute_data, 0, sizeof(zend_execute_data)); fake_execute_data.func = (zend_function*)op_array; EG(current_execute_data) = &fake_execute_data; if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) { uint32_t tv = ZEND_RESULT(opline).var; if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, offset)) { literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); } } EG(current_execute_data) = orig_execute_data; break; } if (ZEND_OP1_TYPE(opline) == IS_UNUSED && ZEND_OP2_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { /* substitute persistent constants */ uint32_t tv = ZEND_RESULT(opline).var; zval c; if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP2_LITERAL(opline)), &c, 1)) { if (!ctx->constants || !zend_optimizer_get_collected_constant(ctx->constants, &ZEND_OP2_LITERAL(opline), &c)) { break; } } if (Z_TYPE(c) == IS_CONSTANT_AST) { break; } if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c)) { literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); } } /* class constant */ if (ZEND_OP1_TYPE(opline) != IS_UNUSED && ZEND_OP2_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { zend_class_entry *ce = NULL; if (ZEND_OP1_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) { /* for A::B */ if (op_array->scope && !strncasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), op_array->scope->name->val, Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1)) { ce = op_array->scope; } else { if ((ce = zend_hash_find_ptr(EG(class_table), Z_STR(op_array->literals[opline->op1.constant + 1]))) == NULL || (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->type != MODULE_PERSISTENT) || (ce->type == ZEND_USER_CLASS && ZEND_CE_FILENAME(ce) != op_array->filename)) { break; } } } else if (op_array->scope && ZEND_OP1_TYPE(opline) == IS_VAR && (opline - 1)->opcode == ZEND_FETCH_CLASS && (ZEND_OP1_TYPE(opline - 1) == IS_UNUSED && ((opline - 1)->extended_value & ~ZEND_FETCH_CLASS_NO_AUTOLOAD) == ZEND_FETCH_CLASS_SELF) && ZEND_RESULT((opline - 1)).var == ZEND_OP1(opline).var) { /* for self::B */ ce = op_array->scope; } if (ce) { uint32_t tv = ZEND_RESULT(opline).var; zval *c, t; if ((c = zend_hash_find(&ce->constants_table, Z_STR(ZEND_OP2_LITERAL(opline)))) != NULL) { ZVAL_DEREF(c); if (Z_TYPE_P(c) == IS_CONSTANT_AST) { break; } if (ZEND_IS_CONSTANT_TYPE(Z_TYPE_P(c))) { if (!zend_optimizer_get_persistent_constant(Z_STR_P(c), &t, 1) || ZEND_IS_CONSTANT_TYPE(Z_TYPE(t))) { break; } } else { ZVAL_COPY_VALUE(&t, c); zval_copy_ctor(&t); } if (ZEND_OP1_TYPE(opline) == IS_CONST) { literal_dtor(&ZEND_OP1_LITERAL(opline)); } else { MAKE_NOP((opline - 1)); } if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &t)) { literal_dtor(&ZEND_OP2_LITERAL(opline)); MAKE_NOP(opline); } } } } break; case ZEND_DO_ICALL: { zend_op *send1_opline = opline - 1; zend_op *send2_opline = NULL; zend_op *init_opline = NULL; while (send1_opline->opcode == ZEND_NOP) { send1_opline--; } if (send1_opline->opcode != ZEND_SEND_VAL || ZEND_OP1_TYPE(send1_opline) != IS_CONST) { /* don't colllect constants after unknown function call */ collect_constants = 0; break; } if (send1_opline->op2.num == 2) { send2_opline = send1_opline; send1_opline--; while (send1_opline->opcode == ZEND_NOP) { send1_opline--; } if (send1_opline->opcode != ZEND_SEND_VAL || ZEND_OP1_TYPE(send1_opline) != IS_CONST) { /* don't colllect constants after unknown function call */ collect_constants = 0; break; } } init_opline = send1_opline - 1; while (init_opline->opcode == ZEND_NOP) { init_opline--; } if (init_opline->opcode != ZEND_INIT_FCALL || ZEND_OP2_TYPE(init_opline) != IS_CONST || Z_TYPE(ZEND_OP2_LITERAL(init_opline)) != IS_STRING) { /* don't colllect constants after unknown function call */ collect_constants = 0; break; } /* define("name", scalar); */ if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("define")-1 && zend_binary_strcasecmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), Z_STRLEN(ZEND_OP2_LITERAL(init_opline)), "define", sizeof("define")-1) == 0) { if (Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING && send2_opline && Z_TYPE(ZEND_OP1_LITERAL(send2_opline)) <= IS_STRING) { if (collect_constants) { zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(send1_opline), &ZEND_OP1_LITERAL(send2_opline)); } if (RESULT_UNUSED(opline) && !zend_memnstr(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), "::", sizeof("::") - 1, Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)) + Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)))) { opline->opcode = ZEND_DECLARE_CONST; opline->op1_type = IS_CONST; opline->op2_type = IS_CONST; opline->result_type = IS_UNUSED; opline->op1.constant = send1_opline->op1.constant; opline->op2.constant = send2_opline->op1.constant; opline->result.num = 0; literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); MAKE_NOP(send1_opline); MAKE_NOP(send2_opline); } break; } } /* pre-evaluate constant functions: defined(x) constant(x) function_exists(x) is_callable(x) extension_loaded(x) */ if (!send2_opline && Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING) { if ((Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("function_exists")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "function_exists", sizeof("function_exists")-1)) || (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "is_callable", sizeof("is_callable")))) { zend_internal_function *func; zend_string *lc_name = zend_string_tolower( Z_STR(ZEND_OP1_LITERAL(send1_opline))); if ((func = zend_hash_find_ptr(EG(function_table), lc_name)) != NULL && func->type == ZEND_INTERNAL_FUNCTION && func->module->type == MODULE_PERSISTENT) { zval t; if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable") - 1 || func->handler != ZEND_FN(display_disabled_function)) { ZVAL_TRUE(&t); } else { ZVAL_FALSE(&t); } if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); MAKE_NOP(opline); zend_string_release(lc_name); break; } } zend_string_release(lc_name); } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("extension_loaded")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "extension_loaded", sizeof("extension_loaded")-1)) { zval t; zend_string *lc_name = zend_string_tolower( Z_STR(ZEND_OP1_LITERAL(send1_opline))); zend_module_entry *m = zend_hash_find_ptr(&module_registry, lc_name); zend_string_release(lc_name); if (!m) { if (!PG(enable_dl)) { break; } else { ZVAL_FALSE(&t); } } else { if (m->type == MODULE_PERSISTENT) { ZVAL_TRUE(&t); } else { break; } } if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); MAKE_NOP(opline); break; } } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("defined")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "defined", sizeof("defined")-1)) { zval t; if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(send1_opline)), &t, 0)) { ZVAL_TRUE(&t); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); MAKE_NOP(opline); break; } } } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("constant")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "constant", sizeof("constant")-1)) { zval t; if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(send1_opline)), &t, 1)) { if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); MAKE_NOP(opline); break; } } } else if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN) == 0 && Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("strlen") - 1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "strlen", sizeof("strlen") - 1)) { zval t; ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(send1_opline))); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); MAKE_NOP(opline); break; } /* dirname(IS_CONST/IS_STRING) -> IS_CONST/IS_STRING */ } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("dirname")-1 && !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "dirname", sizeof("dirname")-1) && IS_ABSOLUTE_PATH(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)))) { zend_string *dirname = zend_string_init(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)), 0); dirname->len = zend_dirname(dirname->val, dirname->len); if (IS_ABSOLUTE_PATH(dirname->val, dirname->len)) { zval t; ZVAL_STR(&t, dirname); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP2_LITERAL(init_opline)); MAKE_NOP(init_opline); literal_dtor(&ZEND_OP1_LITERAL(send1_opline)); MAKE_NOP(send1_opline); MAKE_NOP(opline); break; } } else { zend_string_release(dirname); } } } /* don't colllect constants after any other function call */ collect_constants = 0; break; } case ZEND_STRLEN: if (ZEND_OP1_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) { zval t; ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline))); if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, ZEND_RESULT(opline).var, &t)) { literal_dtor(&ZEND_OP1_LITERAL(opline)); MAKE_NOP(opline); } } break; case ZEND_DEFINED: { zval c; uint32_t tv = ZEND_RESULT(opline).var; if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline)), &c, 0)) { break; } ZVAL_TRUE(&c); if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c)) { literal_dtor(&ZEND_OP1_LITERAL(opline)); MAKE_NOP(opline); } } break; case ZEND_DECLARE_CONST: if (collect_constants && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING && Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_STRING) { zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)); } break; case ZEND_RETURN: case ZEND_RETURN_BY_REF: case ZEND_GENERATOR_RETURN: case ZEND_EXIT: case ZEND_THROW: case ZEND_CATCH: case ZEND_BRK: case ZEND_CONT: case ZEND_GOTO: case ZEND_FAST_CALL: case ZEND_FAST_RET: case ZEND_JMP: case ZEND_JMPZNZ: case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_FE_RESET_R: case ZEND_FE_RESET_RW: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: case ZEND_NEW: case ZEND_JMP_SET: case ZEND_COALESCE: case ZEND_ASSERT_CHECK: collect_constants = 0; break; case ZEND_FETCH_R: case ZEND_FETCH_W: case ZEND_FETCH_RW: case ZEND_FETCH_FUNC_ARG: case ZEND_FETCH_IS: case ZEND_FETCH_UNSET: if (opline != op_array->opcodes && (opline-1)->opcode == ZEND_BEGIN_SILENCE && (opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_LOCAL && opline->op1_type == IS_CONST && opline->op2_type == IS_UNUSED && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING && (Z_STRLEN(ZEND_OP1_LITERAL(opline)) != sizeof("this")-1 || memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), "this", sizeof("this") - 1) != 0)) { int var = opline->result.var; int level = 0; zend_op *op = opline + 1; zend_op *use = NULL; while (op < end) { if (op->opcode == ZEND_BEGIN_SILENCE) { level++; } else if (op->opcode == ZEND_END_SILENCE) { if (level == 0) { break; } else { level--; } } if (op->op1_type == IS_VAR && op->op1.var == var) { if (use) { /* used more than once */ use = NULL; break; } use = op; } else if (op->op2_type == IS_VAR && op->op2.var == var) { if (use) { /* used more than once */ use = NULL; break; } use = op; } op++; } if (use) { if (use->op1_type == IS_VAR && use->op1.var == var) { use->op1_type = IS_CV; use->op1.var = zend_optimizer_lookup_cv(op_array, Z_STR(ZEND_OP1_LITERAL(opline))); MAKE_NOP(opline); } else if (use->op2_type == IS_VAR && use->op2.var == var) { use->op2_type = IS_CV; use->op2.var = zend_optimizer_lookup_cv(op_array, Z_STR(ZEND_OP1_LITERAL(opline))); MAKE_NOP(opline); } } } break; } opline++; i++; } }