1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2017 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 | Dmitry Stogov <dmitry@zend.com> |
18 +----------------------------------------------------------------------+
19 */
20
21 /* $Id$ */
22
23 #include <stdio.h>
24 #include "zend.h"
25 #include "zend_API.h"
26 #include "zend_ast.h"
27 #include "zend_globals.h"
28 #include "zend_constants.h"
29 #include "zend_list.h"
30
_zval_dtor_func(zend_refcounted * p ZEND_FILE_LINE_DC)31 ZEND_API void ZEND_FASTCALL _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC)
32 {
33 if (--GC_REFCOUNT(p)) {
34 return;
35 }
36
37 switch (GC_TYPE(p)) {
38 case IS_STRING:
39 case IS_CONSTANT: {
40 zend_string *str = (zend_string*)p;
41 CHECK_ZVAL_STRING_REL(str);
42 zend_string_free(str);
43 break;
44 }
45 case IS_ARRAY: {
46 zend_array *arr = (zend_array*)p;
47 zend_array_destroy(arr);
48 break;
49 }
50 case IS_CONSTANT_AST: {
51 zend_ast_ref *ast = (zend_ast_ref*)p;
52
53 zend_ast_destroy_and_free(ast->ast);
54 efree_size(ast, sizeof(zend_ast_ref));
55 break;
56 }
57 case IS_OBJECT: {
58 zend_object *obj = (zend_object*)p;
59
60 zend_objects_store_del(obj);
61 break;
62 }
63 case IS_RESOURCE: {
64 zend_resource *res = (zend_resource*)p;
65
66 /* destroy resource */
67 zend_list_free(res);
68 break;
69 }
70 case IS_REFERENCE: {
71 zend_reference *ref = (zend_reference*)p;
72
73 i_zval_ptr_dtor(&ref->val ZEND_FILE_LINE_RELAY_CC);
74 efree_size(ref, sizeof(zend_reference));
75 break;
76 }
77 default:
78 break;
79 }
80 }
81
_zval_dtor_func_for_ptr(zend_refcounted * p ZEND_FILE_LINE_DC)82 ZEND_API void ZEND_FASTCALL _zval_dtor_func_for_ptr(zend_refcounted *p ZEND_FILE_LINE_DC)
83 {
84 switch (GC_TYPE(p)) {
85 case IS_STRING:
86 case IS_CONSTANT: {
87 zend_string *str = (zend_string*)p;
88 CHECK_ZVAL_STRING_REL(str);
89 zend_string_free(str);
90 break;
91 }
92 case IS_ARRAY: {
93 zend_array *arr = (zend_array*)p;
94
95 zend_array_destroy(arr);
96 break;
97 }
98 case IS_CONSTANT_AST: {
99 zend_ast_ref *ast = (zend_ast_ref*)p;
100
101 zend_ast_destroy_and_free(ast->ast);
102 efree_size(ast, sizeof(zend_ast_ref));
103 break;
104 }
105 case IS_OBJECT: {
106 zend_object *obj = (zend_object*)p;
107
108 zend_objects_store_del(obj);
109 break;
110 }
111 case IS_RESOURCE: {
112 zend_resource *res = (zend_resource*)p;
113
114 /* destroy resource */
115 zend_list_free(res);
116 break;
117 }
118 case IS_REFERENCE: {
119 zend_reference *ref = (zend_reference*)p;
120
121 i_zval_ptr_dtor(&ref->val ZEND_FILE_LINE_RELAY_CC);
122 efree_size(ref, sizeof(zend_reference));
123 break;
124 }
125 default:
126 break;
127 }
128 }
129
_zval_internal_dtor(zval * zvalue ZEND_FILE_LINE_DC)130 ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
131 {
132 switch (Z_TYPE_P(zvalue)) {
133 case IS_STRING:
134 case IS_CONSTANT:
135 CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue));
136 zend_string_release(Z_STR_P(zvalue));
137 break;
138 case IS_ARRAY:
139 case IS_CONSTANT_AST:
140 case IS_OBJECT:
141 case IS_RESOURCE:
142 zend_error_noreturn(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
143 break;
144 case IS_REFERENCE: {
145 zend_reference *ref = (zend_reference*)Z_REF_P(zvalue);
146
147 zval_internal_ptr_dtor(&ref->val);
148 free(ref);
149 break;
150 }
151 case IS_LONG:
152 case IS_DOUBLE:
153 case IS_FALSE:
154 case IS_TRUE:
155 case IS_NULL:
156 default:
157 break;
158 }
159 }
160
_zval_internal_dtor_for_ptr(zval * zvalue ZEND_FILE_LINE_DC)161 ZEND_API void _zval_internal_dtor_for_ptr(zval *zvalue ZEND_FILE_LINE_DC)
162 {
163 switch (Z_TYPE_P(zvalue)) {
164 case IS_STRING:
165 case IS_CONSTANT:
166 CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue));
167 zend_string_free(Z_STR_P(zvalue));
168 break;
169 case IS_ARRAY:
170 case IS_CONSTANT_AST:
171 case IS_OBJECT:
172 case IS_RESOURCE:
173 zend_error_noreturn(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
174 break;
175 case IS_REFERENCE: {
176 zend_reference *ref = (zend_reference*)Z_REF_P(zvalue);
177
178 zval_internal_ptr_dtor(&ref->val);
179 free(ref);
180 break;
181 }
182 case IS_LONG:
183 case IS_DOUBLE:
184 case IS_FALSE:
185 case IS_TRUE:
186 case IS_NULL:
187 default:
188 break;
189 }
190 }
191
192 /* This function should only be used as a copy constructor, i.e. it
193 * should only be called AFTER a zval has been copied to another
194 * location using ZVAL_COPY_VALUE. Do not call it before copying,
195 * otherwise a reference may be leaked. */
zval_add_ref(zval * p)196 ZEND_API void zval_add_ref(zval *p)
197 {
198 if (Z_REFCOUNTED_P(p)) {
199 if (Z_ISREF_P(p) && Z_REFCOUNT_P(p) == 1) {
200 ZVAL_COPY(p, Z_REFVAL_P(p));
201 } else {
202 Z_ADDREF_P(p);
203 }
204 }
205 }
206
zval_add_ref_unref(zval * p)207 ZEND_API void zval_add_ref_unref(zval *p)
208 {
209 if (Z_REFCOUNTED_P(p)) {
210 if (Z_ISREF_P(p)) {
211 ZVAL_COPY(p, Z_REFVAL_P(p));
212 } else {
213 Z_ADDREF_P(p);
214 }
215 }
216 }
217
_zval_copy_ctor_func(zval * zvalue ZEND_FILE_LINE_DC)218 ZEND_API void ZEND_FASTCALL _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
219 {
220 if (EXPECTED(Z_TYPE_P(zvalue) == IS_ARRAY)) {
221 ZVAL_ARR(zvalue, zend_array_dup(Z_ARRVAL_P(zvalue)));
222 } else if (EXPECTED(Z_TYPE_P(zvalue) == IS_STRING)) {
223 CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue));
224 ZVAL_NEW_STR(zvalue, zend_string_dup(Z_STR_P(zvalue), 0));
225 } else if (EXPECTED(Z_TYPE_P(zvalue) == IS_CONSTANT)) {
226 CHECK_ZVAL_STRING_REL(Z_STR_P(zvalue));
227 Z_STR_P(zvalue) = zend_string_dup(Z_STR_P(zvalue), 0);
228 } else if (EXPECTED(Z_TYPE_P(zvalue) == IS_CONSTANT_AST)) {
229 zend_ast_ref *ast = emalloc(sizeof(zend_ast_ref));
230
231 GC_REFCOUNT(ast) = 1;
232 GC_TYPE_INFO(ast) = IS_CONSTANT_AST;
233 ast->ast = zend_ast_copy(Z_ASTVAL_P(zvalue));
234 Z_AST_P(zvalue) = ast;
235 }
236 }
237
238
zend_print_variable(zval * var)239 ZEND_API size_t zend_print_variable(zval *var)
240 {
241 return zend_print_zval(var, 0);
242 }
243
244
_zval_dtor_wrapper(zval * zvalue)245 ZEND_API void _zval_dtor_wrapper(zval *zvalue)
246 {
247 zval_dtor(zvalue);
248 }
249
250
251 #if ZEND_DEBUG
_zval_internal_dtor_wrapper(zval * zvalue)252 ZEND_API void _zval_internal_dtor_wrapper(zval *zvalue)
253 {
254 zval_internal_dtor(zvalue);
255 }
256
257
_zval_ptr_dtor_wrapper(zval * zval_ptr)258 ZEND_API void _zval_ptr_dtor_wrapper(zval *zval_ptr)
259 {
260
261 i_zval_ptr_dtor(zval_ptr ZEND_FILE_LINE_CC);
262 }
263
264
_zval_internal_ptr_dtor_wrapper(zval * zval_ptr)265 ZEND_API void _zval_internal_ptr_dtor_wrapper(zval *zval_ptr)
266 {
267 zval_internal_ptr_dtor(zval_ptr);
268 }
269 #endif
270
zval_copy_static_var(zval * p,int num_args,va_list args,zend_hash_key * key)271 ZEND_API int zval_copy_static_var(zval *p, int num_args, va_list args, zend_hash_key *key) /* {{{ */
272 {
273 zend_array *symbol_table;
274 HashTable *target = va_arg(args, HashTable*);
275 zend_bool is_ref;
276 zval tmp;
277
278 if (Z_CONST_FLAGS_P(p) & (IS_LEXICAL_VAR|IS_LEXICAL_REF)) {
279 is_ref = Z_CONST_FLAGS_P(p) & IS_LEXICAL_REF;
280
281 symbol_table = zend_rebuild_symbol_table();
282 p = zend_hash_find(symbol_table, key->key);
283 if (!p) {
284 p = &tmp;
285 ZVAL_NULL(&tmp);
286 if (is_ref) {
287 ZVAL_NEW_REF(&tmp, &tmp);
288 zend_hash_add_new(symbol_table, key->key, &tmp);
289 Z_ADDREF_P(p);
290 } else {
291 zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(key->key));
292 }
293 } else {
294 if (Z_TYPE_P(p) == IS_INDIRECT) {
295 p = Z_INDIRECT_P(p);
296 if (Z_TYPE_P(p) == IS_UNDEF) {
297 if (!is_ref) {
298 zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(key->key));
299 p = &tmp;
300 ZVAL_NULL(&tmp);
301 } else {
302 ZVAL_NULL(p);
303 }
304 }
305 }
306 if (is_ref) {
307 ZVAL_MAKE_REF(p);
308 Z_ADDREF_P(p);
309 } else if (Z_ISREF_P(p)) {
310 ZVAL_DUP(&tmp, Z_REFVAL_P(p));
311 p = &tmp;
312 } else if (Z_REFCOUNTED_P(p)) {
313 Z_ADDREF_P(p);
314 }
315 }
316 } else if (Z_REFCOUNTED_P(p)) {
317 Z_ADDREF_P(p);
318 }
319 zend_hash_add(target, key->key, p);
320 return ZEND_HASH_APPLY_KEEP;
321 }
322 /* }}} */
323
324 /*
325 * Local variables:
326 * tab-width: 4
327 * c-basic-offset: 4
328 * indent-tabs-mode: t
329 * End:
330 */
331