void database_ssdb::__construct(const php::parameter& param) { php::value conf = param[0]; std::string host = conf["host"]; zend_long port = conf["port"]; if(host.empty() || port <= 0 || port > 65535) { zend_throw_error(nullptr, "illegal ssdb config #3"); return; } int timeout = 2000; if(conf.__isset("timeout")) { timeout = (long)conf["timeout"]; } pssdb = ssdb::Client::connect(host, port, timeout); if(pssdb == nullptr) { zend_throw_error(nullptr, "ssd failed to connect ssdb"); return; } if(conf.__isset("auth")) { php::parameter auth(conf["auth"].intern(), 1); __call("auth", auth); } prefix = (std::string)conf["prefix"]; // 保存一个属性,方便客户端调用 php::property prop(this); prop.oset("prefix", prefix); }
php::value database_ssdb::init(const php::parameter& param) { if(param.size < 1 || !param[0].is_type(IS_ARRAY)) { zend_throw_error(NULL, "ssdb config of type array is required"); return false; } php::value conf = param[0]; if(!conf.__isset("master") && !conf.__isset("slave")) { zend_throw_error(NULL, "illegal ssdb config #1"); return false; } php::property prop(database_ssdb::class_entry); prop.sset("_conf", conf); return true; }
/* {{{ proto TimecopDateTime::__construct([string time[, DateTimeZone object]]) Creates new TimecopDateTime object */ PHP_METHOD(TimecopDateTime, __construct) { zval *params; zval *obj = getThis(); params = (zval *)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval), 0); if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), params) == FAILURE) { efree(params); zend_throw_error(NULL, "Cannot get arguments for TimecopDateTime::__construct"); RETURN_FALSE; } /* call original DateTime::__construct() */ timecop_call_original_constructor(obj, TIMECOP_G(ce_DateTime), params, ZEND_NUM_ARGS()); if (!EG(exception)) { zval *time = NULL, *timezone_obj = NULL; if (ZEND_NUM_ARGS() >= 1) { time = ¶ms[0]; } if (ZEND_NUM_ARGS() >= 2) { timezone_obj = ¶ms[1]; } fix_datetime_timestamp(obj, time, timezone_obj); } efree(params); }
/* {{{ proto Exception|Error::__construct(string message, int code [, Throwable previous]) Exception constructor */ ZEND_METHOD(exception, __construct) { zend_string *message = NULL; zend_long code = 0; zval *object, *previous = NULL; zend_class_entry *base_ce; int argc = ZEND_NUM_ARGS(); object = getThis(); base_ce = i_get_exception_base(object); if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SlO!", &message, &code, &previous, zend_ce_throwable) == FAILURE) { zend_class_entry *ce; if (execute_data->called_scope) { ce = execute_data->called_scope; } else { ce = base_ce; } zend_throw_error(NULL, "Wrong parameters for %s([string $message [, long $code [, Throwable $previous = NULL]]])", ZSTR_VAL(ce->name)); return; } if (message) { zend_update_property_str(base_ce, object, "message", sizeof("message")-1, message); } if (code) { zend_update_property_long(base_ce, object, "code", sizeof("code")-1, code); } if (previous) { zend_update_property(base_ce, object, "previous", sizeof("previous")-1, previous); } }
zend_object_iterator *php_com_saproxy_iter_get(zend_class_entry *ce, zval *object, int by_ref) { php_com_saproxy *proxy = SA_FETCH(object); php_com_saproxy_iter *I; int i; if (by_ref) { zend_throw_error(NULL, "An iterator cannot be used with foreach by reference"); return NULL; } I = ecalloc(1, sizeof(*I)); I->iter.funcs = &saproxy_iter_funcs; Z_PTR(I->iter.data) = I; I->proxy = proxy; ZVAL_COPY(&I->proxy_obj, object); I->indices = safe_emalloc(proxy->dimensions + 1, sizeof(LONG), 0); for (i = 0; i < proxy->dimensions; i++) { convert_to_long(&proxy->indices[i]); I->indices[i] = (LONG)Z_LVAL(proxy->indices[i]); } SafeArrayGetLBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imin); SafeArrayGetUBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imax); I->key = I->imin; return &I->iter; }
/* {{{ _timecop_call_mktime - timecop_(gm)mktime helper */ static void _timecop_call_mktime(INTERNAL_FUNCTION_PARAMETERS, const char *mktime_function_name, const char *date_function_name) { zval *params; uint32_t param_count; int i; param_count = MAX(ZEND_NUM_ARGS(), MKTIME_NUM_ARGS); params = (zval *)safe_emalloc(param_count, sizeof(zval), 0); if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), params) == FAILURE) { efree(params); zend_throw_error(NULL, "Cannot get arguments for calling"); return; } param_count = ZEND_NUM_ARGS(); if (param_count < MKTIME_NUM_ARGS) { fill_mktime_params(params, date_function_name, param_count); param_count = MKTIME_NUM_ARGS; } if (ZEND_NUM_ARGS() == 0) { php_error_docref(NULL, E_STRICT, "You should be using the time() function instead"); } simple_call_function(mktime_function_name, return_value, param_count, params); for (i = ZEND_NUM_ARGS(); i < MKTIME_NUM_ARGS; i++) { zval_ptr_dtor(¶ms[i]); } efree(params); }
/* {{{ clone handler for Transliterator */ static zend_object *Transliterator_clone_obj( zval *object ) { Transliterator_object *to_orig, *to_new; zend_object *ret_val; intl_error_reset( NULL ); to_orig = Z_INTL_TRANSLITERATOR_P( object ); intl_error_reset( INTL_DATA_ERROR_P( to_orig ) ); ret_val = Transliterator_ce_ptr->create_object( Z_OBJCE_P( object ) ); to_new = php_intl_transliterator_fetch_object( ret_val ); zend_objects_clone_members( &to_new->zo, &to_orig->zo ); if( to_orig->utrans != NULL ) { zval tempz; /* dummy zval to pass to transliterator_object_construct */ /* guaranteed to return NULL if it fails */ UTransliterator *utrans = utrans_clone( to_orig->utrans, TRANSLITERATOR_ERROR_CODE_P( to_orig ) ); if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to_orig ) ) ) goto err; ZVAL_OBJ(&tempz, ret_val); transliterator_object_construct( &tempz, utrans, TRANSLITERATOR_ERROR_CODE_P( to_orig ) ); if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to_orig ) ) ) { zend_string *err_msg; err: if( utrans != NULL ) transliterator_object_destroy( to_new ); /* set the error anyway, in case in the future we decide not to * throw an error. It also helps build the error message */ intl_error_set_code( NULL, INTL_DATA_ERROR_CODE( to_orig ) ); intl_errors_set_custom_msg( TRANSLITERATOR_ERROR_P( to_orig ), "Could not clone transliterator", 0 ); err_msg = intl_error_get_message( TRANSLITERATOR_ERROR_P( to_orig ) ); zend_throw_error( NULL, "%s", ZSTR_VAL(err_msg) ); zend_string_free( err_msg ); /* if it's changed into a warning */ /* do not destroy tempz; we need to return something */ } } else { /* We shouldn't have unconstructed objects in the first place */ php_error_docref( NULL, E_WARNING, "Cloning unconstructed transliterator." ); } return ret_val; }
/* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Throwable previous]]]) ErrorException constructor */ ZEND_METHOD(error_exception, __construct) { char *message = NULL, *filename = NULL; zend_long code = 0, severity = E_ERROR, lineno; zval tmp, *object, *previous = NULL; int argc = ZEND_NUM_ARGS(); size_t message_len, filename_len; if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|sllslO!", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, zend_ce_throwable) == FAILURE) { zend_class_entry *ce; if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else if (Z_CE(EX(This))) { ce = Z_CE(EX(This)); } else { ce = zend_ce_error_exception; } zend_throw_error(NULL, "Wrong parameters for %s([string $message [, long $code, [ long $severity, [ string $filename, [ long $lineno [, Throwable $previous = NULL]]]]]])", ZSTR_VAL(ce->name)); return; } object = getThis(); if (message) { ZVAL_STRING(&tmp, message); zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_MESSAGE], &tmp); zval_ptr_dtor(&tmp); } if (code) { ZVAL_LONG(&tmp, code); zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_CODE], &tmp); } if (previous) { zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_PREVIOUS], previous); } ZVAL_LONG(&tmp, severity); zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_SEVERITY], &tmp); if (argc >= 4) { ZVAL_STRING(&tmp, filename); zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_FILE], &tmp); zval_ptr_dtor(&tmp); if (argc < 5) { lineno = 0; /* invalidate lineno */ } ZVAL_LONG(&tmp, lineno); zend_update_property_ex(zend_ce_exception, object, CG(known_strings)[ZEND_STR_LINE], &tmp); } }
void ZEND_FASTCALL zend_jit_deprecated_or_abstract_helper(OPLINE_D) { zend_function *fbc = ((zend_execute_data*)(opline))->func; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); } else if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", fbc->common.scope ? ZSTR_VAL(fbc->common.scope->name) : "", fbc->common.scope ? "::" : "", ZSTR_VAL(fbc->common.function_name)); } }
static zval *zephir_std_get_static_property(zend_class_entry *ce, const char *property_name, int property_name_len, zend_bool silent, zend_property_info **param_property_info) { zend_property_info *property_info; zval *ret; if (param_property_info == NULL) { property_info = zend_hash_str_find_ptr(&ce->properties_info, property_name, property_name_len); if (UNEXPECTED(property_info == NULL)) { goto undeclared_property; } /*if (UNEXPECTED(!zend_verify_property_access(property_info, ce))) { if (!silent) { zend_throw_error(NULL, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ZSTR_VAL(ce->name), property_name); } return NULL; }*/ if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) { goto undeclared_property; } if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) { if (UNEXPECTED(zend_update_class_constants(ce)) != SUCCESS) { return NULL; } } ret = CE_STATIC_MEMBERS(ce) + property_info->offset; if (param_property_info) { *param_property_info = property_info; } } else { property_info = *param_property_info; } /* check if static properties were destoyed */ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { undeclared_property: if (!silent) { zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), property_name); } ret = NULL; } return ret; }
static void zend_throw_or_error(int fetch_type, zend_class_entry *exception_ce, const char *format, ...) /* {{{ */ { va_list va; char *message = NULL; va_start(va, format); zend_vspprintf(&message, 0, format, va); if (fetch_type & ZEND_FETCH_CLASS_EXCEPTION) { zend_throw_error(exception_ce, message); } else { zend_error(E_ERROR, message); } efree(message); va_end(va); }
/* {{{ proto TimecopOrigDateTime::__construct([string time[, DateTimeZone object]]) Creates new TimecopOrigDateTime object */ PHP_METHOD(TimecopOrigDateTime, __construct) { zval *params; zval *obj = getThis(); params = (zval *)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval), 0); if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), params) == FAILURE) { efree(params); zend_throw_error(NULL, "Cannot get arguments for TimecopOrigDateTime::__construct"); RETURN_FALSE; } /* call original DateTime::__construct() */ timecop_call_original_constructor(obj, TIMECOP_G(ce_DateTime), params, ZEND_NUM_ARGS()); efree(params); }
/* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Throwable previous]]]) ErrorException constructor */ ZEND_METHOD(error_exception, __construct) { char *message = NULL, *filename = NULL; zend_long code = 0, severity = E_ERROR, lineno; zval *object, *previous = NULL; int argc = ZEND_NUM_ARGS(); size_t message_len, filename_len; if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|sllslO!", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, zend_ce_throwable) == FAILURE) { zend_class_entry *ce; if (execute_data->called_scope) { ce = execute_data->called_scope; } else { ce = zend_ce_error_exception; } zend_throw_error(NULL, "Wrong parameters for %s([string $message [, long $code, [ long $severity, [ string $filename, [ long $lineno [, Throwable $previous = NULL]]]]]])", ZSTR_VAL(ce->name)); return; } object = getThis(); if (message) { zend_update_property_string(zend_ce_exception, object, "message", sizeof("message")-1, message); } if (code) { zend_update_property_long(zend_ce_exception, object, "code", sizeof("code")-1, code); } if (previous) { zend_update_property(zend_ce_exception, object, "previous", sizeof("previous")-1, previous); } zend_update_property_long(zend_ce_error_exception, object, "severity", sizeof("severity")-1, severity); if (argc >= 4) { zend_update_property_string(zend_ce_exception, object, "file", sizeof("file")-1, filename); if (argc < 5) { lineno = 0; /* invalidate lineno */ } zend_update_property_long(zend_ce_exception, object, "line", sizeof("line")-1, lineno); } }
/* {{{ zend_user_it_get_iterator */ static zend_object_iterator *zend_user_it_get_iterator(zend_class_entry *ce, zval *object, int by_ref) { zend_user_iterator *iterator; if (by_ref) { zend_throw_error(NULL, "An iterator cannot be used with foreach by reference"); return NULL; } iterator = emalloc(sizeof(zend_user_iterator)); zend_iterator_init((zend_object_iterator*)iterator); ZVAL_COPY(&iterator->it.data, object); iterator->it.funcs = &zend_interface_iterator_funcs_iterator; iterator->ce = Z_OBJCE_P(object); ZVAL_UNDEF(&iterator->value); return (zend_object_iterator*)iterator; }
php::value database_ssdb::get_slave(const php::parameter& param) { zend_long idx = 0; std::string key = "slave_"; if(param.size == 1) { idx = param[0]; } key.append(std::to_string(idx)); php::property prop(database_ssdb::class_entry); php::value cache = prop.sget("_cache"); php::value db = cache[key]; if(!db.is_type(IS_OBJECT)) { php::value conf = prop.sget("_conf"); conf = conf["slave"][idx]; if(!conf.is_type(IS_ARRAY)) { zend_throw_error(NULL, "illegal ssdb config #2"); return php::null; } db = database_ssdb::create(conf); cache[key] = db; } return db; }
/* {{{ proto Exception|Error::__construct(string message, int code [, Throwable previous]) Exception constructor */ ZEND_METHOD(exception, __construct) { zend_string *message = NULL; zend_long code = 0; zval tmp, *object, *previous = NULL; zend_class_entry *base_ce; int argc = ZEND_NUM_ARGS(); object = getThis(); base_ce = i_get_exception_base(object); if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SlO!", &message, &code, &previous, zend_ce_throwable) == FAILURE) { zend_class_entry *ce; if (Z_TYPE(EX(This)) == IS_OBJECT) { ce = Z_OBJCE(EX(This)); } else if (Z_CE(EX(This))) { ce = Z_CE(EX(This)); } else { ce = base_ce; } zend_throw_error(NULL, "Wrong parameters for %s([string $message [, long $code [, Throwable $previous = NULL]]])", ZSTR_VAL(ce->name)); return; } if (message) { ZVAL_STR(&tmp, message); zend_update_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp); } if (code) { ZVAL_LONG(&tmp, code); zend_update_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_CODE), &tmp); } if (previous) { zend_update_property_ex(base_ce, object, ZSTR_KNOWN(ZEND_STR_PREVIOUS), previous); } }
ZEND_METHOD(Closure, __invoke) /* {{{ */ { zend_function *func = EX(func); zval *arguments; arguments = emalloc(sizeof(zval) * ZEND_NUM_ARGS()); if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) { efree(arguments); zend_throw_error(NULL, "Cannot get arguments for calling closure"); RETVAL_FALSE; } else if (call_user_function_ex(CG(function_table), NULL, getThis(), return_value, ZEND_NUM_ARGS(), arguments, 1, NULL) == FAILURE) { RETVAL_FALSE; } efree(arguments); /* 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 }
/* {{{ proto Closure::__construct() Private constructor preventing instantiation */ ZEND_COLD ZEND_METHOD(Closure, __construct) { zend_throw_error(NULL, "Instantiation of 'Closure' is not allowed"); }
static ZEND_COLD zend_function *zend_closure_get_constructor(zend_object *object) /* {{{ */ { zend_throw_error(NULL, "Instantiation of 'Closure' is not allowed"); return NULL; }
php::value database_ssdb::__call(const std::string& name, const php::parameter& param) { std::vector<std::string> argv; // COMMAND std::string uname = boost::algorithm::to_lower_copy(name); // 找到命令 auto f = cmd_flag.find(uname); if(f == cmd_flag.end()) { // 没有找到对应的方法 zend_throw_error(nullptr, "redis command \"%s\" not found", uname.c_str()); return php::null; } argv.push_back(uname); // 前缀处理 int flag = f->second; if(prefix.empty() || flag & FLAG_PREFIX_NONE) { // 不处理 for(size_t i=0;i<param.size;++i) { zval* v = param.get(i); convert_to_string(v); argv.push_back(std::string(Z_STRVAL_P(v), Z_STRLEN_P(v))); } }else if(flag & FLAG_PREFIX_MULTI_ALL) { // 所有参数都处理 for(size_t i=0;i<param.size;i++) { zval* v = param.get(i); convert_to_string(v); std::string key = prefix; key.append(std::string(Z_STRVAL_P(v), Z_STRLEN_P(v))); argv.push_back(key); } }else if(flag & FLAG_PREFIX_MULTI_JUMP) { // 间隔处理 for(size_t i=0;i<param.size;i++) { zval* v = param.get(i); convert_to_string(v); if(i%2 == 1) { argv.push_back(std::string(Z_STRVAL_P(v), Z_STRLEN_P(v))); }else{ std::string key = prefix; key.append(std::string(Z_STRVAL_P(v), Z_STRLEN_P(v))); argv.push_back(key); } } }else{ // 首个参数处理 zval* v = param.get(0); convert_to_string(v); std::string key = prefix; key.append(std::string(Z_STRVAL_P(v), Z_STRLEN_P(v))); argv.push_back(key); for(size_t i=1;i<param.size;++i) { zval* v = param.get(i); convert_to_string(v); argv.push_back(std::string(Z_STRVAL_P(v), Z_STRLEN_P(v))); } } const std::vector<std::string>* reply = pssdb->request(argv); if(reply == nullptr || reply->size() < 1) { zend_throw_error(nullptr, "ssdb command \"%s\" failed #1", uname.c_str()); return php::null; } ssdb::Status status(reply); if(status.ok()) { // 返回值处理 return database_ssdb::parse(reply, flag); }else if(status.not_found()) { return php::null; }else if(reply->size() > 1){ zend_throw_error(nullptr, "ssdb command \"%s\" faild #2: %s", uname.c_str(), reply->at(1).c_str()); return php::null; }else{ zend_throw_error(nullptr, "ssdb command \"%s\" faild #3", uname.c_str()); return php::null; } }
/* {{{ _php_mb_regex_ereg_replace_exec */ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOptionType options, int is_callable) { zval *arg_pattern_zval; char *arg_pattern; size_t arg_pattern_len; char *replace; size_t replace_len; zend_fcall_info arg_replace_fci; zend_fcall_info_cache arg_replace_fci_cache; char *string; size_t string_len; char *p; php_mb_regex_t *re; OnigSyntaxType *syntax; OnigRegion *regs = NULL; smart_str out_buf = {0}; smart_str eval_buf = {0}; smart_str *pbuf; size_t i; int err, eval, n; OnigUChar *pos; OnigUChar *string_lim; char *description = NULL; char pat_buf[6]; const mbfl_encoding *enc; { const char *current_enc_name; current_enc_name = _php_mb_regex_mbctype2name(MBREX(current_mbctype)); if (current_enc_name == NULL || (enc = mbfl_name2encoding(current_enc_name)) == NULL) { php_error_docref(NULL, E_WARNING, "Unknown error"); RETURN_FALSE; } } eval = 0; { char *option_str = NULL; size_t option_str_len = 0; if (!is_callable) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "zss|s", &arg_pattern_zval, &replace, &replace_len, &string, &string_len, &option_str, &option_str_len) == FAILURE) { RETURN_FALSE; } } else { if (zend_parse_parameters(ZEND_NUM_ARGS(), "zfs|s", &arg_pattern_zval, &arg_replace_fci, &arg_replace_fci_cache, &string, &string_len, &option_str, &option_str_len) == FAILURE) { RETURN_FALSE; } } if (!php_mb_check_encoding( string, string_len, _php_mb_regex_mbctype2name(MBREX(current_mbctype)) )) { RETURN_NULL(); } if (option_str != NULL) { _php_mb_regex_init_options(option_str, option_str_len, &options, &syntax, &eval); } else { options |= MBREX(regex_default_options); syntax = MBREX(regex_default_syntax); } } if (eval && !is_callable) { php_error_docref(NULL, E_DEPRECATED, "The 'e' option is deprecated, use mb_ereg_replace_callback instead"); } if (Z_TYPE_P(arg_pattern_zval) == IS_STRING) { arg_pattern = Z_STRVAL_P(arg_pattern_zval); arg_pattern_len = Z_STRLEN_P(arg_pattern_zval); } else { /* FIXME: this code is not multibyte aware! */ convert_to_long_ex(arg_pattern_zval); pat_buf[0] = (char)Z_LVAL_P(arg_pattern_zval); pat_buf[1] = '\0'; pat_buf[2] = '\0'; pat_buf[3] = '\0'; pat_buf[4] = '\0'; pat_buf[5] = '\0'; arg_pattern = pat_buf; arg_pattern_len = 1; } /* create regex pattern buffer */ re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, options, MBREX(current_mbctype), syntax); if (re == NULL) { RETURN_FALSE; } if (eval || is_callable) { pbuf = &eval_buf; description = zend_make_compiled_string_description("mbregex replace"); } else { pbuf = &out_buf; description = NULL; } if (is_callable) { if (eval) { php_error_docref(NULL, E_WARNING, "Option 'e' cannot be used with replacement callback"); RETURN_FALSE; } } /* do the actual work */ err = 0; pos = (OnigUChar *)string; string_lim = (OnigUChar*)(string + string_len); regs = onig_region_new(); while (err >= 0) { err = onig_search(re, (OnigUChar *)string, (OnigUChar *)string_lim, pos, (OnigUChar *)string_lim, regs, 0); if (err <= -2) { OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(err_str, err); php_error_docref(NULL, E_WARNING, "mbregex search failure in php_mbereg_replace_exec(): %s", err_str); break; } if (err >= 0) { #if moriyoshi_0 if (regs->beg[0] == regs->end[0]) { php_error_docref(NULL, E_WARNING, "Empty regular expression"); break; } #endif /* copy the part of the string before the match */ smart_str_appendl(&out_buf, (char *)pos, (size_t)((OnigUChar *)(string + regs->beg[0]) - pos)); if (!is_callable) { /* copy replacement and backrefs */ i = 0; p = replace; while (i < replace_len) { int fwd = (int) php_mb_mbchar_bytes_ex(p, enc); n = -1; if ((replace_len - i) >= 2 && fwd == 1 && p[0] == '\\' && p[1] >= '0' && p[1] <= '9') { n = p[1] - '0'; } if (n >= 0 && n < regs->num_regs) { if (regs->beg[n] >= 0 && regs->beg[n] < regs->end[n] && (size_t)regs->end[n] <= string_len) { smart_str_appendl(pbuf, string + regs->beg[n], regs->end[n] - regs->beg[n]); } p += 2; i += 2; } else { smart_str_appendl(pbuf, p, fwd); p += fwd; i += fwd; } } } if (eval) { zval v; zend_string *eval_str; /* null terminate buffer */ smart_str_0(&eval_buf); if (eval_buf.s) { eval_str = eval_buf.s; } else { eval_str = ZSTR_EMPTY_ALLOC(); } /* do eval */ if (zend_eval_stringl(ZSTR_VAL(eval_str), ZSTR_LEN(eval_str), &v, description) == FAILURE) { efree(description); zend_throw_error(NULL, "Failed evaluating code: %s%s", PHP_EOL, ZSTR_VAL(eval_str)); onig_region_free(regs, 0); smart_str_free(&out_buf); smart_str_free(&eval_buf); RETURN_FALSE; } /* result of eval */ convert_to_string(&v); smart_str_appendl(&out_buf, Z_STRVAL(v), Z_STRLEN(v)); /* Clean up */ smart_str_free(&eval_buf); zval_dtor(&v); } else if (is_callable) { zval args[1]; zval subpats, retval; int i; array_init(&subpats); for (i = 0; i < regs->num_regs; i++) { add_next_index_stringl(&subpats, string + regs->beg[i], regs->end[i] - regs->beg[i]); } ZVAL_COPY_VALUE(&args[0], &subpats); /* null terminate buffer */ smart_str_0(&eval_buf); arg_replace_fci.param_count = 1; arg_replace_fci.params = args; arg_replace_fci.retval = &retval; if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache) == SUCCESS && !Z_ISUNDEF(retval)) { convert_to_string_ex(&retval); smart_str_appendl(&out_buf, Z_STRVAL(retval), Z_STRLEN(retval)); smart_str_free(&eval_buf); zval_ptr_dtor(&retval); } else { if (!EG(exception)) { php_error_docref(NULL, E_WARNING, "Unable to call custom replacement function"); } } zval_ptr_dtor(&subpats); } n = regs->end[0]; if ((pos - (OnigUChar *)string) < n) { pos = (OnigUChar *)string + n; } else { if (pos < string_lim) { smart_str_appendl(&out_buf, (char *)pos, 1); } pos++; } } else { /* nomatch */ /* stick that last bit of string on our output */ if (string_lim - pos > 0) { smart_str_appendl(&out_buf, (char *)pos, string_lim - pos); } } onig_region_free(regs, 0); } if (description) { efree(description); } if (regs != NULL) { onig_region_free(regs, 1); } smart_str_free(&eval_buf); if (err <= -2) { smart_str_free(&out_buf); RETVAL_FALSE; } else if (out_buf.s) { smart_str_0(&out_buf); RETVAL_STR(out_buf.s); } else { RETVAL_EMPTY_STRING(); } }
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); } }
zend_object_iterator *php_com_iter_get(zend_class_entry *ce, zval *object, int by_ref) { php_com_dotnet_object *obj; struct php_com_iterator *I; IEnumVARIANT *iev = NULL; DISPPARAMS dp; VARIANT v; unsigned long n_fetched; zval ptr; if (by_ref) { zend_throw_error(NULL, "An iterator cannot be used with foreach by reference"); return NULL; } obj = CDNO_FETCH(object); if (V_VT(&obj->v) != VT_DISPATCH && !V_ISARRAY(&obj->v)) { php_error_docref(NULL, E_WARNING, "variant is not an object or array VT=%d", V_VT(&obj->v)); return NULL; } memset(&dp, 0, sizeof(dp)); VariantInit(&v); I = (struct php_com_iterator*)ecalloc(1, sizeof(*I)); zend_iterator_init(&I->iter); I->iter.funcs = &com_iter_funcs; Z_PTR(I->iter.data) = I; I->code_page = obj->code_page; ZVAL_UNDEF(&I->zdata); VariantInit(&I->safe_array); VariantInit(&I->v); if (V_ISARRAY(&obj->v)) { LONG bound; UINT dims; dims = SafeArrayGetDim(V_ARRAY(&obj->v)); if (dims != 1) { php_error_docref(NULL, E_WARNING, "Can only handle single dimension variant arrays (this array has %d)", dims); goto fail; } /* same semantics as foreach on a PHP array; * make a copy and enumerate that copy */ VariantCopy(&I->safe_array, &obj->v); /* determine the key value for the array */ SafeArrayGetLBound(V_ARRAY(&I->safe_array), 1, &bound); SafeArrayGetUBound(V_ARRAY(&I->safe_array), 1, &I->sa_max); /* pre-fetch the element */ if (php_com_safearray_get_elem(&I->safe_array, &I->v, bound)) { I->key = bound; ZVAL_NULL(&ptr); php_com_zval_from_variant(&ptr, &I->v, I->code_page); ZVAL_COPY_VALUE(&I->zdata, &ptr); } else { I->key = (ulong)-1; } } else { /* can we enumerate it? */ if (FAILED(IDispatch_Invoke(V_DISPATCH(&obj->v), DISPID_NEWENUM, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL))) { goto fail; } /* get something useful out of it */ if (V_VT(&v) == VT_UNKNOWN) { IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IEnumVARIANT, (void**)&iev); } else if (V_VT(&v) == VT_DISPATCH) { IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IEnumVARIANT, (void**)&iev); } VariantClear(&v); if (iev == NULL) { goto fail; } I->ev = iev; /* Get the first element now */ if (SUCCEEDED(IEnumVARIANT_Next(I->ev, 1, &I->v, &n_fetched)) && n_fetched > 0) { /* indicate that we have element 0 */ I->key = 0; ZVAL_NULL(&ptr); php_com_zval_from_variant(&ptr, &I->v, I->code_page); ZVAL_COPY_VALUE(&I->zdata, &ptr); } else { /* indicate that there are no more items */ I->key = (ulong)-1; } } return &I->iter; fail: if (I) { VariantClear(&I->safe_array); VariantClear(&I->v); efree(I); } return NULL; }
int zephir_call_func_aparams_fast(zval *return_value_ptr, zephir_fcall_cache_entry **cache_entry, zend_uint param_count, zval *params[]) { uint32_t i; zend_class_entry *calling_scope = NULL; zend_execute_data *call, dummy_execute_data; zval retval_local; zval *retval_ptr = return_value_ptr ? return_value_ptr : &retval_local; zend_class_entry *orig_scope; zend_function *func; if (return_value_ptr) { zval_ptr_dtor(return_value_ptr); ZVAL_UNDEF(return_value_ptr); } else { ZVAL_UNDEF(&retval_local); } if (!EG(active)) { return FAILURE; /* executor is already inactive */ } if (EG(exception)) { return FAILURE; /* we would result in an instable executor otherwise */ } orig_scope = EG(scope); /* Initialize execute_data */ if (!EG(current_execute_data)) { /* This only happens when we're called outside any execute()'s * It shouldn't be strictly necessary to NULL execute_data out, * but it may make bugs easier to spot */ memset(&dummy_execute_data, 0, sizeof(zend_execute_data)); 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_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); dummy_execute_data.call = NULL; dummy_execute_data.opline = NULL; dummy_execute_data.func = NULL; EG(current_execute_data) = &dummy_execute_data; } #ifndef ZEPHIR_RELEASE func = (*cache_entry)->f; ++(*cache_entry)->times; #else func = *cache_entry; #endif calling_scope = NULL; call = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_FUNCTION, func, param_count, NULL, NULL); for (i = 0; i < param_count; i++) { zval *param; zval *arg = params[i]; if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) { if (!Z_ISREF_P(arg)) { /*if (!ARG_MAY_BE_SENT_BY_REF(func, i + 1)) { if (i) { // hack to clean up the stack ZEND_CALL_NUM_ARGS(call) = i; zend_vm_stack_free_args(call); } zend_vm_stack_free_call_frame(call); zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given", i+1, func->common.scope ? ZSTR_VAL(func->common.scope->name) : "", func->common.scope ? "::" : "", ZSTR_VAL(func->common.function_name)); if (EG(current_execute_data) == &dummy_execute_data) { EG(current_execute_data) = dummy_execute_data.prev_execute_data; } return FAILURE; }*/ ZVAL_NEW_REF(arg, arg); } Z_ADDREF_P(arg); } else { if (Z_ISREF_P(arg) && !(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { /* don't separate references for __call */ arg = Z_REFVAL_P(arg); } if (Z_OPT_REFCOUNTED_P(arg)) { Z_ADDREF_P(arg); } } param = ZEND_CALL_ARG(call, i+1); ZVAL_COPY_VALUE(param, arg); } EG(scope) = calling_scope; Z_OBJ(call->This) = NULL; if (func->type == ZEND_USER_FUNCTION) { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; EG(scope) = func->common.scope; call->symbol_table = NULL; if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) { ZEND_ASSERT(GC_TYPE((zend_object*)func->op_array.prototype) == IS_OBJECT); GC_REFCOUNT((zend_object*)func->op_array.prototype)++; ZEND_ADD_CALL_FLAG(call, ZEND_CALL_CLOSURE); } if (EXPECTED((func->op_array.fn_flags & ZEND_ACC_GENERATOR) == 0)) { zend_init_execute_data(call, &func->op_array, retval_ptr); zend_execute_ex(call); } else { zend_generator_create_zval(call, &func->op_array, retval_ptr); } if (call_via_handler) { /* We must re-initialize function again */ *cache_entry = NULL; } } else if (func->type == ZEND_INTERNAL_FUNCTION) { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; if (func->common.scope) { EG(scope) = func->common.scope; } call->prev_execute_data = EG(current_execute_data); call->return_value = NULL; /* this is not a constructor call */ EG(current_execute_data) = call; if (EXPECTED(zend_execute_internal == NULL)) { /* saves one function call if zend_execute_internal is not used */ func->internal_function.handler(call, retval_ptr); } else { zend_execute_internal(call, retval_ptr); } EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); /* We shouldn't fix bad extensions here, because it can break proper ones (Bug #34045) if (!EX(function_state).function->common.return_reference) { INIT_PZVAL(f->retval); }*/ if (EG(exception)) { zval_ptr_dtor(retval_ptr); ZVAL_UNDEF(retval_ptr); } if (call_via_handler) { /* We must re-initialize function again */ *cache_entry = NULL; } } else { /* ZEND_OVERLOADED_FUNCTION */ ZVAL_NULL(retval_ptr); zend_throw_error(NULL, "Cannot call overloaded function for non-object"); zend_vm_stack_free_args(call); if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { zend_string_release(func->common.function_name); } efree(func); if (EG(exception)) { zval_ptr_dtor(retval_ptr); ZVAL_UNDEF(retval_ptr); } } EG(scope) = orig_scope; zend_vm_stack_free_call_frame(call); if (EG(current_execute_data) == &dummy_execute_data) { EG(current_execute_data) = dummy_execute_data.prev_execute_data; } if (EG(exception)) { zend_throw_exception_internal(NULL); } return SUCCESS; }
/* {{{ inifile_delete_replace_append */ static int inifile_delete_replace_append(inifile *dba, const key_type *key, const val_type *value, int append, zend_bool *found) { size_t pos_grp_start=0, pos_grp_next; inifile *ini_tmp = NULL; php_stream *fp_tmp = NULL; int ret; /* 1) Search group start * 2) Search next group * 3) If not append: Copy group to ini_tmp * 4) Open temp_stream and copy remainder * 5) Truncate stream * 6) If not append AND key.name given: Filtered copy back from ini_tmp * to stream. Otherwise the user wanted to delete the group. * 7) Append value if given * 8) Append temporary stream */ assert(!append || (key->name && value)); /* missuse */ /* 1 - 3 */ inifile_find_group(dba, key, &pos_grp_start); inifile_next_group(dba, key, &pos_grp_next); if (append) { ret = SUCCESS; } else { ret = inifile_copy_to(dba, pos_grp_start, pos_grp_next, &ini_tmp); } /* 4 */ if (ret == SUCCESS) { fp_tmp = php_stream_temp_create(0, 64 * 1024); if (!fp_tmp) { php_error_docref(NULL, E_WARNING, "Could not create temporary stream"); ret = FAILURE; } else { php_stream_seek(dba->fp, 0, SEEK_END); if (pos_grp_next != (size_t)php_stream_tell(dba->fp)) { php_stream_seek(dba->fp, pos_grp_next, SEEK_SET); if (SUCCESS != php_stream_copy_to_stream_ex(dba->fp, fp_tmp, PHP_STREAM_COPY_ALL, NULL)) { php_error_docref(NULL, E_WARNING, "Could not copy remainder to temporary stream"); ret = FAILURE; } } } } /* 5 */ if (ret == SUCCESS) { if (!value || (key->name && strlen(key->name))) { ret = inifile_truncate(dba, append ? pos_grp_next : pos_grp_start); /* writes error on fail */ } } if (ret == SUCCESS) { if (key->name && strlen(key->name)) { /* 6 */ if (!append && ini_tmp) { ret = inifile_filter(dba, ini_tmp, key, found); } /* 7 */ /* important: do not query ret==SUCCESS again: inifile_filter might fail but * however next operation must be done. */ if (value) { if (pos_grp_start == pos_grp_next && key->group && strlen(key->group)) { php_stream_printf(dba->fp, "[%s]\n", key->group); } php_stream_printf(dba->fp, "%s=%s\n", key->name, value->value ? value->value : ""); } } /* 8 */ /* important: do not query ret==SUCCESS again: inifile_filter might fail but * however next operation must be done. */ if (fp_tmp && php_stream_tell(fp_tmp)) { php_stream_seek(fp_tmp, 0, SEEK_SET); php_stream_seek(dba->fp, 0, SEEK_END); if (SUCCESS != php_stream_copy_to_stream_ex(fp_tmp, dba->fp, PHP_STREAM_COPY_ALL, NULL)) { zend_throw_error(NULL, "Could not copy from temporary stream - ini file truncated"); ret = FAILURE; } } } if (ini_tmp) { php_stream_close(ini_tmp->fp); inifile_free(ini_tmp, 0); } if (fp_tmp) { php_stream_close(fp_tmp); } php_stream_flush(dba->fp); php_stream_seek(dba->fp, 0, SEEK_SET); return ret; }
/* {{{ mysqli_write_na */ static int mysqli_write_na(mysqli_object *obj, zval *newval) { zend_throw_error(NULL, "Cannot write property"); return FAILURE; }
/* {{{ mysqli_read_na */ static zval *mysqli_read_na(mysqli_object *obj, zval *retval) { zend_throw_error(NULL, "Cannot read property"); return NULL; }
/** * Copies of internal methods from Zend/zend_execute_API.c * These are used to call internal methods (not in the function table) from the external method. * TODO: See if xdebug works */ int runkit_forward_call_user_function(zend_function *fbc, zend_function *fbc_inner, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { uint32_t i; zend_execute_data *call, dummy_execute_data; zend_fcall_info_cache fci_cache_local = {0}; zend_function *func; /* {{{ patch for runkit */ zend_fcall_info fci = {0}; zend_fcall_info_cache *fci_cache = NULL; fci.size = sizeof(fci); fci.object = NULL; // FIXME for methods? // object ? Z_OBJ_P(object) : NULL; ZVAL_STR(&fci.function_name, fbc_inner->common.function_name); zend_string_addref(fbc_inner->common.function_name); fci.retval = return_value; fci.param_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data)); fci.params = ZEND_CALL_ARG(EG(current_execute_data), 1); // params and param_count From zend_API.c fci.no_separation = (zend_bool)1; // ??? /* end patch for runkit }}} */ ZVAL_UNDEF(fci.retval); if (!EG(active)) { return FAILURE; /* executor is already inactive */ } if (EG(exception)) { return FAILURE; /* we would result in an unstable executor otherwise */ } /* Initialize execute_data */ if (!EG(current_execute_data)) { /* This only happens when we're called outside any execute()'s * It shouldn't be strictly necessary to NULL execute_data out, * but it may make bugs easier to spot */ memset(&dummy_execute_data, 0, sizeof(zend_execute_data)); 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_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); dummy_execute_data.call = NULL; dummy_execute_data.opline = NULL; dummy_execute_data.func = NULL; EG(current_execute_data) = &dummy_execute_data; } if (!fci_cache || !RUNKIT_IS_FCI_CACHE_INITIALIZED(fci_cache)) { zend_string *callable_name; char *error = NULL; if (!fci_cache) { fci_cache = &fci_cache_local; } if (!zend_is_callable_ex(&fci.function_name, fci.object, IS_CALLABLE_CHECK_SILENT, &callable_name, fci_cache, &error)) { if (error) { zend_error(E_WARNING, "Invalid callback %s, %s", ZSTR_VAL(callable_name), error); efree(error); } if (callable_name) { zend_string_release(callable_name); } if (EG(current_execute_data) == &dummy_execute_data) { EG(current_execute_data) = dummy_execute_data.prev_execute_data; } return FAILURE; } else if (error) { /* Capitalize the first latter of the error message */ if (error[0] >= 'a' && error[0] <= 'z') { error[0] += ('A' - 'a'); } zend_error(E_DEPRECATED, "%s", error); efree(error); } zend_string_release(callable_name); } func = fbc_inner; fci.object = (func->common.fn_flags & ZEND_ACC_STATIC) ? NULL : fci_cache->object; call = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_FUNCTION | ZEND_CALL_DYNAMIC, func, fci.param_count, fci_cache->called_scope, fci.object); if (fci.object && (!EG(objects_store).object_buckets || !IS_OBJ_VALID(EG(objects_store).object_buckets[fci.object->handle]))) { if (EG(current_execute_data) == &dummy_execute_data) { EG(current_execute_data) = dummy_execute_data.prev_execute_data; } return FAILURE; } if (func->common.fn_flags & (ZEND_ACC_ABSTRACT | ZEND_ACC_DEPRECATED)) { if (func->common.fn_flags & ZEND_ACC_ABSTRACT) { zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name)); if (EG(current_execute_data) == &dummy_execute_data) { EG(current_execute_data) = dummy_execute_data.prev_execute_data; } return FAILURE; } if (func->common.fn_flags & ZEND_ACC_DEPRECATED) { zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", func->common.scope ? ZSTR_VAL(func->common.scope->name) : "", func->common.scope ? "::" : "", ZSTR_VAL(func->common.function_name)); } } for (i = 0; i < fci.param_count; i++) { zval *param; zval *arg = &fci.params[i]; if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) { if (UNEXPECTED(!Z_ISREF_P(arg))) { if (!fci.no_separation) { /* Separation is enabled -- create a ref */ ZVAL_NEW_REF(arg, arg); } else if (!ARG_MAY_BE_SENT_BY_REF(func, i + 1)) { /* By-value send is not allowed -- emit a warning, * but still perform the call with a by-value send. */ zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given", i + 1, func->common.scope ? ZSTR_VAL(func->common.scope->name) : "", func->common.scope ? "::" : "", ZSTR_VAL(func->common.function_name)); } } } else { if (Z_ISREF_P(arg) && !(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { /* don't separate references for __call */ arg = Z_REFVAL_P(arg); } } param = ZEND_CALL_ARG(call, i + 1); ZVAL_COPY(param, arg); } if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) { ZEND_ASSERT(GC_TYPE((zend_object *)func->op_array.prototype) == IS_OBJECT); GC_ADDREF((zend_object *)func->op_array.prototype); ZEND_ADD_CALL_FLAG(call, ZEND_CALL_CLOSURE); } if (func->type == ZEND_USER_FUNCTION) { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; zend_init_execute_data(call, &func->op_array, fci.retval); zend_execute_ex(call); if (call_via_handler) { /* We must re-initialize function again */ RUNKIT_CLEAR_FCI_CACHE(fci_cache); } } else if (func->type == ZEND_INTERNAL_FUNCTION) { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; ZVAL_NULL(fci.retval); call->prev_execute_data = EG(current_execute_data); call->return_value = NULL; /* this is not a constructor call */ EG(current_execute_data) = call; if (EXPECTED(zend_execute_internal == NULL)) { /* saves one function call if zend_execute_internal is not used */ func->internal_function.handler(call, fci.retval); } else { zend_execute_internal(call, fci.retval); } EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); /* We shouldn't fix bad extensions here, because it can break proper ones (Bug #34045) if (!EX(function_state).function->common.return_reference) { INIT_PZVAL(f->retval); }*/ if (EG(exception)) { zval_ptr_dtor(fci.retval); ZVAL_UNDEF(fci.retval); } if (call_via_handler) { /* We must re-initialize function again */ RUNKIT_CLEAR_FCI_CACHE(fci_cache); } } else { /* ZEND_OVERLOADED_FUNCTION */ ZVAL_NULL(fci.retval); /* Not sure what should be done here if it's a static method */ if (fci.object) { call->prev_execute_data = EG(current_execute_data); EG(current_execute_data) = call; fci.object->handlers->call_method(func->common.function_name, fci.object, call, fci.retval); EG(current_execute_data) = call->prev_execute_data; } else { zend_throw_error(NULL, "Cannot call overloaded function for non-object"); } zend_vm_stack_free_args(call); if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { zend_string_release(func->common.function_name); } efree(func); if (EG(exception)) { zval_ptr_dtor(fci.retval); ZVAL_UNDEF(fci.retval); } } zend_vm_stack_free_call_frame(call); if (EG(current_execute_data) == &dummy_execute_data) { EG(current_execute_data) = dummy_execute_data.prev_execute_data; } if (EG(exception)) { zend_throw_exception_internal(NULL); } return SUCCESS; }
PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array) { char *p = NULL; char *ip = NULL; /* index pointer */ char *index; char *var, *var_orig; size_t var_len, index_len; zval gpc_element, *gpc_element_p; zend_bool is_array = 0; HashTable *symtable1 = NULL; ALLOCA_FLAG(use_heap) assert(var_name != NULL); if (track_vars_array && Z_TYPE_P(track_vars_array) == IS_ARRAY) { symtable1 = Z_ARRVAL_P(track_vars_array); } if (!symtable1) { /* Nothing to do */ zval_ptr_dtor_nogc(val); return; } /* ignore leading spaces in the variable name */ while (*var_name==' ') { var_name++; } /* * Prepare variable name */ var_len = strlen(var_name); var = var_orig = do_alloca(var_len + 1, use_heap); memcpy(var_orig, var_name, var_len + 1); /* ensure that we don't have spaces or dots in the variable name (not binary safe) */ for (p = var; *p; p++) { if (*p == ' ' || *p == '.') { *p='_'; } else if (*p == '[') { is_array = 1; ip = p; *p = 0; break; } } var_len = p - var; if (var_len==0) { /* empty variable name, or variable name with a space in it */ zval_ptr_dtor_nogc(val); free_alloca(var_orig, use_heap); return; } if (var_len == sizeof("this")-1 && EG(current_execute_data)) { zend_execute_data *ex = EG(current_execute_data); while (ex) { if (ex->func && ZEND_USER_CODE(ex->func->common.type)) { if ((ZEND_CALL_INFO(ex) & ZEND_CALL_HAS_SYMBOL_TABLE) && ex->symbol_table == symtable1) { if (memcmp(var, "this", sizeof("this")-1) == 0) { zend_throw_error(NULL, "Cannot re-assign $this"); zval_ptr_dtor_nogc(val); free_alloca(var_orig, use_heap); return; } } break; } ex = ex->prev_execute_data; } } /* GLOBALS hijack attempt, reject parameter */ if (symtable1 == &EG(symbol_table) && var_len == sizeof("GLOBALS")-1 && !memcmp(var, "GLOBALS", sizeof("GLOBALS")-1)) { zval_ptr_dtor_nogc(val); free_alloca(var_orig, use_heap); return; } index = var; index_len = var_len; if (is_array) { int nest_level = 0; while (1) { char *index_s; size_t new_idx_len = 0; if(++nest_level > PG(max_input_nesting_level)) { HashTable *ht; /* too many levels of nesting */ if (track_vars_array) { ht = Z_ARRVAL_P(track_vars_array); zend_symtable_str_del(ht, var, var_len); } zval_ptr_dtor_nogc(val); /* do not output the error message to the screen, this helps us to to avoid "information disclosure" */ if (!PG(display_errors)) { php_error_docref(NULL, E_WARNING, "Input variable nesting level exceeded " ZEND_LONG_FMT ". To increase the limit change max_input_nesting_level in php.ini.", PG(max_input_nesting_level)); } free_alloca(var_orig, use_heap); return; } ip++; index_s = ip; if (isspace(*ip)) { ip++; } if (*ip==']') { index_s = NULL; } else { ip = strchr(ip, ']'); if (!ip) { /* PHP variables cannot contain '[' in their names, so we replace the character with a '_' */ *(index_s - 1) = '_'; index_len = 0; if (index) { index_len = strlen(index); } goto plain_var; return; } *ip = 0; new_idx_len = strlen(index_s); } if (!index) { array_init(&gpc_element); if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) { zend_array_destroy(Z_ARR(gpc_element)); zval_ptr_dtor_nogc(val); free_alloca(var_orig, use_heap); return; } } else { gpc_element_p = zend_symtable_str_find(symtable1, index, index_len); if (!gpc_element_p) { zval tmp; array_init(&tmp); gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &tmp); } else { if (Z_TYPE_P(gpc_element_p) == IS_INDIRECT) { gpc_element_p = Z_INDIRECT_P(gpc_element_p); } if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) { zval_ptr_dtor_nogc(gpc_element_p); array_init(gpc_element_p); } else { SEPARATE_ARRAY(gpc_element_p); } } } symtable1 = Z_ARRVAL_P(gpc_element_p); /* ip pointed to the '[' character, now obtain the key */ index = index_s; index_len = new_idx_len; ip++; if (*ip == '[') { is_array = 1; *ip = 0; } else { goto plain_var; } } } else { plain_var: if (!index) { if (zend_hash_next_index_insert(symtable1, val) == NULL) { zval_ptr_dtor_nogc(val); } } else { zend_ulong idx; /* * According to rfc2965, more specific paths are listed above the less specific ones. * If we encounter a duplicate cookie name, we should skip it, since it is not possible * to have the same (plain text) cookie name for the same path and we should not overwrite * more specific cookies with the less specific ones. */ if (Z_TYPE(PG(http_globals)[TRACK_VARS_COOKIE]) != IS_UNDEF && symtable1 == Z_ARRVAL(PG(http_globals)[TRACK_VARS_COOKIE]) && zend_symtable_str_exists(symtable1, index, index_len)) { zval_ptr_dtor_nogc(val); } else if (ZEND_HANDLE_NUMERIC_STR(index, index_len, idx)) { zend_hash_index_update(symtable1, idx, val); } else { php_register_variable_quick(index, index_len, val, symtable1); } } } free_alloca(var_orig, use_heap); }