static inline void zend_clone_zval(zval *src, int bind)
{
	void *ptr;

	if (Z_IMMUTABLE_P(src)) {
		return;
	}

	switch (Z_TYPE_P(src)) {
		case IS_STRING:
	    case IS_CONSTANT:
			Z_STR_P(src) = zend_clone_str(Z_STR_P(src));
			break;
		case IS_ARRAY:
			if (Z_ARR_P(src) != &EG(symbol_table)) {
		    	if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_ARR_P(src))) != NULL) {
		    		Z_ARR_P(src) = ptr;
				} else {
					zend_array *old = Z_ARR_P(src);

					Z_ARR_P(src) = emalloc(sizeof(zend_array));
					Z_ARR_P(src)->gc = old->gc;
			    	if (bind && Z_REFCOUNT_P(src) > 1) {
						accel_xlat_set(old, Z_ARR_P(src));
					}
					zend_hash_clone_zval(Z_ARRVAL_P(src), old, 0);
				}
			}
			break;
	    case IS_REFERENCE:
	    	if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_REF_P(src))) != NULL) {
	    		Z_REF_P(src) = ptr;
			} else {
				zend_reference *old = Z_REF_P(src);
				ZVAL_NEW_REF(src, &old->val);
				Z_REF_P(src)->gc = old->gc;
		    	if (bind && Z_REFCOUNT_P(src) > 1) {
					accel_xlat_set(old, Z_REF_P(src));
				}
				zend_clone_zval(Z_REFVAL_P(src), bind);
			}
	    	break;
	    case IS_CONSTANT_AST:
	    	if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_AST_P(src))) != NULL) {
	    		Z_AST_P(src) = ptr;
			} else {
				zend_ast_ref *old = Z_AST_P(src);

		    	ZVAL_NEW_AST(src, old->ast);
				Z_AST_P(src)->gc = old->gc;
		    	if (bind && Z_REFCOUNT_P(src) > 1) {
					accel_xlat_set(old, Z_AST_P(src));
				}
		    	Z_ASTVAL_P(src) = zend_ast_clone(Z_ASTVAL_P(src));
			}
	    	break;
	}
}
static zend_ast *zend_ast_clone(zend_ast *ast)
{
	uint32_t i;

	if (ast->kind == ZEND_AST_ZVAL) {
		zend_ast_zval *copy = emalloc(sizeof(zend_ast_zval));
		copy->kind = ZEND_AST_ZVAL;
		copy->attr = ast->attr;
		ZVAL_COPY_VALUE(&copy->val, zend_ast_get_zval(ast));
		zend_clone_zval(&copy->val, 0);
		return (zend_ast *) copy;
	} else if (zend_ast_is_list(ast)) {
		zend_ast_list *list = zend_ast_get_list(ast);
		zend_ast_list *copy = emalloc(
			sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children);
		copy->kind = list->kind;
		copy->attr = list->attr;
		copy->children = list->children;
		for (i = 0; i < list->children; i++) {
			if (list->child[i]) {
				copy->child[i] = zend_ast_clone(list->child[i]);
			} else {
				copy->child[i] = NULL;
			}
		}
		return (zend_ast *) copy;
	} else {
		uint32_t children = zend_ast_get_num_children(ast);
		zend_ast *copy = emalloc(sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children);
		copy->kind = ast->kind;
		copy->attr = ast->attr;
		for (i = 0; i < children; i++) {
			if (ast->child[i]) {
				copy->child[i] = zend_ast_clone(ast->child[i]);
			} else {
				copy->child[i] = NULL;
			}
		}
		return copy;
	}
}
/* Protects class' refcount, copies default properties, functions and class name */
static void zend_class_copy_ctor(zend_class_entry **pce)
{
	zend_class_entry *ce = *pce;
	zend_class_entry *old_ce = ce;

	*pce = ce = ARENA_REALLOC(old_ce);
	ce->refcount = 1;

	if (old_ce->default_properties_table) {
		int i;

		ce->default_properties_table = emalloc(sizeof(zval) * old_ce->default_properties_count);
		for (i = 0; i < old_ce->default_properties_count; i++) {
			ZVAL_COPY_VALUE(&ce->default_properties_table[i], &old_ce->default_properties_table[i]);
			zend_clone_zval(&ce->default_properties_table[i], 1);
		}
	}

	zend_hash_clone_methods(&ce->function_table, &old_ce->function_table, old_ce, ce);

	/* static members */
	if (old_ce->default_static_members_table) {
		int i;

		ce->default_static_members_table = emalloc(sizeof(zval) * old_ce->default_static_members_count);
		for (i = 0; i < old_ce->default_static_members_count; i++) {
			ZVAL_COPY_VALUE(&ce->default_static_members_table[i], &old_ce->default_static_members_table[i]);
			zend_clone_zval(&ce->default_static_members_table[i], 1);
		}
	}
	ce->static_members_table = ce->default_static_members_table;

	/* properties_info */
	zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce);

	/* constants table */
	zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 1);
	ce->constants_table.u.flags &= ~HASH_FLAG_APPLY_PROTECTION;

	ce->name = zend_clone_str(ce->name);

	/* interfaces aren't really implemented, so we create a new table */
	if (ce->num_interfaces) {
		ce->interfaces = emalloc(sizeof(zend_class_entry *) * ce->num_interfaces);
		memset(ce->interfaces, 0, sizeof(zend_class_entry *) * ce->num_interfaces);
	} else {
		ce->interfaces = NULL;
	}
	if (ZEND_CE_DOC_COMMENT(ce)) {
		if (ZCG(accel_directives).load_comments) {
			ZEND_CE_DOC_COMMENT(ce) = zend_string_dup(ZEND_CE_DOC_COMMENT(ce), 0);
		} else {
			ZEND_CE_DOC_COMMENT(ce) =  NULL;
		}
	}

	if (ce->parent) {
		ce->parent = ARENA_REALLOC(ce->parent);
	}

	zend_update_inherited_handler(constructor);
	zend_update_inherited_handler(destructor);
	zend_update_inherited_handler(clone);
	zend_update_inherited_handler(__get);
	zend_update_inherited_handler(__set);
	zend_update_inherited_handler(__call);
