void zend_exception_set_previous(zend_object *exception, zend_object *add_previous) /* {{{ */ { zval *previous, *ancestor, *ex; zval pv, zv, rv; zend_class_entry *base_ce; if (exception == add_previous || !add_previous || !exception) { return; } ZVAL_OBJ(&pv, add_previous); if (!instanceof_function(Z_OBJCE(pv), zend_ce_throwable)) { zend_error_noreturn(E_CORE_ERROR, "Previous exception must implement Throwable"); return; } ZVAL_OBJ(&zv, exception); ex = &zv; do { ancestor = zend_read_property_ex(i_get_exception_base(&pv), &pv, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv); while (Z_TYPE_P(ancestor) == IS_OBJECT) { if (Z_OBJ_P(ancestor) == Z_OBJ_P(ex)) { OBJ_RELEASE(add_previous); return; } ancestor = zend_read_property_ex(i_get_exception_base(ancestor), ancestor, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv); } base_ce = i_get_exception_base(ex); previous = zend_read_property_ex(base_ce, ex, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv); if (Z_TYPE_P(previous) == IS_NULL) { zend_update_property_ex(base_ce, ex, ZSTR_KNOWN(ZEND_STR_PREVIOUS), &pv); GC_DELREF(add_previous); return; } ex = previous; } while (Z_OBJ_P(ex) != add_previous); }
static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp) /* {{{ */ { zend_closure *closure = (zend_closure *)Z_OBJ_P(object); zval val; struct _zend_arg_info *arg_info = closure->func.common.arg_info; HashTable *debug_info; *is_temp = 1; ALLOC_HASHTABLE(debug_info); zend_hash_init(debug_info, 8, NULL, ZVAL_PTR_DTOR, 0); if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) { HashTable *static_variables = closure->func.op_array.static_variables; ZVAL_ARR(&val, zend_array_dup(static_variables)); zend_hash_update(debug_info, ZSTR_KNOWN(ZEND_STR_STATIC), &val); } if (Z_TYPE(closure->this_ptr) != IS_UNDEF) { Z_ADDREF(closure->this_ptr); zend_hash_update(debug_info, ZSTR_KNOWN(ZEND_STR_THIS), &closure->this_ptr); } if (arg_info && (closure->func.common.num_args || (closure->func.common.fn_flags & ZEND_ACC_VARIADIC))) { uint32_t i, num_args, required = closure->func.common.required_num_args; array_init(&val); num_args = closure->func.common.num_args; if (closure->func.common.fn_flags & ZEND_ACC_VARIADIC) { num_args++; } for (i = 0; i < num_args; i++) { zend_string *name; zval info; if (arg_info->name) { name = zend_strpprintf(0, "%s$%s", arg_info->pass_by_reference ? "&" : "", ZSTR_VAL(arg_info->name)); } else { name = zend_strpprintf(0, "%s$param%d", arg_info->pass_by_reference ? "&" : "", i + 1); } ZVAL_NEW_STR(&info, zend_strpprintf(0, "%s", i >= required ? "<optional>" : "<required>")); zend_hash_update(Z_ARRVAL(val), name, &info); zend_string_release(name); arg_info++; } zend_hash_str_update(debug_info, "parameter", sizeof("parameter")-1, &val); } return debug_info; }
ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object) /* {{{ */ { zend_closure *closure = (zend_closure *)object; zend_function *invoke = (zend_function*)emalloc(sizeof(zend_function)); const uint32_t keep_flags = ZEND_ACC_RETURN_REFERENCE | ZEND_ACC_VARIADIC | ZEND_ACC_HAS_RETURN_TYPE; invoke->common = closure->func.common; /* We return ZEND_INTERNAL_FUNCTION, but arg_info representation is the * same as for ZEND_USER_FUNCTION (uses zend_string* instead of char*). * This is not a problem, because ZEND_ACC_HAS_TYPE_HINTS is never set, * and we won't check arguments on internal function. We also set * ZEND_ACC_USER_ARG_INFO flag to prevent invalid usage by Reflection */ invoke->type = ZEND_INTERNAL_FUNCTION; invoke->internal_function.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags & keep_flags); if (closure->func.type != ZEND_INTERNAL_FUNCTION || (closure->func.common.fn_flags & ZEND_ACC_USER_ARG_INFO)) { invoke->internal_function.fn_flags |= ZEND_ACC_USER_ARG_INFO; } invoke->internal_function.handler = ZEND_MN(Closure___invoke); invoke->internal_function.module = 0; invoke->internal_function.scope = zend_ce_closure; invoke->internal_function.function_name = ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE); return invoke; }
/* {{{ 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); } }
static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type, int skip_top_traces) /* {{{ */ { zval obj, tmp; zend_object *object; zval trace; zend_class_entry *base_ce; zend_string *filename; Z_OBJ(obj) = object = zend_objects_new(class_type); Z_OBJ_HT(obj) = &default_exception_handlers; object_properties_init(object, class_type); if (EG(current_execute_data)) { zend_fetch_debug_backtrace(&trace, skip_top_traces, 0, 0); } else { array_init(&trace); } Z_SET_REFCOUNT(trace, 0); base_ce = i_get_exception_base(&obj); if (EXPECTED((class_type != zend_ce_parse_error && class_type != zend_ce_compile_error) || !(filename = zend_get_compiled_filename()))) { ZVAL_STRING(&tmp, zend_get_executed_filename()); zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_FILE), &tmp); zval_ptr_dtor(&tmp); ZVAL_LONG(&tmp, zend_get_executed_lineno()); zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_LINE), &tmp); } else { ZVAL_STR(&tmp, filename); zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_FILE), &tmp); ZVAL_LONG(&tmp, zend_get_compiled_lineno()); zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_LINE), &tmp); } zend_update_property_ex(base_ce, &obj, ZSTR_KNOWN(ZEND_STR_TRACE), &trace); return object; }
static zend_bool php_auto_globals_create_server(zend_string *name) { if (PG(variables_order) && (strchr(PG(variables_order),'S') || strchr(PG(variables_order),'s'))) { php_register_server_variables(); if (PG(register_argc_argv)) { if (SG(request_info).argc) { zval *argc, *argv; if ((argc = zend_hash_find_ex_ind(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGC), 1)) != NULL && (argv = zend_hash_find_ex_ind(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV), 1)) != NULL) { Z_ADDREF_P(argv); zend_hash_update(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), ZSTR_KNOWN(ZEND_STR_ARGV), argv); zend_hash_update(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), ZSTR_KNOWN(ZEND_STR_ARGC), argc); } } else { php_build_argv(SG(request_info).query_string, &PG(http_globals)[TRACK_VARS_SERVER]); } } } else { zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_SERVER]); array_init(&PG(http_globals)[TRACK_VARS_SERVER]); } check_http_proxy(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER])); zend_hash_update(&EG(symbol_table), name, &PG(http_globals)[TRACK_VARS_SERVER]); Z_ADDREF(PG(http_globals)[TRACK_VARS_SERVER]); /* TODO: TRACK_VARS_SERVER is modified in a number of places (e.g. phar) past this point, * where rc>1 due to the $_SERVER global. Ideally this shouldn't happen, but for now we * ignore this issue, as it would probably require larger changes. */ HT_ALLOW_COW_VIOLATION(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER])); return 0; /* don't rearm */ }
static void _build_trace_string(smart_str *str, HashTable *ht, uint32_t num) /* {{{ */ { zval *file, *tmp; smart_str_appendc(str, '#'); smart_str_append_long(str, num); smart_str_appendc(str, ' '); file = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_FILE), 1); if (file) { if (Z_TYPE_P(file) != IS_STRING) { zend_error(E_WARNING, "Function name is no string"); smart_str_appends(str, "[unknown function]"); } else{ zend_long line; tmp = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_LINE), 1); if (tmp) { if (Z_TYPE_P(tmp) == IS_LONG) { line = Z_LVAL_P(tmp); } else { zend_error(E_WARNING, "Line is no long"); line = 0; } } else { line = 0; } smart_str_append(str, Z_STR_P(file)); smart_str_appendc(str, '('); smart_str_append_long(str, line); smart_str_appends(str, "): "); } } else { smart_str_appends(str, "[internal function]: "); } TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_CLASS)); TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_TYPE)); TRACE_APPEND_KEY(ZSTR_KNOWN(ZEND_STR_FUNCTION)); smart_str_appendc(str, '('); tmp = zend_hash_find_ex(ht, ZSTR_KNOWN(ZEND_STR_ARGS), 1); if (tmp) { if (Z_TYPE_P(tmp) == IS_ARRAY) { size_t last_len = ZSTR_LEN(str->s); zval *arg; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(tmp), arg) { _build_trace_args(arg, str); } ZEND_HASH_FOREACH_END(); if (last_len != ZSTR_LEN(str->s)) { ZSTR_LEN(str->s) -= 2; /* remove last ', ' */ } } else {
/* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Throwable previous]]]) ErrorException constructor */ ZEND_METHOD(error_exception, __construct) { zend_string *message = NULL, *filename = NULL; zend_long code = 0, severity = E_ERROR, lineno; zval tmp, *object, *previous = NULL; int argc = ZEND_NUM_ARGS(); if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc, "|SllSlO!", &message, &code, &severity, &filename, &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_STR_COPY(&tmp, message); zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_MESSAGE), &tmp); zval_ptr_dtor(&tmp); } if (code) { ZVAL_LONG(&tmp, code); zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_CODE), &tmp); } if (previous) { zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_PREVIOUS), previous); } ZVAL_LONG(&tmp, severity); zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(ZEND_STR_SEVERITY), &tmp); if (argc >= 4) { ZVAL_STR_COPY(&tmp, filename); zend_update_property_ex(zend_ce_exception, object, ZSTR_KNOWN(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, ZSTR_KNOWN(ZEND_STR_LINE), &tmp); } }
/* {{{ php_build_argv */ PHPAPI void php_build_argv(char *s, zval *track_vars_array) { zval arr, argc, tmp; int count = 0; char *ss, *space; if (!(SG(request_info).argc || track_vars_array)) { return; } array_init(&arr); /* Prepare argv */ if (SG(request_info).argc) { /* are we in cli sapi? */ int i; for (i = 0; i < SG(request_info).argc; i++) { ZVAL_STRING(&tmp, SG(request_info).argv[i]); if (zend_hash_next_index_insert(Z_ARRVAL(arr), &tmp) == NULL) { zend_string_efree(Z_STR(tmp)); } } } else if (s && *s) { ss = s; while (ss) { space = strchr(ss, '+'); if (space) { *space = '\0'; } /* auto-type */ ZVAL_STRING(&tmp, ss); count++; if (zend_hash_next_index_insert(Z_ARRVAL(arr), &tmp) == NULL) { zend_string_efree(Z_STR(tmp)); } if (space) { *space = '+'; ss = space + 1; } else { ss = space; } } } /* prepare argc */ if (SG(request_info).argc) { ZVAL_LONG(&argc, SG(request_info).argc); } else { ZVAL_LONG(&argc, count); } if (SG(request_info).argc) { Z_ADDREF(arr); zend_hash_update(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV), &arr); zend_hash_update(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGC), &argc); } if (track_vars_array && Z_TYPE_P(track_vars_array) == IS_ARRAY) { Z_ADDREF(arr); zend_hash_update(Z_ARRVAL_P(track_vars_array), ZSTR_KNOWN(ZEND_STR_ARGV), &arr); zend_hash_update(Z_ARRVAL_P(track_vars_array), ZSTR_KNOWN(ZEND_STR_ARGC), &argc); } zval_ptr_dtor_nogc(&arr); }