static void zend_hash_persist_calc(HashTable *ht, void (*pPersistElement)(zval *pElement)) { uint idx; Bucket *p; if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) { return; } ADD_SIZE(HT_USED_SIZE(ht)); for (idx = 0; idx < ht->nNumUsed; idx++) { p = ht->arData + idx; if (Z_TYPE(p->val) == IS_UNDEF) continue; /* persist bucket and key */ if (p->key) { zend_uchar flags = GC_FLAGS(p->key) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT); ADD_INTERNED_STRING(p->key, 1); GC_FLAGS(p->key) |= flags; } pPersistElement(&p->val); } }
static inline zend_long *pthreads_get_guard(zend_object *zobj, zval *member) /* {{{ */ { HashTable *guards; zend_long stub, *guard; zval tmp; ZEND_ASSERT(GC_FLAGS(zobj) & IS_OBJ_USE_GUARDS); if (GC_FLAGS(zobj) & IS_OBJ_HAS_GUARDS) { guards = Z_PTR(zobj->properties_table[zobj->ce->default_properties_count]); ZEND_ASSERT(guards != NULL); if (Z_TYPE_P(member) == IS_LONG) { if ((guard = (zend_long *)zend_hash_index_find_ptr(guards, Z_LVAL_P(member))) != NULL) { return guard; } } else { if ((guard = (zend_long *)zend_hash_find_ptr(guards, Z_STR_P(member))) != NULL) { return guard; } } } else { ALLOC_HASHTABLE(guards); zend_hash_init(guards, 8, NULL, pthreads_guard_dtor, 0); ZVAL_PTR(&tmp, guards); Z_PTR(zobj->properties_table[zobj->ce->default_properties_count]) = guards; GC_FLAGS(zobj) |= IS_OBJ_HAS_GUARDS; } stub = 0; if (Z_TYPE_P(member) == IS_LONG) { return (zend_long *)zend_hash_index_add_mem(guards, Z_LVAL_P(member), &stub, sizeof(zend_ulong)); } else return (zend_long *)zend_hash_add_mem(guards, Z_STR_P(member), &stub, sizeof(zend_ulong)); }
PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) { void *next; zend_long i; var_entries *var_hash = (*var_hashx)->first; var_dtor_entries *var_dtor_hash = (*var_hashx)->first_dtor; zend_bool wakeup_failed = 0; zval wakeup_name; ZVAL_UNDEF(&wakeup_name); #if VAR_ENTRIES_DBG fprintf(stderr, "var_destroy(%ld)\n", var_hash?var_hash->used_slots:-1L); #endif while (var_hash) { next = var_hash->next; efree_size(var_hash, sizeof(var_entries)); var_hash = next; } while (var_dtor_hash) { for (i = 0; i < var_dtor_hash->used_slots; i++) { zval *zv = &var_dtor_hash->data[i]; #if VAR_ENTRIES_DBG fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_dtor_hash->data[i], Z_REFCOUNT_P(var_dtor_hash->data[i])); #endif /* Perform delayed __wakeup calls */ if (Z_EXTRA_P(zv) == VAR_WAKEUP_FLAG) { if (!wakeup_failed) { zval retval; if (Z_ISUNDEF(wakeup_name)) { ZVAL_STRINGL(&wakeup_name, "__wakeup", sizeof("__wakeup") - 1); } BG(serialize_lock)++; if (call_user_function_ex(CG(function_table), zv, &wakeup_name, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) { wakeup_failed = 1; GC_FLAGS(Z_OBJ_P(zv)) |= IS_OBJ_DESTRUCTOR_CALLED; } BG(serialize_lock)--; zval_ptr_dtor(&retval); } else { GC_FLAGS(Z_OBJ_P(zv)) |= IS_OBJ_DESTRUCTOR_CALLED; } } i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC); } next = var_dtor_hash->next; efree_size(var_dtor_hash, sizeof(var_dtor_entries)); var_dtor_hash = next; } zval_ptr_dtor_nogc(&wakeup_name); }
static void *zend_file_cache_unserialize_interned(zend_string *str, int in_shm) { zend_string *ret; str = (zend_string*)((char*)ZCG(mem) + ((size_t)(str) & ~Z_UL(1))); ret = accel_new_interned_string(str); if (ret == str) { /* String wasn't interned but we will use it as interned anyway */ if (in_shm) { GC_FLAGS(ret) |= IS_STR_INTERNED | IS_STR_PERMANENT; } else { GC_FLAGS(ret) |= IS_STR_INTERNED; GC_FLAGS(ret) &= ~IS_STR_PERMANENT; } } return ret; }
static void ZEND_FASTCALL zend_string_destroy(zend_string *str) { CHECK_ZVAL_STRING(str); ZEND_ASSERT(!ZSTR_IS_INTERNED(str)); ZEND_ASSERT(GC_REFCOUNT(str) == 0); ZEND_ASSERT(!(GC_FLAGS(str) & IS_STR_PERSISTENT)); efree(str); }
static zend_always_inline zend_string *zend_clone_str(zend_string *str) { zend_string *ret; if (EXPECTED(IS_INTERNED(str))) { ret = str; } else if (GC_REFCOUNT(str) <= 1 || (ret = accel_xlat_get(str)) == NULL) { ret = zend_string_dup(str, 0); GC_FLAGS(ret) = GC_FLAGS(str); if (GC_REFCOUNT(str) > 1) { accel_xlat_set(str, ret); } } else { GC_REFCOUNT(ret)++; } return ret; }
ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ */ { /* Make sure we hold a reference count during the destructor call otherwise, when the destructor ends the storage might be freed when the refcount reaches 0 a second time */ if (EG(objects_store).object_buckets && IS_OBJ_VALID(EG(objects_store).object_buckets[object->handle])) { if (GC_REFCOUNT(object) == 0) { if (!(GC_FLAGS(object) & IS_OBJ_DESTRUCTOR_CALLED)) { GC_FLAGS(object) |= IS_OBJ_DESTRUCTOR_CALLED; if (object->handlers->dtor_obj && (object->handlers->dtor_obj != zend_objects_destroy_object || object->ce->destructor)) { GC_ADDREF(object); object->handlers->dtor_obj(object); GC_DELREF(object); } } if (GC_REFCOUNT(object) == 0) { uint32_t handle = object->handle; void *ptr; EG(objects_store).object_buckets[handle] = SET_OBJ_INVALID(object); if (!(GC_FLAGS(object) & IS_OBJ_FREE_CALLED)) { GC_FLAGS(object) |= IS_OBJ_FREE_CALLED; if (object->handlers->free_obj) { GC_ADDREF(object); object->handlers->free_obj(object); GC_DELREF(object); } } ptr = ((char*)object) - object->handlers->offset; GC_REMOVE_FROM_BUFFER(object); efree(ptr); ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle); } } else { GC_DELREF(object); } } }
ZEND_API void ZEND_FASTCALL zend_objects_store_free_object_storage(zend_objects_store *objects, zend_bool fast_shutdown) { zend_object **obj_ptr, **end, *obj; if (objects->top <= 1) { return; } /* Free object contents, but don't free objects themselves, so they show up as leaks */ end = objects->object_buckets + 1; obj_ptr = objects->object_buckets + objects->top; if (fast_shutdown) { do { obj_ptr--; obj = *obj_ptr; if (IS_OBJ_VALID(obj)) { if (!(GC_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { GC_FLAGS(obj) |= IS_OBJ_FREE_CALLED; if (obj->handlers->free_obj && obj->handlers->free_obj != zend_object_std_dtor) { GC_ADDREF(obj); obj->handlers->free_obj(obj); GC_DELREF(obj); } } } } while (obj_ptr != end); } else { do { obj_ptr--; obj = *obj_ptr; if (IS_OBJ_VALID(obj)) { if (!(GC_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { GC_FLAGS(obj) |= IS_OBJ_FREE_CALLED; if (obj->handlers->free_obj) { GC_ADDREF(obj); obj->handlers->free_obj(obj); GC_DELREF(obj); } } } } while (obj_ptr != end); } }
ZEND_API void ZEND_FASTCALL zend_objects_store_call_destructors(zend_objects_store *objects) { if (objects->top > 1) { uint32_t i; for (i = 1; i < objects->top; i++) { zend_object *obj = objects->object_buckets[i]; if (IS_OBJ_VALID(obj)) { if (!(GC_FLAGS(obj) & IS_OBJ_DESTRUCTOR_CALLED)) { GC_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED; if (obj->handlers->dtor_obj && (obj->handlers->dtor_obj != zend_objects_destroy_object || obj->ce->destructor)) { GC_ADDREF(obj); obj->handlers->dtor_obj(obj); GC_DELREF(obj); } } } } } }
/* This function might be not thread safe at least because it would update the hash val in the passed string. Be sure it is called in the appropriate context. */ static zend_always_inline zend_string *zend_add_interned_string(zend_string *str, HashTable *interned_strings, uint32_t flags) { zval val; GC_SET_REFCOUNT(str, 1); GC_FLAGS(str) |= IS_STR_INTERNED | flags; ZVAL_INTERNED_STR(&val, str); zend_hash_add_new(interned_strings, str, &val); return str; }
ZEND_API void ZEND_FASTCALL zend_objects_store_mark_destructed(zend_objects_store *objects) { if (objects->object_buckets && objects->top > 1) { zend_object **obj_ptr = objects->object_buckets + 1; zend_object **end = objects->object_buckets + objects->top; do { zend_object *obj = *obj_ptr; if (IS_OBJ_VALID(obj)) { GC_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED; } obj_ptr++; } while (obj_ptr != end); } }
static void zend_accel_destroy_zend_function(zval *zv) { zend_function *function = Z_PTR_P(zv); if (function->type == ZEND_USER_FUNCTION) { if (function->op_array.static_variables) { if (!(GC_FLAGS(function->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) { if (--GC_REFCOUNT(function->op_array.static_variables) == 0) { FREE_HASHTABLE(function->op_array.static_variables); } } function->op_array.static_variables = NULL; } } destroy_zend_function(function); }
ZEND_API void zval_internal_ptr_dtor(zval *zval_ptr) /* {{{ */ { if (Z_REFCOUNTED_P(zval_ptr)) { zend_refcounted *ref = Z_COUNTED_P(zval_ptr); if (GC_DELREF(ref) == 0) { if (Z_TYPE_P(zval_ptr) == IS_STRING) { zend_string *str = (zend_string*)ref; CHECK_ZVAL_STRING(str); ZEND_ASSERT(!ZSTR_IS_INTERNED(str)); ZEND_ASSERT((GC_FLAGS(str) & IS_STR_PERSISTENT)); free(str); } else { zend_error_noreturn(E_CORE_ERROR, "Internal zval's can't be arrays, objects, resources or reference"); } } } }
static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements) { HashTable *ht; zend_bool has_wakeup; if (Z_TYPE_P(rval) != IS_OBJECT) { return 0; } has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY && zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1); ht = Z_OBJPROP_P(rval); if (elements >= (zend_long)(HT_MAX_SIZE - zend_hash_num_elements(ht))) { return 0; } zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED)); if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) { if (has_wakeup) { ZVAL_DEREF(rval); GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED; } return 0; } ZVAL_DEREF(rval); if (has_wakeup) { /* Delay __wakeup call until end of serialization */ zval *wakeup_var = var_tmp_var(var_hash); ZVAL_COPY(wakeup_var, rval); Z_EXTRA_P(wakeup_var) = VAR_WAKEUP_FLAG; } return finish_nested_data(UNSERIALIZE_PASSTHRU); }
static int pgsql_stmt_dtor(pdo_stmt_t *stmt) { pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; zend_bool server_obj_usable = IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE(stmt->database_object_handle)]) && !(GC_FLAGS(Z_OBJ(stmt->database_object_handle)) & IS_OBJ_FREE_CALLED); if (S->result) { /* free the resource */ PQclear(S->result); S->result = NULL; } if (S->stmt_name) { if (S->is_prepared && server_obj_usable) { pdo_pgsql_db_handle *H = S->H; char *q = NULL; PGresult *res; spprintf(&q, 0, "DEALLOCATE %s", S->stmt_name); res = PQexec(H->server, q); efree(q); if (res) { PQclear(res); } } efree(S->stmt_name); S->stmt_name = NULL; } if (S->param_lengths) { efree(S->param_lengths); S->param_lengths = NULL; } if (S->param_values) { efree(S->param_values); S->param_values = NULL; } if (S->param_formats) { efree(S->param_formats); S->param_formats = NULL; } if (S->param_types) { efree(S->param_types); S->param_types = NULL; } if (S->query) { efree(S->query); S->query = NULL; } if (S->cursor_name) { if (server_obj_usable) { pdo_pgsql_db_handle *H = S->H; char *q = NULL; PGresult *res; spprintf(&q, 0, "CLOSE %s", S->cursor_name); res = PQexec(H->server, q); efree(q); if (res) PQclear(res); } efree(S->cursor_name); S->cursor_name = NULL; } if(S->cols) { efree(S->cols); S->cols = NULL; } efree(S); stmt->driver_data = NULL; return 1; }
static APC_HOTSPOT HashTable* my_copy_hashtable(HashTable *source, apc_context_t *ctxt) { uint32_t idx; HashTable *target; apc_pool *pool = ctxt->pool; if (ctxt->copy == APC_COPY_IN) { target = (HashTable*) pool->palloc(pool, sizeof(HashTable)); } else ALLOC_HASHTABLE(target); GC_REFCOUNT(target) = 1; GC_TYPE_INFO(target) = IS_ARRAY; zend_hash_index_update_ptr(&ctxt->copied, (uintptr_t) source, target); target->nTableSize = source->nTableSize; target->pDestructor = source->pDestructor; if (source->nNumUsed == 0) { target->u.flags = (source->u.flags & ~(HASH_FLAG_INITIALIZED|HASH_FLAG_PACKED|HASH_FLAG_PERSISTENT)) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS; target->nTableMask = HT_MIN_MASK; target->nNumUsed = 0; target->nNumOfElements = 0; target->nNextFreeElement = 0; target->nInternalPointer = HT_INVALID_IDX; HT_SET_DATA_ADDR(target, &uninitialized_bucket); } else if (GC_FLAGS(source) & IS_ARRAY_IMMUTABLE) { target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION; target->nTableMask = source->nTableMask; target->nNumUsed = source->nNumUsed; target->nNumOfElements = source->nNumOfElements; target->nNextFreeElement = source->nNextFreeElement; if (ctxt->copy == APC_COPY_IN) { HT_SET_DATA_ADDR(target, pool->palloc(pool, HT_SIZE(target))); } else HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target))); target->nInternalPointer = source->nInternalPointer; memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_USED_SIZE(source)); if (target->nNumOfElements > 0 && target->nInternalPointer == HT_INVALID_IDX) { idx = 0; while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) { idx++; } target->nInternalPointer = idx; } } else if (source->u.flags & HASH_FLAG_PACKED) { target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION; target->nTableMask = source->nTableMask; target->nNumUsed = source->nNumUsed; target->nNumOfElements = source->nNumOfElements; target->nNextFreeElement = source->nNextFreeElement; if (ctxt->copy == APC_COPY_IN) { HT_SET_DATA_ADDR(target, pool->palloc(pool, HT_SIZE(target))); } else HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target))); target->nInternalPointer = source->nInternalPointer; HT_HASH_RESET_PACKED(target); if (target->nNumUsed == target->nNumOfElements) { apc_array_dup_packed_elements(ctxt, source, target, 0); } else { apc_array_dup_packed_elements(ctxt, source, target, 1); } if (target->nNumOfElements > 0 && target->nInternalPointer == HT_INVALID_IDX) { idx = 0; while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) { idx++; } target->nInternalPointer = idx; } } else { target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION; target->nTableMask = source->nTableMask; target->nNextFreeElement = source->nNextFreeElement; target->nInternalPointer = HT_INVALID_IDX; if (ctxt->copy == APC_COPY_IN) { HT_SET_DATA_ADDR(target, pool->palloc(pool, HT_SIZE(target))); } else HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target))); HT_HASH_RESET(target); if (target->u.flags & HASH_FLAG_STATIC_KEYS) { if (source->nNumUsed == source->nNumOfElements) { idx = apc_array_dup_elements(ctxt, source, target, 1, 0); } else { idx = apc_array_dup_elements(ctxt, source, target, 1, 1); } } else { if (source->nNumUsed == source->nNumOfElements) { idx = apc_array_dup_elements(ctxt, source, target, 0, 0); } else { idx = apc_array_dup_elements(ctxt, source, target, 0, 1); } } target->nNumUsed = idx; target->nNumOfElements = idx; if (idx > 0 && target->nInternalPointer == HT_INVALID_IDX) { target->nInternalPointer = 0; } } return target; }
static void _str_dtor(zval *zv) { zend_string *str = Z_STR_P(zv); GC_FLAGS(str) &= ~IS_STR_INTERNED; GC_REFCOUNT(str) = 1; }
/* {{{ php_url_encode_hash */ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, const char *num_prefix, size_t num_prefix_len, const char *key_prefix, size_t key_prefix_len, const char *key_suffix, size_t key_suffix_len, zval *type, char *arg_sep, int enc_type) { zend_string *key = NULL; char *newprefix, *p; const char *prop_name; size_t arg_sep_len, newprefix_len, prop_len; zend_ulong idx; zval *zdata = NULL; if (!ht) { return FAILURE; } if (GC_IS_RECURSIVE(ht)) { /* Prevent recursion */ return SUCCESS; } if (!arg_sep) { arg_sep = INI_STR("arg_separator.output"); if (!arg_sep || !strlen(arg_sep)) { arg_sep = URL_DEFAULT_ARG_SEP; } } arg_sep_len = strlen(arg_sep); ZEND_HASH_FOREACH_KEY_VAL(ht, idx, key, zdata) { zend_bool is_dynamic = 1; if (Z_TYPE_P(zdata) == IS_INDIRECT) { zdata = Z_INDIRECT_P(zdata); if (Z_ISUNDEF_P(zdata)) { continue; } is_dynamic = 0; } /* handling for private & protected object properties */ if (key) { prop_name = ZSTR_VAL(key); prop_len = ZSTR_LEN(key); if (type != NULL && zend_check_property_access(Z_OBJ_P(type), key, is_dynamic) != SUCCESS) { /* property not visible in this scope */ continue; } if (ZSTR_VAL(key)[0] == '\0' && type != NULL) { const char *tmp; zend_unmangle_property_name_ex(key, &tmp, &prop_name, &prop_len); } else { prop_name = ZSTR_VAL(key); prop_len = ZSTR_LEN(key); } } else { prop_name = NULL; prop_len = 0; } ZVAL_DEREF(zdata); if (Z_TYPE_P(zdata) == IS_ARRAY || Z_TYPE_P(zdata) == IS_OBJECT) { if (key) { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(prop_name, prop_len); } else { ekey = php_url_encode(prop_name, prop_len); } newprefix_len = key_suffix_len + ZSTR_LEN(ekey) + key_prefix_len + 3 /* %5B */; newprefix = emalloc(newprefix_len + 1); p = newprefix; if (key_prefix) { memcpy(p, key_prefix, key_prefix_len); p += key_prefix_len; } memcpy(p, ZSTR_VAL(ekey), ZSTR_LEN(ekey)); p += ZSTR_LEN(ekey); zend_string_free(ekey); if (key_suffix) { memcpy(p, key_suffix, key_suffix_len); p += key_suffix_len; } *(p++) = '%'; *(p++) = '5'; *(p++) = 'B'; *p = '\0'; } else { char *ekey; size_t ekey_len; /* Is an integer key */ ekey_len = spprintf(&ekey, 0, ZEND_LONG_FMT, idx); newprefix_len = key_prefix_len + num_prefix_len + ekey_len + key_suffix_len + 3 /* %5B */; newprefix = emalloc(newprefix_len + 1); p = newprefix; if (key_prefix) { memcpy(p, key_prefix, key_prefix_len); p += key_prefix_len; } memcpy(p, num_prefix, num_prefix_len); p += num_prefix_len; memcpy(p, ekey, ekey_len); p += ekey_len; efree(ekey); if (key_suffix) { memcpy(p, key_suffix, key_suffix_len); p += key_suffix_len; } *(p++) = '%'; *(p++) = '5'; *(p++) = 'B'; *p = '\0'; } if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) { GC_PROTECT_RECURSION(ht); } php_url_encode_hash_ex(HASH_OF(zdata), formstr, NULL, 0, newprefix, newprefix_len, "%5D", 3, (Z_TYPE_P(zdata) == IS_OBJECT ? zdata : NULL), arg_sep, enc_type); if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) { GC_UNPROTECT_RECURSION(ht); } efree(newprefix); } else if (Z_TYPE_P(zdata) == IS_NULL || Z_TYPE_P(zdata) == IS_RESOURCE) { /* Skip these types */ continue; } else { if (formstr->s) { smart_str_appendl(formstr, arg_sep, arg_sep_len); } /* Simple key=value */ smart_str_appendl(formstr, key_prefix, key_prefix_len); if (key) { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(prop_name, prop_len); } else { ekey = php_url_encode(prop_name, prop_len); } smart_str_append(formstr, ekey); zend_string_free(ekey); } else { /* Numeric key */ if (num_prefix) { smart_str_appendl(formstr, num_prefix, num_prefix_len); } smart_str_append_long(formstr, idx); } smart_str_appendl(formstr, key_suffix, key_suffix_len); smart_str_appendl(formstr, "=", 1); switch (Z_TYPE_P(zdata)) { case IS_STRING: { zend_string *ekey; if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); } else { ekey = php_url_encode(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); } smart_str_append(formstr, ekey); zend_string_free(ekey); } break; case IS_LONG: smart_str_append_long(formstr, Z_LVAL_P(zdata)); break; case IS_FALSE: smart_str_appendl(formstr, "0", sizeof("0")-1); break; case IS_TRUE: smart_str_appendl(formstr, "1", sizeof("1")-1); break; case IS_DOUBLE: { char *ekey; size_t ekey_len; ekey_len = spprintf(&ekey, 0, "%.*G", (int) EG(precision), Z_DVAL_P(zdata)); smart_str_appendl(formstr, ekey, ekey_len); efree(ekey); } break; default: { zend_string *ekey; zend_string *tmp; zend_string *str= zval_get_tmp_string(zdata, &tmp); if (enc_type == PHP_QUERY_RFC3986) { ekey = php_raw_url_encode(ZSTR_VAL(str), ZSTR_LEN(str)); } else { ekey = php_url_encode(ZSTR_VAL(str), ZSTR_LEN(str)); } smart_str_append(formstr, ekey); zend_tmp_string_release(tmp); zend_string_free(ekey); } } } } ZEND_HASH_FOREACH_END();
PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */ { HashTable *myht; zend_string *class_name; int is_ref = 0; zend_ulong num; zend_string *key; zval *val; uint32_t count; if (level > 1) { php_printf("%*c", level - 1, ' '); } again: switch (Z_TYPE_P(struc)) { case IS_FALSE: php_printf("%sbool(false)\n", COMMON); break; case IS_TRUE: php_printf("%sbool(true)\n", COMMON); break; case IS_NULL: php_printf("%sNULL\n", COMMON); break; case IS_LONG: php_printf("%sint(" ZEND_LONG_FMT ")\n", COMMON, Z_LVAL_P(struc)); break; case IS_DOUBLE: php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_P(struc)); break; case IS_STRING: php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc)); PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc)); PUTS("\"\n"); break; case IS_ARRAY: myht = Z_ARRVAL_P(struc); if (level > 1 && !(GC_FLAGS(myht) & GC_IMMUTABLE)) { if (GC_IS_RECURSIVE(myht)) { PUTS("*RECURSION*\n"); return; } GC_PROTECT_RECURSION(myht); } count = zend_array_count(myht); php_printf("%sarray(%d) {\n", COMMON, count); ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) { php_array_element_dump(val, num, key, level); } ZEND_HASH_FOREACH_END(); if (level > 1 && !(GC_FLAGS(myht) & GC_IMMUTABLE)) { GC_UNPROTECT_RECURSION(myht); } if (level > 1) { php_printf("%*c", level-1, ' '); } PUTS("}\n"); break; case IS_OBJECT: if (Z_IS_RECURSIVE_P(struc)) { PUTS("*RECURSION*\n"); return; } Z_PROTECT_RECURSION_P(struc); myht = zend_get_properties_for(struc, ZEND_PROP_PURPOSE_DEBUG); class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc)); php_printf("%sobject(%s)#%d (%d) {\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0); zend_string_release_ex(class_name, 0); if (myht) { zend_ulong num; zend_string *key; zval *val; ZEND_HASH_FOREACH_KEY_VAL(myht, num, key, val) { zend_property_info *prop_info = NULL; if (Z_TYPE_P(val) == IS_INDIRECT) { val = Z_INDIRECT_P(val); if (key) { prop_info = zend_get_typed_property_info_for_slot(Z_OBJ_P(struc), val); } } if (!Z_ISUNDEF_P(val) || prop_info) { php_object_property_dump(prop_info, val, num, key, level); } } ZEND_HASH_FOREACH_END(); zend_release_properties(myht); }
static void _str_dtor(zval *zv) { zend_string *str = Z_STR_P(zv); pefree(str, GC_FLAGS(str) & IS_STR_PERSISTENT); }