/* 5.1 stuff */
	zend_update_inherited_handler(serialize_func);
	zend_update_inherited_handler(unserialize_func);
	zend_update_inherited_handler(__isset);
	zend_update_inherited_handler(__unset);
/* 5.2 stuff */
	zend_update_inherited_handler(__tostring);

/* 5.3 stuff */
	zend_update_inherited_handler(__callstatic);
	zend_update_inherited_handler(__debugInfo);

/* 5.4 traits */
	if (ce->trait_aliases) {
		zend_trait_alias **trait_aliases;
		int i = 0;

		while (ce->trait_aliases[i]) {
			i++;
		}
		trait_aliases = emalloc(sizeof(zend_trait_alias*) * (i + 1));
		i = 0;
		while (ce->trait_aliases[i]) {
			trait_aliases[i] = emalloc(sizeof(zend_trait_alias));
			memcpy(trait_aliases[i], ce->trait_aliases[i], sizeof(zend_trait_alias));
			trait_aliases[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
			memcpy(trait_aliases[i]->trait_method, ce->trait_aliases[i]->trait_method, sizeof(zend_trait_method_reference));
			if (trait_aliases[i]->trait_method) {
				if (trait_aliases[i]->trait_method->method_name) {
					trait_aliases[i]->trait_method->method_name =
						zend_clone_str(trait_aliases[i]->trait_method->method_name);
				}
				if (trait_aliases[i]->trait_method->class_name) {
					trait_aliases[i]->trait_method->class_name =
						zend_clone_str(trait_aliases[i]->trait_method->class_name);
				}
			}

			if (trait_aliases[i]->alias) {
				trait_aliases[i]->alias =
					zend_clone_str(trait_aliases[i]->alias);
			}
			i++;
		}
		trait_aliases[i] = NULL;
		ce->trait_aliases = trait_aliases;
	}

	if (ce->trait_precedences) {
		zend_trait_precedence **trait_precedences;
		int i = 0;

		while (ce->trait_precedences[i]) {
			i++;
		}
		trait_precedences = emalloc(sizeof(zend_trait_precedence*) * (i + 1));
		i = 0;
		while (ce->trait_precedences[i]) {
			trait_precedences[i] = emalloc(sizeof(zend_trait_precedence));
			memcpy(trait_precedences[i], ce->trait_precedences[i], sizeof(zend_trait_precedence));
			trait_precedences[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
			memcpy(trait_precedences[i]->trait_method, ce->trait_precedences[i]->trait_method, sizeof(zend_trait_method_reference));

			trait_precedences[i]->trait_method->method_name =
				zend_clone_str(trait_precedences[i]->trait_method->method_name);
			trait_precedences[i]->trait_method->class_name =
				zend_clone_str(trait_precedences[i]->trait_method->class_name);

			if (trait_precedences[i]->exclude_from_classes) {
				zend_string **exclude_from_classes;
				int j = 0;

				while (trait_precedences[i]->exclude_from_classes[j].class_name) {
					j++;
				}
				exclude_from_classes = emalloc(sizeof(zend_string*) * (j + 1));
				j = 0;
				while (trait_precedences[i]->exclude_from_classes[j].class_name) {
					exclude_from_classes[j] =
						zend_clone_str(trait_precedences[i]->exclude_from_classes[j].class_name);
					j++;
				}
				exclude_from_classes[j] = NULL;
				trait_precedences[i]->exclude_from_classes = (void*)exclude_from_classes;
			}
			i++;
		}
		trait_precedences[i] = NULL;
		ce->trait_precedences = trait_precedences;
	}
}
static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
{
	uint idx;
	Bucket *p, *q, *r;
	zend_ulong nIndex;

	ht->nTableSize = source->nTableSize;
	ht->nTableMask = source->nTableMask;
	ht->nNumUsed = 0;
	ht->nNumOfElements = source->nNumOfElements;
	ht->nNextFreeElement = source->nNextFreeElement;
	ht->pDestructor = ZVAL_PTR_DTOR;
	ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED) | HASH_FLAG_APPLY_PROTECTION;
	ht->arData = NULL;
	ht->arHash = NULL;
	ht->nInternalPointer = source->nNumOfElements ? 0 : INVALID_IDX;

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

	if (source->u.flags & HASH_FLAG_PACKED) {
		ht->u.flags |= HASH_FLAG_PACKED;
		ht->arData = (Bucket *) emalloc(ht->nTableSize * sizeof(Bucket));
		ht->arHash = (uint32_t*)&uninitialized_bucket;

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

			r = ht->arData + ht->nNumUsed;
			q = ht->arData + p->h;
			while (r != q) {
				ZVAL_UNDEF(&r->val);
				r++;
			}
			ht->nNumUsed = p->h + 1;

			/* Initialize key */
			q->h = p->h;
			q->key = NULL;

			/* Copy data */
			ZVAL_COPY_VALUE(&q->val, &p->val);
			zend_clone_zval(&q->val, bind);
		}
	} else {
		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;
			if (!p->key) {
				q->key = NULL;
			} else {
				q->key = zend_clone_str(p->key);
			}

			/* Copy data */
			ZVAL_COPY_VALUE(&q->val, &p->val);
			zend_clone_zval(&q->val, bind);
		}
	}
}
Exemplo n.º 5
0
static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
{
	uint idx;
	Bucket *p, *q, *r;
	zend_ulong nIndex;

	ht->nTableSize = source->nTableSize;
	ht->nTableMask = source->nTableMask;
	ht->nNumUsed = 0;
	ht->nNumOfElements = source->nNumOfElements;
	ht->nNextFreeElement = source->nNextFreeElement;
	ht->pDestructor = ZVAL_PTR_DTOR;
	ht->u.flags = (source->u.flags & HASH_FLAG_INITIALIZED) | HASH_FLAG_APPLY_PROTECTION;
	ht->nInternalPointer = source->nNumOfElements ? 0 : HT_INVALID_IDX;

	if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
		ht->arData = source->arData;
		return;
	}

	if (source->u.flags & HASH_FLAG_PACKED) {
		ht->u.flags |= HASH_FLAG_PACKED;
		HT_SET_DATA_ADDR(ht, (Bucket *) emalloc(HT_SIZE(ht)));
		HT_HASH_RESET_PACKED(ht);

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

			r = ht->arData + ht->nNumUsed;
			q = ht->arData + p->h;
			while (r != q) {
				ZVAL_UNDEF(&r->val);
				r++;
			}
			ht->nNumUsed = p->h + 1;

			/* Initialize key */
			q->h = p->h;
			q->key = NULL;

			/* Copy data */
			ZVAL_COPY_VALUE(&q->val, &p->val);
			zend_clone_zval(&q->val, bind);
		}
	} else {
		HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht)));
		HT_HASH_RESET(ht);

		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_HASH(ht, nIndex);
			HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(ht->nNumUsed++);

			/* Initialize key */
			q->h = p->h;
			if (!p->key) {
				q->key = NULL;
			} else {
				q->key = zend_clone_str(p->key);
			}

			/* Copy data */
			ZVAL_COPY_VALUE(&q->val, &p->val);
			zend_clone_zval(&q->val, bind);
		}
	}
}