/** * Open a phar file for streams API */ php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options) /* {{{ */ { php_url *resource; char *arch = NULL, *entry = NULL, *error; int arch_len, entry_len; if (strlen(filename) < 7 || strncasecmp(filename, "phar://", 7)) { return NULL; } if (mode[0] == 'a') { if (!(options & PHP_STREAM_URL_STAT_QUIET)) { php_stream_wrapper_log_error(wrapper, options, "phar error: open mode append not supported"); } return NULL; } if (phar_split_fname(filename, strlen(filename), &arch, &arch_len, &entry, &entry_len, 2, (mode[0] == 'w' ? 2 : 0)) == FAILURE) { if (!(options & PHP_STREAM_URL_STAT_QUIET)) { if (arch && !entry) { php_stream_wrapper_log_error(wrapper, options, "phar error: no directory in \"%s\", must have at least phar://%s/ for root directory (always use full path to a new phar)", filename, arch); arch = NULL; } else { php_stream_wrapper_log_error(wrapper, options, "phar error: invalid url or non-existent phar \"%s\"", filename); } } return NULL; } resource = ecalloc(1, sizeof(php_url)); resource->scheme = estrndup("phar", 4); resource->host = arch; resource->path = entry; #if MBO_0 if (resource) { fprintf(stderr, "Alias: %s\n", alias); fprintf(stderr, "Scheme: %s\n", resource->scheme); /* fprintf(stderr, "User: %s\n", resource->user);*/ /* fprintf(stderr, "Pass: %s\n", resource->pass ? "***" : NULL);*/ fprintf(stderr, "Host: %s\n", resource->host); /* fprintf(stderr, "Port: %d\n", resource->port);*/ fprintf(stderr, "Path: %s\n", resource->path); /* fprintf(stderr, "Query: %s\n", resource->query);*/ /* fprintf(stderr, "Fragment: %s\n", resource->fragment);*/ } #endif if (mode[0] == 'w' || (mode[0] == 'r' && mode[1] == '+')) { phar_archive_data *pphar = NULL, *phar; if (PHAR_GLOBALS->request_init && PHAR_GLOBALS->phar_fname_map.u.flags && NULL == (pphar = zend_hash_str_find_ptr(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len))) { pphar = NULL; } if (PHAR_G(readonly) && (!pphar || !pphar->is_data)) { if (!(options & PHP_STREAM_URL_STAT_QUIET)) { php_stream_wrapper_log_error(wrapper, options, "phar error: write operations disabled by the php.ini setting phar.readonly"); } php_url_free(resource); return NULL; } if (phar_open_or_create_filename(resource->host, arch_len, NULL, 0, 0, options, &phar, &error) == FAILURE) { if (error) { if (!(options & PHP_STREAM_URL_STAT_QUIET)) { php_stream_wrapper_log_error(wrapper, options, "%s", error); } efree(error); } php_url_free(resource); return NULL; } if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar)) { if (error) { spprintf(&error, 0, "Cannot open cached phar '%s' as writeable, copy on write failed", resource->host); if (!(options & PHP_STREAM_URL_STAT_QUIET)) { php_stream_wrapper_log_error(wrapper, options, "%s", error); } efree(error); } php_url_free(resource); return NULL; } } else { if (phar_open_from_filename(resource->host, arch_len, NULL, 0, options, NULL, &error) == FAILURE) { if (error) { if (!(options & PHP_STREAM_URL_STAT_QUIET)) { php_stream_wrapper_log_error(wrapper, options, "%s", error); } efree(error); } php_url_free(resource); return NULL; } } return resource; }
int zend_optimizer_is_disabled_func(const char *name, size_t len) { zend_function *fbc = (zend_function *)zend_hash_str_find_ptr(EG(function_table), name, len); return (fbc && fbc->type == ZEND_INTERNAL_FUNCTION && fbc->internal_function.handler == ZEND_FN(display_disabled_function)); }
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); zend_class_constant *c = NULL; 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) { 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_TYPE_P(ret_constant) == IS_CONSTANT_AST) { int ret; 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); ret = zval_update_constant_ex(ret_constant, c->ce); RESET_CONSTANT_VISITED(ret_constant); if (UNEXPECTED(ret != SUCCESS)) { ret_constant = NULL; goto failure; } } failure: zend_string_release_ex(class_name, 0); zend_string_efree(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); } }
static zend_object *spl_dllist_object_new_ex(zend_class_entry *class_type, zval *orig, int clone_orig) /* {{{ */ { spl_dllist_object *intern; zend_class_entry *parent = class_type; int inherited = 0; intern = ecalloc(1, sizeof(spl_dllist_object) + zend_object_properties_size(parent)); zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); intern->flags = 0; intern->traverse_position = 0; if (orig) { spl_dllist_object *other = Z_SPLDLLIST_P(orig); intern->ce_get_iterator = other->ce_get_iterator; if (clone_orig) { intern->llist = (spl_ptr_llist *)spl_ptr_llist_init(other->llist->ctor, other->llist->dtor); spl_ptr_llist_copy(other->llist, intern->llist); intern->traverse_pointer = intern->llist->head; SPL_LLIST_CHECK_ADDREF(intern->traverse_pointer); } else { intern->llist = other->llist; intern->traverse_pointer = intern->llist->head; SPL_LLIST_CHECK_ADDREF(intern->traverse_pointer); } intern->flags = other->flags; } else { intern->llist = (spl_ptr_llist *)spl_ptr_llist_init(spl_ptr_llist_zval_ctor, spl_ptr_llist_zval_dtor); intern->traverse_pointer = intern->llist->head; SPL_LLIST_CHECK_ADDREF(intern->traverse_pointer); } while (parent) { if (parent == spl_ce_SplStack) { intern->flags |= (SPL_DLLIST_IT_FIX | SPL_DLLIST_IT_LIFO); intern->std.handlers = &spl_handler_SplDoublyLinkedList; } else if (parent == spl_ce_SplQueue) { intern->flags |= SPL_DLLIST_IT_FIX; intern->std.handlers = &spl_handler_SplDoublyLinkedList; } if (parent == spl_ce_SplDoublyLinkedList) { intern->std.handlers = &spl_handler_SplDoublyLinkedList; break; } parent = parent->parent; inherited = 1; } if (!parent) { /* this must never happen */ php_error_docref(NULL, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplDoublyLinkedList"); } if (inherited) { intern->fptr_offset_get = zend_hash_str_find_ptr(&class_type->function_table, "offsetget", sizeof("offsetget") - 1); if (intern->fptr_offset_get->common.scope == parent) { intern->fptr_offset_get = NULL; } intern->fptr_offset_set = zend_hash_str_find_ptr(&class_type->function_table, "offsetset", sizeof("offsetset") - 1); if (intern->fptr_offset_set->common.scope == parent) { intern->fptr_offset_set = NULL; } intern->fptr_offset_has = zend_hash_str_find_ptr(&class_type->function_table, "offsetexists", sizeof("offsetexists") - 1); if (intern->fptr_offset_has->common.scope == parent) { intern->fptr_offset_has = NULL; } intern->fptr_offset_del = zend_hash_str_find_ptr(&class_type->function_table, "offsetunset", sizeof("offsetunset") - 1); if (intern->fptr_offset_del->common.scope == parent) { intern->fptr_offset_del = NULL; } intern->fptr_count = zend_hash_str_find_ptr(&class_type->function_table, "count", sizeof("count") - 1); if (intern->fptr_count->common.scope == parent) { intern->fptr_count = NULL; } } return &intern->std; }
pdo_driver_t *pdo_find_driver(const char *name, int namelen) /* {{{ */ { return zend_hash_str_find_ptr(&pdo_driver_hash, (char*)name, namelen); }
static zend_object *spl_heap_object_new_ex(zend_class_entry *class_type, zval *orig, int clone_orig) /* {{{ */ { spl_heap_object *intern; zend_class_entry *parent = class_type; int inherited = 0; intern = ecalloc(1, sizeof(spl_heap_object) + zend_object_properties_size(parent)); zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); intern->flags = 0; intern->fptr_cmp = NULL; if (orig) { spl_heap_object *other = Z_SPLHEAP_P(orig); intern->ce_get_iterator = other->ce_get_iterator; if (clone_orig) { int i; intern->heap = spl_ptr_heap_clone(other->heap); for (i = 0; i < intern->heap->count; ++i) { if (Z_REFCOUNTED(intern->heap->elements[i])) { Z_ADDREF(intern->heap->elements[i]); } } } else { intern->heap = other->heap; } intern->flags = other->flags; } else { intern->heap = spl_ptr_heap_init(spl_ptr_heap_zval_max_cmp, spl_ptr_heap_zval_ctor, spl_ptr_heap_zval_dtor); } intern->std.handlers = &spl_handler_SplHeap; while (parent) { if (parent == spl_ce_SplPriorityQueue) { intern->heap->cmp = spl_ptr_pqueue_zval_cmp; intern->flags = SPL_PQUEUE_EXTR_DATA; intern->std.handlers = &spl_handler_SplPriorityQueue; break; } if (parent == spl_ce_SplMinHeap) { intern->heap->cmp = spl_ptr_heap_zval_min_cmp; break; } if (parent == spl_ce_SplMaxHeap) { intern->heap->cmp = spl_ptr_heap_zval_max_cmp; break; } if (parent == spl_ce_SplHeap) { break; } parent = parent->parent; inherited = 1; } if (!parent) { /* this must never happen */ php_error_docref(NULL, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplHeap"); } if (inherited) { intern->fptr_cmp = zend_hash_str_find_ptr(&class_type->function_table, "compare", sizeof("compare") - 1); if (intern->fptr_cmp->common.scope == parent) { intern->fptr_cmp = NULL; } intern->fptr_count = zend_hash_str_find_ptr(&class_type->function_table, "count", sizeof("count") - 1); if (intern->fptr_count->common.scope == parent) { intern->fptr_count = NULL; } } return &intern->std; }
static int do_cli(int argc, char **argv) /* {{{ */ { int c; zend_file_handle file_handle; int behavior = PHP_MODE_STANDARD; char *reflection_what = NULL; volatile int request_started = 0; volatile int exit_status = 0; char *php_optarg = NULL, *orig_optarg = NULL; int php_optind = 1, orig_optind = 1; char *exec_direct=NULL, *exec_run=NULL, *exec_begin=NULL, *exec_end=NULL; char *arg_free=NULL, **arg_excp=&arg_free; char *script_file=NULL, *translated_path = NULL; int interactive=0; int lineno = 0; const char *param_error=NULL; int hide_argv = 0; zend_try { CG(in_compilation) = 0; /* not initialized but needed for several options */ while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { switch (c) { case 'i': /* php info & quit */ if (php_request_startup()==FAILURE) { goto err; } request_started = 1; php_print_info(0xFFFFFFFF); php_output_end_all(); exit_status = (c == '?' && argc > 1 && !strchr(argv[1], c)); goto out; case 'v': /* show php version & quit */ php_printf("PHP %s (%s) (built: %s %s) ( %s)\nCopyright (c) 1997-2016 The PHP Group\n%s", PHP_VERSION, cli_sapi_module.name, __DATE__, __TIME__, #if ZTS "ZTS " #else "NTS " #endif #ifdef COMPILER COMPILER " " #endif #ifdef ARCHITECTURE ARCHITECTURE " " #endif #if ZEND_DEBUG "DEBUG " #endif #ifdef HAVE_GCOV "GCOV " #endif , get_zend_version() ); sapi_deactivate(); goto out; case 'm': /* list compiled in modules */ if (php_request_startup()==FAILURE) { goto err; } request_started = 1; php_printf("[PHP Modules]\n"); print_modules(); php_printf("\n[Zend Modules]\n"); print_extensions(); php_printf("\n"); php_output_end_all(); exit_status=0; goto out; default: break; } } /* Set some CLI defaults */ SG(options) |= SAPI_OPTION_NO_CHDIR; php_optind = orig_optind; php_optarg = orig_optarg; while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { switch (c) { case 'a': /* interactive mode */ if (!interactive) { if (behavior != PHP_MODE_STANDARD) { param_error = param_mode_conflict; break; } interactive=1; } break; case 'C': /* don't chdir to the script directory */ /* This is default so NOP */ break; case 'F': if (behavior == PHP_MODE_PROCESS_STDIN) { if (exec_run || script_file) { param_error = "You can use -R or -F only once.\n"; break; } } else if (behavior != PHP_MODE_STANDARD) { param_error = param_mode_conflict; break; } behavior=PHP_MODE_PROCESS_STDIN; script_file = php_optarg; break; case 'f': /* parse file */ if (behavior == PHP_MODE_CLI_DIRECT || behavior == PHP_MODE_PROCESS_STDIN) { param_error = param_mode_conflict; break; } else if (script_file) { param_error = "You can use -f only once.\n"; break; } script_file = php_optarg; break; case 'l': /* syntax check mode */ if (behavior != PHP_MODE_STANDARD) { break; } behavior=PHP_MODE_LINT; break; case 'q': /* do not generate HTTP headers */ /* This is default so NOP */ break; case 'r': /* run code from command line */ if (behavior == PHP_MODE_CLI_DIRECT) { if (exec_direct || script_file) { param_error = "You can use -r only once.\n"; break; } } else if (behavior != PHP_MODE_STANDARD || interactive) { param_error = param_mode_conflict; break; } behavior=PHP_MODE_CLI_DIRECT; exec_direct=php_optarg; break; case 'R': if (behavior == PHP_MODE_PROCESS_STDIN) { if (exec_run || script_file) { param_error = "You can use -R or -F only once.\n"; break; } } else if (behavior != PHP_MODE_STANDARD) { param_error = param_mode_conflict; break; } behavior=PHP_MODE_PROCESS_STDIN; exec_run=php_optarg; break; case 'B': if (behavior == PHP_MODE_PROCESS_STDIN) { if (exec_begin) { param_error = "You can use -B only once.\n"; break; } } else if (behavior != PHP_MODE_STANDARD || interactive) { param_error = param_mode_conflict; break; } behavior=PHP_MODE_PROCESS_STDIN; exec_begin=php_optarg; break; case 'E': if (behavior == PHP_MODE_PROCESS_STDIN) { if (exec_end) { param_error = "You can use -E only once.\n"; break; } } else if (behavior != PHP_MODE_STANDARD || interactive) { param_error = param_mode_conflict; break; } behavior=PHP_MODE_PROCESS_STDIN; exec_end=php_optarg; break; case 's': /* generate highlighted HTML from source */ if (behavior == PHP_MODE_CLI_DIRECT || behavior == PHP_MODE_PROCESS_STDIN) { param_error = "Source highlighting only works for files.\n"; break; } behavior=PHP_MODE_HIGHLIGHT; break; case 'w': if (behavior == PHP_MODE_CLI_DIRECT || behavior == PHP_MODE_PROCESS_STDIN) { param_error = "Source stripping only works for files.\n"; break; } behavior=PHP_MODE_STRIP; break; case 'z': /* load extension file */ zend_load_extension(php_optarg); break; case 'H': hide_argv = 1; break; case 10: behavior=PHP_MODE_REFLECTION_FUNCTION; reflection_what = php_optarg; break; case 11: behavior=PHP_MODE_REFLECTION_CLASS; reflection_what = php_optarg; break; case 12: behavior=PHP_MODE_REFLECTION_EXTENSION; reflection_what = php_optarg; break; case 13: behavior=PHP_MODE_REFLECTION_ZEND_EXTENSION; reflection_what = php_optarg; break; case 14: behavior=PHP_MODE_REFLECTION_EXT_INFO; reflection_what = php_optarg; break; case 15: behavior = PHP_MODE_SHOW_INI_CONFIG; break; default: break; } } if (param_error) { PUTS(param_error); exit_status=1; goto err; } if (interactive) { #if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE) printf("Interactive shell\n\n"); #else printf("Interactive mode enabled\n\n"); #endif fflush(stdout); } /* only set script_file if not set already and not in direct mode and not at end of parameter list */ if (argc > php_optind && !script_file && behavior!=PHP_MODE_CLI_DIRECT && behavior!=PHP_MODE_PROCESS_STDIN && strcmp(argv[php_optind-1],"--")) { script_file=argv[php_optind]; php_optind++; } if (script_file) { if (cli_seek_file_begin(&file_handle, script_file, &lineno) != SUCCESS) { goto err; } else { char real_path[MAXPATHLEN]; if (VCWD_REALPATH(script_file, real_path)) { translated_path = strdup(real_path); } script_filename = script_file; } } else { /* We could handle PHP_MODE_PROCESS_STDIN in a different manner */ /* here but this would make things only more complicated. And it */ /* is consitent with the way -R works where the stdin file handle*/ /* is also accessible. */ file_handle.filename = "-"; file_handle.handle.fp = stdin; } file_handle.type = ZEND_HANDLE_FP; file_handle.opened_path = NULL; file_handle.free_filename = 0; php_self = (char*)file_handle.filename; /* before registering argv to module exchange the *new* argv[0] */ /* we can achieve this without allocating more memory */ SG(request_info).argc=argc-php_optind+1; arg_excp = argv+php_optind-1; arg_free = argv[php_optind-1]; SG(request_info).path_translated = translated_path? translated_path: (char*)file_handle.filename; argv[php_optind-1] = (char*)file_handle.filename; SG(request_info).argv=argv+php_optind-1; if (php_request_startup()==FAILURE) { *arg_excp = arg_free; fclose(file_handle.handle.fp); PUTS("Could not startup.\n"); goto err; } request_started = 1; CG(start_lineno) = lineno; *arg_excp = arg_free; /* reconstuct argv */ if (hide_argv) { int i; for (i = 1; i < argc; i++) { memset(argv[i], 0, strlen(argv[i])); } } zend_is_auto_global_str(ZEND_STRL("_SERVER")); PG(during_request_startup) = 0; switch (behavior) { case PHP_MODE_STANDARD: if (strcmp(file_handle.filename, "-")) { cli_register_file_handles(); } if (interactive && cli_shell_callbacks.cli_shell_run) { exit_status = cli_shell_callbacks.cli_shell_run(); } else { php_execute_script(&file_handle); exit_status = EG(exit_status); } break; case PHP_MODE_LINT: exit_status = php_lint_script(&file_handle); if (exit_status==SUCCESS) { zend_printf("No syntax errors detected in %s\n", file_handle.filename); } else { zend_printf("Errors parsing %s\n", file_handle.filename); } break; case PHP_MODE_STRIP: if (open_file_for_scanning(&file_handle)==SUCCESS) { zend_strip(); } goto out; break; case PHP_MODE_HIGHLIGHT: { zend_syntax_highlighter_ini syntax_highlighter_ini; if (open_file_for_scanning(&file_handle)==SUCCESS) { php_get_highlight_struct(&syntax_highlighter_ini); zend_highlight(&syntax_highlighter_ini); } goto out; } break; case PHP_MODE_CLI_DIRECT: cli_register_file_handles(); if (zend_eval_string_ex(exec_direct, NULL, "Command line code", 1) == FAILURE) { exit_status=254; } break; case PHP_MODE_PROCESS_STDIN: { char *input; size_t len, index = 0; zval argn, argi; cli_register_file_handles(); if (exec_begin && zend_eval_string_ex(exec_begin, NULL, "Command line begin code", 1) == FAILURE) { exit_status=254; } while (exit_status == SUCCESS && (input=php_stream_gets(s_in_process, NULL, 0)) != NULL) { len = strlen(input); while (len > 0 && len-- && (input[len]=='\n' || input[len]=='\r')) { input[len] = '\0'; } ZVAL_STRINGL(&argn, input, len + 1); zend_hash_str_update(&EG(symbol_table), "argn", sizeof("argn")-1, &argn); ZVAL_LONG(&argi, ++index); zend_hash_str_update(&EG(symbol_table), "argi", sizeof("argi")-1, &argi); if (exec_run) { if (zend_eval_string_ex(exec_run, NULL, "Command line run code", 1) == FAILURE) { exit_status=254; } } else { if (script_file) { if (cli_seek_file_begin(&file_handle, script_file, &lineno) != SUCCESS) { exit_status = 1; } else { CG(start_lineno) = lineno; php_execute_script(&file_handle); exit_status = EG(exit_status); } } } efree(input); } if (exec_end && zend_eval_string_ex(exec_end, NULL, "Command line end code", 1) == FAILURE) { exit_status=254; } break; } case PHP_MODE_REFLECTION_FUNCTION: case PHP_MODE_REFLECTION_CLASS: case PHP_MODE_REFLECTION_EXTENSION: case PHP_MODE_REFLECTION_ZEND_EXTENSION: { zend_class_entry *pce = NULL; zval arg, ref; zend_execute_data execute_data; switch (behavior) { default: break; case PHP_MODE_REFLECTION_FUNCTION: if (strstr(reflection_what, "::")) { pce = reflection_method_ptr; } else { pce = reflection_function_ptr; } break; case PHP_MODE_REFLECTION_CLASS: pce = reflection_class_ptr; break; case PHP_MODE_REFLECTION_EXTENSION: pce = reflection_extension_ptr; break; case PHP_MODE_REFLECTION_ZEND_EXTENSION: pce = reflection_zend_extension_ptr; break; } ZVAL_STRING(&arg, reflection_what); object_init_ex(&ref, pce); memset(&execute_data, 0, sizeof(zend_execute_data)); EG(current_execute_data) = &execute_data; zend_call_method_with_1_params(&ref, pce, &pce->constructor, "__construct", NULL, &arg); if (EG(exception)) { zval tmp, *msg, rv; ZVAL_OBJ(&tmp, EG(exception)); msg = zend_read_property(zend_ce_exception, &tmp, "message", sizeof("message")-1, 0, &rv); zend_printf("Exception: %s\n", Z_STRVAL_P(msg)); zval_ptr_dtor(&tmp); EG(exception) = NULL; } else { zend_call_method_with_1_params(NULL, reflection_ptr, NULL, "export", NULL, &ref); } zval_ptr_dtor(&ref); zval_ptr_dtor(&arg); break; } case PHP_MODE_REFLECTION_EXT_INFO: { int len = (int)strlen(reflection_what); char *lcname = zend_str_tolower_dup(reflection_what, len); zend_module_entry *module; if ((module = zend_hash_str_find_ptr(&module_registry, lcname, len)) == NULL) { if (!strcmp(reflection_what, "main")) { display_ini_entries(NULL); } else { zend_printf("Extension '%s' not present.\n", reflection_what); exit_status = 1; } } else { php_info_print_module(module); } efree(lcname); break; } case PHP_MODE_SHOW_INI_CONFIG: { zend_printf("Configuration File (php.ini) Path: %s\n", PHP_CONFIG_FILE_PATH); zend_printf("Loaded Configuration File: %s\n", php_ini_opened_path ? php_ini_opened_path : "(none)"); zend_printf("Scan for additional .ini files in: %s\n", php_ini_scanned_path ? php_ini_scanned_path : "(none)"); zend_printf("Additional .ini files parsed: %s\n", php_ini_scanned_files ? php_ini_scanned_files : "(none)"); break; } } } zend_end_try(); out: if (request_started) { php_request_shutdown((void *) 0); } if (translated_path) { free(translated_path); } if (exit_status == 0) { exit_status = EG(exit_status); } return exit_status; err: sapi_deactivate(); zend_ini_deactivate(); exit_status = 1; goto out; }
static zend_object *spl_fixedarray_object_new_ex(zend_class_entry *class_type, zval *orig, int clone_orig) /* {{{ */ { spl_fixedarray_object *intern; zend_class_entry *parent = class_type; int inherited = 0; intern = ecalloc(1, sizeof(spl_fixedarray_object) + zend_object_properties_size(parent)); zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); intern->current = 0; intern->flags = 0; if (orig && clone_orig) { spl_fixedarray_object *other = Z_SPLFIXEDARRAY_P(orig); intern->ce_get_iterator = other->ce_get_iterator; spl_fixedarray_init(&intern->array, other->array.size); spl_fixedarray_copy(&intern->array, &other->array); } while (parent) { if (parent == spl_ce_SplFixedArray) { intern->std.handlers = &spl_handler_SplFixedArray; class_type->get_iterator = spl_fixedarray_get_iterator; break; } parent = parent->parent; inherited = 1; } if (!parent) { /* this must never happen */ php_error_docref(NULL, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplFixedArray"); } if (!class_type->iterator_funcs.zf_current) { class_type->iterator_funcs.zf_rewind = zend_hash_str_find_ptr(&class_type->function_table, "rewind", sizeof("rewind") - 1); class_type->iterator_funcs.zf_valid = zend_hash_str_find_ptr(&class_type->function_table, "valid", sizeof("valid") - 1); class_type->iterator_funcs.zf_key = zend_hash_str_find_ptr(&class_type->function_table, "key", sizeof("key") - 1); class_type->iterator_funcs.zf_current = zend_hash_str_find_ptr(&class_type->function_table, "current", sizeof("current") - 1); class_type->iterator_funcs.zf_next = zend_hash_str_find_ptr(&class_type->function_table, "next", sizeof("next") - 1); } if (inherited) { if (class_type->iterator_funcs.zf_rewind->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_REWIND; } if (class_type->iterator_funcs.zf_valid->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_VALID; } if (class_type->iterator_funcs.zf_key->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_KEY; } if (class_type->iterator_funcs.zf_current->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_CURRENT; } if (class_type->iterator_funcs.zf_next->common.scope != parent) { intern->flags |= SPL_FIXEDARRAY_OVERLOADED_NEXT; } intern->fptr_offset_get = zend_hash_str_find_ptr(&class_type->function_table, "offsetget", sizeof("offsetget") - 1); if (intern->fptr_offset_get->common.scope == parent) { intern->fptr_offset_get = NULL; } intern->fptr_offset_set = zend_hash_str_find_ptr(&class_type->function_table, "offsetset", sizeof("offsetset") - 1); if (intern->fptr_offset_set->common.scope == parent) { intern->fptr_offset_set = NULL; } intern->fptr_offset_has = zend_hash_str_find_ptr(&class_type->function_table, "offsetexists", sizeof("offsetexists") - 1); if (intern->fptr_offset_has->common.scope == parent) { intern->fptr_offset_has = NULL; } intern->fptr_offset_del = zend_hash_str_find_ptr(&class_type->function_table, "offsetunset", sizeof("offsetunset") - 1); if (intern->fptr_offset_del->common.scope == parent) { intern->fptr_offset_del = NULL; } intern->fptr_count = zend_hash_str_find_ptr(&class_type->function_table, "count", sizeof("count") - 1); if (intern->fptr_count->common.scope == parent) { intern->fptr_count = NULL; } } return &intern->std; }
U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, HashTable *args, UChar **formatted, int *formatted_len) { int arg_count = zend_hash_num_elements(args); std::vector<Formattable> fargs; std::vector<UnicodeString> farg_names; MessageFormat *mf = (MessageFormat *)mfo->mf_data.umsgf; HashTable *types; intl_error& err = INTL_DATA_ERROR(mfo); if (U_FAILURE(err.code)) { return; } types = umsg_get_types(mfo, err); umsg_set_timezone(mfo, err); fargs.resize(arg_count); farg_names.resize(arg_count); int argNum = 0; zval *elem; // Key related variables zend_string *str_index; zend_ulong num_index; ZEND_HASH_FOREACH_KEY_VAL(args, num_index, str_index, elem) { Formattable& formattable = fargs[argNum]; UnicodeString& key = farg_names[argNum]; Formattable::Type argType = Formattable::kObject, //unknown *storedArgType = NULL; if (!U_SUCCESS(err.code)) { break; } /* Process key and retrieve type */ if (str_index == NULL) { /* includes case where index < 0 because it's exposed as unsigned */ if (num_index > (zend_ulong)INT32_MAX) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found negative or too large array key", 0); continue; } UChar temp[16]; int32_t len = u_sprintf(temp, "%u", (uint32_t)num_index); key.append(temp, len); storedArgType = (Formattable::Type*)zend_hash_index_find_ptr(types, (zend_ulong)num_index); } else { //string; assumed to be in UTF-8 intl_stringFromChar(key, str_index->val, str_index->len, &err.code); if (U_FAILURE(err.code)) { char *message; spprintf(&message, 0, "Invalid UTF-8 data in argument key: '%s'", str_index->val); intl_errors_set(&err, err.code, message, 1); efree(message); continue; } storedArgType = (Formattable::Type*)zend_hash_str_find_ptr(types, (char*)key.getBuffer(), key.length()); } if (storedArgType != NULL) { argType = *storedArgType; } /* Convert zval to formattable according to message format type * or (as a fallback) the zval type */ if (argType != Formattable::kObject) { switch (argType) { case Formattable::kString: { string_arg: /* This implicitly converts objects * Note that our vectors will leak if object conversion fails * and PHP ends up with a fatal error and calls longjmp * as a result of that. */ convert_to_string_ex(elem); UnicodeString *text = new UnicodeString(); intl_stringFromChar(*text, Z_STRVAL_P(elem), Z_STRLEN_P(elem), &err.code); if (U_FAILURE(err.code)) { char *message; spprintf(&message, 0, "Invalid UTF-8 data in string argument: " "'%s'", Z_STRVAL_P(elem)); intl_errors_set(&err, err.code, message, 1); efree(message); delete text; continue; } formattable.adoptString(text); break; } case Formattable::kDouble: { double d; if (Z_TYPE_P(elem) == IS_DOUBLE) { d = Z_DVAL_P(elem); } else if (Z_TYPE_P(elem) == IS_LONG) { d = (double)Z_LVAL_P(elem); } else { SEPARATE_ZVAL_IF_NOT_REF(elem); convert_scalar_to_number(elem); d = (Z_TYPE_P(elem) == IS_DOUBLE) ? Z_DVAL_P(elem) : (double)Z_LVAL_P(elem); } formattable.setDouble(d); break; } case Formattable::kLong: { int32_t tInt32 = 0; retry_klong: if (Z_TYPE_P(elem) == IS_DOUBLE) { if (Z_DVAL_P(elem) > (double)INT32_MAX || Z_DVAL_P(elem) < (double)INT32_MIN) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found PHP float with absolute value too large for " "32 bit integer argument", 0); } else { tInt32 = (int32_t)Z_DVAL_P(elem); } } else if (Z_TYPE_P(elem) == IS_LONG) { if (Z_LVAL_P(elem) > INT32_MAX || Z_LVAL_P(elem) < INT32_MIN) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found PHP integer with absolute value too large " "for 32 bit integer argument", 0); } else { tInt32 = (int32_t)Z_LVAL_P(elem); } } else { SEPARATE_ZVAL_IF_NOT_REF(elem); convert_scalar_to_number(elem); goto retry_klong; } formattable.setLong(tInt32); break; } case Formattable::kInt64: { int64_t tInt64 = 0; retry_kint64: if (Z_TYPE_P(elem) == IS_DOUBLE) { if (Z_DVAL_P(elem) > (double)U_INT64_MAX || Z_DVAL_P(elem) < (double)U_INT64_MIN) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found PHP float with absolute value too large for " "64 bit integer argument", 0); } else { tInt64 = (int64_t)Z_DVAL_P(elem); } } else if (Z_TYPE_P(elem) == IS_LONG) { /* assume long is not wider than 64 bits */ tInt64 = (int64_t)Z_LVAL_P(elem); } else { SEPARATE_ZVAL_IF_NOT_REF(elem); convert_scalar_to_number(elem); goto retry_kint64; } formattable.setInt64(tInt64); break; } case Formattable::kDate: { double dd = intl_zval_to_millis(elem, &err, "msgfmt_format"); if (U_FAILURE(err.code)) { char *message, *key_char; int key_len; UErrorCode status = UErrorCode(); if (intl_charFromString(key, &key_char, &key_len, &status) == SUCCESS) { spprintf(&message, 0, "The argument for key '%s' " "cannot be used as a date or time", key_char); intl_errors_set(&err, err.code, message, 1); efree(key_char); efree(message); } continue; } formattable.setDate(dd); break; } default: intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found unsupported argument type", 0); break; } } else { /* We couldn't find any information about the argument in the pattern, this * means it's an extra argument. So convert it to a number if it's a number or * bool or null and to a string if it's anything else except arrays . */ switch (Z_TYPE_P(elem)) { case IS_DOUBLE: formattable.setDouble(Z_DVAL_P(elem)); break; case IS_TRUE: case IS_FALSE: convert_to_long_ex(elem); /* Intentional fallthrough */ case IS_LONG: formattable.setInt64((int64_t)Z_LVAL_P(elem)); break; case IS_NULL: formattable.setInt64((int64_t)0); break; case IS_STRING: case IS_OBJECT: goto string_arg; default: { char *message, *key_char; int key_len; UErrorCode status = UErrorCode(); if (intl_charFromString(key, &key_char, &key_len, &status) == SUCCESS) { spprintf(&message, 0, "No strategy to convert the " "value given for the argument with key '%s' " "is available", key_char); intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, message, 1); efree(key_char); efree(message); } } } } argNum++; } ZEND_HASH_FOREACH_END(); // visiting each argument
/* {{{ mysqlnd_vio::open_tcp_or_unix */ static php_stream * MYSQLND_METHOD(mysqlnd_vio, open_tcp_or_unix)(MYSQLND_VIO * const vio, const MYSQLND_CSTRING scheme, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info) { unsigned int streams_options = 0; unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT; char * hashed_details = NULL; int hashed_details_len = 0; zend_string *errstr = NULL; int errcode = 0; struct timeval tv; dtor_func_t origin_dtor; php_stream * net_stream = NULL; DBG_ENTER("mysqlnd_vio::open_tcp_or_unix"); vio->data->stream = NULL; if (persistent) { hashed_details_len = mnd_sprintf(&hashed_details, 0, "%p", vio); DBG_INF_FMT("hashed_details=%s", hashed_details); } if (vio->data->options.timeout_connect) { tv.tv_sec = vio->data->options.timeout_connect; tv.tv_usec = 0; } DBG_INF_FMT("calling php_stream_xport_create"); net_stream = php_stream_xport_create(scheme.s, scheme.l, streams_options, streams_flags, hashed_details, (vio->data->options.timeout_connect) ? &tv : NULL, NULL /*ctx*/, &errstr, &errcode); if (errstr || !net_stream) { DBG_ERR("Error"); if (hashed_details) { mnd_sprintf_free(hashed_details); } errcode = CR_CONNECTION_ERROR; SET_CLIENT_ERROR(error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, errstr? ZSTR_VAL(errstr):"Unknown error while connecting"); if (errstr) { zend_string_release(errstr); } DBG_RETURN(NULL); } if (hashed_details) { /* If persistent, the streams register it in EG(persistent_list). This is unwanted. ext/mysql or ext/mysqli are responsible to clean, whatever they have to. */ zend_resource *le; if ((le = zend_hash_str_find_ptr(&EG(persistent_list), hashed_details, hashed_details_len))) { origin_dtor = EG(persistent_list).pDestructor; /* in_free will let streams code skip destructing - big HACK, but STREAMS suck big time regarding persistent streams. Just not compatible for extensions that need persistency. */ EG(persistent_list).pDestructor = NULL; zend_hash_str_del(&EG(persistent_list), hashed_details, hashed_details_len); EG(persistent_list).pDestructor = origin_dtor; pefree(le, 1); } #if ZEND_DEBUG /* Shut-up the streams, they don't know what they are doing */ net_stream->__exposed = 1; #endif mnd_sprintf_free(hashed_details); } /* Streams are not meant for C extensions! Thus we need a hack. Every connected stream will be registered as resource (in EG(regular_list). So far, so good. However, it won't be unregistered until the script ends. So, we need to take care of that. */ origin_dtor = EG(regular_list).pDestructor; EG(regular_list).pDestructor = NULL; zend_hash_index_del(&EG(regular_list), net_stream->res->handle); /* ToDO: should it be res->handle, do streams register with addref ?*/ efree(net_stream->res); net_stream->res = NULL; EG(regular_list).pDestructor = origin_dtor; DBG_RETURN(net_stream); }
static HashTable *umsg_parse_format(MessageFormatter_object *mfo, const MessagePattern& mp, intl_error& err) { HashTable *ret; int32_t parts_count; if (U_FAILURE(err.code)) { return NULL; } if (!((MessageFormat *)mfo->mf_data.umsgf)->usesNamedArguments()) { return umsg_get_numeric_types(mfo, err); } if (mfo->mf_data.arg_types) { /* already cached */ return mfo->mf_data.arg_types; } /* Hash table will store Formattable::Type objects directly, * so no need for destructor */ ALLOC_HASHTABLE(ret); zend_hash_init(ret, 32, NULL, arg_types_dtor, 0); parts_count = mp.countParts(); // See MessageFormat::cacheExplicitFormats() /* * Looking through the pattern, go to each arg_start part type. * The arg-typeof that tells us the argument type (simple, complicated) * then the next part is either the arg_name or arg number * and then if it's simple after that there could be a part-type=arg-type * while substring will tell us number, spellout, etc. * If the next thing isn't an arg-type then assume string. */ /* The last two "parts" can at most be ARG_LIMIT and MSG_LIMIT * which we need not examine. */ for (int32_t i = 0; i < parts_count - 2 && U_SUCCESS(err.code); i++) { MessagePattern::Part p = mp.getPart(i); if (p.getType() != UMSGPAT_PART_TYPE_ARG_START) { continue; } MessagePattern::Part name_part = mp.getPart(++i); /* Getting name, advancing i */ Formattable::Type type, *storedType; if (name_part.getType() == UMSGPAT_PART_TYPE_ARG_NAME) { UnicodeString argName = mp.getSubstring(name_part); if ((storedType = (Formattable::Type*)zend_hash_str_find_ptr(ret, (char*)argName.getBuffer(), argName.length())) == NULL) { /* not found already; create new entry in HT */ Formattable::Type bogusType = Formattable::kObject; if ((storedType = (Formattable::Type*)zend_hash_str_update_mem(ret, (char*)argName.getBuffer(), argName.length(), (void*)&bogusType, sizeof(bogusType))) == NULL) { intl_errors_set(&err, U_MEMORY_ALLOCATION_ERROR, "Write to argument types hash table failed", 0); continue; } } } else if (name_part.getType() == UMSGPAT_PART_TYPE_ARG_NUMBER) { int32_t argNumber = name_part.getValue(); if (argNumber < 0) { intl_errors_set(&err, U_INVALID_FORMAT_ERROR, "Found part with negative number", 0); continue; } if ((storedType = (Formattable::Type*)zend_hash_index_find_ptr(ret, (zend_ulong)argNumber)) == NULL) { /* not found already; create new entry in HT */ Formattable::Type bogusType = Formattable::kObject; if ((storedType = (Formattable::Type*)zend_hash_index_update_mem(ret, (zend_ulong)argNumber, (void*)&bogusType, sizeof(bogusType))) == NULL) { intl_errors_set(&err, U_MEMORY_ALLOCATION_ERROR, "Write to argument types hash table failed", 0); continue; } } } else { intl_errors_set(&err, U_INVALID_FORMAT_ERROR, "Invalid part type encountered", 0); continue; } UMessagePatternArgType argType = p.getArgType(); /* No type specified, treat it as a string */ if (argType == UMSGPAT_ARG_TYPE_NONE) { type = Formattable::kString; } else { /* Some type was specified, might be simple or complicated */ if (argType == UMSGPAT_ARG_TYPE_SIMPLE) { /* For a SIMPLE arg, after the name part, there should be * an ARG_TYPE part whose string value tells us what to do */ MessagePattern::Part type_part = mp.getPart(++i); /* Getting type, advancing i */ if (type_part.getType() == UMSGPAT_PART_TYPE_ARG_TYPE) { UnicodeString typeString = mp.getSubstring(type_part); /* This is all based on the rules in the docs for MessageFormat * @see http://icu-project.org/apiref/icu4c/classMessageFormat.html */ if (typeString == "number") { MessagePattern::Part style_part = mp.getPart(i + 1); /* Not advancing i */ if (style_part.getType() == UMSGPAT_PART_TYPE_ARG_STYLE) { UnicodeString styleString = mp.getSubstring(style_part); if (styleString == "integer") { type = Formattable::kInt64; } else if (styleString == "currency") { type = Formattable::kDouble; } else if (styleString == "percent") { type = Formattable::kDouble; } else { /* some style invalid/unknown to us */ type = Formattable::kDouble; } } else { // if missing style, part, make it a double type = Formattable::kDouble; } } else if ((typeString == "date") || (typeString == "time")) { type = Formattable::kDate; } else if ((typeString == "spellout") || (typeString == "ordinal") || (typeString == "duration")) { type = Formattable::kDouble; } } else { /* If there's no UMSGPAT_PART_TYPE_ARG_TYPE right after a * UMSGPAT_ARG_TYPE_SIMPLE argument, then the pattern * is broken. */ intl_errors_set(&err, U_PARSE_ERROR, "Expected UMSGPAT_PART_TYPE_ARG_TYPE part following " "UMSGPAT_ARG_TYPE_SIMPLE part", 0); continue; } } else if (argType == UMSGPAT_ARG_TYPE_PLURAL) { type = Formattable::kDouble; } else if (argType == UMSGPAT_ARG_TYPE_CHOICE) { type = Formattable::kDouble; } else if (argType == UMSGPAT_ARG_TYPE_SELECT) { type = Formattable::kString; } else { type = Formattable::kString; } } /* was type specified? */ /* We found a different type for the same arg! */ if (*storedType != Formattable::kObject && *storedType != type) { intl_errors_set(&err, U_ARGUMENT_TYPE_MISMATCH, "Inconsistent types declared for an argument", 0); continue; } *storedType = type; } /* visiting each part */ if (U_FAILURE(err.code)) { zend_hash_destroy(ret); efree(ret); return NULL; } mfo->mf_data.arg_types = ret; return ret; }
/* {{{ zend_call_method Only returns the returned zval if retval_ptr != NULL */ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_function **fn_proxy, const char *function_name, size_t function_name_len, zval *retval_ptr, int param_count, zval* arg1, zval* arg2) { int result; zend_fcall_info fci; zval retval; zval params[2]; if (param_count > 0) { ZVAL_COPY_VALUE(¶ms[0], arg1); } if (param_count > 1) { ZVAL_COPY_VALUE(¶ms[1], arg2); } fci.size = sizeof(fci); fci.object = object ? Z_OBJ_P(object) : NULL; fci.retval = retval_ptr ? retval_ptr : &retval; fci.param_count = param_count; fci.params = params; fci.no_separation = 1; if (!fn_proxy && !obj_ce) { /* no interest in caching and no information already present that is * needed later inside zend_call_function. */ ZVAL_STRINGL(&fci.function_name, function_name, function_name_len); result = zend_call_function(&fci, NULL); zval_ptr_dtor(&fci.function_name); } else { zend_fcall_info_cache fcic; ZVAL_UNDEF(&fci.function_name); /* Unused */ if (!obj_ce) { obj_ce = object ? Z_OBJCE_P(object) : NULL; } if (!fn_proxy || !*fn_proxy) { if (EXPECTED(obj_ce)) { fcic.function_handler = zend_hash_str_find_ptr( &obj_ce->function_table, function_name, function_name_len); if (UNEXPECTED(fcic.function_handler == NULL)) { /* error at c-level */ zend_error_noreturn(E_CORE_ERROR, "Couldn't find implementation for method %s::%s", ZSTR_VAL(obj_ce->name), function_name); } } else { fcic.function_handler = zend_fetch_function_str(function_name, function_name_len); if (UNEXPECTED(fcic.function_handler == NULL)) { /* error at c-level */ zend_error_noreturn(E_CORE_ERROR, "Couldn't find implementation for function %s", function_name); } } if (fn_proxy) { *fn_proxy = fcic.function_handler; } } else { fcic.function_handler = *fn_proxy; } if (object) { fcic.called_scope = Z_OBJCE_P(object); } else { zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data)); if (obj_ce && (!called_scope || !instanceof_function(called_scope, obj_ce))) { fcic.called_scope = obj_ce; } else { fcic.called_scope = called_scope; } } fcic.object = object ? Z_OBJ_P(object) : NULL; result = zend_call_function(&fci, &fcic); } if (result == FAILURE) { /* error at c-level */ if (!obj_ce) { obj_ce = object ? Z_OBJCE_P(object) : NULL; } if (!EG(exception)) { zend_error_noreturn(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? ZSTR_VAL(obj_ce->name) : "", obj_ce ? "::" : "", function_name); } } if (!retval_ptr) { zval_ptr_dtor(&retval); return NULL; } return retval_ptr; }
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; zend_string *class_name; 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); 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_throw_error(NULL, "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_throw_error(NULL, "Cannot access parent:: when no class scope is active"); return NULL; } else if (UNEXPECTED(!scope->parent)) { zend_throw_error(NULL, "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_throw_error(NULL, "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_throw_error(NULL, "Undefined class constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name)); 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); } }
/* {{{ php_dba_open */ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent) { zval *args = NULL; int ac = ZEND_NUM_ARGS(); dba_mode_t modenr; dba_info *info, *other; dba_handler *hptr; char *key = NULL, *error = NULL; int keylen = 0; int i; int lock_mode, lock_flag, lock_dbf = 0; char *file_mode; char mode[4], *pmode, *lock_file_mode = NULL; int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0; zend_string *opened_path = NULL; char *lock_name; if (ac < 2) { WRONG_PARAM_COUNT; } /* we pass additional args to the respective handler */ args = safe_emalloc(ac, sizeof(zval), 0); if (zend_get_parameters_array_ex(ac, args) != SUCCESS) { efree(args); WRONG_PARAM_COUNT; } /* we only take string arguments */ for (i = 0; i < ac; i++) { ZVAL_STR(&args[i], zval_get_string(&args[i])); keylen += Z_STRLEN(args[i]); } if (persistent) { zend_resource *le; /* calculate hash */ key = safe_emalloc(keylen, 1, 1); key[keylen] = '\0'; keylen = 0; for(i = 0; i < ac; i++) { memcpy(key+keylen, Z_STRVAL(args[i]), Z_STRLEN(args[i])); keylen += Z_STRLEN(args[i]); } /* try to find if we already have this link in our persistent list */ if ((le = zend_hash_str_find_ptr(&EG(persistent_list), key, keylen)) != NULL) { FREENOW; if (le->type != le_pdb) { RETURN_FALSE; } info = (dba_info *)le->ptr; GC_REFCOUNT(le)++; RETURN_RES(zend_register_resource(info, le_pdb)); return; } } if (ac==2) { hptr = DBA_G(default_hptr); if (!hptr) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "No default handler selected"); FREENOW; RETURN_FALSE; } } else { for (hptr = handler; hptr->name && strcasecmp(hptr->name, Z_STRVAL(args[2])); hptr++); } if (!hptr->name) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "No such handler: %s", Z_STRVAL(args[2])); FREENOW; RETURN_FALSE; } /* Check mode: [rwnc][fl]?t? * r: Read * w: Write * n: Create/Truncate * c: Create * * d: force lock on database file * l: force lock on lck file * -: ignore locking * * t: test open database, warning if locked */ strlcpy(mode, Z_STRVAL(args[1]), sizeof(mode)); pmode = &mode[0]; if (pmode[0] && (pmode[1]=='d' || pmode[1]=='l' || pmode[1]=='-')) { /* force lock on db file or lck file or disable locking */ switch (pmode[1]) { case 'd': lock_dbf = 1; if ((hptr->flags & DBA_LOCK_ALL) == 0) { lock_flag = (hptr->flags & DBA_LOCK_ALL); break; } /* no break */ case 'l': lock_flag = DBA_LOCK_ALL; if ((hptr->flags & DBA_LOCK_ALL) == 0) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_NOTICE, "Handler %s does locking internally", hptr->name); } break; default: case '-': if ((hptr->flags & DBA_LOCK_ALL) == 0) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Locking cannot be disabled for handler %s", hptr->name); FREENOW; RETURN_FALSE; } lock_flag = 0; break; } } else { lock_flag = (hptr->flags&DBA_LOCK_ALL); lock_dbf = 1; } switch (*pmode++) { case 'r': modenr = DBA_READER; lock_mode = (lock_flag & DBA_LOCK_READER) ? LOCK_SH : 0; file_mode = "r"; break; case 'w': modenr = DBA_WRITER; lock_mode = (lock_flag & DBA_LOCK_WRITER) ? LOCK_EX : 0; file_mode = "r+b"; break; case 'c': modenr = DBA_CREAT; lock_mode = (lock_flag & DBA_LOCK_CREAT) ? LOCK_EX : 0; if (lock_mode) { if (lock_dbf) { /* the create/append check will be done on the lock * when the lib opens the file it is already created */ file_mode = "r+b"; /* read & write, seek 0 */ lock_file_mode = "a+b"; /* append */ } else { file_mode = "a+b"; /* append */ lock_file_mode = "w+b"; /* create/truncate */ } } else { file_mode = "a+b"; } /* In case of the 'a+b' append mode, the handler is responsible * to handle any rewind problems (see flatfile handler). */ break; case 'n': modenr = DBA_TRUNC; lock_mode = (lock_flag & DBA_LOCK_TRUNC) ? LOCK_EX : 0; file_mode = "w+b"; break; default: php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Illegal DBA mode"); FREENOW; RETURN_FALSE; } if (!lock_file_mode) { lock_file_mode = file_mode; } if (*pmode=='d' || *pmode=='l' || *pmode=='-') { pmode++; /* done already - skip here */ } if (*pmode=='t') { pmode++; if (!lock_flag) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "You cannot combine modifiers - (no lock) and t (test lock)"); FREENOW; RETURN_FALSE; } if (!lock_mode) { if ((hptr->flags & DBA_LOCK_ALL) == 0) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Handler %s uses its own locking which doesn't support mode modifier t (test lock)", hptr->name); FREENOW; RETURN_FALSE; } else { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Handler %s doesn't uses locking for this mode which makes modifier t (test lock) obsolete", hptr->name); FREENOW; RETURN_FALSE; } } else { lock_mode |= LOCK_NB; /* test =: non blocking */ } } if (*pmode) { php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Illegal DBA mode"); FREENOW; RETURN_FALSE; } info = pemalloc(sizeof(dba_info), persistent); memset(info, 0, sizeof(dba_info)); info->path = pestrdup(Z_STRVAL(args[0]), persistent); info->mode = modenr; info->argc = ac - 3; info->argv = args + 3; info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0); info->lock.mode = lock_mode; /* if any open call is a locking call: * check if we already habe a locking call open that should block this call * the problem is some systems would allow read during write */ if (hptr->flags & DBA_LOCK_ALL) { if ((other = php_dba_find(info->path)) != NULL) { if ( ( (lock_mode&LOCK_EX) && (other->lock.mode&(LOCK_EX|LOCK_SH)) ) || ( (other->lock.mode&LOCK_EX) && (lock_mode&(LOCK_EX|LOCK_SH)) ) ) { error = "Unable to establish lock (database file already open)"; /* force failure exit */ } } } if (!error && lock_mode) { if (lock_dbf) { lock_name = Z_STRVAL(args[0]); } else { spprintf(&lock_name, 0, "%s.lck", info->path); if (!strcmp(file_mode, "r")) { /* when in read only mode try to use existing .lck file first */ /* do not log errors for .lck file while in read ony mode on .lck file */ lock_file_mode = "rb"; info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, &opened_path); } if (!info->lock.fp) { /* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */ lock_file_mode = "a+b"; } else { if (opened_path) { info->lock.name = pestrndup(ZSTR_VAL(opened_path), ZSTR_LEN(opened_path), persistent); zend_string_release(opened_path); } } } if (!info->lock.fp) { info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path); if (info->lock.fp) { if (lock_dbf) { /* replace the path info with the real path of the opened file */ pefree(info->path, persistent); info->path = pestrndup(ZSTR_VAL(opened_path), ZSTR_LEN(opened_path), persistent); } /* now store the name of the lock */ info->lock.name = pestrndup(ZSTR_VAL(opened_path), ZSTR_LEN(opened_path), persistent); zend_string_release(opened_path); } } if (!lock_dbf) { efree(lock_name); } if (!info->lock.fp) { dba_close(info); /* stream operation already wrote an error message */ FREENOW; RETURN_FALSE; } if (!php_stream_supports_lock(info->lock.fp)) { error = "Stream does not support locking"; } if (php_stream_lock(info->lock.fp, lock_mode)) { error = "Unable to establish lock"; /* force failure exit */ } } /* centralised open stream for builtin */ if (!error && (hptr->flags&DBA_STREAM_OPEN)==DBA_STREAM_OPEN) { if (info->lock.fp && lock_dbf) { info->fp = info->lock.fp; /* use the same stream for locking and database access */ } else { info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL); } if (!info->fp) { dba_close(info); /* stream operation already wrote an error message */ FREENOW; RETURN_FALSE; } if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) { /* Needed because some systems do not allow to write to the original * file contents with O_APPEND being set. */ if (SUCCESS != php_stream_cast(info->fp, PHP_STREAM_AS_FD, (void*)&info->fd, 1)) { php_error_docref(NULL, E_WARNING, "Could not cast stream"); dba_close(info); FREENOW; RETURN_FALSE; #ifdef F_SETFL } else if (modenr == DBA_CREAT) { int flags = fcntl(info->fd, F_GETFL); fcntl(info->fd, F_SETFL, flags & ~O_APPEND); #endif } } } if (error || hptr->open(info, &error) != SUCCESS) { dba_close(info); php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Driver initialization failed for handler: %s%s%s", hptr->name, error?": ":"", error?error:""); FREENOW; RETURN_FALSE; } info->hnd = hptr; info->argc = 0; info->argv = NULL; if (persistent) { zval new_le; ZVAL_NEW_PERSISTENT_RES(&new_le, -1, info, le_pdb); if (zend_hash_str_update(&EG(persistent_list), key, keylen, &new_le) == NULL) { dba_close(info); php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Could not register persistent resource"); FREENOW; RETURN_FALSE; } } RETVAL_RES(zend_register_resource(info, (persistent ? le_pdb : le_db))); FREENOW; }
static php_stream_filter *user_filter_factory_create(const char *filtername, zval *filterparams, int persistent) { struct php_user_filter_data *fdat = NULL; php_stream_filter *filter; zval obj, zfilter; zval func_name; zval retval; int len; /* some sanity checks */ if (persistent) { php_error_docref(NULL, E_WARNING, "cannot use a user-space filter with a persistent stream"); return NULL; } len = (int)strlen(filtername); /* determine the classname/class entry */ if (NULL == (fdat = zend_hash_str_find_ptr(BG(user_filter_map), (char*)filtername, len))) { char *period; /* Userspace Filters using ambiguous wildcards could cause problems. i.e.: myfilter.foo.bar will always call into myfilter.foo.* never seeing myfilter.* TODO: Allow failed userfilter creations to continue scanning through the list */ if ((period = strrchr(filtername, '.'))) { char *wildcard = emalloc(len + 3); /* Search for wildcard matches instead */ memcpy(wildcard, filtername, len + 1); /* copy \0 */ period = wildcard + (period - filtername); while (period) { *period = '\0'; strncat(wildcard, ".*", 2); if (NULL != (fdat = zend_hash_str_find_ptr(BG(user_filter_map), wildcard, strlen(wildcard)))) { period = NULL; } else { *period = '\0'; period = strrchr(wildcard, '.'); } } efree(wildcard); } if (fdat == NULL) { php_error_docref(NULL, E_WARNING, "Err, filter \"%s\" is not in the user-filter map, but somehow the user-filter-factory was invoked for it!?", filtername); return NULL; } } /* bind the classname to the actual class */ if (fdat->ce == NULL) { if (NULL == (fdat->ce = zend_lookup_class(fdat->classname))) { php_error_docref(NULL, E_WARNING, "user-filter \"%s\" requires class \"%s\", but that class is not defined", filtername, ZSTR_VAL(fdat->classname)); return NULL; } } filter = php_stream_filter_alloc(&userfilter_ops, NULL, 0); if (filter == NULL) { return NULL; } /* create the object */ object_init_ex(&obj, fdat->ce); /* filtername */ add_property_string(&obj, "filtername", (char*)filtername); /* and the parameters, if any */ if (filterparams) { add_property_zval(&obj, "params", filterparams); } else { add_property_null(&obj, "params"); } /* invoke the constructor */ ZVAL_STRINGL(&func_name, "oncreate", sizeof("oncreate")-1); call_user_function_ex(NULL, &obj, &func_name, &retval, 0, NULL, 0, NULL); if (Z_TYPE(retval) != IS_UNDEF) { if (Z_TYPE(retval) == IS_FALSE) { /* User reported filter creation error "return false;" */ zval_ptr_dtor(&retval); /* Kill the filter (safely) */ ZVAL_UNDEF(&filter->abstract); php_stream_filter_free(filter); /* Kill the object */ zval_ptr_dtor(&obj); /* Report failure to filter_alloc */ return NULL; } zval_ptr_dtor(&retval); } zval_ptr_dtor(&func_name); /* set the filter property, this will be used during cleanup */ ZVAL_RES(&zfilter, zend_register_resource(filter, le_userfilters)); ZVAL_COPY_VALUE(&filter->abstract, &obj); add_property_zval(&obj, "filter", &zfilter); /* add_property_zval increments the refcount which is unwanted here */ zval_ptr_dtor(&zfilter); return filter; }