Exemplo n.º 1
0
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));
}
Exemplo n.º 2
0
ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref)
{
	uint32_t idx;
	gc_root_buffer *newRoot;

	if (UNEXPECTED(GC_G(gc_protected))) {
		return;
	}

	GC_BENCH_INC(zval_possible_root);

	if (EXPECTED(GC_HAS_UNUSED())) {
		idx = GC_FETCH_UNUSED();
	} else if (EXPECTED(GC_HAS_NEXT_UNUSED_UNDER_THRESHOLD())) {
		idx = GC_FETCH_NEXT_UNUSED();
	} else {
		gc_possible_root_when_full(ref);
		return;
	}

	ZEND_ASSERT(GC_TYPE(ref) == IS_ARRAY || GC_TYPE(ref) == IS_OBJECT);
	ZEND_ASSERT(GC_INFO(ref) == 0);

	newRoot = GC_IDX2PTR(idx);
	newRoot->ref = ref; /* GC_ROOT tag is 0 */
	GC_TRACE_SET_COLOR(ref, GC_PURPLE);

	idx = gc_compress(idx);
	GC_REF_SET_INFO(ref, idx | GC_PURPLE);
	GC_G(num_roots)++;

	GC_BENCH_INC(zval_buffered);
	GC_BENCH_INC(root_buf_length);
	GC_BENCH_PEAK(root_buf_peak, root_buf_length);
}
Exemplo n.º 3
0
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 void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce)
{
	uint idx;
	Bucket *p, *q;
	zend_ulong nIndex;
	zend_op_array *new_entry;

	ht->nTableSize = source->nTableSize;
	ht->nTableMask = source->nTableMask;
	ht->nNumUsed = 0;
	ht->nNumOfElements = source->nNumOfElements;
	ht->nNextFreeElement = source->nNextFreeElement;
	ht->pDestructor = ZEND_FUNCTION_DTOR;
	ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED);
	ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX;

	if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
		ht->arHash = (uint32_t*)&uninitialized_bucket;
		return;
	}

	ZEND_ASSERT(!(source->u.flags & HASH_FLAG_PACKED));
	ht->arData = (Bucket *) emalloc(ht->nTableSize * (sizeof(Bucket) + sizeof(uint32_t)));
	ht->arHash = (uint32_t *)(ht->arData + ht->nTableSize);
	memset(ht->arHash, INVALID_IDX, sizeof(uint32_t) * ht->nTableSize);

	for (idx = 0; idx < source->nNumUsed; idx++) {
		p = source->arData + idx;
		if (Z_TYPE(p->val) == IS_UNDEF) continue;

		nIndex = p->h & ht->nTableMask;

		/* Insert into hash collision list */
		q = ht->arData + ht->nNumUsed;
		Z_NEXT(q->val) = ht->arHash[nIndex];
		ht->arHash[nIndex] = ht->nNumUsed++;

		/* Initialize key */
		q->h = p->h;
		ZEND_ASSERT(p->key != NULL);
		q->key = zend_clone_str(p->key);

		/* Copy data */
		ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val)));
		new_entry = (zend_op_array*)Z_PTR(q->val);

		if ((void*)new_entry->scope >= ZCG(current_persistent_script)->arena_mem &&
		    (void*)new_entry->scope < (void*)((char*)ZCG(current_persistent_script)->arena_mem + ZCG(current_persistent_script)->arena_size)) {

			new_entry->scope = ARENA_REALLOC(new_entry->scope);

			/* update prototype */
			if (new_entry->prototype) {
				new_entry->prototype = ARENA_REALLOC(new_entry->prototype);
			}
		}
	}
}
Exemplo n.º 5
0
static zend_always_inline uint32_t gc_fetch_unused(void)
{
	uint32_t idx;
	gc_root_buffer *root;

	ZEND_ASSERT(GC_HAS_UNUSED());
	idx = GC_G(unused);
	root = GC_IDX2PTR(idx);
	ZEND_ASSERT(GC_IS_UNUSED(root->ref));
	GC_G(unused) = GC_LIST2IDX(root->ref);
	return idx;
}
Exemplo n.º 6
0
void *zend_shared_alloc(size_t size)
{
	int i;
	unsigned int block_size = ZEND_ALIGNED_SIZE(size);

#if 1
	if (!ZCG(locked)) {
		zend_accel_error(ACCEL_LOG_ERROR, "Shared memory lock not obtained");
	}
#endif
	if (block_size > ZSMMG(shared_free)) { /* No hope to find a big-enough block */
		SHARED_ALLOC_FAILED();
		return NULL;
	}
	for (i = 0; i < ZSMMG(shared_segments_count); i++) {
		if (ZSMMG(shared_segments)[i]->size - ZSMMG(shared_segments)[i]->pos >= block_size) { /* found a valid block */
			void *retval = (void *) (((char *) ZSMMG(shared_segments)[i]->p) + ZSMMG(shared_segments)[i]->pos);

			ZSMMG(shared_segments)[i]->pos += block_size;
			ZSMMG(shared_free) -= block_size;
			memset(retval, 0, block_size);
			ZEND_ASSERT(((zend_uintptr_t)retval & 0x7) == 0); /* should be 8 byte aligned */
			return retval;
		}
	}
	SHARED_ALLOC_FAILED();
	return NULL;
}
Exemplo n.º 7
0
static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement)
{
	uint32_t idx, nIndex;
	Bucket *p;

	if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
		HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
		return;
	}
	if (ht->nNumUsed == 0) {
		efree(HT_GET_DATA_ADDR(ht));
		ht->nTableMask = HT_MIN_MASK;
		HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
		ht->u.flags &= ~HASH_FLAG_INITIALIZED;
		return;
	}
	if (ht->u.flags & HASH_FLAG_PACKED) {
		void *data = HT_GET_DATA_ADDR(ht);
		zend_accel_store(data, HT_USED_SIZE(ht));
		HT_SET_DATA_ADDR(ht, data);
	} else if (ht->nNumUsed < (uint32_t)(-(int32_t)ht->nTableMask) / 2) {
		/* compact table */
		void *old_data = HT_GET_DATA_ADDR(ht);
		Bucket *old_buckets = ht->arData;
		uint32_t hash_size;

		if (ht->nNumUsed <= HT_MIN_SIZE) {
			hash_size = HT_MIN_SIZE;
		} else {
			hash_size = (uint32_t)(-(int32_t)ht->nTableMask);
			while (hash_size >> 1 > ht->nNumUsed) {
				hash_size >>= 1;
			}
		}
		ht->nTableMask = (uint32_t)(-(int32_t)hash_size);
		ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
		HT_SET_DATA_ADDR(ht, ZCG(mem));
		ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE((hash_size * sizeof(uint32_t)) + (ht->nNumUsed * sizeof(Bucket))));
		HT_HASH_RESET(ht);
		memcpy(ht->arData, old_buckets, ht->nNumUsed * sizeof(Bucket));
		efree(old_data);

		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_accel_store_interned_string(p->key);
			}

			/* persist the data itself */
			pPersistElement(&p->val);

			nIndex = p->h | ht->nTableMask;
			Z_NEXT(p->val) = HT_HASH(ht, nIndex);
			HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
		}
		return;
	} else {
Exemplo n.º 8
0
static int phpdbg_create_recursive_ht_watch(phpdbg_watchpoint_t *watch) {
	zval *zv;
	zend_string *key;
	zend_long h;

	ZEND_ASSERT(watch->type == WATCH_ON_HASHTABLE);

	ZEND_HASH_FOREACH_KEY_VAL(HT_WATCH_HT(watch), h, key, zv) {
		phpdbg_watchpoint_t *new_watch = emalloc(sizeof(phpdbg_watchpoint_t));

		new_watch->flags = PHPDBG_WATCH_RECURSIVE;
		new_watch->parent = watch;
		new_watch->parent_container = HT_WATCH_HT(watch);

		if (key) {
			new_watch->name_in_parent = key;
			++GC_REFCOUNT(key);
		} else {
			new_watch->name_in_parent = strpprintf(0, ZEND_LONG_FMT, h);
		}

		new_watch->str = strpprintf(0, "%.*s%s%s%s", (int) ZSTR_LEN(watch->str) - 2, ZSTR_VAL(watch->str), (watch->flags & PHPDBG_WATCH_ARRAY) ? "[" : "->", phpdbg_get_property_key(ZSTR_VAL(new_watch->name_in_parent)), (watch->flags & PHPDBG_WATCH_ARRAY) ? "]" : "");

		while (Z_TYPE_P(zv) == IS_INDIRECT) {
			zv = Z_INDIRECT_P(zv);
		}

		phpdbg_create_zval_watchpoint(zv, new_watch);
		new_watch = phpdbg_create_watchpoint(new_watch);
		phpdbg_create_recursive_zval_watch(new_watch);
	} ZEND_HASH_FOREACH_END();
static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor)
{
	zend_class_entry *ce1;
	uint idx;
	Bucket *p;
	zval *t;

	for (idx = 0; idx < source->nNumUsed; idx++) {
		p = source->arData + idx;
		if (Z_TYPE(p->val) == IS_UNDEF) continue;
		ZEND_ASSERT(p->key);
		t = zend_hash_add(target, p->key, &p->val);
		if (UNEXPECTED(t == NULL)) {
			if (p->key->len > 0 && p->key->val[0] == 0) {
				/* Mangled key - ignore and wait for runtime */
				continue;
			} else if (!ZCG(accel_directives).ignore_dups) {
				t = zend_hash_find(target, p->key);
				goto failure;
			}
		}
		if (pCopyConstructor) {
			pCopyConstructor(&Z_PTR_P(t));
		}
	}
	target->nInternalPointer = target->nNumOfElements ? 0 : INVALID_IDX;
	return;

failure:
	ce1 = Z_PTR(p->val);
	CG(in_compilation) = 1;
	zend_set_compiled_filename(ce1->info.user.filename);
	CG(zend_lineno) = ce1->info.user.line_start;
	zend_error(E_ERROR, "Cannot redeclare class %s", ce1->name->val);
}
Exemplo n.º 10
0
/* {{{ proto mixed Closure::call(object $to [, mixed $parameter] [, mixed $...] )
   Call closure, binding to a given object with its class as the scope */
ZEND_METHOD(Closure, call)
{
    zval *zclosure, *newthis, closure_result;
    zend_closure *closure;
    zend_fcall_info fci;
    zend_fcall_info_cache fci_cache;
    zval *my_params;
    int my_param_count = 0;
    zend_function my_function;
    zend_object *newobj;

    if (zend_parse_parameters(ZEND_NUM_ARGS(), "o*", &newthis, &my_params, &my_param_count) == FAILURE) {
        return;
    }

    zclosure = getThis();
    closure = (zend_closure *)Z_OBJ_P(zclosure);

    if (closure->func.common.fn_flags & ZEND_ACC_STATIC) {
        zend_error(E_WARNING, "Cannot bind an instance to a static closure");
        return;
    }

    if (closure->func.type == ZEND_INTERNAL_FUNCTION) {
        /* verify that we aren't binding internal function to a wrong object */
        if ((closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0 &&
                !instanceof_function(Z_OBJCE_P(newthis), closure->func.common.scope)) {
            zend_error(E_WARNING, "Cannot bind function %s::%s to object of class %s", closure->func.common.scope->name->val, closure->func.common.function_name->val, Z_OBJCE_P(newthis)->name->val);
            return;
        }
    }

    newobj = Z_OBJ_P(newthis);

    if (newobj->ce != closure->func.common.scope && newobj->ce->type == ZEND_INTERNAL_CLASS) {
        /* rebinding to internal class is not allowed */
        zend_error(E_WARNING, "Cannot bind closure to object of internal class %s", newobj->ce->name->val);
        return;
    }

    /* This should never happen as closures will always be callable */
    if (zend_fcall_info_init(zclosure, 0, &fci, &fci_cache, NULL, NULL) != SUCCESS) {
        ZEND_ASSERT(0);
    }

    fci.retval = &closure_result;
    fci.params = my_params;
    fci.param_count = my_param_count;
    fci.object = fci_cache.object = newobj;
    fci_cache.initialized = 1;

    my_function = *fci_cache.function_handler;
    /* use scope of passed object */
    my_function.common.scope = Z_OBJCE_P(newthis);
    fci_cache.function_handler = &my_function;

    if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(closure_result) != IS_UNDEF) {
        ZVAL_COPY_VALUE(return_value, &closure_result);
    }
}
Exemplo n.º 11
0
static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
{
	zend_ulong h;
	uint32_t nIndex;
	uint32_t idx;
	Bucket *p;

	IS_CONSISTENT(ht);

	if (UNEXPECTED(ht->nTableMask == 0)) {
		CHECK_INIT(ht, 0);
		goto add_to_hash; 
	} else if (ht->u.flags & HASH_FLAG_PACKED) {
		zend_hash_packed_to_hash(ht);
	} else if ((flag & HASH_ADD_NEW) == 0) {
		p = zend_hash_find_bucket(ht, key);

		if (p) {
			zval *data;

			if (flag & HASH_ADD) {
				return NULL;
			}
			ZEND_ASSERT(&p->val != pData);
			data = &p->val;
			if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
				data = Z_INDIRECT_P(data);
			}
			HANDLE_BLOCK_INTERRUPTIONS();
			if (ht->pDestructor) {
				ht->pDestructor(data);
			}
			ZVAL_COPY_VALUE(data, pData);
			HANDLE_UNBLOCK_INTERRUPTIONS();
			return data;
		}
	}
	
	ZEND_HASH_IF_FULL_DO_RESIZE(ht);		/* If the Hash table is full, resize it */

add_to_hash:
	HANDLE_BLOCK_INTERRUPTIONS();
	idx = ht->nNumUsed++;
	ht->nNumOfElements++;
	if (ht->nInternalPointer == INVALID_IDX) {
		ht->nInternalPointer = idx;
	}
	p = ht->arData + idx; 
	p->h = h = zend_string_hash_val(key);
	p->key = key;
	zend_string_addref(key);
	ZVAL_COPY_VALUE(&p->val, pData);
	nIndex = h & ht->nTableMask;
	Z_NEXT(p->val) = ht->arHash[nIndex];
	ht->arHash[nIndex] = idx;
	HANDLE_UNBLOCK_INTERRUPTIONS();

	return &p->val;
}
Exemplo n.º 12
0
ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
{
	uint nIndex;
	Bucket *p;
#ifdef ZEND_SIGNALS
	TSRMLS_FETCH();
#endif

	IS_CONSISTENT(ht);
	CHECK_INIT(ht);

	if (flag & HASH_NEXT_INSERT) {
		h = ht->nNextFreeElement;
	}
	nIndex = h & ht->nTableMask;

	p = ht->arBuckets[nIndex];
	while (p != NULL) {
		if ((p->nKeyLength == 0) && (p->h == h)) {
			if (flag & HASH_NEXT_INSERT || flag & HASH_ADD) {
				return FAILURE;
			}
			ZEND_ASSERT(p->pData != pData);
			HANDLE_BLOCK_INTERRUPTIONS();
			if (ht->pDestructor) {
				ht->pDestructor(p->pData);
			}
			UPDATE_DATA(ht, p, pData, nDataSize);
			HANDLE_UNBLOCK_INTERRUPTIONS();
			if (pDest) {
				*pDest = p->pData;
			}
			return SUCCESS;
		}
		p = p->pNext;
	}
	p = (Bucket *) pemalloc_rel(sizeof(Bucket), ht->persistent);
	p->arKey = NULL;
	p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */
	p->h = h;
	INIT_DATA(ht, p, pData, nDataSize);
	if (pDest) {
		*pDest = p->pData;
	}

	CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);

	HANDLE_BLOCK_INTERRUPTIONS();
	ht->arBuckets[nIndex] = p;
	CONNECT_TO_GLOBAL_DLLIST(p, ht);
	HANDLE_UNBLOCK_INTERRUPTIONS();

	if ((long)h >= (long)ht->nNextFreeElement) {
		ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX;
	}
	ht->nNumOfElements++;
	ZEND_HASH_IF_FULL_DO_RESIZE(ht);
	return SUCCESS;
}
Exemplo n.º 13
0
ZEND_API zend_object_iterator* zend_iterator_unwrap(zval *array_ptr)
{
	ZEND_ASSERT(Z_TYPE_P(array_ptr) == IS_OBJECT);
	if (Z_OBJ_HT_P(array_ptr) == &iterator_object_handlers) {
		return (zend_object_iterator *)Z_OBJ_P(array_ptr);
	}
	return NULL;
}
Exemplo n.º 14
0
static void zend_get_windows_version_info(OSVERSIONINFOEX *osvi) /* {{{ */
{
	ZeroMemory(osvi, sizeof(OSVERSIONINFOEX));
	osvi->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
	if(!GetVersionEx((OSVERSIONINFO *) osvi)) {
		ZEND_ASSERT(0); /* Should not happen as sizeof is used. */
	}
}
Exemplo n.º 15
0
static zend_always_inline uint32_t gc_fetch_next_unused(void)
{
	uint32_t idx;

	ZEND_ASSERT(GC_HAS_NEXT_UNUSED());
	idx = GC_G(first_unused);
	GC_G(first_unused) = GC_G(first_unused) + 1;
	return idx;
}
Exemplo n.º 16
0
/* {{{ zend_implement_aggregate */
static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entry *class_type)
{
	uint32_t i;
	int t = -1;
	zend_class_iterator_funcs *funcs_ptr;

	if (class_type->get_iterator) {
		if (class_type->type == ZEND_INTERNAL_CLASS) {
			/* inheritance ensures the class has necessary userland methods */
			return SUCCESS;
		} else if (class_type->get_iterator != zend_user_it_get_new_iterator) {
			/* c-level get_iterator cannot be changed (exception being only Traversable is implemented) */
			if (class_type->num_interfaces) {
				ZEND_ASSERT(class_type->ce_flags & (ZEND_ACC_LINKED|ZEND_ACC_LINKING_IN_PROGRESS));
				for (i = 0; i < class_type->num_interfaces; i++) {
					if (class_type->interfaces[i] == zend_ce_iterator) {
						zend_error_noreturn(E_ERROR, "Class %s cannot implement both %s and %s at the same time",
									ZSTR_VAL(class_type->name),
									ZSTR_VAL(interface->name),
									ZSTR_VAL(zend_ce_iterator->name));
						return FAILURE;
					}
					if (class_type->interfaces[i] == zend_ce_traversable) {
						t = i;
					}
				}
			}
			if (t == -1) {
				return FAILURE;
			}
		}
	}
	if (class_type->parent
	 && (class_type->parent->ce_flags & ZEND_ACC_REUSE_GET_ITERATOR)) {
		class_type->get_iterator = class_type->parent->get_iterator;
		class_type->ce_flags |= ZEND_ACC_REUSE_GET_ITERATOR;
	} else {
		class_type->get_iterator = zend_user_it_get_new_iterator;
	}
	funcs_ptr = class_type->iterator_funcs_ptr;
	if (class_type->type == ZEND_INTERNAL_CLASS) {
		if (!funcs_ptr) {
			funcs_ptr = calloc(1, sizeof(zend_class_iterator_funcs));
			class_type->iterator_funcs_ptr = funcs_ptr;
		}
		funcs_ptr->zf_new_iterator = zend_hash_str_find_ptr(&class_type->function_table, "getiterator", sizeof("getiterator") - 1);
	} else {
		if (!funcs_ptr) {
			funcs_ptr = zend_arena_alloc(&CG(arena), sizeof(zend_class_iterator_funcs));
			class_type->iterator_funcs_ptr = funcs_ptr;
			memset(funcs_ptr, 0, sizeof(zend_class_iterator_funcs));
		} else {
			funcs_ptr->zf_new_iterator = NULL;
		}
	}
	return SUCCESS;
}
Exemplo n.º 17
0
ZEND_API void ZEND_FASTCALL zval_copy_ctor_func(zval *zvalue)
{
	if (EXPECTED(Z_TYPE_P(zvalue) == IS_ARRAY)) {
		ZVAL_ARR(zvalue, zend_array_dup(Z_ARRVAL_P(zvalue)));
	} else if (EXPECTED(Z_TYPE_P(zvalue) == IS_STRING)) {
		ZEND_ASSERT(!ZSTR_IS_INTERNED(Z_STR_P(zvalue)));
		CHECK_ZVAL_STRING(Z_STR_P(zvalue));
		ZVAL_NEW_STR(zvalue, zend_string_dup(Z_STR_P(zvalue), 0));
	}
}
Exemplo n.º 18
0
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");
			}
		}
	}
}
Exemplo n.º 19
0
static zend_never_inline void ZEND_FASTCALL gc_possible_root_when_full(zend_refcounted *ref)
{
	uint32_t idx;
	gc_root_buffer *newRoot;

	ZEND_ASSERT(GC_TYPE(ref) == IS_ARRAY || GC_TYPE(ref) == IS_OBJECT);
	ZEND_ASSERT(GC_INFO(ref) == 0);

	if (GC_G(gc_enabled) && !GC_G(gc_active)) {
		GC_ADDREF(ref);
		gc_adjust_threshold(gc_collect_cycles());
		if (UNEXPECTED(GC_DELREF(ref)) == 0) {
			rc_dtor_func(ref);
			return;
		} else if (UNEXPECTED(GC_INFO(ref))) {
			return;
		}
	}

	if (GC_HAS_UNUSED()) {
		idx = GC_FETCH_UNUSED();
	} else if (EXPECTED(GC_HAS_NEXT_UNUSED())) {
		idx = GC_FETCH_NEXT_UNUSED();
	} else {
		gc_grow_root_buffer();
		if (UNEXPECTED(!GC_HAS_NEXT_UNUSED())) {
			return;
		}
		idx = GC_FETCH_NEXT_UNUSED();
	}

	newRoot = GC_IDX2PTR(idx);
	newRoot->ref = ref; /* GC_ROOT tag is 0 */
	GC_TRACE_SET_COLOR(ref, GC_PURPLE);

	idx = gc_compress(idx);
	GC_REF_SET_INFO(ref, idx | GC_PURPLE);
	GC_G(num_roots)++;

	GC_BENCH_INC(zval_buffered);
	GC_BENCH_INC(root_buf_length);
	GC_BENCH_PEAK(root_buf_peak, root_buf_length);
}
Exemplo n.º 20
0
ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ */
{
	ZEND_ASSERT(GC_REFCOUNT(object) == 0);

	/* GC might have released this object already. */
	if (UNEXPECTED(GC_TYPE(object) == IS_NULL)) {
		return;
	}

	/*	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 (!(OBJ_FLAGS(object) & IS_OBJ_DESTRUCTOR_CALLED)) {
		GC_ADD_FLAGS(object, IS_OBJ_DESTRUCTOR_CALLED);

		if (object->handlers->dtor_obj != zend_objects_destroy_object
				|| object->ce->destructor) {
			GC_SET_REFCOUNT(object, 1);
			object->handlers->dtor_obj(object);
			GC_DELREF(object);
		}
	}

	if (GC_REFCOUNT(object) == 0) {
		uint32_t handle = object->handle;
		void *ptr;

		ZEND_ASSERT(EG(objects_store).object_buckets != NULL);
		ZEND_ASSERT(IS_OBJ_VALID(EG(objects_store).object_buckets[handle]));
		EG(objects_store).object_buckets[handle] = SET_OBJ_INVALID(object);
		if (!(OBJ_FLAGS(object) & IS_OBJ_FREE_CALLED)) {
			GC_ADD_FLAGS(object, IS_OBJ_FREE_CALLED);
			GC_SET_REFCOUNT(object, 1);
			object->handlers->free_obj(object);
		}
		ptr = ((char*)object) - object->handlers->offset;
		GC_REMOVE_FROM_BUFFER(object);
		efree(ptr);
		ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle);
	}
}
Exemplo n.º 21
0
/* {{{ spl_add_interfaces */
void spl_add_interfaces(zval *list, zend_class_entry * pce, int allow, int ce_flags)
{
	uint32_t num_interfaces;

	if (pce->num_interfaces) {
		ZEND_ASSERT(pce->ce_flags & ZEND_ACC_LINKED);
		for (num_interfaces = 0; num_interfaces < pce->num_interfaces; num_interfaces++) {
			spl_add_class_name(list, pce->interfaces[num_interfaces], allow, ce_flags);
		}
	}
}
Exemplo n.º 22
0
ZEND_API int zend_verify_const_access(zend_class_constant *c, zend_class_entry *scope) /* {{{ */
{
	if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PUBLIC) {
		return 1;
	} else if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PRIVATE) {
		return (c->ce == scope);
	} else {
		ZEND_ASSERT(Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PROTECTED);
		return zend_check_protected(c->ce, scope);
	}
}
Exemplo n.º 23
0
/* {{{ spl_add_traits */
void spl_add_traits(zval *list, zend_class_entry * pce, int allow, int ce_flags)
{
	uint32_t num_traits;
	zend_class_entry *trait;

	for (num_traits = 0; num_traits < pce->num_traits; num_traits++) {
		trait = zend_fetch_class_by_name(pce->trait_names[num_traits].name,
			pce->trait_names[num_traits].lc_name, ZEND_FETCH_CLASS_TRAIT);
		ZEND_ASSERT(trait);
		spl_add_class_name(list, trait, allow, ce_flags);
	}
}
Exemplo n.º 24
0
static zend_always_inline void mysqlnd_arena_release(zend_arena **arena_ptr, void *checkpoint)
{
	zend_arena *arena = *arena_ptr;

	while (UNEXPECTED((char*)checkpoint > arena->end) ||
	       UNEXPECTED((char*)checkpoint <= (char*)arena)) {
		zend_arena *prev = arena->prev;
		mnd_efree(arena);
		*arena_ptr = arena = prev;
	}
	ZEND_ASSERT((char*)checkpoint > (char*)arena && (char*)checkpoint <= arena->end);
	arena->ptr = (char*)checkpoint;
}
Exemplo n.º 25
0
static void copy_zend_constant(zval *zv)
{
	zend_constant *c = Z_PTR_P(zv);

	ZEND_ASSERT(c->flags & CONST_PERSISTENT);
	Z_PTR_P(zv) = pemalloc(sizeof(zend_constant), 1);
	memcpy(Z_PTR_P(zv), c, sizeof(zend_constant));

	c = Z_PTR_P(zv);
	c->name = zend_string_copy(c->name);
	if (Z_TYPE(c->value) == IS_STRING) {
		Z_STR(c->value) = zend_string_dup(Z_STR(c->value), 1);
	}
}
Exemplo n.º 26
0
zend_string * ion_stream_describe(ion_stream * stream) {
    zend_string * describe = NULL;
    zend_string * address_remote = NULL;
    zend_string * address_local = NULL;

    if(stream->buffer == NULL) {
        return zend_string_init(STRARGS("Stream"), 0);
    }
    if (stream->state & ION_STREAM_RESERVED) {
        switch(bufferevent_getfd(stream->buffer)) {
            case STDIN_FILENO:
                return zend_string_init(STRARGS("Stream(stdin)"), 0);
            case STDOUT_FILENO:
                return zend_string_init(STRARGS("Stream(stdout)"), 0);
            case STDERR_FILENO:
                return zend_string_init(STRARGS("Stream(stderr)"), 0);
            default:
                ZEND_ASSERT(0);
        }
    }
    if(stream->state & ION_STREAM_STATE_SOCKET) {
        if(ion_stream_is_valid_fd(stream)) {
            return zend_string_init(STRARGS("Stream"), 0);
        }
        address_local   = ion_stream_get_name_self(stream);
        address_remote  = ion_stream_get_name_remote(stream);
        if(address_remote == NULL) {
            address_remote = zend_string_init(STRARGS("undefined"), 0);
        }
        if(address_local == NULL) {
            address_remote = zend_string_init(STRARGS("undefined"), 0);
        }

        if(stream->state & ION_STREAM_FROM_PEER) {
            describe = strpprintf(MAX_DOMAIN_LENGTH, "Stream(%s<-%s)", address_local->val, address_remote->val);
        } else if(stream->state & ION_STREAM_FROM_ME) {
            describe = strpprintf(MAX_DOMAIN_LENGTH, "Stream(%s->%s)", address_local->val, address_remote->val);
        } else {
            describe = strpprintf(MAX_DOMAIN_LENGTH, "Stream(%s<->%s)", address_local->val, address_remote->val);
        }
        zend_string_release(address_local);
        zend_string_release(address_remote);
        return describe;
    } else if(stream->state & ION_STREAM_STATE_PAIR) {
        return zend_string_init(STRARGS("Stream(twin)"), 0);
    } else {
        return zend_string_init(STRARGS("Stream(pipe)"), 0);
    }
}
Exemplo n.º 27
0
static zend_always_inline gc_root_buffer* gc_decompress(zend_refcounted *ref, uint32_t idx)
{
	gc_root_buffer *root = GC_IDX2PTR(idx);

	if (EXPECTED(GC_GET_PTR(root->ref) == ref)) {
		return root;
	}

	while (1) {
		idx += GC_MAX_UNCOMPRESSED;
		ZEND_ASSERT(idx < GC_G(first_unused));
		root = GC_IDX2PTR(idx);
		if (GC_GET_PTR(root->ref) == ref) {
			return root;
		}
	}
}
Exemplo n.º 28
0
/* {{{ mysqlnd_res_meta::read_metadata */
static enum_func_status
MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn, MYSQLND_RES * result)
{
	unsigned int i = 0;
	MYSQLND_PACKET_RES_FIELD field_packet;

	DBG_ENTER("mysqlnd_res_meta::read_metadata");

	conn->payload_decoder_factory->m.init_result_field_packet(&field_packet);
	field_packet.memory_pool = result->memory_pool;
	for (;i < meta->field_count; i++) {
		zend_ulong idx;

		/* We re-read metadata for PS */
		ZEND_ASSERT(meta->fields[i].root == NULL);
		meta->fields[i].root = NULL;

		field_packet.metadata = &(meta->fields[i]);
		if (FAIL == PACKET_READ(conn, &field_packet)) {
			PACKET_FREE(&field_packet);
			DBG_RETURN(FAIL);
		}
		if (field_packet.error_info.error_no) {
			COPY_CLIENT_ERROR(conn->error_info, field_packet.error_info);
			/* Return back from CONN_QUERY_SENT */
			PACKET_FREE(&field_packet);
			DBG_RETURN(FAIL);
		}

		if (mysqlnd_ps_fetch_functions[meta->fields[i].type].func == NULL) {
			DBG_ERR_FMT("Unknown type %u sent by the server.  Please send a report to the developers", meta->fields[i].type);
			php_error_docref(NULL, E_WARNING, "Unknown type %u sent by the server. Please send a report to the developers", meta->fields[i].type);
			PACKET_FREE(&field_packet);
			DBG_RETURN(FAIL);
		}

		/* For BC we have to check whether the key is numeric and use it like this */
		if ((meta->fields[i].is_numeric = ZEND_HANDLE_NUMERIC(field_packet.metadata->sname, idx))) {
			meta->fields[i].num_key = idx;
		}
	}
	PACKET_FREE(&field_packet);

	DBG_RETURN(PASS);
}
Exemplo n.º 29
0
static zend_always_inline Bucket *zend_hash_index_find_bucket(const HashTable *ht, zend_uint_t h)
{
	uint nIndex;
	uint idx;
	Bucket *p;

	nIndex = h & ht->nTableMask;
	idx = ht->arHash[nIndex];
	while (idx != INVALID_IDX) {
		ZEND_ASSERT(idx < ht->nTableSize);
		p = ht->arData + idx;
		if (p->h == h && !p->key) {
			return p;
		}
		idx = Z_NEXT(p->val);
	}
	return NULL;
}
Exemplo n.º 30
0
static int check_host_whitelist(url_adapt_state_ex_t *ctx)
{
	php_url *url_parts = NULL;
	HashTable *allowed_hosts = ctx->type ? &BG(url_adapt_session_hosts_ht) : &BG(url_adapt_output_hosts_ht);

	ZEND_ASSERT(ctx->tag_type == TAG_FORM);

	if (ctx->attr_val.s && ZSTR_LEN(ctx->attr_val.s)) {
		url_parts = php_url_parse_ex(ZSTR_VAL(ctx->attr_val.s), ZSTR_LEN(ctx->attr_val.s));
	} else {
		return SUCCESS; /* empty URL is valid */
	}

	if (!url_parts) {
		return FAILURE;
	}
	if (url_parts->scheme) {
		/* Only http/https should be handled.
		   A bit hacky check this here, but saves a URL parse. */
		if (strcasecmp(url_parts->scheme, "http") &&
			strcasecmp(url_parts->scheme, "https")) {
		php_url_free(url_parts);
		return FAILURE;
		}
	}
	if (!url_parts->host) {
		php_url_free(url_parts);
		return SUCCESS;
	}
	if (!zend_hash_num_elements(allowed_hosts) &&
		check_http_host(url_parts->host) == SUCCESS) {
		php_url_free(url_parts);
		return SUCCESS;
	}
	if (!zend_hash_str_find(allowed_hosts,
							url_parts->host,
							strlen(url_parts->host))) {
		php_url_free(url_parts);
		return FAILURE;
	}
	php_url_free(url_parts);
	return SUCCESS;
}