xref: /PHP-5.6/Zend/zend_variables.c (revision 3537e95d)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 2.00 of the Zend license,     |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.zend.com/license/2_00.txt.                                |
11    | If you did not receive a copy of the Zend license and are unable to  |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@zend.com so we can mail you a copy immediately.              |
14    +----------------------------------------------------------------------+
15    | Authors: Andi Gutmans <andi@zend.com>                                |
16    |          Zeev Suraski <zeev@zend.com>                                |
17    +----------------------------------------------------------------------+
18 */
19 
20 /* $Id$ */
21 
22 #include <stdio.h>
23 #include "zend.h"
24 #include "zend_API.h"
25 #include "zend_ast.h"
26 #include "zend_globals.h"
27 #include "zend_constants.h"
28 #include "zend_list.h"
29 
30 
_zval_dtor_func(zval * zvalue ZEND_FILE_LINE_DC)31 ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
32 {
33 	switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
34 		case IS_STRING:
35 		case IS_CONSTANT:
36 			CHECK_ZVAL_STRING_REL(zvalue);
37 			str_efree_rel(zvalue->value.str.val);
38 			break;
39 		case IS_ARRAY: {
40 				TSRMLS_FETCH();
41 
42 				if (zvalue->value.ht && (zvalue->value.ht != &EG(symbol_table))) {
43 					/* break possible cycles */
44 					Z_TYPE_P(zvalue) = IS_NULL;
45 					zend_hash_destroy(zvalue->value.ht);
46 					FREE_HASHTABLE(zvalue->value.ht);
47 				}
48 			}
49 			break;
50 		case IS_CONSTANT_AST:
51 			zend_ast_destroy(Z_AST_P(zvalue));
52 			break;
53 		case IS_OBJECT:
54 			{
55 				TSRMLS_FETCH();
56 
57 				Z_OBJ_HT_P(zvalue)->del_ref(zvalue TSRMLS_CC);
58 			}
59 			break;
60 		case IS_RESOURCE:
61 			{
62 				TSRMLS_FETCH();
63 
64 				/* destroy resource */
65 				zend_list_delete(zvalue->value.lval);
66 			}
67 			break;
68 		case IS_LONG:
69 		case IS_DOUBLE:
70 		case IS_BOOL:
71 		case IS_NULL:
72 		default:
73 			return;
74 			break;
75 	}
76 }
77 
78 
_zval_internal_dtor(zval * zvalue ZEND_FILE_LINE_DC)79 ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
80 {
81 	switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
82 		case IS_STRING:
83 		case IS_CONSTANT:
84 			CHECK_ZVAL_STRING_REL(zvalue);
85 			str_free(zvalue->value.str.val);
86 			break;
87 		case IS_ARRAY:
88 		case IS_CONSTANT_AST:
89 		case IS_OBJECT:
90 		case IS_RESOURCE:
91 			zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
92 			break;
93 		case IS_LONG:
94 		case IS_DOUBLE:
95 		case IS_BOOL:
96 		case IS_NULL:
97 		default:
98 			break;
99 	}
100 }
101 
102 
zval_add_ref(zval ** p)103 ZEND_API void zval_add_ref(zval **p)
104 {
105 	Z_ADDREF_PP(p);
106 }
107 
108 
_zval_copy_ctor_func(zval * zvalue ZEND_FILE_LINE_DC)109 ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
110 {
111 	switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
112 		case IS_RESOURCE: {
113 				TSRMLS_FETCH();
114 
115 				zend_list_addref(zvalue->value.lval);
116 			}
117 			break;
118 		case IS_BOOL:
119 		case IS_LONG:
120 		case IS_NULL:
121 			break;
122 		case IS_CONSTANT:
123 		case IS_STRING:
124 			CHECK_ZVAL_STRING_REL(zvalue);
125 			if (!IS_INTERNED(zvalue->value.str.val)) {
126 				zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val, zvalue->value.str.len);
127 			}
128 			break;
129 		case IS_ARRAY: {
130 				zval *tmp;
131 				HashTable *original_ht = zvalue->value.ht;
132 				HashTable *tmp_ht = NULL;
133 				TSRMLS_FETCH();
134 
135 				if (zvalue->value.ht == &EG(symbol_table)) {
136 					return; /* do nothing */
137 				}
138 				ALLOC_HASHTABLE_REL(tmp_ht);
139 				zend_hash_init(tmp_ht, zend_hash_num_elements(original_ht), NULL, ZVAL_PTR_DTOR, 0);
140 				zvalue->value.ht = tmp_ht;
141 				zend_hash_copy(tmp_ht, original_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
142 				tmp_ht->nNextFreeElement = original_ht->nNextFreeElement;
143 			}
144 			break;
145 		case IS_CONSTANT_AST:
146 			Z_AST_P(zvalue) = zend_ast_copy(Z_AST_P(zvalue));
147 			break;
148 		case IS_OBJECT:
149 			{
150 				TSRMLS_FETCH();
151 				Z_OBJ_HT_P(zvalue)->add_ref(zvalue TSRMLS_CC);
152 			}
153 			break;
154 	}
155 }
156 
157 
zend_print_variable(zval * var)158 ZEND_API int zend_print_variable(zval *var)
159 {
160 	return zend_print_zval(var, 0);
161 }
162 
163 
_zval_dtor_wrapper(zval * zvalue)164 ZEND_API void _zval_dtor_wrapper(zval *zvalue)
165 {
166 	TSRMLS_FETCH();
167 
168 	GC_REMOVE_ZVAL_FROM_BUFFER(zvalue);
169 	zval_dtor(zvalue);
170 }
171 
172 
173 #if ZEND_DEBUG
_zval_copy_ctor_wrapper(zval * zvalue)174 ZEND_API void _zval_copy_ctor_wrapper(zval *zvalue)
175 {
176 	zval_copy_ctor(zvalue);
177 }
178 
179 
_zval_internal_dtor_wrapper(zval * zvalue)180 ZEND_API void _zval_internal_dtor_wrapper(zval *zvalue)
181 {
182 	zval_internal_dtor(zvalue);
183 }
184 
185 
_zval_ptr_dtor_wrapper(zval ** zval_ptr)186 ZEND_API void _zval_ptr_dtor_wrapper(zval **zval_ptr)
187 {
188 	zval_ptr_dtor(zval_ptr);
189 }
190 
191 
_zval_internal_ptr_dtor_wrapper(zval ** zval_ptr)192 ZEND_API void _zval_internal_ptr_dtor_wrapper(zval **zval_ptr)
193 {
194 	zval_internal_ptr_dtor(zval_ptr);
195 }
196 #endif
197 
zval_copy_static_var(zval ** p TSRMLS_DC,int num_args,va_list args,zend_hash_key * key)198 ZEND_API int zval_copy_static_var(zval **p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */
199 {
200 	HashTable *target = va_arg(args, HashTable*);
201 	zend_bool is_ref;
202 	zval *tmp;
203 
204 	if (Z_TYPE_PP(p) & (IS_LEXICAL_VAR|IS_LEXICAL_REF)) {
205 		is_ref = Z_TYPE_PP(p) & IS_LEXICAL_REF;
206 
207 		if (!EG(active_symbol_table)) {
208 			zend_rebuild_symbol_table(TSRMLS_C);
209 		}
210 		if (zend_hash_quick_find(EG(active_symbol_table), key->arKey, key->nKeyLength, key->h, (void **) &p) == FAILURE) {
211 			if (is_ref) {
212 				ALLOC_INIT_ZVAL(tmp);
213 				Z_SET_ISREF_P(tmp);
214 				zend_hash_quick_add(EG(active_symbol_table), key->arKey, key->nKeyLength, key->h, &tmp, sizeof(zval*), (void**)&p);
215 			} else {
216 				tmp = EG(uninitialized_zval_ptr);
217 				zend_error(E_NOTICE,"Undefined variable: %s", key->arKey);
218 			}
219 		} else {
220 			if (is_ref) {
221 				SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
222 				tmp = *p;
223 			} else if (Z_ISREF_PP(p)) {
224 				ALLOC_INIT_ZVAL(tmp);
225 				ZVAL_COPY_VALUE(tmp, *p);
226 				zval_copy_ctor(tmp);
227 				Z_SET_REFCOUNT_P(tmp, 0);
228 				Z_UNSET_ISREF_P(tmp);
229 			} else {
230 				tmp = *p;
231 			}
232 		}
233 	} else {
234 		tmp = *p;
235 	}
236 	if (zend_hash_quick_add(target, key->arKey, key->nKeyLength, key->h, &tmp, sizeof(zval*), NULL) == SUCCESS) {
237 		Z_ADDREF_P(tmp);
238 	}
239 	return ZEND_HASH_APPLY_KEEP;
240 }
241 /* }}} */
242 
243 /*
244  * Local variables:
245  * tab-width: 4
246  * c-basic-offset: 4
247  * indent-tabs-mode: t
248  * End:
249  */
250