xref: /PHP-5.6/Zend/zend_compile.c (revision 1f541298)
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 <zend_language_parser.h>
23 #include "zend.h"
24 #include "zend_compile.h"
25 #include "zend_constants.h"
26 #include "zend_llist.h"
27 #include "zend_API.h"
28 #include "zend_exceptions.h"
29 #include "zend_virtual_cwd.h"
30 #include "zend_multibyte.h"
31 #include "zend_language_scanner.h"
32 
33 #define CONSTANT_EX(op_array, op) \
34 	(op_array)->literals[op].constant
35 
36 #define CONSTANT(op) \
37 	CONSTANT_EX(CG(active_op_array), op)
38 
39 #define SET_NODE(target, src) do { \
40 		target ## _type = (src)->op_type; \
41 		if ((src)->op_type == IS_CONST) { \
42 			target.constant = zend_add_literal(CG(active_op_array), &(src)->u.constant TSRMLS_CC); \
43 		} else { \
44 			target = (src)->u.op; \
45 		} \
46 	} while (0)
47 
48 #define GET_NODE(target, src) do { \
49 		(target)->op_type = src ## _type; \
50 		if ((target)->op_type == IS_CONST) { \
51 			(target)->u.constant = CONSTANT(src.constant); \
52 		} else { \
53 			(target)->u.op = src; \
54 			(target)->EA = 0; \
55 		} \
56 	} while (0)
57 
58 #define COPY_NODE(target, src) do { \
59 		target ## _type = src ## _type; \
60 		target = src; \
61 	} while (0)
62 
63 #define CALCULATE_LITERAL_HASH(num) do { \
64 		zval *c = &CONSTANT(num); \
65 		Z_HASH_P(c) = str_hash(Z_STRVAL_P(c), Z_STRLEN_P(c)); \
66 	} while (0)
67 
68 #define GET_CACHE_SLOT(literal) do { \
69 		CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot++; \
70 		if ((CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) && CG(active_op_array)->run_time_cache) { \
71 			CG(active_op_array)->run_time_cache = erealloc(CG(active_op_array)->run_time_cache, CG(active_op_array)->last_cache_slot * sizeof(void*)); \
72 			CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 1] = NULL; \
73 		} \
74 	} while (0)
75 
76 #define POLYMORPHIC_CACHE_SLOT_SIZE 2
77 
78 #define GET_POLYMORPHIC_CACHE_SLOT(literal) do { \
79 		CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot; \
80 		CG(active_op_array)->last_cache_slot += POLYMORPHIC_CACHE_SLOT_SIZE; \
81 		if ((CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) && CG(active_op_array)->run_time_cache) { \
82 			CG(active_op_array)->run_time_cache = erealloc(CG(active_op_array)->run_time_cache, CG(active_op_array)->last_cache_slot * sizeof(void*)); \
83 			CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 1] = NULL; \
84 			CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 2] = NULL; \
85 		} \
86 	} while (0)
87 
88 #define FREE_POLYMORPHIC_CACHE_SLOT(literal) do { \
89 		if (CG(active_op_array)->literals[literal].cache_slot != -1 && \
90 		    CG(active_op_array)->literals[literal].cache_slot == \
91 		    CG(active_op_array)->last_cache_slot - POLYMORPHIC_CACHE_SLOT_SIZE) { \
92 			CG(active_op_array)->literals[literal].cache_slot = -1; \
93 			CG(active_op_array)->last_cache_slot -= POLYMORPHIC_CACHE_SLOT_SIZE; \
94 		} \
95 	} while (0)
96 
97 ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
98 ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
99 
100 #ifndef ZTS
101 ZEND_API zend_compiler_globals compiler_globals;
102 ZEND_API zend_executor_globals executor_globals;
103 #endif
104 
zend_push_function_call_entry(zend_function * fbc TSRMLS_DC)105 static void zend_push_function_call_entry(zend_function *fbc TSRMLS_DC) /* {{{ */
106 {
107 	zend_function_call_entry fcall = { fbc };
108 	zend_stack_push(&CG(function_call_stack), &fcall, sizeof(zend_function_call_entry));
109 }
110 /* }}} */
111 
zend_duplicate_property_info(zend_property_info * property_info)112 static void zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */
113 {
114 	property_info->name = str_estrndup(property_info->name, property_info->name_length);
115 	if (property_info->doc_comment) {
116 		property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len);
117 	}
118 }
119 /* }}} */
120 
zend_duplicate_property_info_internal(zend_property_info * property_info)121 static void zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */
122 {
123 	property_info->name = str_strndup(property_info->name, property_info->name_length);
124 }
125 /* }}} */
126 
zend_destroy_property_info(zend_property_info * property_info)127 static void zend_destroy_property_info(zend_property_info *property_info) /* {{{ */
128 {
129 	str_efree(property_info->name);
130 	if (property_info->doc_comment) {
131 		efree((char*)property_info->doc_comment);
132 	}
133 }
134 /* }}} */
135 
zend_destroy_property_info_internal(zend_property_info * property_info)136 static void zend_destroy_property_info_internal(zend_property_info *property_info) /* {{{ */
137 {
138 	str_free((char*)property_info->name);
139 }
140 /* }}} */
141 
build_runtime_defined_function_key(zval * result,const char * name,int name_length TSRMLS_DC)142 static void build_runtime_defined_function_key(zval *result, const char *name, int name_length TSRMLS_DC) /* {{{ */
143 {
144 	char char_pos_buf[32];
145 	uint char_pos_len;
146 	const char *filename;
147 
148 	char_pos_len = zend_sprintf(char_pos_buf, "%p", LANG_SCNG(yy_text));
149 	if (CG(active_op_array)->filename) {
150 		filename = CG(active_op_array)->filename;
151 	} else {
152 		filename = "-";
153 	}
154 
155 	/* NULL, name length, filename length, last accepting char position length */
156 	Z_STRLEN_P(result) = 1+name_length+strlen(filename)+char_pos_len;
157 
158  	/* must be binary safe */
159  	Z_STRVAL_P(result) = (char *) safe_emalloc(Z_STRLEN_P(result), 1, 1);
160  	Z_STRVAL_P(result)[0] = '\0';
161  	sprintf(Z_STRVAL_P(result)+1, "%s%s%s", name, filename, char_pos_buf);
162 
163 	result->type = IS_STRING;
164 	Z_SET_REFCOUNT_P(result, 1);
165 }
166 /* }}} */
167 
init_compiler_declarables(TSRMLS_D)168 static void init_compiler_declarables(TSRMLS_D) /* {{{ */
169 {
170 	Z_TYPE(CG(declarables).ticks) = IS_LONG;
171 	Z_LVAL(CG(declarables).ticks) = 0;
172 }
173 /* }}} */
174 
zend_init_compiler_context(TSRMLS_D)175 void zend_init_compiler_context(TSRMLS_D) /* {{{ */
176 {
177 	CG(context).opcodes_size = (CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) ? INITIAL_INTERACTIVE_OP_ARRAY_SIZE : INITIAL_OP_ARRAY_SIZE;
178 	CG(context).vars_size = 0;
179 	CG(context).literals_size = 0;
180 	CG(context).current_brk_cont = -1;
181 	CG(context).backpatch_count = 0;
182 	CG(context).nested_calls = 0;
183 	CG(context).used_stack = 0;
184 	CG(context).in_finally = 0;
185 	CG(context).labels = NULL;
186 }
187 /* }}} */
188 
zend_init_compiler_data_structures(TSRMLS_D)189 void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
190 {
191 	zend_stack_init(&CG(bp_stack));
192 	zend_stack_init(&CG(function_call_stack));
193 	zend_stack_init(&CG(switch_cond_stack));
194 	zend_stack_init(&CG(foreach_copy_stack));
195 	zend_stack_init(&CG(object_stack));
196 	zend_stack_init(&CG(declare_stack));
197 	CG(active_class_entry) = NULL;
198 	zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
199 	zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
200 	zend_stack_init(&CG(list_stack));
201 	CG(in_compilation) = 0;
202 	CG(start_lineno) = 0;
203 	CG(current_namespace) = NULL;
204 	CG(in_namespace) = 0;
205 	CG(has_bracketed_namespaces) = 0;
206 	CG(current_import) = NULL;
207 	CG(current_import_function) = NULL;
208 	CG(current_import_const) = NULL;
209 	zend_hash_init(&CG(const_filenames), 0, NULL, NULL, 0);
210 	init_compiler_declarables(TSRMLS_C);
211 	zend_stack_init(&CG(context_stack));
212 
213 	CG(encoding_declared) = 0;
214 }
215 /* }}} */
216 
file_handle_dtor(zend_file_handle * fh)217 ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
218 {
219 	TSRMLS_FETCH();
220 
221 	zend_file_handle_dtor(fh TSRMLS_CC);
222 }
223 /* }}} */
224 
init_compiler(TSRMLS_D)225 void init_compiler(TSRMLS_D) /* {{{ */
226 {
227 	CG(active_op_array) = NULL;
228 	memset(&CG(context), 0, sizeof(CG(context)));
229 	zend_init_compiler_data_structures(TSRMLS_C);
230 	zend_init_rsrc_list(TSRMLS_C);
231 	zend_hash_init(&CG(filenames_table), 5, NULL, (dtor_func_t) free_estring, 0);
232 	zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) file_handle_dtor, 0);
233 	CG(unclean_shutdown) = 0;
234 }
235 /* }}} */
236 
shutdown_compiler(TSRMLS_D)237 void shutdown_compiler(TSRMLS_D) /* {{{ */
238 {
239 	zend_stack_destroy(&CG(bp_stack));
240 	zend_stack_destroy(&CG(function_call_stack));
241 	zend_stack_destroy(&CG(switch_cond_stack));
242 	zend_stack_destroy(&CG(foreach_copy_stack));
243 	zend_stack_destroy(&CG(object_stack));
244 	zend_stack_destroy(&CG(declare_stack));
245 	zend_stack_destroy(&CG(list_stack));
246 	zend_hash_destroy(&CG(filenames_table));
247 	zend_llist_destroy(&CG(open_files));
248 	zend_hash_destroy(&CG(const_filenames));
249 	zend_stack_destroy(&CG(context_stack));
250 }
251 /* }}} */
252 
zend_set_compiled_filename(const char * new_compiled_filename TSRMLS_DC)253 ZEND_API char *zend_set_compiled_filename(const char *new_compiled_filename TSRMLS_DC) /* {{{ */
254 {
255 	char **pp, *p;
256 	int length = strlen(new_compiled_filename);
257 
258 	if (zend_hash_find(&CG(filenames_table), new_compiled_filename, length+1, (void **) &pp) == SUCCESS) {
259 		CG(compiled_filename) = *pp;
260 		return *pp;
261 	}
262 	p = estrndup(new_compiled_filename, length);
263 	zend_hash_update(&CG(filenames_table), new_compiled_filename, length+1, &p, sizeof(char *), (void **) &pp);
264 	CG(compiled_filename) = p;
265 	return p;
266 }
267 /* }}} */
268 
zend_restore_compiled_filename(char * original_compiled_filename TSRMLS_DC)269 ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename TSRMLS_DC) /* {{{ */
270 {
271 	CG(compiled_filename) = original_compiled_filename;
272 }
273 /* }}} */
274 
zend_get_compiled_filename(TSRMLS_D)275 ZEND_API char *zend_get_compiled_filename(TSRMLS_D) /* {{{ */
276 {
277 	return CG(compiled_filename);
278 }
279 /* }}} */
280 
zend_get_compiled_lineno(TSRMLS_D)281 ZEND_API int zend_get_compiled_lineno(TSRMLS_D) /* {{{ */
282 {
283 	return CG(zend_lineno);
284 }
285 /* }}} */
286 
zend_is_compiling(TSRMLS_D)287 ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */
288 {
289 	return CG(in_compilation);
290 }
291 /* }}} */
292 
get_temporary_variable(zend_op_array * op_array)293 static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
294 {
295 	return (zend_uint)(zend_uintptr_t)EX_TMP_VAR_NUM(0, (op_array->T)++);
296 }
297 /* }}} */
298 
lookup_cv(zend_op_array * op_array,char * name,int name_len,ulong hash TSRMLS_DC)299 static int lookup_cv(zend_op_array *op_array, char* name, int name_len, ulong hash TSRMLS_DC) /* {{{ */
300 {
301 	int i = 0;
302 	ulong hash_value = hash ? hash : zend_inline_hash_func(name, name_len+1);
303 
304 	while (i < op_array->last_var) {
305 		if (op_array->vars[i].name == name ||
306 		    (op_array->vars[i].hash_value == hash_value &&
307 		     op_array->vars[i].name_len == name_len &&
308 		     memcmp(op_array->vars[i].name, name, name_len) == 0)) {
309 			str_efree(name);
310 			return i;
311 		}
312 		i++;
313 	}
314 	i = op_array->last_var;
315 	op_array->last_var++;
316 	if (op_array->last_var > CG(context).vars_size) {
317 		CG(context).vars_size += 16; /* FIXME */
318 		op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_compiled_variable));
319 	}
320 	op_array->vars[i].name = zend_new_interned_string(name, name_len + 1, 1 TSRMLS_CC);
321 	op_array->vars[i].name_len = name_len;
322 	op_array->vars[i].hash_value = hash_value;
323 	return i;
324 }
325 /* }}} */
326 
zend_del_literal(zend_op_array * op_array,int n)327 void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */
328 {
329 	zval_dtor(&CONSTANT_EX(op_array, n));
330 	if (n + 1 == op_array->last_literal) {
331 		op_array->last_literal--;
332 	} else {
333 		Z_TYPE(CONSTANT_EX(op_array, n)) = IS_NULL;
334 	}
335 }
336 /* }}} */
337 
338 /* Common part of zend_add_literal and zend_append_individual_literal */
zend_insert_literal(zend_op_array * op_array,const zval * zv,int literal_position TSRMLS_DC)339 static inline void zend_insert_literal(zend_op_array *op_array, const zval *zv, int literal_position TSRMLS_DC) /* {{{ */
340 {
341 	if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) {
342 		zval *z = (zval*)zv;
343 		Z_STRVAL_P(z) = (char*)zend_new_interned_string(Z_STRVAL_P(zv), Z_STRLEN_P(zv) + 1, 1 TSRMLS_CC);
344 	}
345 	CONSTANT_EX(op_array, literal_position) = *zv;
346 	Z_SET_REFCOUNT(CONSTANT_EX(op_array, literal_position), 2);
347 	Z_SET_ISREF(CONSTANT_EX(op_array, literal_position));
348 	op_array->literals[literal_position].hash_value = 0;
349 	op_array->literals[literal_position].cache_slot = -1;
350 }
351 /* }}} */
352 
353 /* Is used while compiling a function, using the context to keep track
354    of an approximate size to avoid to relocate to often.
355    Literals are truncated to actual size in the second compiler pass (pass_two()). */
zend_add_literal(zend_op_array * op_array,const zval * zv TSRMLS_DC)356 int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
357 {
358 	int i = op_array->last_literal;
359 	op_array->last_literal++;
360 	if (i >= CG(context).literals_size) {
361 		while (i >= CG(context).literals_size) {
362 			CG(context).literals_size += 16; /* FIXME */
363 		}
364 		op_array->literals = (zend_literal*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zend_literal));
365 	}
366 	zend_insert_literal(op_array, zv, i TSRMLS_CC);
367 	return i;
368 }
369 /* }}} */
370 
371 /* Is used after normal compilation to append an additional literal.
372    Allocation is done precisely here. */
zend_append_individual_literal(zend_op_array * op_array,const zval * zv TSRMLS_DC)373 int zend_append_individual_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
374 {
375 	int i = op_array->last_literal;
376 	op_array->last_literal++;
377 	op_array->literals = (zend_literal*)erealloc(op_array->literals, (i + 1) * sizeof(zend_literal));
378 	zend_insert_literal(op_array, zv, i TSRMLS_CC);
379 	return i;
380 }
381 /* }}} */
382 
zend_add_func_name_literal(zend_op_array * op_array,const zval * zv TSRMLS_DC)383 int zend_add_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
384 {
385 	int ret;
386 	char *lc_name;
387 	zval c;
388 	int lc_literal;
389 
390 	if (op_array->last_literal > 0 &&
391 	    &op_array->literals[op_array->last_literal - 1].constant == zv &&
392 	    op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
393 		/* we already have function name as last literal (do nothing) */
394 		ret = op_array->last_literal - 1;
395 	} else {
396 		ret = zend_add_literal(op_array, zv TSRMLS_CC);
397 	}
398 
399 	lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
400 	ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0);
401 	lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
402 	CALCULATE_LITERAL_HASH(lc_literal);
403 
404 	return ret;
405 }
406 /* }}} */
407 
zend_add_ns_func_name_literal(zend_op_array * op_array,const zval * zv TSRMLS_DC)408 int zend_add_ns_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
409 {
410 	int ret;
411 	char *lc_name;
412 	const char *ns_separator;
413 	int lc_len;
414 	zval c;
415 	int lc_literal;
416 
417 	if (op_array->last_literal > 0 &&
418 	    &op_array->literals[op_array->last_literal - 1].constant == zv &&
419 	    op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
420 		/* we already have function name as last literal (do nothing) */
421 		ret = op_array->last_literal - 1;
422 	} else {
423 		ret = zend_add_literal(op_array, zv TSRMLS_CC);
424 	}
425 
426 	lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
427 	ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0);
428 	lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
429 	CALCULATE_LITERAL_HASH(lc_literal);
430 
431 	ns_separator = (const char*)zend_memrchr(Z_STRVAL_P(zv), '\\', Z_STRLEN_P(zv));
432 
433 	if (ns_separator != NULL) {
434 		ns_separator += 1;
435 		lc_len = Z_STRLEN_P(zv) - (ns_separator - Z_STRVAL_P(zv));
436 		lc_name = zend_str_tolower_dup(ns_separator, lc_len);
437 		ZVAL_STRINGL(&c, lc_name, lc_len, 0);
438 		lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
439 		CALCULATE_LITERAL_HASH(lc_literal);
440 	}
441 
442 	return ret;
443 }
444 /* }}} */
445 
zend_add_class_name_literal(zend_op_array * op_array,const zval * zv TSRMLS_DC)446 int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
447 {
448 	int ret;
449 	char *lc_name;
450 	int lc_len;
451 	zval c;
452 	int lc_literal;
453 
454 	if (op_array->last_literal > 0 &&
455 	    &op_array->literals[op_array->last_literal - 1].constant == zv &&
456 	    op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
457 		/* we already have function name as last literal (do nothing) */
458 		ret = op_array->last_literal - 1;
459 	} else {
460 		ret = zend_add_literal(op_array, zv TSRMLS_CC);
461 	}
462 
463 	if (Z_STRVAL_P(zv)[0] == '\\') {
464 		lc_len = Z_STRLEN_P(zv) - 1;
465 		lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv) + 1, lc_len);
466 	} else {
467 		lc_len = Z_STRLEN_P(zv);
468 		lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), lc_len);
469 	}
470 	ZVAL_STRINGL(&c, lc_name, lc_len, 0);
471 	lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
472 	CALCULATE_LITERAL_HASH(lc_literal);
473 
474 	GET_CACHE_SLOT(ret);
475 
476 	return ret;
477 }
478 /* }}} */
479 
zend_add_const_name_literal(zend_op_array * op_array,const zval * zv,int unqualified TSRMLS_DC)480 int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unqualified TSRMLS_DC) /* {{{ */
481 {
482 	int ret, tmp_literal;
483 	char *name, *tmp_name;
484 	const char *ns_separator;
485 	int name_len, ns_len;
486 	zval c;
487 
488 	if (op_array->last_literal > 0 &&
489 	    &op_array->literals[op_array->last_literal - 1].constant == zv &&
490 	    op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
491 		/* we already have function name as last literal (do nothing) */
492 		ret = op_array->last_literal - 1;
493 	} else {
494 		ret = zend_add_literal(op_array, zv TSRMLS_CC);
495 	}
496 
497 	/* skip leading '\\' */
498 	if (Z_STRVAL_P(zv)[0] == '\\') {
499 		name_len = Z_STRLEN_P(zv) - 1;
500 		name = Z_STRVAL_P(zv) + 1;
501 	} else {
502 		name_len = Z_STRLEN_P(zv);
503 		name = Z_STRVAL_P(zv);
504 	}
505 	ns_separator = zend_memrchr(name, '\\', name_len);
506 	if (ns_separator) {
507 		ns_len = ns_separator - name;
508 	} else {
509 		ns_len = 0;
510 	}
511 
512 	if (ns_len) {
513 		/* lowercased namespace name & original constant name */
514 		tmp_name = estrndup(name, name_len);
515 		zend_str_tolower(tmp_name, ns_len);
516 		ZVAL_STRINGL(&c, tmp_name, name_len, 0);
517 		tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
518 		CALCULATE_LITERAL_HASH(tmp_literal);
519 
520 		/* lowercased namespace name & lowercased constant name */
521 		tmp_name = zend_str_tolower_dup(name, name_len);
522 		ZVAL_STRINGL(&c, tmp_name, name_len, 0);
523 		tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
524 		CALCULATE_LITERAL_HASH(tmp_literal);
525 	}
526 
527 	if (ns_len) {
528 		if (!unqualified) {
529 			return ret;
530 		}
531 		ns_len++;
532 		name += ns_len;
533 		name_len -= ns_len;
534 	}
535 
536 	/* original constant name */
537 	tmp_name = estrndup(name, name_len);
538 	ZVAL_STRINGL(&c, tmp_name, name_len, 0);
539 	tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
540 	CALCULATE_LITERAL_HASH(tmp_literal);
541 
542 	/* lowercased constant name */
543 	tmp_name = zend_str_tolower_dup(name, name_len);
544 	ZVAL_STRINGL(&c, tmp_name, name_len, 0);
545 	tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
546 	CALCULATE_LITERAL_HASH(tmp_literal);
547 
548 	return ret;
549 }
550 /* }}} */
551 
552 #define LITERAL_STRINGL(op, str, len, copy) do { \
553 		zval _c; \
554 		ZVAL_STRINGL(&_c, str, len, copy); \
555 		op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
556 	} while (0)
557 
558 #define LITERAL_LONG(op, val) do { \
559 		zval _c; \
560 		ZVAL_LONG(&_c, val); \
561 		op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
562 	} while (0)
563 
564 #define LITERAL_LONG_EX(op_array, op, val) do { \
565 		zval _c; \
566 		ZVAL_LONG(&_c, val); \
567 		op.constant = zend_add_literal(op_array, &_c TSRMLS_CC); \
568 	} while (0)
569 
570 #define LITERAL_NULL(op) do { \
571 		zval _c; \
572 		INIT_ZVAL(	_c); \
573 		op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
574 	} while (0)
575 
zend_is_function_or_method_call(const znode * variable)576 static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
577 {
578 	zend_uint type = variable->EA;
579 
580 	return  ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
581 }
582 /* }}} */
583 
zend_do_binary_op(zend_uchar op,znode * result,const znode * op1,const znode * op2 TSRMLS_DC)584 void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
585 {
586 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
587 
588 	opline->opcode = op;
589 	opline->result_type = IS_TMP_VAR;
590 	opline->result.var = get_temporary_variable(CG(active_op_array));
591 	SET_NODE(opline->op1, op1);
592 	SET_NODE(opline->op2, op2);
593 	GET_NODE(result, opline->result);
594 }
595 /* }}} */
596 
zend_do_unary_op(zend_uchar op,znode * result,const znode * op1 TSRMLS_DC)597 void zend_do_unary_op(zend_uchar op, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */
598 {
599 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
600 
601 	opline->opcode = op;
602 	opline->result_type = IS_TMP_VAR;
603 	opline->result.var = get_temporary_variable(CG(active_op_array));
604 	SET_NODE(opline->op1, op1);
605 	GET_NODE(result, opline->result);
606 	SET_UNUSED(opline->op2);
607 }
608 /* }}} */
609 
610 #define MAKE_NOP(opline)	{ opline->opcode = ZEND_NOP;  memset(&opline->result,0,sizeof(opline->result)); memset(&opline->op1,0,sizeof(opline->op1)); memset(&opline->op2,0,sizeof(opline->op2)); opline->result_type=opline->op1_type=opline->op2_type=IS_UNUSED;  }
611 
zend_do_op_data(zend_op * data_op,const znode * value TSRMLS_DC)612 static void zend_do_op_data(zend_op *data_op, const znode *value TSRMLS_DC) /* {{{ */
613 {
614 	data_op->opcode = ZEND_OP_DATA;
615 	SET_NODE(data_op->op1, value);
616 	SET_UNUSED(data_op->op2);
617 }
618 /* }}} */
619 
zend_do_binary_assign_op(zend_uchar op,znode * result,const znode * op1,const znode * op2 TSRMLS_DC)620 void zend_do_binary_assign_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
621 {
622 	int last_op_number = get_next_op_number(CG(active_op_array));
623 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
624 
625 	if (last_op_number > 0) {
626 		zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
627 
628 		switch (last_op->opcode) {
629 			case ZEND_FETCH_OBJ_RW:
630 				last_op->opcode = op;
631 				last_op->extended_value = ZEND_ASSIGN_OBJ;
632 
633 				zend_do_op_data(opline, op2 TSRMLS_CC);
634 				SET_UNUSED(opline->result);
635 				GET_NODE(result, last_op->result);
636 				return;
637 			case ZEND_FETCH_DIM_RW:
638 				last_op->opcode = op;
639 				last_op->extended_value = ZEND_ASSIGN_DIM;
640 
641 				zend_do_op_data(opline, op2 TSRMLS_CC);
642 				opline->op2.var = get_temporary_variable(CG(active_op_array));
643 				opline->op2_type = IS_VAR;
644 				SET_UNUSED(opline->result);
645 				GET_NODE(result,last_op->result);
646 				return;
647 			default:
648 				break;
649 		}
650 	}
651 
652 	opline->opcode = op;
653 	SET_NODE(opline->op1, op1);
654 	SET_NODE(opline->op2, op2);
655 	opline->result_type = IS_VAR;
656 	opline->result.var = get_temporary_variable(CG(active_op_array));
657 	GET_NODE(result, opline->result);
658 }
659 /* }}} */
660 
fetch_simple_variable_ex(znode * result,znode * varname,int bp,zend_uchar op TSRMLS_DC)661 void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC) /* {{{ */
662 {
663 	zend_op opline;
664 	zend_op *opline_ptr;
665 	zend_llist *fetch_list_ptr;
666 
667 	if (varname->op_type == IS_CONST) {
668 		ulong hash;
669 
670 		if (Z_TYPE(varname->u.constant) != IS_STRING) {
671 			convert_to_string(&varname->u.constant);
672 		}
673 
674 		hash = str_hash(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant));
675 		if (!zend_is_auto_global_quick(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), hash TSRMLS_CC) &&
676 		    !(Z_STRLEN(varname->u.constant) == (sizeof("this")-1) &&
677 		      !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1)) &&
678 		    (CG(active_op_array)->last == 0 ||
679 		     CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
680 			result->op_type = IS_CV;
681 			result->u.op.var = lookup_cv(CG(active_op_array), Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), hash TSRMLS_CC);
682 			Z_STRVAL(varname->u.constant) = (char*)CG(active_op_array)->vars[result->u.op.var].name;
683 			result->EA = 0;
684 			return;
685 		}
686 	}
687 
688 	if (bp) {
689 		opline_ptr = &opline;
690 		init_op(opline_ptr TSRMLS_CC);
691 	} else {
692 		opline_ptr = get_next_op(CG(active_op_array) TSRMLS_CC);
693 	}
694 
695 	opline_ptr->opcode = op;
696 	opline_ptr->result_type = IS_VAR;
697 	opline_ptr->result.var = get_temporary_variable(CG(active_op_array));
698 	SET_NODE(opline_ptr->op1, varname);
699 	GET_NODE(result, opline_ptr->result);
700 	SET_UNUSED(opline_ptr->op2);
701 	opline_ptr->extended_value = ZEND_FETCH_LOCAL;
702 
703 	if (varname->op_type == IS_CONST) {
704 		CALCULATE_LITERAL_HASH(opline_ptr->op1.constant);
705 		if (zend_is_auto_global_quick(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), Z_HASH_P(&CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC)) {
706 			opline_ptr->extended_value = ZEND_FETCH_GLOBAL;
707 		}
708 	}
709 
710 	if (bp) {
711 		zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
712 		zend_llist_add_element(fetch_list_ptr, opline_ptr);
713 	}
714 }
715 /* }}} */
716 
fetch_simple_variable(znode * result,znode * varname,int bp TSRMLS_DC)717 void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC) /* {{{ */
718 {
719 	/* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
720 	fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
721 }
722 /* }}} */
723 
zend_do_fetch_static_member(znode * result,znode * class_name TSRMLS_DC)724 void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
725 {
726 	znode class_node;
727 	zend_llist *fetch_list_ptr;
728 	zend_llist_element *le;
729 	zend_op *opline_ptr;
730 	zend_op opline;
731 
732 	if (class_name->op_type == IS_CONST &&
733 	    ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
734 		zend_resolve_class_name(class_name TSRMLS_CC);
735 		class_node = *class_name;
736 	} else {
737 		zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
738 	}
739 	zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
740 	if (result->op_type == IS_CV) {
741 		init_op(&opline TSRMLS_CC);
742 
743 		opline.opcode = ZEND_FETCH_W;
744 		opline.result_type = IS_VAR;
745 		opline.result.var = get_temporary_variable(CG(active_op_array));
746 		opline.op1_type = IS_CONST;
747 		LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[result->u.op.var].name), CG(active_op_array)->vars[result->u.op.var].name_len, 0);
748 		CALCULATE_LITERAL_HASH(opline.op1.constant);
749 		GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
750 		if (class_node.op_type == IS_CONST) {
751 			opline.op2_type = IS_CONST;
752 			opline.op2.constant =
753 				zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
754 		} else {
755 			SET_NODE(opline.op2, &class_node);
756 		}
757 		GET_NODE(result,opline.result);
758 		opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
759 		opline_ptr = &opline;
760 
761 		zend_llist_add_element(fetch_list_ptr, &opline);
762 	} else {
763 		le = fetch_list_ptr->head;
764 
765 		opline_ptr = (zend_op *)le->data;
766 		if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1_type == IS_CV) {
767 			init_op(&opline TSRMLS_CC);
768 			opline.opcode = ZEND_FETCH_W;
769 			opline.result_type = IS_VAR;
770 			opline.result.var = get_temporary_variable(CG(active_op_array));
771 			opline.op1_type = IS_CONST;
772 			LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[opline_ptr->op1.var].name), CG(active_op_array)->vars[opline_ptr->op1.var].name_len, 0);
773 			CALCULATE_LITERAL_HASH(opline.op1.constant);
774 			GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
775 			if (class_node.op_type == IS_CONST) {
776 				opline.op2_type = IS_CONST;
777 				opline.op2.constant =
778 					zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
779 			} else {
780 				SET_NODE(opline.op2, &class_node);
781 			}
782 			opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
783 			COPY_NODE(opline_ptr->op1, opline.result);
784 
785 			zend_llist_prepend_element(fetch_list_ptr, &opline);
786 		} else {
787 			if (opline_ptr->op1_type == IS_CONST) {
788 				GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op1.constant);
789 			}
790 			if (class_node.op_type == IS_CONST) {
791 				opline_ptr->op2_type = IS_CONST;
792 				opline_ptr->op2.constant =
793 					zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
794 			} else {
795 				SET_NODE(opline_ptr->op2, &class_node);
796 			}
797 			opline_ptr->extended_value |= ZEND_FETCH_STATIC_MEMBER;
798 		}
799 	}
800 }
801 /* }}} */
802 
fetch_array_begin(znode * result,znode * varname,znode * first_dim TSRMLS_DC)803 void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC) /* {{{ */
804 {
805 	fetch_simple_variable(result, varname, 1 TSRMLS_CC);
806 
807 	fetch_array_dim(result, result, first_dim TSRMLS_CC);
808 }
809 /* }}} */
810 
fetch_array_dim(znode * result,const znode * parent,const znode * dim TSRMLS_DC)811 void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS_DC) /* {{{ */
812 {
813 	zend_op opline;
814 	zend_llist *fetch_list_ptr;
815 
816 	zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
817 
818 	if (zend_is_function_or_method_call(parent)) {
819 		init_op(&opline TSRMLS_CC);
820 		opline.opcode = ZEND_SEPARATE;
821 		SET_NODE(opline.op1, parent);
822 		SET_UNUSED(opline.op2);
823 		opline.result_type = IS_VAR;
824 		opline.result.var = opline.op1.var;
825 		zend_llist_add_element(fetch_list_ptr, &opline);
826 	}
827 
828 	init_op(&opline TSRMLS_CC);
829 	opline.opcode = ZEND_FETCH_DIM_W;	/* the backpatching routine assumes W */
830 	opline.result_type = IS_VAR;
831 	opline.result.var = get_temporary_variable(CG(active_op_array));
832 	SET_NODE(opline.op1, parent);
833 	SET_NODE(opline.op2, dim);
834 	if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
835 		ulong index;
836 		int numeric = 0;
837 
838 		ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline.op2.constant)), Z_STRLEN(CONSTANT(opline.op2.constant))+1, index, numeric = 1);
839 		if (numeric) {
840 			zval_dtor(&CONSTANT(opline.op2.constant));
841 			ZVAL_LONG(&CONSTANT(opline.op2.constant), index);
842 		} else {
843 			CALCULATE_LITERAL_HASH(opline.op2.constant);
844 		}
845 	}
846 
847 	GET_NODE(result, opline.result);
848 
849 	zend_llist_add_element(fetch_list_ptr, &opline);
850 }
851 /* }}} */
852 
fetch_string_offset(znode * result,const znode * parent,const znode * offset TSRMLS_DC)853 void fetch_string_offset(znode *result, const znode *parent, const znode *offset TSRMLS_DC) /* {{{ */
854 {
855 	fetch_array_dim(result, parent, offset TSRMLS_CC);
856 }
857 /* }}} */
858 
zend_do_print(znode * result,const znode * arg TSRMLS_DC)859 void zend_do_print(znode *result, const znode *arg TSRMLS_DC) /* {{{ */
860 {
861 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
862 
863 	opline->result_type = IS_TMP_VAR;
864 	opline->result.var = get_temporary_variable(CG(active_op_array));
865 	opline->opcode = ZEND_PRINT;
866 	SET_NODE(opline->op1, arg);
867 	SET_UNUSED(opline->op2);
868 	GET_NODE(result, opline->result);
869 }
870 /* }}} */
871 
zend_do_echo(const znode * arg TSRMLS_DC)872 void zend_do_echo(const znode *arg TSRMLS_DC) /* {{{ */
873 {
874 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
875 
876 	opline->opcode = ZEND_ECHO;
877 	SET_NODE(opline->op1, arg);
878 	SET_UNUSED(opline->op2);
879 }
880 /* }}} */
881 
zend_do_abstract_method(const znode * function_name,znode * modifiers,const znode * body TSRMLS_DC)882 void zend_do_abstract_method(const znode *function_name, znode *modifiers, const znode *body TSRMLS_DC) /* {{{ */
883 {
884 	char *method_type;
885 
886 	if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
887 		Z_LVAL(modifiers->u.constant) |= ZEND_ACC_ABSTRACT;
888 		method_type = "Interface";
889 	} else {
890 		method_type = "Abstract";
891 	}
892 
893 	if (Z_LVAL(modifiers->u.constant) & ZEND_ACC_ABSTRACT) {
894 		if(Z_LVAL(modifiers->u.constant) & ZEND_ACC_PRIVATE) {
895 			zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private", method_type, CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
896 		}
897 		if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
898 			zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
899 
900 			opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
901 			SET_UNUSED(opline->op1);
902 			SET_UNUSED(opline->op2);
903 		} else {
904 			/* we had code in the function body */
905 			zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body", method_type, CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
906 		}
907 	} else {
908 		if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
909 			zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body", CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
910 		}
911 	}
912 }
913 /* }}} */
914 
opline_is_fetch_this(const zend_op * opline TSRMLS_DC)915 static zend_bool opline_is_fetch_this(const zend_op *opline TSRMLS_DC) /* {{{ */
916 {
917 	if ((opline->opcode == ZEND_FETCH_W) && (opline->op1_type == IS_CONST)
918 		&& (Z_TYPE(CONSTANT(opline->op1.constant)) == IS_STRING)
919 		&& ((opline->extended_value & ZEND_FETCH_STATIC_MEMBER) != ZEND_FETCH_STATIC_MEMBER)
920 		&& (Z_HASH_P(&CONSTANT(opline->op1.constant)) == THIS_HASHVAL)
921 		&& (Z_STRLEN(CONSTANT(opline->op1.constant)) == (sizeof("this")-1))
922 		&& !memcmp(Z_STRVAL(CONSTANT(opline->op1.constant)), "this", sizeof("this") - 1)) {
923 		return 1;
924 	} else {
925 		return 0;
926 	}
927 }
928 /* }}} */
929 
zend_do_assign(znode * result,znode * variable,znode * value TSRMLS_DC)930 void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) /* {{{ */
931 {
932 	int last_op_number;
933 	zend_op *opline;
934 
935 	if (value->op_type == IS_CV) {
936 		zend_llist *fetch_list_ptr;
937 
938 		zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
939 		if (fetch_list_ptr && fetch_list_ptr->head) {
940 			opline = (zend_op *)fetch_list_ptr->head->data;
941 
942 			if (opline->opcode == ZEND_FETCH_DIM_W &&
943 			    opline->op1_type == IS_CV &&
944 			    opline->op1.var == value->u.op.var) {
945 
946 				opline = get_next_op(CG(active_op_array) TSRMLS_CC);
947 				opline->opcode = ZEND_FETCH_R;
948 				opline->result_type = IS_VAR;
949 				opline->result.var = get_temporary_variable(CG(active_op_array));
950 				opline->op1_type = IS_CONST;
951 				LITERAL_STRINGL(opline->op1,
952 					CG(active_op_array)->vars[value->u.op.var].name,
953 					CG(active_op_array)->vars[value->u.op.var].name_len, 1);
954 				CALCULATE_LITERAL_HASH(opline->op1.constant);
955 				SET_UNUSED(opline->op2);
956 				opline->extended_value = ZEND_FETCH_LOCAL;
957 				GET_NODE(value, opline->result);
958 			}
959 		}
960 	}
961 
962 	zend_do_end_variable_parse(variable, BP_VAR_W, 0 TSRMLS_CC);
963 
964 	last_op_number = get_next_op_number(CG(active_op_array));
965 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
966 
967 	if (variable->op_type == IS_CV) {
968 		if (variable->u.op.var == CG(active_op_array)->this_var) {
969 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
970 		}
971 	} else if (variable->op_type == IS_VAR) {
972 		int n = 0;
973 
974 		while (last_op_number - n > 0) {
975 			zend_op *last_op;
976 
977 			last_op = &CG(active_op_array)->opcodes[last_op_number-n-1];
978 
979 			if (last_op->result_type == IS_VAR &&
980 			    last_op->result.var == variable->u.op.var) {
981 				if (last_op->opcode == ZEND_FETCH_OBJ_W) {
982 					if (n > 0) {
983 						int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
984 						*opline = *last_op;
985 						MAKE_NOP(last_op);
986 						/* last_op = opline; */
987 						opline = get_next_op(CG(active_op_array) TSRMLS_CC);
988 						/* get_next_op can realloc, we need to move last_op */
989 						last_op = &CG(active_op_array)->opcodes[opline_no];
990 					}
991 					last_op->opcode = ZEND_ASSIGN_OBJ;
992 					zend_do_op_data(opline, value TSRMLS_CC);
993 					SET_UNUSED(opline->result);
994 					GET_NODE(result, last_op->result);
995 					return;
996 				} else if (last_op->opcode == ZEND_FETCH_DIM_W) {
997 					if (n > 0) {
998 						int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
999 						*opline = *last_op;
1000 						MAKE_NOP(last_op);
1001 						/* last_op = opline; */
1002 						/* TBFixed: this can realloc opcodes, leaving last_op pointing wrong */
1003 						opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1004 						/* get_next_op can realloc, we need to move last_op */
1005 						last_op = &CG(active_op_array)->opcodes[opline_no];
1006 					}
1007 					last_op->opcode = ZEND_ASSIGN_DIM;
1008 					zend_do_op_data(opline, value TSRMLS_CC);
1009 					opline->op2.var = get_temporary_variable(CG(active_op_array));
1010 					opline->op2_type = IS_VAR;
1011 					SET_UNUSED(opline->result);
1012 					GET_NODE(result, last_op->result);
1013 					return;
1014 				} else if (opline_is_fetch_this(last_op TSRMLS_CC)) {
1015 					zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
1016 				} else {
1017 					break;
1018 				}
1019 			}
1020 			n++;
1021 		}
1022 	}
1023 
1024 	opline->opcode = ZEND_ASSIGN;
1025 	SET_NODE(opline->op1, variable);
1026 	SET_NODE(opline->op2, value);
1027 	opline->result_type = IS_VAR;
1028 	opline->result.var = get_temporary_variable(CG(active_op_array));
1029 	GET_NODE(result, opline->result);
1030 }
1031 /* }}} */
1032 
zend_do_assign_ref(znode * result,const znode * lvar,const znode * rvar TSRMLS_DC)1033 void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRMLS_DC) /* {{{ */
1034 {
1035 	zend_op *opline;
1036 
1037 	if (lvar->op_type == IS_CV) {
1038 		if (lvar->u.op.var == CG(active_op_array)->this_var) {
1039  			zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
1040 		}
1041 	} else if (lvar->op_type == IS_VAR) {
1042 		int last_op_number = get_next_op_number(CG(active_op_array));
1043 
1044 		if (last_op_number > 0) {
1045 			opline = &CG(active_op_array)->opcodes[last_op_number-1];
1046 			if (opline_is_fetch_this(opline TSRMLS_CC)) {
1047 	 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
1048 			}
1049  		}
1050  	}
1051 
1052 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1053 	opline->opcode = ZEND_ASSIGN_REF;
1054 	if (zend_is_function_or_method_call(rvar)) {
1055 		opline->extended_value = ZEND_RETURNS_FUNCTION;
1056 	} else if (rvar->EA & ZEND_PARSED_NEW) {
1057 		opline->extended_value = ZEND_RETURNS_NEW;
1058 	} else {
1059 		opline->extended_value = 0;
1060 	}
1061 	if (result) {
1062 		opline->result_type = IS_VAR;
1063 		opline->result.var = get_temporary_variable(CG(active_op_array));
1064 		GET_NODE(result, opline->result);
1065 	} else {
1066 		opline->result_type = IS_UNUSED | EXT_TYPE_UNUSED;
1067 	}
1068 	SET_NODE(opline->op1, lvar);
1069 	SET_NODE(opline->op2, rvar);
1070 }
1071 /* }}} */
1072 
do_begin_loop(TSRMLS_D)1073 static inline void do_begin_loop(TSRMLS_D) /* {{{ */
1074 {
1075 	zend_brk_cont_element *brk_cont_element;
1076 	int parent;
1077 
1078 	parent = CG(context).current_brk_cont;
1079 	CG(context).current_brk_cont = CG(active_op_array)->last_brk_cont;
1080 	brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
1081 	brk_cont_element->start = get_next_op_number(CG(active_op_array));
1082 	brk_cont_element->parent = parent;
1083 }
1084 /* }}} */
1085 
do_end_loop(int cont_addr,int has_loop_var TSRMLS_DC)1086 static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{ */
1087 {
1088 	if (!has_loop_var) {
1089 		/* The start fileld is used to free temporary variables in case of exceptions.
1090 		 * We won't try to free something of we don't have loop variable.
1091 		 */
1092 		CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].start = -1;
1093 	}
1094 	CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = cont_addr;
1095 	CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
1096 	CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
1097 }
1098 /* }}} */
1099 
zend_do_while_cond(const znode * expr,znode * close_bracket_token TSRMLS_DC)1100 void zend_do_while_cond(const znode *expr, znode *close_bracket_token TSRMLS_DC) /* {{{ */
1101 {
1102 	int while_cond_op_number = get_next_op_number(CG(active_op_array));
1103 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1104 
1105 	opline->opcode = ZEND_JMPZ;
1106 	SET_NODE(opline->op1, expr);
1107 	close_bracket_token->u.op.opline_num = while_cond_op_number;
1108 	SET_UNUSED(opline->op2);
1109 
1110 	do_begin_loop(TSRMLS_C);
1111 	INC_BPC(CG(active_op_array));
1112 }
1113 /* }}} */
1114 
zend_do_while_end(const znode * while_token,const znode * close_bracket_token TSRMLS_DC)1115 void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC) /* {{{ */
1116 {
1117 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1118 
1119 	/* add unconditional jump */
1120 	opline->opcode = ZEND_JMP;
1121 	opline->op1.opline_num = while_token->u.op.opline_num;
1122 	SET_UNUSED(opline->op1);
1123 	SET_UNUSED(opline->op2);
1124 
1125 	/* update while's conditional jmp */
1126 	CG(active_op_array)->opcodes[close_bracket_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
1127 
1128 	do_end_loop(while_token->u.op.opline_num, 0 TSRMLS_CC);
1129 
1130 	DEC_BPC(CG(active_op_array));
1131 }
1132 /* }}} */
1133 
zend_do_for_cond(const znode * expr,znode * second_semicolon_token TSRMLS_DC)1134 void zend_do_for_cond(const znode *expr, znode *second_semicolon_token TSRMLS_DC) /* {{{ */
1135 {
1136 	int for_cond_op_number = get_next_op_number(CG(active_op_array));
1137 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1138 
1139 	opline->opcode = ZEND_JMPZNZ;
1140 	SET_NODE(opline->op1, expr);  /* the conditional expression */
1141 	second_semicolon_token->u.op.opline_num = for_cond_op_number;
1142 	SET_UNUSED(opline->op2);
1143 }
1144 /* }}} */
1145 
zend_do_for_before_statement(const znode * cond_start,const znode * second_semicolon_token TSRMLS_DC)1146 void zend_do_for_before_statement(const znode *cond_start, const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
1147 {
1148 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1149 
1150 	opline->opcode = ZEND_JMP;
1151 	opline->op1.opline_num = cond_start->u.op.opline_num;
1152 	CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
1153 	SET_UNUSED(opline->op1);
1154 	SET_UNUSED(opline->op2);
1155 
1156 	do_begin_loop(TSRMLS_C);
1157 
1158 	INC_BPC(CG(active_op_array));
1159 }
1160 /* }}} */
1161 
zend_do_for_end(const znode * second_semicolon_token TSRMLS_DC)1162 void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
1163 {
1164 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1165 
1166 	opline->opcode = ZEND_JMP;
1167 	opline->op1.opline_num = second_semicolon_token->u.op.opline_num+1;
1168 	CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
1169 	SET_UNUSED(opline->op1);
1170 	SET_UNUSED(opline->op2);
1171 
1172 	do_end_loop(second_semicolon_token->u.op.opline_num+1, 0 TSRMLS_CC);
1173 
1174 	DEC_BPC(CG(active_op_array));
1175 }
1176 /* }}} */
1177 
zend_do_pre_incdec(znode * result,const znode * op1,zend_uchar op TSRMLS_DC)1178 void zend_do_pre_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
1179 {
1180 	int last_op_number = get_next_op_number(CG(active_op_array));
1181 	zend_op *opline;
1182 
1183 	if (last_op_number > 0) {
1184 		zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
1185 
1186 		if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
1187 			last_op->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
1188 			last_op->result_type = IS_VAR;
1189 			last_op->result.var = get_temporary_variable(CG(active_op_array));
1190 			GET_NODE(result, last_op->result);
1191 			return;
1192 		}
1193 	}
1194 
1195 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1196 	opline->opcode = op;
1197 	SET_NODE(opline->op1, op1);
1198 	SET_UNUSED(opline->op2);
1199 	opline->result_type = IS_VAR;
1200 	opline->result.var = get_temporary_variable(CG(active_op_array));
1201 	GET_NODE(result, opline->result);
1202 }
1203 /* }}} */
1204 
zend_do_post_incdec(znode * result,const znode * op1,zend_uchar op TSRMLS_DC)1205 void zend_do_post_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
1206 {
1207 	int last_op_number = get_next_op_number(CG(active_op_array));
1208 	zend_op *opline;
1209 
1210 	if (last_op_number > 0) {
1211 		zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
1212 
1213 		if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
1214 			last_op->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
1215 			last_op->result_type = IS_TMP_VAR;
1216 			last_op->result.var = get_temporary_variable(CG(active_op_array));
1217 			GET_NODE(result, last_op->result);
1218 			return;
1219 		}
1220 	}
1221 
1222 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1223 	opline->opcode = op;
1224 	SET_NODE(opline->op1, op1);
1225 	SET_UNUSED(opline->op2);
1226 	opline->result_type = IS_TMP_VAR;
1227 	opline->result.var = get_temporary_variable(CG(active_op_array));
1228 	GET_NODE(result, opline->result);
1229 }
1230 /* }}} */
1231 
zend_do_if_cond(const znode * cond,znode * closing_bracket_token TSRMLS_DC)1232 void zend_do_if_cond(const znode *cond, znode *closing_bracket_token TSRMLS_DC) /* {{{ */
1233 {
1234 	int if_cond_op_number = get_next_op_number(CG(active_op_array));
1235 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1236 
1237 	opline->opcode = ZEND_JMPZ;
1238 	SET_NODE(opline->op1, cond);
1239 	closing_bracket_token->u.op.opline_num = if_cond_op_number;
1240 	SET_UNUSED(opline->op2);
1241 	INC_BPC(CG(active_op_array));
1242 }
1243 /* }}} */
1244 
zend_do_if_after_statement(const znode * closing_bracket_token,unsigned char initialize TSRMLS_DC)1245 void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned char initialize TSRMLS_DC) /* {{{ */
1246 {
1247 	int if_end_op_number = get_next_op_number(CG(active_op_array));
1248 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1249 	zend_llist *jmp_list_ptr;
1250 
1251 	opline->opcode = ZEND_JMP;
1252 	/* save for backpatching */
1253 	if (initialize) {
1254 		zend_llist jmp_list;
1255 
1256 		zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
1257 		zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
1258 	}
1259 	zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
1260 	zend_llist_add_element(jmp_list_ptr, &if_end_op_number);
1261 
1262 	CG(active_op_array)->opcodes[closing_bracket_token->u.op.opline_num].op2.opline_num = if_end_op_number+1;
1263 	SET_UNUSED(opline->op1);
1264 	SET_UNUSED(opline->op2);
1265 }
1266 /* }}} */
1267 
zend_do_if_end(TSRMLS_D)1268 void zend_do_if_end(TSRMLS_D) /* {{{ */
1269 {
1270 	int next_op_number = get_next_op_number(CG(active_op_array));
1271 	zend_llist *jmp_list_ptr;
1272 	zend_llist_element *le;
1273 
1274 	zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
1275 	for (le=jmp_list_ptr->head; le; le = le->next) {
1276 		CG(active_op_array)->opcodes[*((int *) le->data)].op1.opline_num = next_op_number;
1277 	}
1278 	zend_llist_destroy(jmp_list_ptr);
1279 	zend_stack_del_top(&CG(bp_stack));
1280 	DEC_BPC(CG(active_op_array));
1281 }
1282 /* }}} */
1283 
zend_check_writable_variable(const znode * variable)1284 void zend_check_writable_variable(const znode *variable) /* {{{ */
1285 {
1286 	zend_uint type = variable->EA;
1287 
1288 	if (type & ZEND_PARSED_METHOD_CALL) {
1289 		zend_error_noreturn(E_COMPILE_ERROR, "Can't use method return value in write context");
1290 	}
1291 	if (type == ZEND_PARSED_FUNCTION_CALL) {
1292 		zend_error_noreturn(E_COMPILE_ERROR, "Can't use function return value in write context");
1293 	}
1294 }
1295 /* }}} */
1296 
zend_do_begin_variable_parse(TSRMLS_D)1297 void zend_do_begin_variable_parse(TSRMLS_D) /* {{{ */
1298 {
1299 	zend_llist fetch_list;
1300 
1301 	zend_llist_init(&fetch_list, sizeof(zend_op), NULL, 0);
1302 	zend_stack_push(&CG(bp_stack), (void *) &fetch_list, sizeof(zend_llist));
1303 }
1304 /* }}} */
1305 
zend_do_end_variable_parse(znode * variable,int type,int arg_offset TSRMLS_DC)1306 void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC) /* {{{ */
1307 {
1308 	zend_llist *fetch_list_ptr;
1309 	zend_llist_element *le;
1310 	zend_op *opline = NULL;
1311 	zend_op *opline_ptr;
1312 	zend_uint this_var = -1;
1313 
1314 	zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
1315 
1316 	le = fetch_list_ptr->head;
1317 
1318 	/* TODO: $foo->x->y->z = 1 should fetch "x" and "y" for R or RW, not just W */
1319 
1320 	if (le) {
1321 		opline_ptr = (zend_op *)le->data;
1322 		if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
1323 			/* convert to FETCH_?(this) into IS_CV */
1324 			if (CG(active_op_array)->last == 0 ||
1325 			    CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
1326 
1327 				this_var = opline_ptr->result.var;
1328 				if (CG(active_op_array)->this_var == -1) {
1329 					CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(CONSTANT(opline_ptr->op1.constant)), Z_STRLEN(CONSTANT(opline_ptr->op1.constant)), Z_HASH_P(&CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC);
1330 					Z_TYPE(CONSTANT(opline_ptr->op1.constant)) = IS_NULL;
1331 				} else {
1332 					zend_del_literal(CG(active_op_array), opline_ptr->op1.constant);
1333 				}
1334 				le = le->next;
1335 				if (variable->op_type == IS_VAR &&
1336 				    variable->u.op.var == this_var) {
1337 					variable->op_type = IS_CV;
1338 					variable->u.op.var = CG(active_op_array)->this_var;
1339 				}
1340 			} else if (CG(active_op_array)->this_var == -1) {
1341 				CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1, THIS_HASHVAL TSRMLS_CC);
1342 			}
1343 		}
1344 
1345 		while (le) {
1346 			opline_ptr = (zend_op *)le->data;
1347 			if (opline_ptr->opcode == ZEND_SEPARATE) {
1348 				if (type != BP_VAR_R && type != BP_VAR_IS) {
1349 					opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1350 					memcpy(opline, opline_ptr, sizeof(zend_op));
1351 				}
1352 				le = le->next;
1353 				continue;
1354 			}
1355 			opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1356 			memcpy(opline, opline_ptr, sizeof(zend_op));
1357 			if (opline->op1_type == IS_VAR &&
1358 			    opline->op1.var == this_var) {
1359 				opline->op1_type = IS_CV;
1360 				opline->op1.var = CG(active_op_array)->this_var;
1361 			}
1362 			switch (type) {
1363 				case BP_VAR_R:
1364 					if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
1365 						zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
1366 					}
1367 					opline->opcode -= 3;
1368 					break;
1369 				case BP_VAR_W:
1370 					break;
1371 				case BP_VAR_RW:
1372 					opline->opcode += 3;
1373 					break;
1374 				case BP_VAR_IS:
1375 					if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
1376 						zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
1377 					}
1378 					opline->opcode += 6; /* 3+3 */
1379 					break;
1380 				case BP_VAR_FUNC_ARG:
1381 					opline->opcode += 9; /* 3+3+3 */
1382 					opline->extended_value |= arg_offset;
1383 					break;
1384 				case BP_VAR_UNSET:
1385 					if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
1386 						zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
1387 					}
1388 					opline->opcode += 12; /* 3+3+3+3 */
1389 					break;
1390 			}
1391 			le = le->next;
1392 		}
1393 		if (opline && type == BP_VAR_W && arg_offset) {
1394 			opline->extended_value |= ZEND_FETCH_MAKE_REF;
1395 		}
1396 	}
1397 	zend_llist_destroy(fetch_list_ptr);
1398 	zend_stack_del_top(&CG(bp_stack));
1399 }
1400 /* }}} */
1401 
zend_do_add_string(znode * result,const znode * op1,znode * op2 TSRMLS_DC)1402 void zend_do_add_string(znode *result, const znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
1403 {
1404 	zend_op *opline;
1405 
1406 	if (Z_STRLEN(op2->u.constant) > 1) {
1407 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1408 		opline->opcode = ZEND_ADD_STRING;
1409 	} else if (Z_STRLEN(op2->u.constant) == 1) {
1410 		int ch = *Z_STRVAL(op2->u.constant);
1411 
1412 		/* Free memory and use ZEND_ADD_CHAR in case of 1 character strings */
1413 		efree(Z_STRVAL(op2->u.constant));
1414 		ZVAL_LONG(&op2->u.constant, ch);
1415 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1416 		opline->opcode = ZEND_ADD_CHAR;
1417 	} else { /* String can be empty after a variable at the end of a heredoc */
1418 		efree(Z_STRVAL(op2->u.constant));
1419 		return;
1420 	}
1421 
1422 	if (op1) {
1423 		SET_NODE(opline->op1, op1);
1424 		SET_NODE(opline->result, op1);
1425 	} else {
1426 		SET_UNUSED(opline->op1);
1427 		opline->result_type = IS_TMP_VAR;
1428 		opline->result.var = get_temporary_variable(CG(active_op_array));
1429 	}
1430 	SET_NODE(opline->op2, op2);
1431 	GET_NODE(result, opline->result);
1432 }
1433 /* }}} */
1434 
zend_do_add_variable(znode * result,const znode * op1,const znode * op2 TSRMLS_DC)1435 void zend_do_add_variable(znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
1436 {
1437 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1438 
1439 	opline->opcode = ZEND_ADD_VAR;
1440 
1441 	if (op1) {
1442 		SET_NODE(opline->op1, op1);
1443 		SET_NODE(opline->result, op1);
1444 	} else {
1445 		SET_UNUSED(opline->op1);
1446 		opline->result_type = IS_TMP_VAR;
1447 		opline->result.var = get_temporary_variable(CG(active_op_array));
1448 	}
1449 	SET_NODE(opline->op2, op2);
1450 	GET_NODE(result, opline->result);
1451 }
1452 /* }}} */
1453 
zend_do_free(znode * op1 TSRMLS_DC)1454 void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
1455 {
1456 	if (op1->op_type==IS_TMP_VAR) {
1457 		zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1458 
1459 		opline->opcode = ZEND_FREE;
1460 		SET_NODE(opline->op1, op1);
1461 		SET_UNUSED(opline->op2);
1462 	} else if (op1->op_type==IS_VAR) {
1463 		zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
1464 
1465 		while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END || opline->opcode == ZEND_OP_DATA) {
1466 			opline--;
1467 		}
1468 		if (opline->result_type == IS_VAR
1469 			&& opline->result.var == op1->u.op.var) {
1470 			if (opline->opcode == ZEND_FETCH_R ||
1471 			    opline->opcode == ZEND_FETCH_DIM_R ||
1472 			    opline->opcode == ZEND_FETCH_OBJ_R ||
1473 			    opline->opcode == ZEND_QM_ASSIGN_VAR) {
1474 				/* It's very rare and useless case. It's better to use
1475 				   additional FREE opcode and simplify the FETCH handlers
1476 				   their selves */
1477 				opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1478 				opline->opcode = ZEND_FREE;
1479 				SET_NODE(opline->op1, op1);
1480 				SET_UNUSED(opline->op2);
1481 			} else {
1482 				opline->result_type |= EXT_TYPE_UNUSED;
1483 			}
1484 		} else {
1485 			while (opline>CG(active_op_array)->opcodes) {
1486 				if (opline->opcode == ZEND_FETCH_DIM_R
1487 				    && opline->op1_type == IS_VAR
1488 				    && opline->op1.var == op1->u.op.var) {
1489 					/* This should the end of a list() construct
1490 					 * Mark its result as unused
1491 					 */
1492 					opline->extended_value = ZEND_FETCH_STANDARD;
1493 					break;
1494 				} else if (opline->result_type==IS_VAR
1495 					&& opline->result.var == op1->u.op.var) {
1496 					if (opline->opcode == ZEND_NEW) {
1497 						opline->result_type |= EXT_TYPE_UNUSED;
1498 					}
1499 					break;
1500 				}
1501 				opline--;
1502 			}
1503 		}
1504 	} else if (op1->op_type == IS_CONST) {
1505 		zval_dtor(&op1->u.constant);
1506 	}
1507 }
1508 /* }}} */
1509 
zend_do_verify_access_types(const znode * current_access_type,const znode * new_modifier)1510 int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier) /* {{{ */
1511 {
1512 	if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_PPP_MASK)
1513 		&& (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_PPP_MASK)) {
1514 		zend_error_noreturn(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
1515 	}
1516 	if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_ABSTRACT)
1517 		&& (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_ABSTRACT)) {
1518 		zend_error_noreturn(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
1519 	}
1520 	if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_STATIC)
1521 		&& (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_STATIC)) {
1522 		zend_error_noreturn(E_COMPILE_ERROR, "Multiple static modifiers are not allowed");
1523 	}
1524 	if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_FINAL)
1525 		&& (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_FINAL)) {
1526 		zend_error_noreturn(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
1527 	}
1528 	if (((Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant)) & (ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL)) == (ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL)) {
1529 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class member");
1530 	}
1531 	return (Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant));
1532 }
1533 /* }}} */
1534 
zend_do_begin_function_declaration(znode * function_token,znode * function_name,int is_method,int return_reference,znode * fn_flags_znode TSRMLS_DC)1535 void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC) /* {{{ */
1536 {
1537 	zend_op_array op_array;
1538 	char *name = Z_STRVAL(function_name->u.constant);
1539 	int name_len = Z_STRLEN(function_name->u.constant);
1540 	int function_begin_line = function_token->u.op.opline_num;
1541 	zend_uint fn_flags;
1542 	const char *lcname;
1543 	zend_bool orig_interactive;
1544 	ALLOCA_FLAG(use_heap)
1545 
1546 	if (is_method) {
1547 		if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
1548 			if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
1549 				zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method %s::%s() must be omitted", CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
1550 			}
1551 			Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
1552 		}
1553 		fn_flags = Z_LVAL(fn_flags_znode->u.constant); /* must be done *after* the above check */
1554 	} else {
1555 		fn_flags = 0;
1556 	}
1557 	if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
1558 		zend_error(E_STRICT, "Static function %s%s%s() should not be abstract", is_method ? CG(active_class_entry)->name : "", is_method ? "::" : "", Z_STRVAL(function_name->u.constant));
1559 	}
1560 
1561 	function_token->u.op_array = CG(active_op_array);
1562 
1563 	orig_interactive = CG(interactive);
1564 	CG(interactive) = 0;
1565 	init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
1566 	CG(interactive) = orig_interactive;
1567 
1568 	op_array.function_name = name;
1569 	if (return_reference) {
1570 		op_array.fn_flags |= ZEND_ACC_RETURN_REFERENCE;
1571 	}
1572 	op_array.fn_flags |= fn_flags;
1573 
1574 	op_array.scope = is_method?CG(active_class_entry):NULL;
1575 	op_array.prototype = NULL;
1576 
1577 	op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
1578 
1579 	if (is_method) {
1580 		zend_ulong hash;
1581 
1582 		lcname = zend_new_interned_string(zend_str_tolower_dup(name, name_len), name_len + 1, 1 TSRMLS_CC);
1583 		hash = str_hash(lcname, name_len);
1584 		if (zend_hash_quick_add(&CG(active_class_entry)->function_table, lcname, name_len+1, hash, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
1585 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
1586 		}
1587 
1588 		zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
1589 		zend_init_compiler_context(TSRMLS_C);
1590 
1591 		if (fn_flags & ZEND_ACC_ABSTRACT) {
1592 			CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
1593 		}
1594 
1595 		if (!(fn_flags & ZEND_ACC_PPP_MASK)) {
1596 			fn_flags |= ZEND_ACC_PUBLIC;
1597 		}
1598 
1599 		if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
1600 			if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1601 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1602 					zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
1603 				}
1604 			} else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
1605 				if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
1606 					zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
1607 				}
1608 			} else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
1609 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1610 					zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
1611 				}
1612 			} else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
1613 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1614 					zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
1615 				}
1616 			} else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
1617 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1618 					zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
1619 				}
1620 			} else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
1621 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1622 					zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
1623 				}
1624 			} else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
1625 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1626 					zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
1627 				}
1628 			} else if ((name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1))) {
1629 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1630 					zend_error(E_WARNING, "The magic method __invoke() must have public visibility and cannot be static");
1631 				}
1632 
1633 			} else if ((name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1))) {
1634 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1635 					zend_error(E_WARNING, "The magic method __debugInfo() must have public visibility and cannot be static");
1636 				}
1637 			}
1638 		} else {
1639 			char *class_lcname;
1640 
1641 			class_lcname = do_alloca(CG(active_class_entry)->name_length + 1, use_heap);
1642 			zend_str_tolower_copy(class_lcname, CG(active_class_entry)->name, CG(active_class_entry)->name_length);
1643 			/* Improve after RC: cache the lowercase class name */
1644 
1645 			if ((CG(active_class_entry)->name_length == name_len) && ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT) && (!memcmp(class_lcname, lcname, name_len))) {
1646 				if (!CG(active_class_entry)->constructor) {
1647 					CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
1648 				}
1649 			} else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) {
1650 				if (CG(active_class_entry)->constructor) {
1651 					zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
1652 				}
1653 				CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
1654 			} else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1))) {
1655 				CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
1656 			} else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1))) {
1657 				CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
1658 			} else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1659 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1660 					zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
1661 				}
1662 				CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
1663 			} else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
1664 				if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
1665 					zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
1666 				}
1667 				CG(active_class_entry)->__callstatic = (zend_function *) CG(active_op_array);
1668 			} else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
1669 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1670 					zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
1671 				}
1672 				CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
1673 			} else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
1674 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1675 					zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
1676 				}
1677 				CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
1678 			} else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
1679 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1680 					zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
1681 				}
1682 				CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
1683 			} else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
1684 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1685 					zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
1686 				}
1687 				CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
1688 			} else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
1689 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1690 					zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
1691 				}
1692 				CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array);
1693 			} else if ((name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1))) {
1694 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1695 					zend_error(E_WARNING, "The magic method __invoke() must have public visibility and cannot be static");
1696 				}
1697 			} else if ((name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1))) {
1698 				if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1699 					zend_error(E_WARNING, "The magic method __debugInfo() must have public visibility and cannot be static");
1700 				}
1701 				CG(active_class_entry)->__debugInfo = (zend_function *) CG(active_op_array);
1702 			} else if (!(fn_flags & ZEND_ACC_STATIC)) {
1703 				CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
1704 			}
1705 			free_alloca(class_lcname, use_heap);
1706 		}
1707 
1708 		str_efree(lcname);
1709 	} else {
1710 		zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1711 		zval key;
1712 		zval **ns_name;
1713 
1714 		if (CG(current_namespace)) {
1715 			/* Prefix function name with current namespace name */
1716 			znode tmp;
1717 
1718 			tmp.u.constant = *CG(current_namespace);
1719 			zval_copy_ctor(&tmp.u.constant);
1720 			zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
1721 			op_array.function_name = Z_STRVAL(tmp.u.constant);
1722 			name_len = Z_STRLEN(tmp.u.constant);
1723 			lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
1724 		} else {
1725 			lcname = zend_str_tolower_dup(name, name_len);
1726 		}
1727 
1728 		/* Function name must not conflict with import names */
1729 		if (CG(current_import_function) &&
1730 		    zend_hash_find(CG(current_import_function), lcname, Z_STRLEN(function_name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
1731 
1732 			char *tmp = zend_str_tolower_dup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
1733 
1734 			if (Z_STRLEN_PP(ns_name) != Z_STRLEN(function_name->u.constant) ||
1735 				memcmp(tmp, lcname, Z_STRLEN(function_name->u.constant))) {
1736 				zend_error(E_COMPILE_ERROR, "Cannot declare function %s because the name is already in use", Z_STRVAL(function_name->u.constant));
1737 			}
1738 			efree(tmp);
1739 		}
1740 
1741 		opline->opcode = ZEND_DECLARE_FUNCTION;
1742 		opline->op1_type = IS_CONST;
1743 		build_runtime_defined_function_key(&key, lcname, name_len TSRMLS_CC);
1744 		opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
1745 		Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
1746 		opline->op2_type = IS_CONST;
1747 		LITERAL_STRINGL(opline->op2, lcname, name_len, 1);
1748 		CALCULATE_LITERAL_HASH(opline->op2.constant);
1749 		opline->extended_value = ZEND_DECLARE_FUNCTION;
1750 		zend_hash_quick_update(CG(function_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
1751 		zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
1752 		zend_init_compiler_context(TSRMLS_C);
1753 		str_efree(lcname);
1754 	}
1755 
1756 	if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
1757 		zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1758 
1759 		opline->opcode = ZEND_EXT_NOP;
1760 		opline->lineno = function_begin_line;
1761 		SET_UNUSED(opline->op1);
1762 		SET_UNUSED(opline->op2);
1763 	}
1764 
1765 	{
1766 		/* Push a separator to the switch stack */
1767 		zend_switch_entry switch_entry;
1768 
1769 		switch_entry.cond.op_type = IS_UNUSED;
1770 		switch_entry.default_case = 0;
1771 		switch_entry.control_var = 0;
1772 
1773 		zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
1774 	}
1775 
1776 	{
1777 		/* Push a separator to the foreach stack */
1778 		zend_op dummy_opline;
1779 
1780 		dummy_opline.result_type = IS_UNUSED;
1781 
1782 		zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
1783 	}
1784 
1785 	if (CG(doc_comment)) {
1786 		CG(active_op_array)->doc_comment = CG(doc_comment);
1787 		CG(active_op_array)->doc_comment_len = CG(doc_comment_len);
1788 		CG(doc_comment) = NULL;
1789 		CG(doc_comment_len) = 0;
1790 	}
1791 }
1792 /* }}} */
1793 
zend_do_begin_lambda_function_declaration(znode * result,znode * function_token,int return_reference,int is_static TSRMLS_DC)1794 void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC) /* {{{ */
1795 {
1796 	znode          function_name;
1797 	zend_op_array *current_op_array = CG(active_op_array);
1798 	int            current_op_number = get_next_op_number(CG(active_op_array));
1799 	zend_op       *current_op;
1800 
1801 	function_name.op_type = IS_CONST;
1802 	ZVAL_STRINGL(&function_name.u.constant, "{closure}", sizeof("{closure}")-1, 1);
1803 
1804 	zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC);
1805 
1806 	result->op_type = IS_TMP_VAR;
1807 	result->u.op.var = get_temporary_variable(current_op_array);
1808 
1809 	current_op = &current_op_array->opcodes[current_op_number];
1810 	current_op->opcode = ZEND_DECLARE_LAMBDA_FUNCTION;
1811 	zend_del_literal(current_op_array, current_op->op2.constant);
1812 	SET_UNUSED(current_op->op2);
1813 	SET_NODE(current_op->result, result);
1814 	if (is_static) {
1815 		CG(active_op_array)->fn_flags |= ZEND_ACC_STATIC;
1816 	}
1817 	CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE;
1818 }
1819 /* }}} */
1820 
zend_do_handle_exception(TSRMLS_D)1821 void zend_do_handle_exception(TSRMLS_D) /* {{{ */
1822 {
1823 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1824 
1825 	opline->opcode = ZEND_HANDLE_EXCEPTION;
1826 	SET_UNUSED(opline->op1);
1827 	SET_UNUSED(opline->op2);
1828 }
1829 /* }}} */
1830 
zend_do_end_function_declaration(const znode * function_token TSRMLS_DC)1831 void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC) /* {{{ */
1832 {
1833 	char lcname[16];
1834 	int name_len;
1835 
1836 	zend_do_extended_info(TSRMLS_C);
1837 	zend_do_return(NULL, 0 TSRMLS_CC);
1838 
1839 	pass_two(CG(active_op_array) TSRMLS_CC);
1840 	zend_release_labels(0 TSRMLS_CC);
1841 
1842 	if (CG(active_class_entry)) {
1843 		zend_check_magic_method_implementation(CG(active_class_entry), (zend_function*)CG(active_op_array), E_COMPILE_ERROR TSRMLS_CC);
1844 	} else {
1845 		/* we don't care if the function name is longer, in fact lowercasing only
1846 		 * the beginning of the name speeds up the check process */
1847 		name_len = strlen(CG(active_op_array)->function_name);
1848 		zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1));
1849 		lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
1850 		if (name_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)) && CG(active_op_array)->num_args != 1) {
1851 			zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
1852 		}
1853 	}
1854 
1855 	CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
1856 	CG(active_op_array) = function_token->u.op_array;
1857 
1858 
1859 	/* Pop the switch and foreach separators */
1860 	zend_stack_del_top(&CG(switch_cond_stack));
1861 	zend_stack_del_top(&CG(foreach_copy_stack));
1862 }
1863 /* }}} */
1864 
zend_do_receive_param(zend_uchar op,znode * varname,const znode * initialization,znode * class_type,zend_uchar pass_by_reference,zend_bool is_variadic TSRMLS_DC)1865 void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initialization, znode *class_type, zend_uchar pass_by_reference, zend_bool is_variadic TSRMLS_DC) /* {{{ */
1866 {
1867 	zend_op *opline;
1868 	zend_arg_info *cur_arg_info;
1869 	znode var;
1870 
1871 	if (zend_is_auto_global(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant) TSRMLS_CC)) {
1872 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s", Z_STRVAL(varname->u.constant));
1873 	} else {
1874 		var.op_type = IS_CV;
1875 		var.u.op.var = lookup_cv(CG(active_op_array), Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), 0 TSRMLS_CC);
1876 		Z_STRVAL(varname->u.constant) = (char*)CG(active_op_array)->vars[var.u.op.var].name;
1877 		var.EA = 0;
1878 		if (CG(active_op_array)->vars[var.u.op.var].hash_value == THIS_HASHVAL &&
1879 			Z_STRLEN(varname->u.constant) == sizeof("this")-1 &&
1880 		    !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")-1)) {
1881 			if (CG(active_op_array)->scope &&
1882 			    (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
1883 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
1884 			}
1885 			CG(active_op_array)->this_var = var.u.op.var;
1886 		}
1887 	}
1888 
1889 	if (CG(active_op_array)->fn_flags & ZEND_ACC_VARIADIC) {
1890 		zend_error_noreturn(E_COMPILE_ERROR, "Only the last parameter can be variadic");
1891 	}
1892 
1893 	if (is_variadic) {
1894 		if (op == ZEND_RECV_INIT) {
1895 			zend_error_noreturn(E_COMPILE_ERROR, "Variadic parameter cannot have a default value");
1896 		}
1897 
1898 		op = ZEND_RECV_VARIADIC;
1899 		CG(active_op_array)->fn_flags |= ZEND_ACC_VARIADIC;
1900 	}
1901 
1902 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1903 	CG(active_op_array)->num_args++;
1904 	opline->opcode = op;
1905 	SET_NODE(opline->result, &var);
1906 	opline->op1_type = IS_UNUSED;
1907 	opline->op1.num = CG(active_op_array)->num_args;
1908 	if (op == ZEND_RECV_INIT) {
1909 		SET_NODE(opline->op2, initialization);
1910 	} else {
1911 		SET_UNUSED(opline->op2);
1912 		if (!is_variadic) {
1913 			CG(active_op_array)->required_num_args = CG(active_op_array)->num_args;
1914 		}
1915 	}
1916 	CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
1917 	cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
1918 	cur_arg_info->name = zend_new_interned_string(estrndup(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant)), Z_STRLEN(varname->u.constant) + 1, 1 TSRMLS_CC);
1919 	cur_arg_info->name_len = Z_STRLEN(varname->u.constant);
1920 	cur_arg_info->type_hint = 0;
1921 	cur_arg_info->pass_by_reference = pass_by_reference;
1922 	cur_arg_info->allow_null = 1;
1923 	cur_arg_info->is_variadic = is_variadic;
1924 	cur_arg_info->class_name = NULL;
1925 	cur_arg_info->class_name_len = 0;
1926 
1927 	if (class_type->op_type != IS_UNUSED) {
1928 		cur_arg_info->allow_null = 0;
1929 
1930 		if (class_type->u.constant.type != IS_NULL) {
1931 			if (class_type->u.constant.type == IS_ARRAY) {
1932 				cur_arg_info->type_hint = IS_ARRAY;
1933 				if (op == ZEND_RECV_INIT) {
1934 					if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
1935 						cur_arg_info->allow_null = 1;
1936 					} else if (IS_CONSTANT_TYPE(Z_TYPE(initialization->u.constant))) {
1937 						/* delay constant resolution and check to run-time */
1938 						cur_arg_info->allow_null = 0;
1939 					} else if (Z_TYPE(initialization->u.constant) != IS_ARRAY) {
1940 						zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
1941 					}
1942 				}
1943 			} else if (class_type->u.constant.type == IS_CALLABLE) {
1944 				cur_arg_info->type_hint = IS_CALLABLE;
1945 				if (op == ZEND_RECV_INIT) {
1946 					if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
1947 						cur_arg_info->allow_null = 1;
1948 					} else if (IS_CONSTANT_TYPE(Z_TYPE(initialization->u.constant))) {
1949 						/* delay constant resolution and check to run-time */
1950 						cur_arg_info->allow_null = 0;
1951 					} else {
1952 						zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with callable type hint can only be NULL");
1953 					}
1954 				}
1955 			} else {
1956 				cur_arg_info->type_hint = IS_OBJECT;
1957 				if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
1958 					zend_resolve_class_name(class_type TSRMLS_CC);
1959 				}
1960 				Z_STRVAL(class_type->u.constant) = (char*)zend_new_interned_string(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant) + 1, 1 TSRMLS_CC);
1961 				cur_arg_info->class_name = Z_STRVAL(class_type->u.constant);
1962 				cur_arg_info->class_name_len = Z_STRLEN(class_type->u.constant);
1963 				if (op == ZEND_RECV_INIT) {
1964 					if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
1965 						cur_arg_info->allow_null = 1;
1966 					} else if (IS_CONSTANT_TYPE(Z_TYPE(initialization->u.constant))) {
1967 						/* delay constant resolution and check to run-time */
1968 						cur_arg_info->allow_null = 0;
1969 					} else {
1970 						zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
1971 					}
1972 				}
1973 			}
1974 		}
1975 	}
1976 }
1977 /* }}} */
1978 
zend_do_begin_function_call(znode * function_name,zend_bool check_namespace TSRMLS_DC)1979 int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
1980 {
1981 	zend_function *function;
1982 	char *lcname;
1983 	char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
1984 
1985 	zend_resolve_function_name(function_name, &check_namespace TSRMLS_CC);
1986 
1987 	if (check_namespace && CG(current_namespace) && !is_compound) {
1988 			/* We assume we call function from the current namespace
1989 			if it is not prefixed. */
1990 
1991 			/* In run-time PHP will check for function with full name and
1992 			internal function with short name */
1993 			zend_do_begin_dynamic_function_call(function_name, 1 TSRMLS_CC);
1994 			return 1;
1995 	}
1996 
1997 	lcname = zend_str_tolower_dup(Z_STRVAL(function_name->u.constant), Z_STRLEN(function_name->u.constant));
1998 	if ((zend_hash_find(CG(function_table), lcname, Z_STRLEN(function_name->u.constant)+1, (void **) &function)==FAILURE) ||
1999 	 	((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
2000  		(function->type == ZEND_INTERNAL_FUNCTION))) {
2001  			zend_do_begin_dynamic_function_call(function_name, 0 TSRMLS_CC);
2002  			efree(lcname);
2003  			return 1; /* Dynamic */
2004  	}
2005 	efree(Z_STRVAL(function_name->u.constant));
2006 	Z_STRVAL(function_name->u.constant) = lcname;
2007 
2008 	zend_push_function_call_entry(function TSRMLS_CC);
2009 	if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
2010 		CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
2011 	}
2012 	zend_do_extended_fcall_begin(TSRMLS_C);
2013 	return 0;
2014 }
2015 /* }}} */
2016 
zend_do_begin_method_call(znode * left_bracket TSRMLS_DC)2017 void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
2018 {
2019 	zend_op *last_op;
2020 	int last_op_number;
2021 
2022 	zend_do_end_variable_parse(left_bracket, BP_VAR_R, 0 TSRMLS_CC);
2023 	zend_do_begin_variable_parse(TSRMLS_C);
2024 
2025 	last_op_number = get_next_op_number(CG(active_op_array))-1;
2026 	last_op = &CG(active_op_array)->opcodes[last_op_number];
2027 
2028 	if ((last_op->op2_type == IS_CONST) && (Z_TYPE(CONSTANT(last_op->op2.constant)) == IS_STRING) && (Z_STRLEN(CONSTANT(last_op->op2.constant)) == sizeof(ZEND_CLONE_FUNC_NAME)-1)
2029 		&& !zend_binary_strcasecmp(Z_STRVAL(CONSTANT(last_op->op2.constant)), Z_STRLEN(CONSTANT(last_op->op2.constant)), ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1)) {
2030 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot call __clone() method on objects - use 'clone $obj' instead");
2031 	}
2032 
2033 	if (last_op->opcode == ZEND_FETCH_OBJ_R) {
2034 		if (last_op->op2_type == IS_CONST) {
2035 			zval name;
2036 			name = CONSTANT(last_op->op2.constant);
2037 			if (Z_TYPE(name) != IS_STRING) {
2038 				zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
2039 			}
2040 			Z_STRVAL(name) = str_estrndup(Z_STRVAL(name), Z_STRLEN(name));
2041 			FREE_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
2042 			last_op->op2.constant =
2043 				zend_add_func_name_literal(CG(active_op_array), &name TSRMLS_CC);
2044 			GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
2045 		}
2046 		last_op->opcode = ZEND_INIT_METHOD_CALL;
2047 		last_op->result_type = IS_UNUSED;
2048 		last_op->result.num = CG(context).nested_calls;
2049 		Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
2050 	} else {
2051 		zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2052 		opline->opcode = ZEND_INIT_FCALL_BY_NAME;
2053 		opline->result.num = CG(context).nested_calls;
2054 		SET_UNUSED(opline->op1);
2055 		if (left_bracket->op_type == IS_CONST) {
2056 			opline->op2_type = IS_CONST;
2057 			opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &left_bracket->u.constant TSRMLS_CC);
2058 			GET_CACHE_SLOT(opline->op2.constant);
2059 		} else {
2060 			SET_NODE(opline->op2, left_bracket);
2061 		}
2062 	}
2063 
2064 	zend_push_function_call_entry(NULL TSRMLS_CC);
2065 	if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
2066 		CG(active_op_array)->nested_calls = CG(context).nested_calls;
2067 	}
2068 	zend_do_extended_fcall_begin(TSRMLS_C);
2069 }
2070 /* }}} */
2071 
zend_do_clone(znode * result,const znode * expr TSRMLS_DC)2072 void zend_do_clone(znode *result, const znode *expr TSRMLS_DC) /* {{{ */
2073 {
2074 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2075 
2076 	opline->opcode = ZEND_CLONE;
2077 	SET_NODE(opline->op1, expr);
2078 	SET_UNUSED(opline->op2);
2079 	opline->result_type = IS_VAR;
2080 	opline->result.var = get_temporary_variable(CG(active_op_array));
2081 	GET_NODE(result, opline->result);
2082 }
2083 /* }}} */
2084 
zend_do_begin_dynamic_function_call(znode * function_name,int ns_call TSRMLS_DC)2085 void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC) /* {{{ */
2086 {
2087 	zend_op *opline;
2088 
2089 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2090 	if (ns_call) {
2091 		/* In run-time PHP will check for function with full name and
2092 		   internal function with short name */
2093 		opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
2094 		opline->result.num = CG(context).nested_calls;
2095 		SET_UNUSED(opline->op1);
2096 		opline->op2_type = IS_CONST;
2097 		opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
2098 		GET_CACHE_SLOT(opline->op2.constant);
2099 	} else {
2100 		opline->opcode = ZEND_INIT_FCALL_BY_NAME;
2101 		opline->result.num = CG(context).nested_calls;
2102 		SET_UNUSED(opline->op1);
2103 		if (function_name->op_type == IS_CONST) {
2104 			opline->op2_type = IS_CONST;
2105 			opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
2106 			GET_CACHE_SLOT(opline->op2.constant);
2107 		} else {
2108 			SET_NODE(opline->op2, function_name);
2109 		}
2110 	}
2111 
2112 	zend_push_function_call_entry(NULL TSRMLS_CC);
2113 	if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
2114 		CG(active_op_array)->nested_calls = CG(context).nested_calls;
2115 	}
2116 	zend_do_extended_fcall_begin(TSRMLS_C);
2117 }
2118 /* }}} */
2119 
zend_resolve_non_class_name(znode * element_name,zend_bool * check_namespace,zend_bool case_sensitive,HashTable * current_import_sub TSRMLS_DC)2120 void zend_resolve_non_class_name(znode *element_name, zend_bool *check_namespace, zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC) /* {{{ */
2121 {
2122 	znode tmp;
2123 	int len;
2124 	zval **ns;
2125 	char *lookup_name, *compound = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
2126 
2127 	if (Z_STRVAL(element_name->u.constant)[0] == '\\') {
2128 		/* name starts with \ so it is known and unambiguos, nothing to do here but shorten it */
2129 		memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+1, Z_STRLEN(element_name->u.constant));
2130 		--Z_STRLEN(element_name->u.constant);
2131 		return;
2132 	}
2133 
2134 	if(!*check_namespace) {
2135 		return;
2136 	}
2137 
2138 	if (current_import_sub) {
2139 		len = Z_STRLEN(element_name->u.constant)+1;
2140 		if (case_sensitive) {
2141 			lookup_name = estrndup(Z_STRVAL(element_name->u.constant), len);
2142 		} else {
2143 			lookup_name = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
2144 		}
2145 		/* Check if function/const matches imported name */
2146 		if (zend_hash_find(current_import_sub, lookup_name, len, (void**)&ns) == SUCCESS) {
2147 			zval_dtor(&element_name->u.constant);
2148 			element_name->u.constant = **ns;
2149 			zval_copy_ctor(&element_name->u.constant);
2150 			efree(lookup_name);
2151 			*check_namespace = 0;
2152 			return;
2153 		}
2154 		efree(lookup_name);
2155 	}
2156 
2157 	if (compound && CG(current_import)) {
2158 		len = compound - Z_STRVAL(element_name->u.constant);
2159 		/* namespace is always lowercase */
2160 		lookup_name = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
2161 		/* Check if first part of compound name is an import name */
2162 		if (zend_hash_find(CG(current_import), lookup_name, len+1, (void**)&ns) == SUCCESS) {
2163 			/* Substitute import name */
2164 			tmp.op_type = IS_CONST;
2165 			tmp.u.constant = **ns;
2166 			zval_copy_ctor(&tmp.u.constant);
2167 			len += 1;
2168 			Z_STRLEN(element_name->u.constant) -= len;
2169 			memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+len, Z_STRLEN(element_name->u.constant)+1);
2170 			zend_do_build_namespace_name(&tmp, &tmp, element_name TSRMLS_CC);
2171 			*element_name = tmp;
2172 			efree(lookup_name);
2173 			*check_namespace = 0;
2174 			return;
2175 		}
2176 		efree(lookup_name);
2177 	}
2178 
2179 	if (CG(current_namespace)) {
2180 		tmp = *element_name;
2181 		Z_STRLEN(tmp.u.constant) = sizeof("\\")-1 + Z_STRLEN(element_name->u.constant) + Z_STRLEN_P(CG(current_namespace));
2182 		Z_STRVAL(tmp.u.constant) = (char *) emalloc(Z_STRLEN(tmp.u.constant)+1);
2183 		memcpy(Z_STRVAL(tmp.u.constant), Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
2184 		memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN_P(CG(current_namespace))]), "\\", sizeof("\\")-1);
2185 		memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN_P(CG(current_namespace)) + sizeof("\\")-1]), Z_STRVAL(element_name->u.constant), Z_STRLEN(element_name->u.constant)+1);
2186 		str_efree(Z_STRVAL(element_name->u.constant));
2187 		*element_name = tmp;
2188 	}
2189 }
2190 /* }}} */
2191 
zend_resolve_function_name(znode * element_name,zend_bool * check_namespace TSRMLS_DC)2192 void zend_resolve_function_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC) /* {{{ */
2193 {
2194 	zend_resolve_non_class_name(element_name, check_namespace, 0, CG(current_import_function) TSRMLS_CC);
2195 }
2196 /* }}} */
2197 
zend_resolve_const_name(znode * element_name,zend_bool * check_namespace TSRMLS_DC)2198 void zend_resolve_const_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC) /* {{{ */
2199 {
2200 	zend_resolve_non_class_name(element_name, check_namespace, 1, CG(current_import_const) TSRMLS_CC);
2201 }
2202 /* }}} */
2203 
zend_do_resolve_class_name(znode * result,znode * class_name,int is_static TSRMLS_DC)2204 void zend_do_resolve_class_name(znode *result, znode *class_name, int is_static TSRMLS_DC) /* {{{ */
2205 {
2206 	char *lcname;
2207 	int lctype;
2208 	znode constant_name;
2209 
2210 	lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
2211 	lctype = zend_get_class_fetch_type(lcname, strlen(lcname));
2212 	switch (lctype) {
2213 		case ZEND_FETCH_CLASS_SELF:
2214 			if (!CG(active_class_entry)) {
2215 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot access self::class when no class scope is active");
2216 			}
2217 			if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
2218 				zval_dtor(&class_name->u.constant);
2219 				constant_name.op_type = IS_CONST;
2220 				ZVAL_STRINGL(&constant_name.u.constant, "__CLASS__", sizeof("__CLASS__")-1, 1);
2221 				if (is_static) {
2222 					*result = constant_name;
2223 					result->u.constant.type = IS_CONSTANT;
2224 				} else {
2225 					zend_do_fetch_constant(result, NULL, &constant_name, ZEND_RT, 1 TSRMLS_CC);
2226 				}
2227 				break;
2228 			}
2229 			zval_dtor(&class_name->u.constant);
2230 			class_name->op_type = IS_CONST;
2231 			ZVAL_STRINGL(&class_name->u.constant, CG(active_class_entry)->name, CG(active_class_entry)->name_length, 1);
2232 			*result = *class_name;
2233 			break;
2234         case ZEND_FETCH_CLASS_STATIC:
2235         case ZEND_FETCH_CLASS_PARENT:
2236 			if (is_static) {
2237 				zend_error_noreturn(E_COMPILE_ERROR,
2238 					"%s::class cannot be used for compile-time class name resolution",
2239 					lctype == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
2240 					);
2241 			}
2242 			if (!CG(active_class_entry)) {
2243 				zend_error_noreturn(E_COMPILE_ERROR,
2244 					"Cannot access %s::class when no class scope is active",
2245 					lctype == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
2246 					);
2247 			}
2248 			constant_name.op_type = IS_CONST;
2249 			ZVAL_STRINGL(&constant_name.u.constant, "class", sizeof("class")-1, 1);
2250 			zend_do_fetch_constant(result, class_name, &constant_name, ZEND_RT, 1 TSRMLS_CC);
2251 			break;
2252 		case ZEND_FETCH_CLASS_DEFAULT:
2253 			zend_resolve_class_name(class_name TSRMLS_CC);
2254 			*result = *class_name;
2255 			break;
2256 	}
2257 
2258 	efree(lcname);
2259 
2260 }
2261 /* }}} */
2262 
zend_resolve_class_name(znode * class_name TSRMLS_DC)2263 void zend_resolve_class_name(znode *class_name TSRMLS_DC) /* {{{ */
2264 {
2265 	char *compound;
2266 	char *lcname;
2267 	zval **ns;
2268 	znode tmp;
2269 	int len;
2270 
2271 	compound = memchr(Z_STRVAL(class_name->u.constant), '\\', Z_STRLEN(class_name->u.constant));
2272 	if (compound) {
2273 		/* This is a compound class name that contains namespace prefix */
2274 		if (Z_STRVAL(class_name->u.constant)[0] == '\\') {
2275 			/* The STRING name has "\" prefix */
2276 			Z_STRLEN(class_name->u.constant) -= 1;
2277 			memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+1, Z_STRLEN(class_name->u.constant)+1);
2278 			Z_STRVAL(class_name->u.constant) = erealloc(
2279 			Z_STRVAL(class_name->u.constant),
2280 			Z_STRLEN(class_name->u.constant) + 1);
2281 
2282 			if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
2283 				zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", Z_STRVAL(class_name->u.constant));
2284 			}
2285 		} else {
2286 			if (CG(current_import)) {
2287 				len = compound - Z_STRVAL(class_name->u.constant);
2288 				lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), len);
2289 				/* Check if first part of compound name is an import name */
2290 				if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
2291 					/* Substitute import name */
2292 					tmp.op_type = IS_CONST;
2293 					tmp.u.constant = **ns;
2294 					zval_copy_ctor(&tmp.u.constant);
2295 					len += 1;
2296 					Z_STRLEN(class_name->u.constant) -= len;
2297 					memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+len, Z_STRLEN(class_name->u.constant)+1);
2298 					zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
2299 					*class_name = tmp;
2300 					efree(lcname);
2301 					return;
2302 				}
2303 				efree(lcname);
2304 			}
2305 			/* Here name is not prefixed with \ and not imported */
2306 			if (CG(current_namespace)) {
2307 				tmp.op_type = IS_CONST;
2308 				tmp.u.constant = *CG(current_namespace);
2309 				zval_copy_ctor(&tmp.u.constant);
2310 				zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
2311 				*class_name = tmp;
2312 			}
2313 		}
2314 	} else if (CG(current_import) || CG(current_namespace)) {
2315 		/* this is a plain name (without \) */
2316 		lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
2317 
2318 		if (CG(current_import) &&
2319 		    zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns) == SUCCESS) {
2320 		    /* The given name is an import name. Substitute it. */
2321 			zval_dtor(&class_name->u.constant);
2322 			class_name->u.constant = **ns;
2323 			zval_copy_ctor(&class_name->u.constant);
2324 		} else if (CG(current_namespace)) {
2325 			/* plain name, no import - prepend current namespace to it */
2326 			tmp.op_type = IS_CONST;
2327 			tmp.u.constant = *CG(current_namespace);
2328 			zval_copy_ctor(&tmp.u.constant);
2329 			zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
2330 			*class_name = tmp;
2331 		}
2332 		efree(lcname);
2333 	}
2334 }
2335 /* }}} */
2336 
zend_do_fetch_class(znode * result,znode * class_name TSRMLS_DC)2337 void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
2338 {
2339 	long fetch_class_op_number;
2340 	zend_op *opline;
2341 
2342 	fetch_class_op_number = get_next_op_number(CG(active_op_array));
2343 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2344 
2345 	opline->opcode = ZEND_FETCH_CLASS;
2346 	SET_UNUSED(opline->op1);
2347 	opline->extended_value = ZEND_FETCH_CLASS_DEFAULT;
2348 	CG(catch_begin) = fetch_class_op_number;
2349 	if (class_name->op_type == IS_CONST) {
2350 		int fetch_type;
2351 
2352 		fetch_type = zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
2353 		switch (fetch_type) {
2354 			case ZEND_FETCH_CLASS_SELF:
2355 			case ZEND_FETCH_CLASS_PARENT:
2356 			case ZEND_FETCH_CLASS_STATIC:
2357 				SET_UNUSED(opline->op2);
2358 				opline->extended_value = fetch_type;
2359 				zval_dtor(&class_name->u.constant);
2360 				break;
2361 			default:
2362 				zend_resolve_class_name(class_name TSRMLS_CC);
2363 				opline->op2_type = IS_CONST;
2364 				opline->op2.constant =
2365 					zend_add_class_name_literal(CG(active_op_array), &class_name->u.constant TSRMLS_CC);
2366 				break;
2367 		}
2368 	} else {
2369 		SET_NODE(opline->op2, class_name);
2370 	}
2371 	opline->result.var = get_temporary_variable(CG(active_op_array));
2372 	opline->result_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
2373 	GET_NODE(result, opline->result);
2374 	result->EA = opline->extended_value;
2375 }
2376 /* }}} */
2377 
zend_do_label(znode * label TSRMLS_DC)2378 void zend_do_label(znode *label TSRMLS_DC) /* {{{ */
2379 {
2380 	zend_label dest;
2381 
2382 	if (!CG(context).labels) {
2383 		ALLOC_HASHTABLE(CG(context).labels);
2384 		zend_hash_init(CG(context).labels, 4, NULL, NULL, 0);
2385 	}
2386 
2387 	dest.brk_cont = CG(context).current_brk_cont;
2388 	dest.opline_num = get_next_op_number(CG(active_op_array));
2389 
2390 	if (zend_hash_add(CG(context).labels, Z_STRVAL(label->u.constant), Z_STRLEN(label->u.constant) + 1, (void**)&dest, sizeof(zend_label), NULL) == FAILURE) {
2391 		zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", Z_STRVAL(label->u.constant));
2392 	}
2393 
2394 	/* Done with label now */
2395 	zval_dtor(&label->u.constant);
2396 }
2397 /* }}} */
2398 
zend_resolve_goto_label(zend_op_array * op_array,zend_op * opline,int pass2 TSRMLS_DC)2399 void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC) /* {{{ */
2400 {
2401 	zend_label *dest;
2402 	long current, distance;
2403 	zval *label;
2404 
2405 	if (pass2) {
2406 		label = opline->op2.zv;
2407 	} else {
2408 		label = &CONSTANT_EX(op_array, opline->op2.constant);
2409 	}
2410 	if (CG(context).labels == NULL ||
2411 	    zend_hash_find(CG(context).labels, Z_STRVAL_P(label), Z_STRLEN_P(label)+1, (void**)&dest) == FAILURE) {
2412 
2413 		if (pass2) {
2414 			CG(in_compilation) = 1;
2415 			CG(active_op_array) = op_array;
2416 			CG(zend_lineno) = opline->lineno;
2417 			zend_error_noreturn(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL_P(label));
2418 		} else {
2419 			/* Label is not defined. Delay to pass 2. */
2420 			INC_BPC(op_array);
2421 			return;
2422 		}
2423 	}
2424 
2425 	opline->op1.opline_num = dest->opline_num;
2426 	zval_dtor(label);
2427 	Z_TYPE_P(label) = IS_NULL;
2428 
2429 	/* Check that we are not moving into loop or switch */
2430 	current = opline->extended_value;
2431 	for (distance = 0; current != dest->brk_cont; distance++) {
2432 		if (current == -1) {
2433 			if (pass2) {
2434 				CG(in_compilation) = 1;
2435 				CG(active_op_array) = op_array;
2436 				CG(zend_lineno) = opline->lineno;
2437 			}
2438 			zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
2439 		}
2440 		current = op_array->brk_cont_array[current].parent;
2441 	}
2442 
2443 	if (distance == 0) {
2444 		/* Nothing to break out of, optimize to ZEND_JMP */
2445 		opline->opcode = ZEND_JMP;
2446 		opline->extended_value = 0;
2447 		SET_UNUSED(opline->op2);
2448 	} else {
2449 		/* Set real break distance */
2450 		ZVAL_LONG(label, distance);
2451 	}
2452 
2453 	if (pass2) {
2454 		DEC_BPC(op_array);
2455 	}
2456 }
2457 /* }}} */
2458 
zend_do_goto(const znode * label TSRMLS_DC)2459 void zend_do_goto(const znode *label TSRMLS_DC) /* {{{ */
2460 {
2461 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2462 
2463 	opline->opcode = ZEND_GOTO;
2464 	opline->extended_value = CG(context).current_brk_cont;
2465 	SET_UNUSED(opline->op1);
2466 	SET_NODE(opline->op2, label);
2467 	zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC);
2468 }
2469 /* }}} */
2470 
zend_release_labels(int temporary TSRMLS_DC)2471 void zend_release_labels(int temporary TSRMLS_DC) /* {{{ */
2472 {
2473 	if (CG(context).labels) {
2474 		zend_hash_destroy(CG(context).labels);
2475 		FREE_HASHTABLE(CG(context).labels);
2476 		CG(context).labels = NULL;
2477 	}
2478 	if (!temporary && !zend_stack_is_empty(&CG(context_stack))) {
2479 		zend_compiler_context *ctx;
2480 
2481 		zend_stack_top(&CG(context_stack), (void**)&ctx);
2482 		CG(context) = *ctx;
2483 		zend_stack_del_top(&CG(context_stack));
2484 	}
2485 }
2486 /* }}} */
2487 
zend_do_build_full_name(znode * result,znode * prefix,znode * name,int is_class_member TSRMLS_DC)2488 void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_class_member TSRMLS_DC) /* {{{ */
2489 {
2490 	zend_uint length;
2491 
2492 	if (!result) {
2493 		result = prefix;
2494 	} else {
2495 		*result = *prefix;
2496 	}
2497 
2498 	if (is_class_member) {
2499 		length = sizeof("::")-1 + Z_STRLEN(result->u.constant) + Z_STRLEN(name->u.constant);
2500 		Z_STRVAL(result->u.constant) = str_erealloc(Z_STRVAL(result->u.constant), length+1);
2501 		memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)], "::", sizeof("::")-1);
2502 		memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant) + sizeof("::")-1], Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1);
2503 		str_efree(Z_STRVAL(name->u.constant));
2504 		Z_STRLEN(result->u.constant) = length;
2505 	} else {
2506 		length = sizeof("\\")-1 + Z_STRLEN(result->u.constant) + Z_STRLEN(name->u.constant);
2507 		Z_STRVAL(result->u.constant) = str_erealloc(Z_STRVAL(result->u.constant), length+1);
2508 		memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)], "\\", sizeof("\\")-1);
2509 		memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant) + sizeof("\\")-1], Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1);
2510 		str_efree(Z_STRVAL(name->u.constant));
2511 		Z_STRLEN(result->u.constant) = length;
2512 	}
2513 }
2514 /* }}} */
2515 
zend_do_begin_class_member_function_call(znode * class_name,znode * method_name TSRMLS_DC)2516 int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
2517 {
2518 	znode class_node;
2519 	zend_op *opline;
2520 
2521 	if (method_name->op_type == IS_CONST) {
2522 		char *lcname;
2523 		if (Z_TYPE(method_name->u.constant) != IS_STRING) {
2524 			zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
2525 		}
2526 		lcname = zend_str_tolower_dup(Z_STRVAL(method_name->u.constant), Z_STRLEN(method_name->u.constant));
2527 		if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(method_name->u.constant) &&
2528 		    memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
2529 			zval_dtor(&method_name->u.constant);
2530 			method_name->op_type = IS_UNUSED;
2531 		}
2532 		efree(lcname);
2533 	}
2534 
2535 	if (class_name->op_type == IS_CONST &&
2536 	    ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
2537 		zend_resolve_class_name(class_name TSRMLS_CC);
2538 		class_node = *class_name;
2539 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2540 	} else {
2541 		zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
2542 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2543 		opline->extended_value = class_node.EA	;
2544 	}
2545 	opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
2546 	opline->result.num = CG(context).nested_calls;
2547 	if (class_node.op_type == IS_CONST) {
2548 		opline->op1_type = IS_CONST;
2549 		opline->op1.constant =
2550 			zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
2551 	} else {
2552 		SET_NODE(opline->op1, &class_node);
2553 	}
2554 	if (method_name->op_type == IS_CONST) {
2555 		opline->op2_type = IS_CONST;
2556 		opline->op2.constant =
2557 			zend_add_func_name_literal(CG(active_op_array), &method_name->u.constant TSRMLS_CC);
2558 		if (opline->op1_type == IS_CONST) {
2559 			GET_CACHE_SLOT(opline->op2.constant);
2560 		} else {
2561 			GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
2562 		}
2563 	} else {
2564 		SET_NODE(opline->op2, method_name);
2565 	}
2566 
2567 	zend_push_function_call_entry(NULL TSRMLS_CC);
2568 	if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
2569 		CG(active_op_array)->nested_calls = CG(context).nested_calls;
2570 	}
2571 	zend_do_extended_fcall_begin(TSRMLS_C);
2572 	return 1; /* Dynamic */
2573 }
2574 /* }}} */
2575 
zend_do_end_function_call(znode * function_name,znode * result,int is_method,int is_dynamic_fcall TSRMLS_DC)2576 void zend_do_end_function_call(znode *function_name, znode *result, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */
2577 {
2578 	zend_op *opline;
2579 	zend_function_call_entry *fcall;
2580 	zend_stack_top(&CG(function_call_stack), (void **) &fcall);
2581 
2582 	if (is_method && function_name && function_name->op_type == IS_UNUSED) {
2583 		/* clone */
2584 		if (fcall->arg_num != 0) {
2585 			zend_error(E_WARNING, "Clone method does not require arguments");
2586 		}
2587 		opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
2588 	} else {
2589 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2590 		if (fcall->fbc) {
2591 			opline->opcode = ZEND_DO_FCALL;
2592 			SET_NODE(opline->op1, function_name);
2593 			SET_UNUSED(opline->op2);
2594 			opline->op2.num = CG(context).nested_calls;
2595 			CALCULATE_LITERAL_HASH(opline->op1.constant);
2596 			GET_CACHE_SLOT(opline->op1.constant);
2597 		} else {
2598 			opline->opcode = ZEND_DO_FCALL_BY_NAME;
2599 			SET_UNUSED(opline->op1);
2600 			SET_UNUSED(opline->op2);
2601 			opline->op2.num = --CG(context).nested_calls;
2602 
2603 			/* This would normally be a ZEND_DO_FCALL, but was forced to use
2604 			 * ZEND_DO_FCALL_BY_NAME due to a ... argument. In this case we need to
2605 			 * free the function_name */
2606 			if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
2607 				zval_dtor(&function_name->u.constant);
2608 			}
2609 		}
2610 	}
2611 
2612 	opline->result.var = get_temporary_variable(CG(active_op_array));
2613 	opline->result_type = IS_VAR;
2614 	GET_NODE(result, opline->result);
2615 	opline->extended_value = fcall->arg_num;
2616 
2617 	if (CG(context).used_stack + 1 > CG(active_op_array)->used_stack) {
2618 		CG(active_op_array)->used_stack = CG(context).used_stack + 1;
2619 	}
2620 	CG(context).used_stack -= fcall->arg_num;
2621 	zend_stack_del_top(&CG(function_call_stack));
2622 }
2623 /* }}} */
2624 
zend_do_pass_param(znode * param,zend_uchar op TSRMLS_DC)2625 void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC) /* {{{ */
2626 {
2627 	zend_op *opline;
2628 	int original_op = op;
2629 	zend_function_call_entry *fcall;
2630 	zend_function *function_ptr;
2631 	int send_by_reference = 0;
2632 	int send_function = 0;
2633 
2634 	zend_stack_top(&CG(function_call_stack), (void **) &fcall);
2635 	function_ptr = fcall->fbc;
2636 	fcall->arg_num++;
2637 
2638 	if (fcall->uses_argument_unpacking) {
2639 		zend_error_noreturn(E_COMPILE_ERROR,
2640 			"Cannot use positional argument after argument unpacking");
2641 	}
2642 
2643 	if (original_op == ZEND_SEND_REF) {
2644 		if (function_ptr &&
2645 		    function_ptr->common.function_name &&
2646 		    function_ptr->common.type == ZEND_USER_FUNCTION &&
2647 		    !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
2648 			zend_error_noreturn(E_COMPILE_ERROR,
2649 						"Call-time pass-by-reference has been removed; "
2650 						"If you would like to pass argument by reference, modify the declaration of %s().",
2651 						function_ptr->common.function_name);
2652 		} else {
2653 			zend_error_noreturn(E_COMPILE_ERROR, "Call-time pass-by-reference has been removed");
2654 		}
2655 		return;
2656 	}
2657 
2658 	if (function_ptr) {
2659 		if (ARG_MAY_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
2660 			if (op == ZEND_SEND_VAR && param->op_type & (IS_VAR|IS_CV)) {
2661 				send_by_reference = ZEND_ARG_SEND_BY_REF;
2662 				if (zend_is_function_or_method_call(param)) {
2663 					/* Method call */
2664 					op = ZEND_SEND_VAR_NO_REF;
2665 					send_function = ZEND_ARG_SEND_FUNCTION | ZEND_ARG_SEND_SILENT;
2666 				}
2667 			} else {
2668 				op = ZEND_SEND_VAL;
2669 			}
2670 		} else if (ARG_SHOULD_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
2671 			send_by_reference = ZEND_ARG_SEND_BY_REF;
2672 		}
2673 	}
2674 
2675 	if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
2676 		/* Method call */
2677 		op = ZEND_SEND_VAR_NO_REF;
2678 		send_function = ZEND_ARG_SEND_FUNCTION;
2679 	} else if (op == ZEND_SEND_VAL && (param->op_type & (IS_VAR|IS_CV))) {
2680 		op = ZEND_SEND_VAR_NO_REF;
2681 	}
2682 
2683 	if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference==ZEND_ARG_SEND_BY_REF) {
2684 		/* change to passing by reference */
2685 		switch (param->op_type) {
2686 			case IS_VAR:
2687 			case IS_CV:
2688 				op = ZEND_SEND_REF;
2689 				break;
2690 			default:
2691 				zend_error_noreturn(E_COMPILE_ERROR, "Only variables can be passed by reference");
2692 				break;
2693 		}
2694 	}
2695 
2696 	if (original_op == ZEND_SEND_VAR) {
2697 		switch (op) {
2698 			case ZEND_SEND_VAR_NO_REF:
2699 				zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
2700 				break;
2701 			case ZEND_SEND_VAR:
2702 				if (function_ptr) {
2703 					zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
2704 				} else {
2705 					zend_do_end_variable_parse(param, BP_VAR_FUNC_ARG, fcall->arg_num TSRMLS_CC);
2706 				}
2707 				break;
2708 			case ZEND_SEND_REF:
2709 				zend_do_end_variable_parse(param, BP_VAR_W, 0 TSRMLS_CC);
2710 				break;
2711 		}
2712 	}
2713 
2714 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2715 
2716 	if (op == ZEND_SEND_VAR_NO_REF) {
2717 		if (function_ptr) {
2718 			opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference | send_function;
2719 		} else {
2720 			opline->extended_value = send_function;
2721 		}
2722 	} else {
2723 		if (function_ptr) {
2724 			opline->extended_value = ZEND_DO_FCALL;
2725 		} else {
2726 			opline->extended_value = ZEND_DO_FCALL_BY_NAME;
2727 		}
2728 	}
2729 	opline->opcode = op;
2730 	SET_NODE(opline->op1, param);
2731 	opline->op2.opline_num = fcall->arg_num;
2732 	SET_UNUSED(opline->op2);
2733 
2734 	if (++CG(context).used_stack > CG(active_op_array)->used_stack) {
2735 		CG(active_op_array)->used_stack = CG(context).used_stack;
2736 	}
2737 }
2738 /* }}} */
2739 
zend_do_unpack_params(znode * params TSRMLS_DC)2740 void zend_do_unpack_params(znode *params TSRMLS_DC) /* {{{ */
2741 {
2742 	zend_op *opline;
2743 	zend_function_call_entry *fcall;
2744 
2745 	zend_stack_top(&CG(function_call_stack), (void **) &fcall);
2746 	fcall->uses_argument_unpacking = 1;
2747 
2748 	if (fcall->fbc) {
2749 		/* If argument unpacking is used argument numbers and sending modes can no longer be
2750 		 * computed at compile time, thus we need access to EX(call). In order to have it we
2751 		 * retroactively emit a ZEND_INIT_FCALL_BY_NAME opcode. */
2752 		zval func_name;
2753 		ZVAL_STRING(&func_name, fcall->fbc->common.function_name, 1);
2754 
2755 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2756 		opline->opcode = ZEND_INIT_FCALL_BY_NAME;
2757 		opline->result.num = CG(context).nested_calls;
2758 		SET_UNUSED(opline->op1);
2759 		opline->op2_type = IS_CONST;
2760 		opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &func_name TSRMLS_CC);
2761 		GET_CACHE_SLOT(opline->op2.constant);
2762 
2763 		++CG(context).nested_calls;
2764 		fcall->fbc = NULL;
2765 	}
2766 
2767 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2768 	opline->opcode = ZEND_SEND_UNPACK;
2769 	SET_NODE(opline->op1, params);
2770 	SET_UNUSED(opline->op2);
2771 	opline->op2.num = fcall->arg_num;
2772 }
2773 /* }}} */
2774 
generate_free_switch_expr(const zend_switch_entry * switch_entry TSRMLS_DC)2775 static int generate_free_switch_expr(const zend_switch_entry *switch_entry TSRMLS_DC) /* {{{ */
2776 {
2777 	zend_op *opline;
2778 
2779 	if (switch_entry->cond.op_type != IS_VAR && switch_entry->cond.op_type != IS_TMP_VAR) {
2780 		return (switch_entry->cond.op_type == IS_UNUSED);
2781 	}
2782 
2783 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2784 
2785 	opline->opcode = (switch_entry->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2786 	SET_NODE(opline->op1, &switch_entry->cond);
2787 	SET_UNUSED(opline->op2);
2788 
2789 	return 0;
2790 }
2791 /* }}} */
2792 
generate_free_foreach_copy(const zend_op * foreach_copy TSRMLS_DC)2793 static int generate_free_foreach_copy(const zend_op *foreach_copy TSRMLS_DC) /* {{{ */
2794 {
2795 	zend_op *opline;
2796 
2797 	/* If we reach the separator then stop applying the stack */
2798 	if (foreach_copy->result_type == IS_UNUSED) {
2799 		return 1;
2800 	}
2801 
2802 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2803 
2804 	opline->opcode = (foreach_copy->result_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2805 	COPY_NODE(opline->op1, foreach_copy->result);
2806 	SET_UNUSED(opline->op2);
2807 
2808 	return 0;
2809 }
2810 /* }}} */
2811 
zend_do_return(znode * expr,int do_end_vparse TSRMLS_DC)2812 void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
2813 {
2814 	zend_op *opline;
2815 	int start_op_number, end_op_number;
2816 	zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
2817 
2818 	/* The error for use of return inside a generator is thrown in pass_two. */
2819 
2820 	if (do_end_vparse) {
2821 		if (returns_reference && !zend_is_function_or_method_call(expr)) {
2822 			zend_do_end_variable_parse(expr, BP_VAR_W, 0 TSRMLS_CC);
2823 		} else {
2824 			zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
2825 		}
2826 	}
2827 
2828 	start_op_number = get_next_op_number(CG(active_op_array));
2829 
2830 #ifdef ZTS
2831 	zend_stack_apply_with_argument(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_switch_expr TSRMLS_CC);
2832 	zend_stack_apply_with_argument(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_foreach_copy TSRMLS_CC);
2833 #else
2834 	zend_stack_apply(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_switch_expr);
2835 	zend_stack_apply(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_foreach_copy);
2836 #endif
2837 
2838 	end_op_number = get_next_op_number(CG(active_op_array));
2839 	while (start_op_number < end_op_number) {
2840 		CG(active_op_array)->opcodes[start_op_number].extended_value |= EXT_TYPE_FREE_ON_RETURN;
2841 		start_op_number++;
2842 	}
2843 
2844 	if (CG(context).in_finally) {
2845 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2846 		opline->opcode = ZEND_DISCARD_EXCEPTION;
2847 		SET_UNUSED(opline->op1);
2848 		SET_UNUSED(opline->op2);
2849 	}
2850 
2851 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2852 
2853 	opline->opcode = returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN;
2854 
2855 	if (expr) {
2856 		SET_NODE(opline->op1, expr);
2857 
2858 		if (!do_end_vparse) {
2859 			opline->extended_value = ZEND_RETURNS_VALUE;
2860 		} else if (zend_is_function_or_method_call(expr)) {
2861 			opline->extended_value = ZEND_RETURNS_FUNCTION;
2862 		}
2863 	} else {
2864 		opline->op1_type = IS_CONST;
2865 		LITERAL_NULL(opline->op1);
2866 	}
2867 
2868 	SET_UNUSED(opline->op2);
2869 }
2870 /* }}} */
2871 
zend_do_yield(znode * result,znode * value,const znode * key,zend_bool is_variable TSRMLS_DC)2872 void zend_do_yield(znode *result, znode *value, const znode *key, zend_bool is_variable TSRMLS_DC) /* {{{ */
2873 {
2874 	zend_op *opline;
2875 
2876 	if (!CG(active_op_array)->function_name) {
2877 		zend_error_noreturn(E_COMPILE_ERROR, "The \"yield\" expression can only be used inside a function");
2878 	}
2879 
2880 	CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR;
2881 
2882 	if (is_variable) {
2883 		if ((CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) && !zend_is_function_or_method_call(value)) {
2884 			zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
2885 		} else {
2886 			zend_do_end_variable_parse(value, BP_VAR_R, 0 TSRMLS_CC);
2887 		}
2888 	}
2889 
2890 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2891 
2892 	opline->opcode = ZEND_YIELD;
2893 
2894 	if (value) {
2895 		SET_NODE(opline->op1, value);
2896 
2897 		if (is_variable && zend_is_function_or_method_call(value)) {
2898 			opline->extended_value = ZEND_RETURNS_FUNCTION;
2899 		}
2900 	} else {
2901 		SET_UNUSED(opline->op1);
2902 	}
2903 
2904 	if (key) {
2905 		SET_NODE(opline->op2, key);
2906 	} else {
2907 		SET_UNUSED(opline->op2);
2908 	}
2909 
2910 	opline->result_type = IS_VAR;
2911 	opline->result.var = get_temporary_variable(CG(active_op_array));
2912 	GET_NODE(result, opline->result);
2913 }
2914 /* }}} */
2915 
zend_add_try_element(zend_uint try_op TSRMLS_DC)2916 static int zend_add_try_element(zend_uint try_op TSRMLS_DC) /* {{{ */
2917 {
2918 	int try_catch_offset = CG(active_op_array)->last_try_catch++;
2919 
2920 	CG(active_op_array)->try_catch_array = erealloc(CG(active_op_array)->try_catch_array, sizeof(zend_try_catch_element)*CG(active_op_array)->last_try_catch);
2921 	CG(active_op_array)->try_catch_array[try_catch_offset].try_op = try_op;
2922 	CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = 0;
2923 	CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = 0;
2924 	CG(active_op_array)->try_catch_array[try_catch_offset].finally_end = 0;
2925 	return try_catch_offset;
2926 }
2927 /* }}} */
2928 
zend_add_catch_element(int offset,zend_uint catch_op TSRMLS_DC)2929 static void zend_add_catch_element(int offset, zend_uint catch_op TSRMLS_DC) /* {{{ */
2930 {
2931 	CG(active_op_array)->try_catch_array[offset].catch_op = catch_op;
2932 }
2933 /* }}} */
2934 
zend_do_first_catch(znode * open_parentheses TSRMLS_DC)2935 void zend_do_first_catch(znode *open_parentheses TSRMLS_DC) /* {{{ */
2936 {
2937 	open_parentheses->u.op.opline_num = get_next_op_number(CG(active_op_array));
2938 }
2939 /* }}} */
2940 
zend_initialize_try_catch_element(znode * catch_token TSRMLS_DC)2941 void zend_initialize_try_catch_element(znode *catch_token TSRMLS_DC) /* {{{ */
2942 {
2943 	int jmp_op_number = get_next_op_number(CG(active_op_array));
2944 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2945 	zend_llist jmp_list;
2946 	zend_llist *jmp_list_ptr;
2947 
2948 	opline->opcode = ZEND_JMP;
2949 	SET_UNUSED(opline->op1);
2950 	SET_UNUSED(opline->op2);
2951 	/* save for backpatching */
2952 
2953 	zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
2954 	zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
2955 	zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
2956 	zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
2957 
2958 	catch_token->EA = get_next_op_number(CG(active_op_array));
2959 }
2960 /* }}} */
2961 
zend_do_mark_last_catch(const znode * first_catch,const znode * last_additional_catch TSRMLS_DC)2962 void zend_do_mark_last_catch(const znode *first_catch, const znode *last_additional_catch TSRMLS_DC) /* {{{ */
2963 {
2964 	CG(active_op_array)->last--;
2965 	zend_do_if_end(TSRMLS_C);
2966 	if (last_additional_catch->u.op.opline_num == -1) {
2967 		CG(active_op_array)->opcodes[first_catch->u.op.opline_num].result.num = 1;
2968 		CG(active_op_array)->opcodes[first_catch->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
2969 	} else {
2970 		CG(active_op_array)->opcodes[last_additional_catch->u.op.opline_num].result.num = 1;
2971 		CG(active_op_array)->opcodes[last_additional_catch->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
2972 	}
2973 	DEC_BPC(CG(active_op_array));
2974 }
2975 /* }}} */
2976 
zend_do_try(znode * try_token TSRMLS_DC)2977 void zend_do_try(znode *try_token TSRMLS_DC) /* {{{ */
2978 {
2979 	try_token->u.op.opline_num = zend_add_try_element(get_next_op_number(CG(active_op_array)) TSRMLS_CC);
2980 	INC_BPC(CG(active_op_array));
2981 }
2982 /* }}} */
2983 
zend_do_finally(znode * finally_token TSRMLS_DC)2984 void zend_do_finally(znode *finally_token TSRMLS_DC) /* {{{ */
2985 {
2986 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2987 
2988 	finally_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
2989 	/* call the the "finally" block */
2990 	opline->opcode = ZEND_FAST_CALL;
2991 	SET_UNUSED(opline->op1);
2992 	opline->op1.opline_num = finally_token->u.op.opline_num + 1;
2993 	SET_UNUSED(opline->op2);
2994 	/* jump to code after the "finally" block,
2995 	 * the actual jump address is going to be set in zend_do_end_finally()
2996 	 */
2997 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2998 	opline->opcode = ZEND_JMP;
2999 	SET_UNUSED(opline->op1);
3000 	SET_UNUSED(opline->op2);
3001 
3002 	CG(context).in_finally++;
3003 }
3004 /* }}} */
3005 
zend_do_begin_catch(znode * catch_token,znode * class_name,znode * catch_var,znode * first_catch TSRMLS_DC)3006 void zend_do_begin_catch(znode *catch_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */
3007 {
3008 	long catch_op_number;
3009 	zend_op *opline;
3010 	znode catch_class;
3011 
3012 	if (class_name->op_type == IS_CONST &&
3013 	    ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
3014 		zend_resolve_class_name(class_name TSRMLS_CC);
3015 		catch_class = *class_name;
3016 	} else {
3017 		zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
3018 	}
3019 
3020 	catch_op_number = get_next_op_number(CG(active_op_array));
3021 	if (first_catch) {
3022 		first_catch->u.op.opline_num = catch_op_number;
3023 	}
3024 
3025 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3026 	opline->opcode = ZEND_CATCH;
3027 	opline->op1_type = IS_CONST;
3028 	opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), &catch_class.u.constant TSRMLS_CC);
3029 	opline->op2_type = IS_CV;
3030 	opline->op2.var = lookup_cv(CG(active_op_array), Z_STRVAL(catch_var->u.constant), Z_STRLEN(catch_var->u.constant), 0 TSRMLS_CC);
3031 	Z_STRVAL(catch_var->u.constant) = (char*)CG(active_op_array)->vars[opline->op2.var].name;
3032 	opline->result.num = 0; /* 1 means it's the last catch in the block */
3033 
3034 	catch_token->u.op.opline_num = catch_op_number;
3035 }
3036 /* }}} */
3037 
zend_do_end_catch(znode * catch_token TSRMLS_DC)3038 void zend_do_end_catch(znode *catch_token TSRMLS_DC) /* {{{ */
3039 {
3040 	int jmp_op_number = get_next_op_number(CG(active_op_array));
3041 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3042 	zend_llist *jmp_list_ptr;
3043 
3044 	opline->opcode = ZEND_JMP;
3045 	SET_UNUSED(opline->op1);
3046 	SET_UNUSED(opline->op2);
3047 	/* save for backpatching */
3048 
3049 	zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
3050 	zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
3051 
3052 	CG(active_op_array)->opcodes[catch_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
3053 }
3054 /* }}} */
3055 
zend_do_bind_catch(znode * try_token,znode * catch_token TSRMLS_DC)3056 void zend_do_bind_catch(znode *try_token, znode *catch_token TSRMLS_DC) /* {{{ */ {
3057 	if (catch_token->op_type != IS_UNUSED) {
3058 		zend_add_catch_element(try_token->u.op.opline_num, catch_token->EA TSRMLS_CC);
3059 	}
3060 }
3061 /* }}} */
3062 
zend_do_end_finally(znode * try_token,znode * catch_token,znode * finally_token TSRMLS_DC)3063 void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_token TSRMLS_DC) /* {{{ */
3064 {
3065 	if (catch_token->op_type == IS_UNUSED && finally_token->op_type == IS_UNUSED) {
3066 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
3067 	}
3068 	if (finally_token->op_type != IS_UNUSED) {
3069 		zend_op *opline;
3070 
3071 		CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_op = finally_token->u.op.opline_num + 1;
3072 		CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_end = get_next_op_number(CG(active_op_array));
3073 		CG(active_op_array)->has_finally_block = 1;
3074 
3075 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3076 		opline->opcode = ZEND_FAST_RET;
3077 		SET_UNUSED(opline->op1);
3078 		SET_UNUSED(opline->op2);
3079 
3080 		CG(active_op_array)->opcodes[finally_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
3081 
3082 		CG(context).in_finally--;
3083 	}
3084 }
3085 /* }}} */
3086 
zend_do_throw(const znode * expr TSRMLS_DC)3087 void zend_do_throw(const znode *expr TSRMLS_DC) /* {{{ */
3088 {
3089 	zend_op *opline;
3090 
3091 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3092 	opline->opcode = ZEND_THROW;
3093 	SET_NODE(opline->op1, expr);
3094 	SET_UNUSED(opline->op2);
3095 }
3096 /* }}} */
3097 
function_add_ref(zend_function * function)3098 ZEND_API void function_add_ref(zend_function *function) /* {{{ */
3099 {
3100 	if (function->type == ZEND_USER_FUNCTION) {
3101 		zend_op_array *op_array = &function->op_array;
3102 
3103 		(*op_array->refcount)++;
3104 		if (op_array->static_variables) {
3105 			HashTable *static_variables = op_array->static_variables;
3106 			zval *tmp_zval;
3107 
3108 			ALLOC_HASHTABLE(op_array->static_variables);
3109 			zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
3110 			zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
3111 		}
3112 		op_array->run_time_cache = NULL;
3113 	}
3114 }
3115 /* }}} */
3116 
do_inherit_parent_constructor(zend_class_entry * ce)3117 static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
3118 {
3119 	zend_function *function, *new_function;
3120 
3121 	if (!ce->parent) {
3122 		return;
3123 	}
3124 
3125 	/* You cannot change create_object */
3126 	ce->create_object = ce->parent->create_object;
3127 
3128 	/* Inherit special functions if needed */
3129 	if (!ce->get_iterator) {
3130 		ce->get_iterator = ce->parent->get_iterator;
3131 	}
3132 	if (!ce->iterator_funcs.funcs) {
3133 		ce->iterator_funcs.funcs = ce->parent->iterator_funcs.funcs;
3134 	}
3135 	if (!ce->__get) {
3136 		ce->__get   = ce->parent->__get;
3137 	}
3138 	if (!ce->__set) {
3139 		ce->__set = ce->parent->__set;
3140 	}
3141 	if (!ce->__unset) {
3142 		ce->__unset = ce->parent->__unset;
3143 	}
3144 	if (!ce->__isset) {
3145 		ce->__isset = ce->parent->__isset;
3146 	}
3147 	if (!ce->__call) {
3148 		ce->__call = ce->parent->__call;
3149 	}
3150 	if (!ce->__callstatic) {
3151 		ce->__callstatic = ce->parent->__callstatic;
3152 	}
3153 	if (!ce->__tostring) {
3154 		ce->__tostring = ce->parent->__tostring;
3155 	}
3156 	if (!ce->clone) {
3157 		ce->clone = ce->parent->clone;
3158 	}
3159 	if(!ce->serialize) {
3160 		ce->serialize = ce->parent->serialize;
3161 	}
3162 	if(!ce->unserialize) {
3163 		ce->unserialize = ce->parent->unserialize;
3164 	}
3165 	if (!ce->destructor) {
3166 		ce->destructor   = ce->parent->destructor;
3167 	}
3168 	if (!ce->__debugInfo) {
3169 		ce->__debugInfo = ce->parent->__debugInfo;
3170 	}
3171 	if (ce->constructor) {
3172 		if (ce->parent->constructor && ce->parent->constructor->common.fn_flags & ZEND_ACC_FINAL) {
3173 			zend_error(E_ERROR, "Cannot override final %s::%s() with %s::%s()",
3174 				ce->parent->name, ce->parent->constructor->common.function_name,
3175 				ce->name, ce->constructor->common.function_name
3176 				);
3177 		}
3178 		return;
3179 	}
3180 
3181 	if (zend_hash_find(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), (void **)&function)==SUCCESS) {
3182 		/* inherit parent's constructor */
3183 		zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), (void**)&new_function);
3184 		function_add_ref(new_function);
3185 	} else {
3186 		/* Don't inherit the old style constructor if we already have the new style constructor */
3187 		char *lc_class_name;
3188 		char *lc_parent_class_name;
3189 
3190 		lc_class_name = zend_str_tolower_dup(ce->name, ce->name_length);
3191 		if (!zend_hash_exists(&ce->function_table, lc_class_name, ce->name_length+1)) {
3192 			lc_parent_class_name = zend_str_tolower_dup(ce->parent->name, ce->parent->name_length);
3193 			if (!zend_hash_exists(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1) &&
3194 					zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
3195 				if (function->common.fn_flags & ZEND_ACC_CTOR) {
3196 					/* inherit parent's constructor */
3197 					zend_hash_update(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1, function, sizeof(zend_function), (void**)&new_function);
3198 					function_add_ref(new_function);
3199 				}
3200 			}
3201 			efree(lc_parent_class_name);
3202 		}
3203 		efree(lc_class_name);
3204 	}
3205 	ce->constructor = ce->parent->constructor;
3206 }
3207 /* }}} */
3208 
zend_visibility_string(zend_uint fn_flags)3209 char *zend_visibility_string(zend_uint fn_flags) /* {{{ */
3210 {
3211 	if (fn_flags & ZEND_ACC_PRIVATE) {
3212 		return "private";
3213 	}
3214 	if (fn_flags & ZEND_ACC_PROTECTED) {
3215 		return "protected";
3216 	}
3217 	if (fn_flags & ZEND_ACC_PUBLIC) {
3218 		return "public";
3219 	}
3220 	return "";
3221 }
3222 /* }}} */
3223 
do_inherit_method(zend_function * function)3224 static void do_inherit_method(zend_function *function) /* {{{ */
3225 {
3226 	/* The class entry of the derived function intentionally remains the same
3227 	 * as that of the parent class.  That allows us to know in which context
3228 	 * we're running, and handle private method calls properly.
3229 	 */
3230 	function_add_ref(function);
3231 }
3232 /* }}} */
3233 
zend_do_perform_implementation_check(const zend_function * fe,const zend_function * proto TSRMLS_DC)3234 static zend_bool zend_do_perform_implementation_check(const zend_function *fe, const zend_function *proto TSRMLS_DC) /* {{{ */
3235 {
3236 	zend_uint i, num_args;
3237 
3238 	/* If it's a user function then arg_info == NULL means we don't have any parameters but
3239 	 * we still need to do the arg number checks.  We are only willing to ignore this for internal
3240 	 * functions because extensions don't always define arg_info.
3241 	 */
3242 	if (!proto || (!proto->common.arg_info && proto->common.type != ZEND_USER_FUNCTION)) {
3243 		return 1;
3244 	}
3245 
3246 	/* Checks for constructors only if they are declared in an interface,
3247 	 * or explicitly marked as abstract
3248 	 */
3249 	if ((fe->common.fn_flags & ZEND_ACC_CTOR)
3250 		&& ((proto->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
3251 			&& (proto->common.fn_flags & ZEND_ACC_ABSTRACT) == 0)) {
3252 		return 1;
3253 	}
3254 
3255 	/* If the prototype method is private do not enforce a signature */
3256 	if (proto->common.fn_flags & ZEND_ACC_PRIVATE) {
3257 		return 1;
3258 	}
3259 
3260 	/* check number of arguments */
3261 	if (proto->common.required_num_args < fe->common.required_num_args
3262 		|| proto->common.num_args > fe->common.num_args) {
3263 		return 0;
3264 	}
3265 
3266 	/* by-ref constraints on return values are covariant */
3267 	if ((proto->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
3268 		&& !(fe->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
3269 		return 0;
3270 	}
3271 
3272 	if ((proto->common.fn_flags & ZEND_ACC_VARIADIC)
3273 		&& !(fe->common.fn_flags & ZEND_ACC_VARIADIC)) {
3274 		return 0;
3275 	}
3276 
3277 	/* For variadic functions any additional (optional) arguments that were added must be
3278 	 * checked against the signature of the variadic argument, so in this case we have to
3279 	 * go through all the parameters of the function and not just those present in the
3280 	 * prototype. */
3281 	num_args = proto->common.num_args;
3282 	if ((proto->common.fn_flags & ZEND_ACC_VARIADIC)
3283 		&& fe->common.num_args > proto->common.num_args) {
3284 		num_args = fe->common.num_args;
3285 	}
3286 
3287 	for (i = 0; i < num_args; i++) {
3288 		zend_arg_info *fe_arg_info = &fe->common.arg_info[i];
3289 
3290 		zend_arg_info *proto_arg_info;
3291 		if (i < proto->common.num_args) {
3292 			proto_arg_info = &proto->common.arg_info[i];
3293 		} else {
3294 			proto_arg_info = &proto->common.arg_info[proto->common.num_args-1];
3295 		}
3296 
3297 		if (ZEND_LOG_XOR(fe_arg_info->class_name, proto_arg_info->class_name)) {
3298 			/* Only one has a type hint and the other one doesn't */
3299 			return 0;
3300 		}
3301 
3302 		if (fe_arg_info->class_name) {
3303 			const char *fe_class_name, *proto_class_name;
3304 			zend_uint fe_class_name_len, proto_class_name_len;
3305 
3306 			if (!strcasecmp(fe_arg_info->class_name, "parent") && proto->common.scope) {
3307 				fe_class_name = proto->common.scope->name;
3308 				fe_class_name_len = proto->common.scope->name_length;
3309 			} else if (!strcasecmp(fe_arg_info->class_name, "self") && fe->common.scope) {
3310 				fe_class_name = fe->common.scope->name;
3311 				fe_class_name_len = fe->common.scope->name_length;
3312 			} else {
3313 				fe_class_name = fe_arg_info->class_name;
3314 				fe_class_name_len = fe_arg_info->class_name_len;
3315 			}
3316 
3317 			if (!strcasecmp(proto_arg_info->class_name, "parent") && proto->common.scope && proto->common.scope->parent) {
3318 				proto_class_name = proto->common.scope->parent->name;
3319 				proto_class_name_len = proto->common.scope->parent->name_length;
3320 			} else if (!strcasecmp(proto_arg_info->class_name, "self") && proto->common.scope) {
3321 				proto_class_name = proto->common.scope->name;
3322 				proto_class_name_len = proto->common.scope->name_length;
3323 			} else {
3324 				proto_class_name = proto_arg_info->class_name;
3325 				proto_class_name_len = proto_arg_info->class_name_len;
3326 			}
3327 
3328 			if (strcasecmp(fe_class_name, proto_class_name)!=0) {
3329 				const char *colon;
3330 
3331 				if (fe->common.type != ZEND_USER_FUNCTION) {
3332 					return 0;
3333 			    } else if (strchr(proto_class_name, '\\') != NULL ||
3334 						(colon = zend_memrchr(fe_class_name, '\\', fe_class_name_len)) == NULL ||
3335 						strcasecmp(colon+1, proto_class_name) != 0) {
3336 					zend_class_entry **fe_ce, **proto_ce;
3337 					int found, found2;
3338 
3339 					found = zend_lookup_class(fe_class_name, fe_class_name_len, &fe_ce TSRMLS_CC);
3340 					found2 = zend_lookup_class(proto_class_name, proto_class_name_len, &proto_ce TSRMLS_CC);
3341 
3342 					/* Check for class alias */
3343 					if (found != SUCCESS || found2 != SUCCESS ||
3344 							(*fe_ce)->type == ZEND_INTERNAL_CLASS ||
3345 							(*proto_ce)->type == ZEND_INTERNAL_CLASS ||
3346 							*fe_ce != *proto_ce) {
3347 						return 0;
3348 					}
3349 				}
3350 			}
3351 		}
3352 		if (fe_arg_info->type_hint != proto_arg_info->type_hint) {
3353 			/* Incompatible type hint */
3354 			return 0;
3355 		}
3356 
3357 		/* by-ref constraints on arguments are invariant */
3358 		if (fe_arg_info->pass_by_reference != proto_arg_info->pass_by_reference) {
3359 			return 0;
3360 		}
3361 	}
3362 
3363 	return 1;
3364 }
3365 /* }}} */
3366 
3367 #define REALLOC_BUF_IF_EXCEED(buf, offset, length, size) \
3368 	if (UNEXPECTED(offset - buf + size >= length)) { 	\
3369 		length += size + 1; 				\
3370 		buf = erealloc(buf, length); 		\
3371 	}
3372 
zend_get_function_declaration(zend_function * fptr TSRMLS_DC)3373 static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{{ */
3374 {
3375 	char *offset, *buf;
3376 	zend_uint length = 1024;
3377 
3378 	offset = buf = (char *)emalloc(length * sizeof(char));
3379 	if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
3380 		*(offset++) = '&';
3381 		*(offset++) = ' ';
3382 	}
3383 
3384 	if (fptr->common.scope) {
3385 		memcpy(offset, fptr->common.scope->name, fptr->common.scope->name_length);
3386 		offset += fptr->common.scope->name_length;
3387 		*(offset++) = ':';
3388 		*(offset++) = ':';
3389 	}
3390 
3391 	{
3392 		size_t name_len = strlen(fptr->common.function_name);
3393 		REALLOC_BUF_IF_EXCEED(buf, offset, length, name_len);
3394 		memcpy(offset, fptr->common.function_name, name_len);
3395 		offset += name_len;
3396 	}
3397 
3398 	*(offset++) = '(';
3399 	if (fptr->common.arg_info) {
3400 		zend_uint i, required;
3401 		zend_arg_info *arg_info = fptr->common.arg_info;
3402 
3403 		required = fptr->common.required_num_args;
3404 		for (i = 0; i < fptr->common.num_args;) {
3405 			if (arg_info->class_name) {
3406 				const char *class_name;
3407 				zend_uint class_name_len;
3408 				if (!strcasecmp(arg_info->class_name, "self") && fptr->common.scope ) {
3409 					class_name = fptr->common.scope->name;
3410 					class_name_len = fptr->common.scope->name_length;
3411 				} else if (!strcasecmp(arg_info->class_name, "parent") && fptr->common.scope->parent) {
3412 					class_name = fptr->common.scope->parent->name;
3413 					class_name_len = fptr->common.scope->parent->name_length;
3414 				} else {
3415 					class_name = arg_info->class_name;
3416 					class_name_len = arg_info->class_name_len;
3417 				}
3418 				REALLOC_BUF_IF_EXCEED(buf, offset, length, class_name_len);
3419 				memcpy(offset, class_name, class_name_len);
3420 				offset += class_name_len;
3421 				*(offset++) = ' ';
3422 			} else if (arg_info->type_hint) {
3423 				zend_uint type_name_len;
3424 				char *type_name = zend_get_type_by_const(arg_info->type_hint);
3425 				type_name_len = strlen(type_name);
3426 				REALLOC_BUF_IF_EXCEED(buf, offset, length, type_name_len);
3427 				memcpy(offset, type_name, type_name_len);
3428 				offset += type_name_len;
3429 				*(offset++) = ' ';
3430 			}
3431 
3432 			if (arg_info->pass_by_reference) {
3433 				*(offset++) = '&';
3434 			}
3435 
3436 			if (arg_info->is_variadic) {
3437 				*(offset++) = '.';
3438 				*(offset++) = '.';
3439 				*(offset++) = '.';
3440 			}
3441 
3442 			*(offset++) = '$';
3443 
3444 			if (arg_info->name) {
3445 				REALLOC_BUF_IF_EXCEED(buf, offset, length, arg_info->name_len);
3446 				memcpy(offset, arg_info->name, arg_info->name_len);
3447 				offset += arg_info->name_len;
3448 			} else {
3449 				zend_uint idx = i;
3450 				memcpy(offset, "param", 5);
3451 				offset += 5;
3452 				do {
3453 					*(offset++) = (char) (idx % 10) + '0';
3454 					idx /= 10;
3455 				} while (idx > 0);
3456 			}
3457 			if (i >= required && !arg_info->is_variadic) {
3458 				*(offset++) = ' ';
3459 				*(offset++) = '=';
3460 				*(offset++) = ' ';
3461 				if (fptr->type == ZEND_USER_FUNCTION) {
3462 					zend_op *precv = NULL;
3463 					{
3464 						zend_uint idx  = i;
3465 						zend_op *op = ((zend_op_array *)fptr)->opcodes;
3466 						zend_op *end = op + ((zend_op_array *)fptr)->last;
3467 
3468 						++idx;
3469 						while (op < end) {
3470 							if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
3471 									&& op->op1.num == (long)idx)
3472 							{
3473 								precv = op;
3474 							}
3475 							++op;
3476 						}
3477 					}
3478 					if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
3479 						zval *zv, zv_copy;
3480 						int use_copy;
3481 						zv = precv->op2.zv;
3482 						if ((Z_TYPE_P(zv) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
3483 							REALLOC_BUF_IF_EXCEED(buf, offset, length, Z_STRLEN_P(zv));
3484 							memcpy(offset, Z_STRVAL_P(zv), Z_STRLEN_P(zv));
3485 							offset += Z_STRLEN_P(zv);
3486 						} else if (Z_TYPE_P(zv) == IS_BOOL) {
3487 							if (Z_LVAL_P(zv)) {
3488 								memcpy(offset, "true", 4);
3489 								offset += 4;
3490 							} else {
3491 								memcpy(offset, "false", 5);
3492 								offset += 5;
3493 							}
3494 						} else if (Z_TYPE_P(zv) == IS_NULL) {
3495 							memcpy(offset, "NULL", 4);
3496 							offset += 4;
3497 						} else if (Z_TYPE_P(zv) == IS_STRING) {
3498 							*(offset++) = '\'';
3499 							REALLOC_BUF_IF_EXCEED(buf, offset, length, MIN(Z_STRLEN_P(zv), 10));
3500 							memcpy(offset, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 10));
3501 							offset += MIN(Z_STRLEN_P(zv), 10);
3502 							if (Z_STRLEN_P(zv) > 10) {
3503 								*(offset++) = '.';
3504 								*(offset++) = '.';
3505 								*(offset++) = '.';
3506 							}
3507 							*(offset++) = '\'';
3508 						} else if (Z_TYPE_P(zv) == IS_ARRAY) {
3509 							memcpy(offset, "Array", 5);
3510 							offset += 5;
3511 						} else if ((Z_TYPE_P(zv) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT_AST) {
3512 							memcpy(offset, "<expression>", 12);
3513 							offset += 12;
3514 						} else {
3515 							zend_make_printable_zval(zv, &zv_copy, &use_copy);
3516 							REALLOC_BUF_IF_EXCEED(buf, offset, length, Z_STRLEN(zv_copy));
3517 							memcpy(offset, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
3518 							offset += Z_STRLEN(zv_copy);
3519 							if (use_copy) {
3520 								zval_dtor(&zv_copy);
3521 							}
3522 						}
3523 					}
3524 				} else {
3525 					memcpy(offset, "NULL", 4);
3526 					offset += 4;
3527 				}
3528 			}
3529 
3530 			if (++i < fptr->common.num_args) {
3531 				*(offset++) = ',';
3532 				*(offset++) = ' ';
3533 			}
3534 			arg_info++;
3535 			REALLOC_BUF_IF_EXCEED(buf, offset, length, 32);
3536 		}
3537 	}
3538 	*(offset++) = ')';
3539 	*offset = '\0';
3540 
3541 	return buf;
3542 }
3543 /* }}} */
3544 
do_inheritance_check_on_method(zend_function * child,zend_function * parent TSRMLS_DC)3545 static void do_inheritance_check_on_method(zend_function *child, zend_function *parent TSRMLS_DC) /* {{{ */
3546 {
3547 	zend_uint child_flags;
3548 	zend_uint parent_flags = parent->common.fn_flags;
3549 
3550 	if ((parent->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
3551 		&& parent->common.fn_flags & ZEND_ACC_ABSTRACT
3552 		&& parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
3553 		&& child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
3554 		zend_error_noreturn(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)",
3555 			parent->common.scope->name,
3556 			child->common.function_name,
3557 			child->common.prototype ? child->common.prototype->common.scope->name : child->common.scope->name);
3558 	}
3559 
3560 	if (parent_flags & ZEND_ACC_FINAL) {
3561 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name);
3562 	}
3563 
3564 	child_flags	= child->common.fn_flags;
3565 	/* You cannot change from static to non static and vice versa.
3566 	 */
3567 	if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) {
3568 		if (child->common.fn_flags & ZEND_ACC_STATIC) {
3569 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot make non static method %s::%s() static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
3570 		} else {
3571 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot make static method %s::%s() non static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
3572 		}
3573 	}
3574 
3575 	/* Disallow making an inherited method abstract. */
3576 	if ((child_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_ABSTRACT)) {
3577 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot make non abstract method %s::%s() abstract in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
3578 	}
3579 
3580 	if (parent_flags & ZEND_ACC_CHANGED) {
3581 		child->common.fn_flags |= ZEND_ACC_CHANGED;
3582 	} else {
3583 		/* Prevent derived classes from restricting access that was available in parent classes
3584 		 */
3585 		if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) {
3586 			zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
3587 		} else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
3588 			&& ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
3589 			child->common.fn_flags |= ZEND_ACC_CHANGED;
3590 		}
3591 	}
3592 
3593 	if (parent_flags & ZEND_ACC_PRIVATE) {
3594 		child->common.prototype = NULL;
3595 	} else if (parent_flags & ZEND_ACC_ABSTRACT) {
3596 		child->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
3597 		child->common.prototype = parent;
3598 	} else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) {
3599 		/* ctors only have a prototype if it comes from an interface */
3600 		child->common.prototype = parent->common.prototype ? parent->common.prototype : parent;
3601 	}
3602 
3603 	if (child->common.prototype && (child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) {
3604 		if (!zend_do_perform_implementation_check(child, child->common.prototype TSRMLS_CC)) {
3605 			zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s::%s() must be compatible with %s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_get_function_declaration(child->common.prototype TSRMLS_CC));
3606 		}
3607 	} else if (EG(error_reporting) & E_STRICT || EG(user_error_handler)) { /* Check E_STRICT (or custom error handler) before the check so that we save some time */
3608 		if (!zend_do_perform_implementation_check(child, parent TSRMLS_CC)) {
3609 			char *method_prototype = zend_get_function_declaration(parent TSRMLS_CC);
3610 			zend_error(E_STRICT, "Declaration of %s::%s() should be compatible with %s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, method_prototype);
3611 			efree(method_prototype);
3612 		}
3613 	}
3614 }
3615 /* }}} */
3616 
do_inherit_method_check(HashTable * child_function_table,zend_function * parent,const zend_hash_key * hash_key,zend_class_entry * child_ce)3617 static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, const zend_hash_key *hash_key, zend_class_entry *child_ce) /* {{{ */
3618 {
3619 	zend_uint parent_flags = parent->common.fn_flags;
3620 	zend_function *child;
3621 	TSRMLS_FETCH();
3622 
3623 	if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
3624 		if (parent_flags & (ZEND_ACC_ABSTRACT)) {
3625 			child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
3626 		}
3627 		return 1; /* method doesn't exist in child, copy from parent */
3628 	}
3629 
3630 	do_inheritance_check_on_method(child, parent TSRMLS_CC);
3631 
3632 	return 0;
3633 }
3634 /* }}} */
3635 
do_inherit_property_access_check(HashTable * target_ht,zend_property_info * parent_info,const zend_hash_key * hash_key,zend_class_entry * ce)3636 static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_property_info *parent_info, const zend_hash_key *hash_key, zend_class_entry *ce) /* {{{ */
3637 {
3638 	zend_property_info *child_info;
3639 	zend_class_entry *parent_ce = ce->parent;
3640 	TSRMLS_FETCH();
3641 
3642 	if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
3643 		if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
3644 			child_info->flags |= ZEND_ACC_CHANGED;
3645 		} else {
3646 			zend_hash_quick_update(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, parent_info, sizeof(zend_property_info), (void **) &child_info);
3647 			if(ce->type & ZEND_INTERNAL_CLASS) {
3648 				zend_duplicate_property_info_internal(child_info);
3649 			} else {
3650 				zend_duplicate_property_info(child_info);
3651 			}
3652 			child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */
3653 			child_info->flags |= ZEND_ACC_SHADOW; /* but it's a shadow of private */
3654 		}
3655 		return 0; /* don't copy access information to child */
3656 	}
3657 
3658 	if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
3659 		if ((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC)) {
3660 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s",
3661 				(parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->arKey,
3662 				(child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey);
3663 
3664 		}
3665 
3666 		if(parent_info->flags & ZEND_ACC_CHANGED) {
3667 			child_info->flags |= ZEND_ACC_CHANGED;
3668 		}
3669 
3670 		if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
3671 			zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
3672 		} else if ((child_info->flags & ZEND_ACC_STATIC) == 0) {
3673 			/* Don't keep default properties in GC (thry may be freed by opcache) */
3674 			i_zval_ptr_dtor_nogc(ce->default_properties_table[parent_info->offset] ZEND_FILE_LINE_CC TSRMLS_CC);
3675 			ce->default_properties_table[parent_info->offset] = ce->default_properties_table[child_info->offset];
3676 			ce->default_properties_table[child_info->offset] = NULL;
3677 			child_info->offset = parent_info->offset;
3678 		}
3679 		return 0;	/* Don't copy from parent */
3680 	} else {
3681 		return 1;	/* Copy from parent */
3682 	}
3683 }
3684 /* }}} */
3685 
do_implement_interface(zend_class_entry * ce,zend_class_entry * iface TSRMLS_DC)3686 static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
3687 {
3688 	if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce TSRMLS_CC) == FAILURE) {
3689 		zend_error(E_CORE_ERROR, "Class %s could not implement interface %s", ce->name, iface->name);
3690 	}
3691 	if (ce == iface) {
3692 		zend_error(E_ERROR, "Interface %s cannot implement itself", ce->name);
3693 	}
3694 }
3695 /* }}} */
3696 
zend_do_inherit_interfaces(zend_class_entry * ce,const zend_class_entry * iface TSRMLS_DC)3697 ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC) /* {{{ */
3698 {
3699 	/* expects interface to be contained in ce's interface list already */
3700 	zend_uint i, ce_num, if_num = iface->num_interfaces;
3701 	zend_class_entry *entry;
3702 
3703 	if (if_num==0) {
3704 		return;
3705 	}
3706 	ce_num = ce->num_interfaces;
3707 
3708 	if (ce->type == ZEND_INTERNAL_CLASS) {
3709 		ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
3710 	} else {
3711 		ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
3712 	}
3713 
3714 	/* Inherit the interfaces, only if they're not already inherited by the class */
3715 	while (if_num--) {
3716 		entry = iface->interfaces[if_num];
3717 		for (i = 0; i < ce_num; i++) {
3718 			if (ce->interfaces[i] == entry) {
3719 				break;
3720 			}
3721 		}
3722 		if (i == ce_num) {
3723 			ce->interfaces[ce->num_interfaces++] = entry;
3724 		}
3725 	}
3726 
3727 	/* and now call the implementing handlers */
3728 	while (ce_num < ce->num_interfaces) {
3729 		do_implement_interface(ce, ce->interfaces[ce_num++] TSRMLS_CC);
3730 	}
3731 }
3732 /* }}} */
3733 
3734 #ifdef ZTS
zval_internal_ctor(zval ** p)3735 static void zval_internal_ctor(zval **p) /* {{{ */
3736 {
3737 	zval *orig_ptr = *p;
3738 
3739 	ALLOC_ZVAL(*p);
3740 	MAKE_COPY_ZVAL(&orig_ptr, *p);
3741 }
3742 /* }}} */
3743 
3744 # define zval_property_ctor(parent_ce, ce) \
3745 	((void (*)(void *)) (((parent_ce)->type != (ce)->type) ? zval_internal_ctor : zval_add_ref))
3746 #else
3747 # define zval_property_ctor(parent_ce, ce) \
3748 	((void (*)(void *)) zval_add_ref)
3749 #endif
3750 
zend_do_inheritance(zend_class_entry * ce,zend_class_entry * parent_ce TSRMLS_DC)3751 ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
3752 {
3753 	zend_property_info *property_info;
3754 
3755 	if ((ce->ce_flags & ZEND_ACC_INTERFACE)
3756 		&& !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
3757 		zend_error_noreturn(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
3758 	}
3759 	if (parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
3760 		zend_error_noreturn(E_COMPILE_ERROR, "Class %s may not inherit from final class (%s)", ce->name, parent_ce->name);
3761 	}
3762 
3763 	ce->parent = parent_ce;
3764 	/* Copy serialize/unserialize callbacks */
3765 	if (!ce->serialize) {
3766 		ce->serialize   = parent_ce->serialize;
3767 	}
3768 	if (!ce->unserialize) {
3769 		ce->unserialize = parent_ce->unserialize;
3770 	}
3771 
3772 	/* Inherit interfaces */
3773 	zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);
3774 
3775 	/* Inherit properties */
3776 	if (parent_ce->default_properties_count) {
3777 		int i = ce->default_properties_count + parent_ce->default_properties_count;
3778 
3779 		ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
3780 		if (ce->default_properties_count) {
3781 			while (i-- > parent_ce->default_properties_count) {
3782 				ce->default_properties_table[i] = ce->default_properties_table[i - parent_ce->default_properties_count];
3783 			}
3784 		}
3785 		for (i = 0; i < parent_ce->default_properties_count; i++) {
3786 			ce->default_properties_table[i] = parent_ce->default_properties_table[i];
3787 			if (ce->default_properties_table[i]) {
3788 #ifdef ZTS
3789 				if (parent_ce->type != ce->type) {
3790 					zval *p;
3791 
3792 					ALLOC_ZVAL(p);
3793 					MAKE_COPY_ZVAL(&ce->default_properties_table[i], p);
3794 					ce->default_properties_table[i] = p;
3795 				} else {
3796 					Z_ADDREF_P(ce->default_properties_table[i]);
3797 				}
3798 #else
3799 				Z_ADDREF_P(ce->default_properties_table[i]);
3800 #endif
3801 			}
3802 		}
3803 		ce->default_properties_count += parent_ce->default_properties_count;
3804 	}
3805 
3806 	if (parent_ce->type != ce->type) {
3807 		/* User class extends internal class */
3808 		zend_update_class_constants(parent_ce  TSRMLS_CC);
3809 		if (parent_ce->default_static_members_count) {
3810 			int i = ce->default_static_members_count + parent_ce->default_static_members_count;
3811 
3812 			ce->default_static_members_table = erealloc(ce->default_static_members_table, sizeof(void*) * i);
3813 			if (ce->default_static_members_count) {
3814 				while (i-- > parent_ce->default_static_members_count) {
3815 					ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
3816 				}
3817 			}
3818 			for (i = 0; i < parent_ce->default_static_members_count; i++) {
3819 				SEPARATE_ZVAL_TO_MAKE_IS_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
3820 				ce->default_static_members_table[i] = CE_STATIC_MEMBERS(parent_ce)[i];
3821 				Z_ADDREF_P(ce->default_static_members_table[i]);
3822 			}
3823 			ce->default_static_members_count += parent_ce->default_static_members_count;
3824 			ce->static_members_table = ce->default_static_members_table;
3825 		}
3826 	} else {
3827 		if (parent_ce->default_static_members_count) {
3828 			int i = ce->default_static_members_count + parent_ce->default_static_members_count;
3829 
3830 			ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
3831 			if (ce->default_static_members_count) {
3832 				while (i-- > parent_ce->default_static_members_count) {
3833 					ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
3834 				}
3835 			}
3836 			for (i = 0; i < parent_ce->default_static_members_count; i++) {
3837 				SEPARATE_ZVAL_TO_MAKE_IS_REF(&parent_ce->default_static_members_table[i]);
3838 				ce->default_static_members_table[i] = parent_ce->default_static_members_table[i];
3839 				Z_ADDREF_P(ce->default_static_members_table[i]);
3840 			}
3841 			ce->default_static_members_count += parent_ce->default_static_members_count;
3842 			if (ce->type == ZEND_USER_CLASS) {
3843 				ce->static_members_table = ce->default_static_members_table;
3844 			}
3845 		}
3846 	}
3847 
3848 	for (zend_hash_internal_pointer_reset(&ce->properties_info);
3849 	zend_hash_get_current_data(&ce->properties_info, (void *) &property_info) == SUCCESS;
3850 	zend_hash_move_forward(&ce->properties_info)) {
3851 		if (property_info->ce == ce) {
3852 			if (property_info->flags & ZEND_ACC_STATIC) {
3853 				property_info->offset += parent_ce->default_static_members_count;
3854 			} else {
3855 				property_info->offset += parent_ce->default_properties_count;
3856 			}
3857 		}
3858 	}
3859 
3860 	zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce);
3861 
3862 	zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);
3863 	zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce);
3864 	do_inherit_parent_constructor(ce);
3865 
3866 	if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
3867 		ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
3868 	} else if (!(ce->ce_flags & (ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
3869 		/* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */
3870 		zend_verify_abstract_class(ce TSRMLS_CC);
3871 	}
3872 	ce->ce_flags |= parent_ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS;
3873 }
3874 /* }}} */
3875 
do_inherit_constant_check(HashTable * child_constants_table,const zval ** parent_constant,const zend_hash_key * hash_key,const zend_class_entry * iface)3876 static zend_bool do_inherit_constant_check(HashTable *child_constants_table, const zval **parent_constant, const zend_hash_key *hash_key, const zend_class_entry *iface) /* {{{ */
3877 {
3878 	zval **old_constant;
3879 
3880 	if (zend_hash_quick_find(child_constants_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**)&old_constant) == SUCCESS) {
3881 		if (*old_constant != *parent_constant) {
3882 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", hash_key->arKey, iface->name);
3883 		}
3884 		return 0;
3885 	}
3886 	return 1;
3887 }
3888 /* }}} */
3889 
do_interface_constant_check(zval ** val TSRMLS_DC,int num_args,va_list args,const zend_hash_key * key)3890 static int do_interface_constant_check(zval **val TSRMLS_DC, int num_args, va_list args, const zend_hash_key *key) /* {{{ */
3891 {
3892 	zend_class_entry **iface = va_arg(args, zend_class_entry**);
3893 
3894 	do_inherit_constant_check(&(*iface)->constants_table, (const zval **) val, key, *iface);
3895 
3896 	return ZEND_HASH_APPLY_KEEP;
3897 }
3898 /* }}} */
3899 
zend_do_implement_interface(zend_class_entry * ce,zend_class_entry * iface TSRMLS_DC)3900 ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
3901 {
3902 	zend_uint i, ignore = 0;
3903 	zend_uint current_iface_num = ce->num_interfaces;
3904 	zend_uint parent_iface_num  = ce->parent ? ce->parent->num_interfaces : 0;
3905 
3906 	for (i = 0; i < ce->num_interfaces; i++) {
3907 		if (ce->interfaces[i] == NULL) {
3908 			memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i));
3909 			i--;
3910 		} else if (ce->interfaces[i] == iface) {
3911 			if (i < parent_iface_num) {
3912 				ignore = 1;
3913 			} else {
3914 				zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ce->name, iface->name);
3915 			}
3916 		}
3917 	}
3918 	if (ignore) {
3919 		/* Check for attempt to redeclare interface constants */
3920 		zend_hash_apply_with_arguments(&ce->constants_table TSRMLS_CC, (apply_func_args_t) do_interface_constant_check, 1, &iface);
3921 	} else {
3922 		if (ce->num_interfaces >= current_iface_num) {
3923 			if (ce->type == ZEND_INTERNAL_CLASS) {
3924 				ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
3925 			} else {
3926 				ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
3927 			}
3928 		}
3929 		ce->interfaces[ce->num_interfaces++] = iface;
3930 
3931 		zend_hash_merge_ex(&ce->constants_table, &iface->constants_table, (copy_ctor_func_t) zval_add_ref, sizeof(zval *), (merge_checker_func_t) do_inherit_constant_check, iface);
3932 		zend_hash_merge_ex(&ce->function_table, &iface->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce);
3933 
3934 		do_implement_interface(ce, iface TSRMLS_CC);
3935 		zend_do_inherit_interfaces(ce, iface TSRMLS_CC);
3936 	}
3937 }
3938 /* }}} */
3939 
zend_do_implement_trait(zend_class_entry * ce,zend_class_entry * trait TSRMLS_DC)3940 ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC) /* {{{ */
3941 {
3942 	zend_uint i, ignore = 0;
3943 	zend_uint current_trait_num = ce->num_traits;
3944 	zend_uint parent_trait_num  = ce->parent ? ce->parent->num_traits : 0;
3945 
3946 	for (i = 0; i < ce->num_traits; i++) {
3947 		if (ce->traits[i] == NULL) {
3948 			memmove(ce->traits + i, ce->traits + i + 1, sizeof(zend_class_entry*) * (--ce->num_traits - i));
3949 			i--;
3950 		} else if (ce->traits[i] == trait) {
3951 			if (i < parent_trait_num) {
3952 				ignore = 1;
3953 			}
3954 		}
3955 	}
3956 	if (!ignore) {
3957 		if (ce->num_traits >= current_trait_num) {
3958 			if (ce->type == ZEND_INTERNAL_CLASS) {
3959 				ce->traits = (zend_class_entry **) realloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
3960 			} else {
3961 				ce->traits = (zend_class_entry **) erealloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
3962 			}
3963 		}
3964 		ce->traits[ce->num_traits++] = trait;
3965 	}
3966 }
3967 /* }}} */
3968 
zend_traits_method_compatibility_check(zend_function * fn,zend_function * other_fn TSRMLS_DC)3969 static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_function *other_fn TSRMLS_DC) /* {{{ */
3970 {
3971 	zend_uint    fn_flags = fn->common.scope->ce_flags;
3972 	zend_uint other_flags = other_fn->common.scope->ce_flags;
3973 
3974 	return zend_do_perform_implementation_check(fn, other_fn TSRMLS_CC)
3975 		&& ((other_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) || zend_do_perform_implementation_check(other_fn, fn TSRMLS_CC))
3976 		&& ((fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC)) ==
3977 		    (other_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC))); /* equal final and static qualifier */
3978 }
3979 /* }}} */
3980 
zend_add_magic_methods(zend_class_entry * ce,const char * mname,uint mname_len,zend_function * fe TSRMLS_DC)3981 static void zend_add_magic_methods(zend_class_entry* ce, const char* mname, uint mname_len, zend_function* fe TSRMLS_DC) /* {{{ */
3982 {
3983 	if (!strncmp(mname, ZEND_CLONE_FUNC_NAME, mname_len)) {
3984 		ce->clone = fe; fe->common.fn_flags |= ZEND_ACC_CLONE;
3985 	} else if (!strncmp(mname, ZEND_CONSTRUCTOR_FUNC_NAME, mname_len)) {
3986 		if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
3987 			zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name);
3988 		}
3989 		ce->constructor = fe; fe->common.fn_flags |= ZEND_ACC_CTOR;
3990 	} else if (!strncmp(mname, ZEND_DESTRUCTOR_FUNC_NAME,  mname_len)) {
3991 		ce->destructor = fe; fe->common.fn_flags |= ZEND_ACC_DTOR;
3992 	} else if (!strncmp(mname, ZEND_GET_FUNC_NAME, mname_len)) {
3993 		ce->__get = fe;
3994 	} else if (!strncmp(mname, ZEND_SET_FUNC_NAME, mname_len)) {
3995 		ce->__set = fe;
3996 	} else if (!strncmp(mname, ZEND_CALL_FUNC_NAME, mname_len)) {
3997 		ce->__call = fe;
3998 	} else if (!strncmp(mname, ZEND_UNSET_FUNC_NAME, mname_len)) {
3999 		ce->__unset = fe;
4000 	} else if (!strncmp(mname, ZEND_ISSET_FUNC_NAME, mname_len)) {
4001 		ce->__isset = fe;
4002 	} else if (!strncmp(mname, ZEND_CALLSTATIC_FUNC_NAME, mname_len)) {
4003 		ce->__callstatic = fe;
4004 	} else if (!strncmp(mname, ZEND_TOSTRING_FUNC_NAME, mname_len)) {
4005 		ce->__tostring = fe;
4006 	} else if (!strncmp(mname, ZEND_DEBUGINFO_FUNC_NAME, mname_len)) {
4007 		ce->__debugInfo = fe;
4008 	} else if (ce->name_length + 1 == mname_len) {
4009 		char *lowercase_name = emalloc(ce->name_length + 1);
4010 		zend_str_tolower_copy(lowercase_name, ce->name, ce->name_length);
4011 		lowercase_name = (char*)zend_new_interned_string(lowercase_name, ce->name_length + 1, 1 TSRMLS_CC);
4012 		if (!memcmp(mname, lowercase_name, mname_len)) {
4013 			if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
4014 				zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name);
4015 			}
4016 			ce->constructor = fe;
4017 			fe->common.fn_flags |= ZEND_ACC_CTOR;
4018 		}
4019 		str_efree(lowercase_name);
4020 	}
4021 }
4022 /* }}} */
4023 
zend_add_trait_method(zend_class_entry * ce,const char * name,const char * arKey,uint nKeyLength,zend_function * fn,HashTable ** overriden TSRMLS_DC)4024 static void zend_add_trait_method(zend_class_entry *ce, const char *name, const char *arKey, uint nKeyLength, zend_function *fn, HashTable **overriden TSRMLS_DC) /* {{{ */
4025 {
4026 	zend_function *existing_fn = NULL;
4027 	ulong h = zend_hash_func(arKey, nKeyLength);
4028 
4029 	if (zend_hash_quick_find(&ce->function_table, arKey, nKeyLength, h, (void**) &existing_fn) == SUCCESS) {
4030 		if (existing_fn->common.scope == ce) {
4031 			/* members from the current class override trait methods */
4032 			/* use temporary *overriden HashTable to detect hidden conflict */
4033 			if (*overriden) {
4034 				if (zend_hash_quick_find(*overriden, arKey, nKeyLength, h, (void**) &existing_fn) == SUCCESS) {
4035 					if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4036 						/* Make sure the trait method is compatible with previosly declared abstract method */
4037 						if (!zend_traits_method_compatibility_check(fn, existing_fn TSRMLS_CC)) {
4038 							zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
4039 								zend_get_function_declaration(fn TSRMLS_CC),
4040 								zend_get_function_declaration(existing_fn TSRMLS_CC));
4041 						}
4042 					} else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4043 						/* Make sure the abstract declaration is compatible with previous declaration */
4044 						if (!zend_traits_method_compatibility_check(existing_fn, fn TSRMLS_CC)) {
4045 							zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
4046 								zend_get_function_declaration(fn TSRMLS_CC),
4047 								zend_get_function_declaration(existing_fn TSRMLS_CC));
4048 						}
4049 						return;
4050 					}
4051 				}
4052 			} else {
4053 				ALLOC_HASHTABLE(*overriden);
4054 				zend_hash_init_ex(*overriden, 2, NULL, NULL, 0, 0);
4055 			}
4056 			zend_hash_quick_update(*overriden, arKey, nKeyLength, h, fn, sizeof(zend_function), (void**)&fn);
4057 			return;
4058 		} else if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT &&
4059 				(existing_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0) {
4060 			/* Make sure the trait method is compatible with previosly declared abstract method */
4061 			if (!zend_traits_method_compatibility_check(fn, existing_fn TSRMLS_CC)) {
4062 				zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
4063 					zend_get_function_declaration(fn TSRMLS_CC),
4064 					zend_get_function_declaration(existing_fn TSRMLS_CC));
4065 			}
4066 		} else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4067 			/* Make sure the abstract declaration is compatible with previous declaration */
4068 			if (!zend_traits_method_compatibility_check(existing_fn, fn TSRMLS_CC)) {
4069 				zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
4070 					zend_get_function_declaration(fn TSRMLS_CC),
4071 					zend_get_function_declaration(existing_fn TSRMLS_CC));
4072 			}
4073 			return;
4074 		} else if ((existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
4075 			/* two traits can't define the same non-abstract method */
4076 #if 1
4077 			zend_error_noreturn(E_COMPILE_ERROR, "Trait method %s has not been applied, because there are collisions with other trait methods on %s",
4078 				name, ce->name);
4079 #else		/* TODO: better error message */
4080 			zend_error_noreturn(E_COMPILE_ERROR, "Trait method %s::%s has not been applied as %s::%s, because of collision with %s::%s",
4081 				fn->common.scope->name, fn->common.function_name,
4082 				ce->name, name,
4083 				existing_fn->common.scope->name, existing_fn->common.function_name);
4084 #endif
4085 		} else {
4086 			/* inherited members are overridden by members inserted by traits */
4087 			/* check whether the trait method fulfills the inheritance requirements */
4088 			do_inheritance_check_on_method(fn, existing_fn TSRMLS_CC);
4089 			fn->common.prototype = NULL;
4090 		}
4091 	}
4092 
4093 	function_add_ref(fn);
4094 	zend_hash_quick_update(&ce->function_table, arKey, nKeyLength, h, fn, sizeof(zend_function), (void**)&fn);
4095 	zend_add_magic_methods(ce, arKey, nKeyLength, fn TSRMLS_CC);
4096 }
4097 /* }}} */
4098 
zend_fixup_trait_method(zend_function * fn,zend_class_entry * ce TSRMLS_DC)4099 static int zend_fixup_trait_method(zend_function *fn, zend_class_entry *ce TSRMLS_DC) /* {{{ */
4100 {
4101 	if ((fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
4102 
4103 		fn->common.scope = ce;
4104 
4105 		if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4106 			ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
4107 		}
4108 		if (fn->type == ZEND_USER_FUNCTION && fn->op_array.static_variables) {
4109 			ce->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
4110 		}
4111 	}
4112 	return ZEND_HASH_APPLY_KEEP;
4113 }
4114 /* }}} */
4115 
zend_traits_copy_functions(zend_function * fn TSRMLS_DC,int num_args,va_list args,zend_hash_key * hash_key)4116 static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
4117 {
4118 	zend_class_entry  *ce;
4119 	HashTable         **overriden;
4120 	zend_trait_alias  *alias, **alias_ptr;
4121 	HashTable         *exclude_table;
4122 	char              *lcname;
4123 	unsigned int       fnname_len;
4124 	zend_function      fn_copy;
4125 	void              *dummy;
4126 
4127 	ce            = va_arg(args, zend_class_entry*);
4128 	overriden     = va_arg(args, HashTable**);
4129 	exclude_table = va_arg(args, HashTable*);
4130 
4131 	fnname_len = hash_key->nKeyLength - 1;
4132 
4133 	/* apply aliases which are qualified with a class name, there should not be any ambiguity */
4134 	if (ce->trait_aliases) {
4135 		alias_ptr = ce->trait_aliases;
4136 		alias = *alias_ptr;
4137 		while (alias) {
4138 			/* Scope unset or equal to the function we compare to, and the alias applies to fn */
4139 			if (alias->alias != NULL
4140 				&& (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce)
4141 				&& alias->trait_method->mname_len == fnname_len
4142 				&& (zend_binary_strcasecmp(alias->trait_method->method_name, alias->trait_method->mname_len, hash_key->arKey, fnname_len) == 0)) {
4143 				fn_copy = *fn;
4144 
4145 				/* if it is 0, no modifieres has been changed */
4146 				if (alias->modifiers) {
4147 					fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK));
4148 				}
4149 
4150 				lcname = zend_str_tolower_dup(alias->alias, alias->alias_len);
4151 				zend_add_trait_method(ce, alias->alias, lcname, alias->alias_len+1, &fn_copy, overriden TSRMLS_CC);
4152 				efree(lcname);
4153 
4154 				/* Record the trait from which this alias was resolved. */
4155 				if (!alias->trait_method->ce) {
4156 					alias->trait_method->ce = fn->common.scope;
4157 				}
4158 			}
4159 			alias_ptr++;
4160 			alias = *alias_ptr;
4161 		}
4162 	}
4163 
4164 	lcname = (char *) hash_key->arKey;
4165 
4166 	if (exclude_table == NULL || zend_hash_find(exclude_table, lcname, fnname_len, &dummy) == FAILURE) {
4167 		/* is not in hashtable, thus, function is not to be excluded */
4168 		fn_copy = *fn;
4169 
4170 		/* apply aliases which have not alias name, just setting visibility */
4171 		if (ce->trait_aliases) {
4172 			alias_ptr = ce->trait_aliases;
4173 			alias = *alias_ptr;
4174 			while (alias) {
4175 				/* Scope unset or equal to the function we compare to, and the alias applies to fn */
4176 				if (alias->alias == NULL && alias->modifiers != 0
4177 					&& (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce)
4178 					&& (alias->trait_method->mname_len == fnname_len)
4179 					&& (zend_binary_strcasecmp(alias->trait_method->method_name, alias->trait_method->mname_len, lcname, fnname_len) == 0)) {
4180 
4181 					fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK));
4182 
4183 					/** Record the trait from which this alias was resolved. */
4184 					if (!alias->trait_method->ce) {
4185 						alias->trait_method->ce = fn->common.scope;
4186 					}
4187 				}
4188 				alias_ptr++;
4189 				alias = *alias_ptr;
4190 			}
4191 		}
4192 
4193 		zend_add_trait_method(ce, fn->common.function_name, lcname, fnname_len+1, &fn_copy, overriden TSRMLS_CC);
4194 	}
4195 
4196 	return ZEND_HASH_APPLY_KEEP;
4197 }
4198 /* }}} */
4199 
zend_check_trait_usage(zend_class_entry * ce,zend_class_entry * trait TSRMLS_DC)4200 static void zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC) /* {{{ */
4201 {
4202 	zend_uint i;
4203 
4204 	if ((trait->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT) {
4205 		zend_error_noreturn(E_COMPILE_ERROR, "Class %s is not a trait, Only traits may be used in 'as' and 'insteadof' statements", trait->name);
4206 	}
4207 
4208 	for (i = 0; i < ce->num_traits; i++) {
4209 		if (ce->traits[i] == trait) {
4210 			return;
4211 		}
4212 	}
4213 	zend_error_noreturn(E_COMPILE_ERROR, "Required Trait %s wasn't added to %s", trait->name, ce->name);
4214 }
4215 /* }}} */
4216 
zend_traits_init_trait_structures(zend_class_entry * ce TSRMLS_DC)4217 static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4218 {
4219 	size_t i, j = 0;
4220 	zend_trait_precedence **precedences;
4221 	zend_trait_precedence *cur_precedence;
4222 	zend_trait_method_reference *cur_method_ref;
4223 	char *lcname;
4224 	zend_bool method_exists;
4225 
4226 	/* resolve class references */
4227 	if (ce->trait_precedences) {
4228 		i = 0;
4229 		precedences = ce->trait_precedences;
4230 		ce->trait_precedences = NULL;
4231 		while ((cur_precedence = precedences[i])) {
4232 			/** Resolve classes for all precedence operations. */
4233 			if (cur_precedence->exclude_from_classes) {
4234 				cur_method_ref = cur_precedence->trait_method;
4235 				if (!(cur_precedence->trait_method->ce = zend_fetch_class(cur_method_ref->class_name, cur_method_ref->cname_len,
4236 								ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
4237 					zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", cur_method_ref->class_name);
4238 				}
4239 				zend_check_trait_usage(ce, cur_precedence->trait_method->ce TSRMLS_CC);
4240 
4241 				/** Ensure that the prefered method is actually available. */
4242 				lcname = zend_str_tolower_dup(cur_method_ref->method_name,
4243 											  cur_method_ref->mname_len);
4244 				method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
4245 												 lcname,
4246 												 cur_method_ref->mname_len + 1);
4247 				efree(lcname);
4248 				if (!method_exists) {
4249 					zend_error_noreturn(E_COMPILE_ERROR,
4250 							   "A precedence rule was defined for %s::%s but this method does not exist",
4251 							   cur_method_ref->ce->name,
4252 							   cur_method_ref->method_name);
4253 				}
4254 
4255 				/** With the other traits, we are more permissive.
4256 					We do not give errors for those. This allows to be more
4257 					defensive in such definitions.
4258 					However, we want to make sure that the insteadof declaration
4259 					is consistent in itself.
4260 				 */
4261 				j = 0;
4262 				while (cur_precedence->exclude_from_classes[j]) {
4263 					char* class_name = (char*)cur_precedence->exclude_from_classes[j];
4264 					zend_uint name_length = strlen(class_name);
4265 
4266 					if (!(cur_precedence->exclude_from_classes[j] = zend_fetch_class(class_name, name_length, ZEND_FETCH_CLASS_TRAIT |ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
4267 						zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", class_name);
4268 					}
4269 					zend_check_trait_usage(ce, cur_precedence->exclude_from_classes[j] TSRMLS_CC);
4270 
4271 					/* make sure that the trait method is not from a class mentioned in
4272 					 exclude_from_classes, for consistency */
4273 					if (cur_precedence->trait_method->ce == cur_precedence->exclude_from_classes[j]) {
4274 						zend_error(E_COMPILE_ERROR,
4275 								   "Inconsistent insteadof definition. "
4276 								   "The method %s is to be used from %s, but %s is also on the exclude list",
4277 								   cur_method_ref->method_name,
4278 								   cur_precedence->trait_method->ce->name,
4279 								   cur_precedence->trait_method->ce->name);
4280 					}
4281 
4282 					efree(class_name);
4283 					j++;
4284 				}
4285 			}
4286 			i++;
4287 		}
4288 		ce->trait_precedences = precedences;
4289 	}
4290 
4291 	if (ce->trait_aliases) {
4292 		i = 0;
4293 		while (ce->trait_aliases[i]) {
4294 			/** For all aliases with an explicit class name, resolve the class now. */
4295 			if (ce->trait_aliases[i]->trait_method->class_name) {
4296 				cur_method_ref = ce->trait_aliases[i]->trait_method;
4297 				if (!(cur_method_ref->ce = zend_fetch_class(cur_method_ref->class_name, cur_method_ref->cname_len, ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
4298 					zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", cur_method_ref->class_name);
4299 				}
4300 				zend_check_trait_usage(ce, cur_method_ref->ce TSRMLS_CC);
4301 
4302 				/** And, ensure that the referenced method is resolvable, too. */
4303 				lcname = zend_str_tolower_dup(cur_method_ref->method_name,
4304 						cur_method_ref->mname_len);
4305 				method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
4306 						lcname, cur_method_ref->mname_len + 1);
4307 				efree(lcname);
4308 
4309 				if (!method_exists) {
4310 					zend_error_noreturn(E_COMPILE_ERROR, "An alias was defined for %s::%s but this method does not exist", cur_method_ref->ce->name, cur_method_ref->method_name);
4311 				}
4312 			}
4313 			i++;
4314 		}
4315 	}
4316 }
4317 /* }}} */
4318 
zend_traits_compile_exclude_table(HashTable * exclude_table,zend_trait_precedence ** precedences,zend_class_entry * trait)4319 static void zend_traits_compile_exclude_table(HashTable* exclude_table, zend_trait_precedence **precedences, zend_class_entry *trait) /* {{{ */
4320 {
4321 	size_t i = 0, j;
4322 
4323 	if (!precedences) {
4324 		return;
4325 	}
4326 	while (precedences[i]) {
4327 		if (precedences[i]->exclude_from_classes) {
4328 			j = 0;
4329 			while (precedences[i]->exclude_from_classes[j]) {
4330 				if (precedences[i]->exclude_from_classes[j] == trait) {
4331 					zend_uint lcname_len = precedences[i]->trait_method->mname_len;
4332 					char *lcname = zend_str_tolower_dup(precedences[i]->trait_method->method_name, lcname_len);
4333 
4334 					if (zend_hash_add(exclude_table, lcname, lcname_len, NULL, 0, NULL) == FAILURE) {
4335 						efree(lcname);
4336 						zend_error_noreturn(E_COMPILE_ERROR, "Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times", precedences[i]->trait_method->method_name, trait->name);
4337 					}
4338 					efree(lcname);
4339 				}
4340 				++j;
4341 			}
4342 		}
4343 		++i;
4344 	}
4345 }
4346 /* }}} */
4347 
zend_do_traits_method_binding(zend_class_entry * ce TSRMLS_DC)4348 static void zend_do_traits_method_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4349 {
4350 	zend_uint i;
4351 	HashTable *overriden = NULL;
4352 
4353 	for (i = 0; i < ce->num_traits; i++) {
4354 		if (ce->trait_precedences) {
4355 			HashTable exclude_table;
4356 			zend_trait_precedence **precedences;
4357 
4358 			/* TODO: revisit this start size, may be its not optimal */
4359 			zend_hash_init_ex(&exclude_table, 2, NULL, NULL, 0, 0);
4360 
4361 			precedences = ce->trait_precedences;
4362 			ce->trait_precedences = NULL;
4363 			zend_traits_compile_exclude_table(&exclude_table, precedences, ce->traits[i]);
4364 
4365 			/* copies functions, applies defined aliasing, and excludes unused trait methods */
4366 			zend_hash_apply_with_arguments(&ce->traits[i]->function_table TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, ce, &overriden, &exclude_table);
4367 
4368 			zend_hash_destroy(&exclude_table);
4369 			ce->trait_precedences = precedences;
4370 		} else {
4371 			zend_hash_apply_with_arguments(&ce->traits[i]->function_table TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, ce, &overriden, NULL);
4372 		}
4373 	}
4374 
4375     zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t)zend_fixup_trait_method, ce TSRMLS_CC);
4376 
4377 	if (ce->trait_precedences) {
4378 		i = 0;
4379 		while (ce->trait_precedences[i]) {
4380 			if (ce->trait_precedences[i]->exclude_from_classes) {
4381 				efree(ce->trait_precedences[i]->exclude_from_classes);
4382 				ce->trait_precedences[i]->exclude_from_classes = NULL;
4383 			}
4384 			i++;
4385 		}
4386 	}
4387 
4388 	if (overriden) {
4389 		zend_hash_destroy(overriden);
4390 		FREE_HASHTABLE(overriden);
4391 	}
4392 }
4393 /* }}} */
4394 
find_first_definition(zend_class_entry * ce,size_t current_trait,const char * prop_name,int prop_name_length,ulong prop_hash,zend_class_entry * coliding_ce)4395 static zend_class_entry* find_first_definition(zend_class_entry *ce, size_t current_trait, const char* prop_name, int prop_name_length, ulong prop_hash, zend_class_entry *coliding_ce) /* {{{ */
4396 {
4397 	size_t i;
4398 
4399 	if (coliding_ce == ce) {
4400 		for (i = 0; i < current_trait; i++) {
4401 			if (zend_hash_quick_exists(&ce->traits[i]->properties_info, prop_name, prop_name_length+1, prop_hash)) {
4402 				return ce->traits[i];
4403 			}
4404 		}
4405 	}
4406 
4407 	return coliding_ce;
4408 }
4409 /* }}} */
4410 
zend_do_traits_property_binding(zend_class_entry * ce TSRMLS_DC)4411 static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4412 {
4413 	size_t i;
4414 	zend_property_info *property_info;
4415 	zend_property_info *coliding_prop;
4416 	zval compare_result;
4417 	const char* prop_name;
4418 	int   prop_name_length;
4419 	ulong prop_hash;
4420 	const char* class_name_unused;
4421 	zend_bool not_compatible;
4422 	zval* prop_value;
4423 	char* doc_comment;
4424 	zend_uint flags;
4425 
4426 	/* In the following steps the properties are inserted into the property table
4427 	 * for that, a very strict approach is applied:
4428 	 * - check for compatibility, if not compatible with any property in class -> fatal
4429 	 * - if compatible, then strict notice
4430 	 */
4431 	for (i = 0; i < ce->num_traits; i++) {
4432 		for (zend_hash_internal_pointer_reset(&ce->traits[i]->properties_info);
4433 			 zend_hash_get_current_data(&ce->traits[i]->properties_info, (void *) &property_info) == SUCCESS;
4434 			 zend_hash_move_forward(&ce->traits[i]->properties_info)) {
4435 			/* first get the unmangeld name if necessary,
4436 			 * then check whether the property is already there
4437 			 */
4438 			flags = property_info->flags;
4439 			if ((flags & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) {
4440 				prop_hash = property_info->h;
4441 				prop_name = property_info->name;
4442 				prop_name_length = property_info->name_length;
4443 			} else {
4444 				/* for private and protected we need to unmangle the names */
4445 				zend_unmangle_property_name_ex(property_info->name, property_info->name_length,
4446 											&class_name_unused, &prop_name, &prop_name_length);
4447 				prop_hash = zend_get_hash_value(prop_name, prop_name_length + 1);
4448 			}
4449 
4450 			/* next: check for conflicts with current class */
4451 			if (zend_hash_quick_find(&ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop) == SUCCESS) {
4452 				if (coliding_prop->flags & ZEND_ACC_SHADOW) {
4453 					zend_hash_quick_del(&ce->properties_info, prop_name, prop_name_length+1, prop_hash);
4454 					flags |= ZEND_ACC_CHANGED;
4455 				} else {
4456 					if ((coliding_prop->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))
4457 						== (flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
4458 						/* flags are identical, now the value needs to be checked */
4459 						if (flags & ZEND_ACC_STATIC) {
4460 							not_compatible = (FAILURE == compare_function(&compare_result,
4461 											  ce->default_static_members_table[coliding_prop->offset],
4462 											  ce->traits[i]->default_static_members_table[property_info->offset] TSRMLS_CC))
4463 								  || (Z_LVAL(compare_result) != 0);
4464 						} else {
4465 							not_compatible = (FAILURE == compare_function(&compare_result,
4466 											  ce->default_properties_table[coliding_prop->offset],
4467 											  ce->traits[i]->default_properties_table[property_info->offset] TSRMLS_CC))
4468 								  || (Z_LVAL(compare_result) != 0);
4469 						}
4470 					} else {
4471 						/* the flags are not identical, thus, we assume properties are not compatible */
4472 						not_compatible = 1;
4473 					}
4474 
4475 					if (not_compatible) {
4476 						zend_error_noreturn(E_COMPILE_ERROR,
4477 							   "%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
4478 								find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
4479 								property_info->ce->name,
4480 								prop_name,
4481 								ce->name);
4482 					} else {
4483 						zend_error(E_STRICT,
4484 							   "%s and %s define the same property ($%s) in the composition of %s. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed",
4485 								find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
4486 								property_info->ce->name,
4487 								prop_name,
4488 								ce->name);
4489 						continue;
4490 					}
4491 				}
4492 			}
4493 
4494 			/* property not found, so lets add it */
4495 			if (flags & ZEND_ACC_STATIC) {
4496 				prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
4497 			} else {
4498 				prop_value = ce->traits[i]->default_properties_table[property_info->offset];
4499 			}
4500 			Z_ADDREF_P(prop_value);
4501 
4502 			doc_comment = property_info->doc_comment ? estrndup(property_info->doc_comment, property_info->doc_comment_len) : NULL;
4503 			zend_declare_property_ex(ce, prop_name, prop_name_length,
4504 									 prop_value, flags,
4505 								     doc_comment, property_info->doc_comment_len TSRMLS_CC);
4506 		}
4507 	}
4508 }
4509 /* }}} */
4510 
zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry * ce TSRMLS_DC)4511 static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4512 {
4513 	int i = 0;
4514 	zend_trait_alias* cur_alias;
4515 	char* lc_method_name;
4516 
4517 	if (ce->trait_aliases) {
4518 		while (ce->trait_aliases[i]) {
4519 			cur_alias = ce->trait_aliases[i];
4520 			/** The trait for this alias has not been resolved, this means, this
4521 				alias was not applied. Abort with an error. */
4522 			if (!cur_alias->trait_method->ce) {
4523 				if (cur_alias->alias) {
4524 					/** Plain old inconsistency/typo/bug */
4525 					zend_error_noreturn(E_COMPILE_ERROR,
4526 							   "An alias (%s) was defined for method %s(), but this method does not exist",
4527 							   cur_alias->alias,
4528 							   cur_alias->trait_method->method_name);
4529 				} else {
4530 					/** Here are two possible cases:
4531 						1) this is an attempt to modifiy the visibility
4532 						   of a method introduce as part of another alias.
4533 						   Since that seems to violate the DRY principle,
4534 						   we check against it and abort.
4535 						2) it is just a plain old inconsitency/typo/bug
4536 						   as in the case where alias is set. */
4537 
4538 					lc_method_name = zend_str_tolower_dup(cur_alias->trait_method->method_name,
4539 														  cur_alias->trait_method->mname_len);
4540 					if (zend_hash_exists(&ce->function_table,
4541 										 lc_method_name,
4542 										 cur_alias->trait_method->mname_len+1)) {
4543 						efree(lc_method_name);
4544 						zend_error_noreturn(E_COMPILE_ERROR,
4545 								   "The modifiers for the trait alias %s() need to be changed in the same statment in which the alias is defined. Error",
4546 								   cur_alias->trait_method->method_name);
4547 					} else {
4548 						efree(lc_method_name);
4549 						zend_error_noreturn(E_COMPILE_ERROR,
4550 								   "The modifiers of the trait method %s() are changed, but this method does not exist. Error",
4551 								   cur_alias->trait_method->method_name);
4552 
4553 					}
4554 				}
4555 			}
4556 			i++;
4557 		}
4558 	}
4559 }
4560 /* }}} */
4561 
zend_do_bind_traits(zend_class_entry * ce TSRMLS_DC)4562 ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4563 {
4564 
4565 	if (ce->num_traits <= 0) {
4566 		return;
4567 	}
4568 
4569 	/* complete initialization of trait strutures in ce */
4570 	zend_traits_init_trait_structures(ce TSRMLS_CC);
4571 
4572 	/* first care about all methods to be flattened into the class */
4573 	zend_do_traits_method_binding(ce TSRMLS_CC);
4574 
4575 	/* Aliases which have not been applied indicate typos/bugs. */
4576 	zend_do_check_for_inconsistent_traits_aliasing(ce TSRMLS_CC);
4577 
4578 	/* then flatten the properties into it, to, mostly to notfiy developer about problems */
4579 	zend_do_traits_property_binding(ce TSRMLS_CC);
4580 
4581 	/* verify that all abstract methods from traits have been implemented */
4582 	zend_verify_abstract_class(ce TSRMLS_CC);
4583 
4584 	/* now everything should be fine and an added ZEND_ACC_IMPLICIT_ABSTRACT_CLASS should be removed */
4585 	if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
4586 		ce->ce_flags -= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
4587 	}
4588 }
4589 /* }}} */
4590 
do_bind_function(const zend_op_array * op_array,zend_op * opline,HashTable * function_table,zend_bool compile_time)4591 ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
4592 {
4593 	zend_function *function;
4594 	zval *op1, *op2;
4595 
4596 	if (compile_time) {
4597 		op1 = &CONSTANT_EX(op_array, opline->op1.constant);
4598 		op2 = &CONSTANT_EX(op_array, opline->op2.constant);
4599 	} else {
4600 		op1 = opline->op1.zv;
4601 		op2 = opline->op2.zv;
4602 	}
4603 
4604 	zend_hash_quick_find(function_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void *) &function);
4605 	if (zend_hash_quick_add(function_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), function, sizeof(zend_function), NULL)==FAILURE) {
4606 		int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
4607 		zend_function *old_function;
4608 
4609 		if (zend_hash_quick_find(function_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), (void *) &old_function)==SUCCESS
4610 			&& old_function->type == ZEND_USER_FUNCTION
4611 			&& old_function->op_array.last > 0) {
4612 			zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
4613 						function->common.function_name,
4614 						old_function->op_array.filename,
4615 						old_function->op_array.opcodes[0].lineno);
4616 		} else {
4617 			zend_error(error_level, "Cannot redeclare %s()", function->common.function_name);
4618 		}
4619 		return FAILURE;
4620 	} else {
4621 		(*function->op_array.refcount)++;
4622 		function->op_array.static_variables = NULL; /* NULL out the unbound function */
4623 		return SUCCESS;
4624 	}
4625 }
4626 /* }}} */
4627 
zend_prepare_reference(znode * result,znode * class_name,znode * method_name TSRMLS_DC)4628 void zend_prepare_reference(znode *result, znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
4629 {
4630 	zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference));
4631 	method_ref->ce = NULL;
4632 
4633 	/* REM: There should not be a need for copying,
4634 	   zend_do_begin_class_declaration is also just using that string */
4635 	if (class_name) {
4636 		zend_resolve_class_name(class_name TSRMLS_CC);
4637 		method_ref->class_name = Z_STRVAL(class_name->u.constant);
4638 		method_ref->cname_len  = Z_STRLEN(class_name->u.constant);
4639 	} else {
4640 		method_ref->class_name = NULL;
4641 		method_ref->cname_len  = 0;
4642 	}
4643 
4644 	method_ref->method_name = Z_STRVAL(method_name->u.constant);
4645 	method_ref->mname_len   = Z_STRLEN(method_name->u.constant);
4646 
4647 	result->u.op.ptr = method_ref;
4648 	result->op_type = IS_TMP_VAR;
4649 }
4650 /* }}} */
4651 
zend_add_trait_alias(znode * method_reference,znode * modifiers,znode * alias TSRMLS_DC)4652 void zend_add_trait_alias(znode *method_reference, znode *modifiers, znode *alias TSRMLS_DC) /* {{{ */
4653 {
4654 	zend_class_entry *ce = CG(active_class_entry);
4655 	zend_trait_alias *trait_alias;
4656 
4657 	if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_STATIC) {
4658 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as method modifier");
4659 		return;
4660 	} else if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_ABSTRACT) {
4661 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier");
4662 		return;
4663 	} else if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_FINAL) {
4664 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as method modifier");
4665 		return;
4666 	}
4667 
4668 	trait_alias = emalloc(sizeof(zend_trait_alias));
4669 	trait_alias->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
4670 	trait_alias->modifiers = Z_LVAL(modifiers->u.constant);
4671 	if (alias) {
4672 		trait_alias->alias = Z_STRVAL(alias->u.constant);
4673 		trait_alias->alias_len = Z_STRLEN(alias->u.constant);
4674 	} else {
4675 		trait_alias->alias = NULL;
4676 	}
4677 	zend_add_to_list(&ce->trait_aliases, trait_alias TSRMLS_CC);
4678 }
4679 /* }}} */
4680 
zend_add_trait_precedence(znode * method_reference,znode * trait_list TSRMLS_DC)4681 void zend_add_trait_precedence(znode *method_reference, znode *trait_list TSRMLS_DC) /* {{{ */
4682 {
4683 	zend_class_entry *ce = CG(active_class_entry);
4684 	zend_trait_precedence *trait_precedence = emalloc(sizeof(zend_trait_precedence));
4685 
4686 	trait_precedence->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
4687 	trait_precedence->exclude_from_classes = (zend_class_entry**) trait_list->u.op.ptr;
4688 
4689 	zend_add_to_list(&ce->trait_precedences, trait_precedence TSRMLS_CC);
4690 }
4691 /* }}} */
4692 
do_bind_class(const zend_op_array * op_array,const zend_op * opline,HashTable * class_table,zend_bool compile_time TSRMLS_DC)4693 ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
4694 {
4695 	zend_class_entry *ce, **pce;
4696 	zval *op1, *op2;
4697 
4698 	if (compile_time) {
4699 		op1 = &CONSTANT_EX(op_array, opline->op1.constant);
4700 		op2 = &CONSTANT_EX(op_array, opline->op2.constant);
4701 	} else {
4702 		op1 = opline->op1.zv;
4703 		op2 = opline->op2.zv;
4704 	}
4705 	if (zend_hash_quick_find(class_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void **) &pce)==FAILURE) {
4706 		zend_error_noreturn(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", Z_STRVAL_P(op1));
4707 		return NULL;
4708 	} else {
4709 		ce = *pce;
4710 	}
4711 	ce->refcount++;
4712 	if (zend_hash_quick_add(class_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
4713 		ce->refcount--;
4714 		if (!compile_time) {
4715 			/* If we're in compile time, in practice, it's quite possible
4716 			 * that we'll never reach this class declaration at runtime,
4717 			 * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
4718 			 * approach to work.
4719 			 */
4720 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
4721 		}
4722 		return NULL;
4723 	} else {
4724 		if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
4725 			zend_verify_abstract_class(ce TSRMLS_CC);
4726 		}
4727 		return ce;
4728 	}
4729 }
4730 /* }}} */
4731 
do_bind_inherited_class(const zend_op_array * op_array,const zend_op * opline,HashTable * class_table,zend_class_entry * parent_ce,zend_bool compile_time TSRMLS_DC)4732 ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC) /* {{{ */
4733 {
4734 	zend_class_entry *ce, **pce;
4735 	int found_ce;
4736 	zval *op1, *op2;
4737 
4738 	if (compile_time) {
4739 		op1 = &CONSTANT_EX(op_array, opline->op1.constant);
4740 		op2 = &CONSTANT_EX(op_array, opline->op2.constant);
4741 	} else {
4742 		op1 = opline->op1.zv;
4743 		op2 = opline->op2.zv;
4744 	}
4745 
4746 	found_ce = zend_hash_quick_find(class_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void **) &pce);
4747 
4748 	if (found_ce == FAILURE) {
4749 		if (!compile_time) {
4750 			/* If we're in compile time, in practice, it's quite possible
4751 			 * that we'll never reach this class declaration at runtime,
4752 			 * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
4753 			 * approach to work.
4754 			 */
4755 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare class %s", Z_STRVAL_P(op2));
4756 		}
4757 		return NULL;
4758 	} else {
4759 		ce = *pce;
4760 	}
4761 
4762 	if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
4763 		zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name, parent_ce->name);
4764 	} else if ((parent_ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
4765 		zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend from trait %s", ce->name, parent_ce->name);
4766 	}
4767 
4768 	zend_do_inheritance(ce, parent_ce TSRMLS_CC);
4769 
4770 	ce->refcount++;
4771 
4772 	/* Register the derived class */
4773 	if (zend_hash_quick_add(class_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
4774 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
4775 	}
4776 	return ce;
4777 }
4778 /* }}} */
4779 
zend_do_early_binding(TSRMLS_D)4780 void zend_do_early_binding(TSRMLS_D) /* {{{ */
4781 {
4782 	zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
4783 	HashTable *table;
4784 
4785 	while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) {
4786 		opline--;
4787 	}
4788 
4789 	switch (opline->opcode) {
4790 		case ZEND_DECLARE_FUNCTION:
4791 			if (do_bind_function(CG(active_op_array), opline, CG(function_table), 1) == FAILURE) {
4792 				return;
4793 			}
4794 			table = CG(function_table);
4795 			break;
4796 		case ZEND_DECLARE_CLASS:
4797 			if (do_bind_class(CG(active_op_array), opline, CG(class_table), 1 TSRMLS_CC) == NULL) {
4798 				return;
4799 			}
4800 			table = CG(class_table);
4801 			break;
4802 		case ZEND_DECLARE_INHERITED_CLASS:
4803 			{
4804 				zend_op *fetch_class_opline = opline-1;
4805 				zval *parent_name;
4806 				zend_class_entry **pce;
4807 
4808 				parent_name = &CONSTANT(fetch_class_opline->op2.constant);
4809 				if ((zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) ||
4810 				    ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
4811 				     ((*pce)->type == ZEND_INTERNAL_CLASS))) {
4812 				    if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
4813 						zend_uint *opline_num = &CG(active_op_array)->early_binding;
4814 
4815 						while (*opline_num != -1) {
4816 							opline_num = &CG(active_op_array)->opcodes[*opline_num].result.opline_num;
4817 						}
4818 						*opline_num = opline - CG(active_op_array)->opcodes;
4819 						opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
4820 						opline->result_type = IS_UNUSED;
4821 						opline->result.opline_num = -1;
4822 					}
4823 					return;
4824 				}
4825 				if (do_bind_inherited_class(CG(active_op_array), opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
4826 					return;
4827 				}
4828 				/* clear unnecessary ZEND_FETCH_CLASS opcode */
4829 				zend_del_literal(CG(active_op_array), fetch_class_opline->op2.constant);
4830 				MAKE_NOP(fetch_class_opline);
4831 
4832 				table = CG(class_table);
4833 				break;
4834 			}
4835 		case ZEND_VERIFY_ABSTRACT_CLASS:
4836 		case ZEND_ADD_INTERFACE:
4837 		case ZEND_ADD_TRAIT:
4838 		case ZEND_BIND_TRAITS:
4839 			/* We currently don't early-bind classes that implement interfaces */
4840 			/* Classes with traits are handled exactly the same, no early-bind here */
4841 			return;
4842 		default:
4843 			zend_error_noreturn(E_COMPILE_ERROR, "Invalid binding type");
4844 			return;
4845 	}
4846 
4847 	zend_hash_quick_del(table, Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)), Z_HASH_P(&CONSTANT(opline->op1.constant)));
4848 	zend_del_literal(CG(active_op_array), opline->op1.constant);
4849 	zend_del_literal(CG(active_op_array), opline->op2.constant);
4850 	MAKE_NOP(opline);
4851 }
4852 /* }}} */
4853 
zend_do_delayed_early_binding(const zend_op_array * op_array TSRMLS_DC)4854 ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS_DC) /* {{{ */
4855 {
4856 	if (op_array->early_binding != -1) {
4857 		zend_bool orig_in_compilation = CG(in_compilation);
4858 		zend_uint opline_num = op_array->early_binding;
4859 		zend_class_entry **pce;
4860 
4861 		CG(in_compilation) = 1;
4862 		while (opline_num != -1) {
4863 			if (zend_lookup_class(Z_STRVAL_P(op_array->opcodes[opline_num-1].op2.zv), Z_STRLEN_P(op_array->opcodes[opline_num-1].op2.zv), &pce TSRMLS_CC) == SUCCESS) {
4864 				do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), *pce, 0 TSRMLS_CC);
4865 			}
4866 			opline_num = op_array->opcodes[opline_num].result.opline_num;
4867 		}
4868 		CG(in_compilation) = orig_in_compilation;
4869 	}
4870 }
4871 /* }}} */
4872 
zend_do_boolean_or_begin(znode * expr1,znode * op_token TSRMLS_DC)4873 void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
4874 {
4875 	int next_op_number = get_next_op_number(CG(active_op_array));
4876 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4877 
4878 	opline->opcode = ZEND_JMPNZ_EX;
4879 	if (expr1->op_type == IS_TMP_VAR) {
4880 		SET_NODE(opline->result, expr1);
4881 	} else {
4882 		opline->result.var = get_temporary_variable(CG(active_op_array));
4883 		opline->result_type = IS_TMP_VAR;
4884 	}
4885 	SET_NODE(opline->op1, expr1);
4886 	SET_UNUSED(opline->op2);
4887 
4888 	op_token->u.op.opline_num = next_op_number;
4889 
4890 	GET_NODE(expr1, opline->result);
4891 }
4892 /* }}} */
4893 
zend_do_boolean_or_end(znode * result,const znode * expr1,const znode * expr2,znode * op_token TSRMLS_DC)4894 void zend_do_boolean_or_end(znode *result, const znode *expr1, const znode *expr2, znode *op_token TSRMLS_DC) /* {{{ */
4895 {
4896 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4897 
4898 	*result = *expr1; /* we saved the original result in expr1 */
4899 	opline->opcode = ZEND_BOOL;
4900 	SET_NODE(opline->result, result);
4901 	SET_NODE(opline->op1, expr2);
4902 	SET_UNUSED(opline->op2);
4903 
4904 	CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
4905 }
4906 /* }}} */
4907 
zend_do_boolean_and_begin(znode * expr1,znode * op_token TSRMLS_DC)4908 void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
4909 {
4910 	int next_op_number = get_next_op_number(CG(active_op_array));
4911 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4912 
4913 	opline->opcode = ZEND_JMPZ_EX;
4914 	if (expr1->op_type == IS_TMP_VAR) {
4915 		SET_NODE(opline->result, expr1);
4916 	} else {
4917 		opline->result.var = get_temporary_variable(CG(active_op_array));
4918 		opline->result_type = IS_TMP_VAR;
4919 	}
4920 	SET_NODE(opline->op1, expr1);
4921 	SET_UNUSED(opline->op2);
4922 
4923 	op_token->u.op.opline_num = next_op_number;
4924 
4925 	GET_NODE(expr1, opline->result);
4926 }
4927 /* }}} */
4928 
zend_do_boolean_and_end(znode * result,const znode * expr1,const znode * expr2,const znode * op_token TSRMLS_DC)4929 void zend_do_boolean_and_end(znode *result, const znode *expr1, const znode *expr2, const znode *op_token TSRMLS_DC) /* {{{ */
4930 {
4931 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4932 
4933 	*result = *expr1; /* we saved the original result in expr1 */
4934 	opline->opcode = ZEND_BOOL;
4935 	SET_NODE(opline->result, result);
4936 	SET_NODE(opline->op1, expr2);
4937 	SET_UNUSED(opline->op2);
4938 
4939 	CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
4940 }
4941 /* }}} */
4942 
zend_do_do_while_begin(TSRMLS_D)4943 void zend_do_do_while_begin(TSRMLS_D) /* {{{ */
4944 {
4945 	do_begin_loop(TSRMLS_C);
4946 	INC_BPC(CG(active_op_array));
4947 }
4948 /* }}} */
4949 
zend_do_do_while_end(const znode * do_token,const znode * expr_open_bracket,const znode * expr TSRMLS_DC)4950 void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket, const znode *expr TSRMLS_DC) /* {{{ */
4951 {
4952 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4953 
4954 	opline->opcode = ZEND_JMPNZ;
4955 	SET_NODE(opline->op1, expr);
4956 	opline->op2.opline_num = do_token->u.op.opline_num;
4957 	SET_UNUSED(opline->op2);
4958 
4959 	do_end_loop(expr_open_bracket->u.op.opline_num, 0 TSRMLS_CC);
4960 
4961 	DEC_BPC(CG(active_op_array));
4962 }
4963 /* }}} */
4964 
zend_do_brk_cont(zend_uchar op,const znode * expr TSRMLS_DC)4965 void zend_do_brk_cont(zend_uchar op, const znode *expr TSRMLS_DC) /* {{{ */
4966 {
4967 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4968 
4969 	opline->opcode = op;
4970 	opline->op1.opline_num = CG(context).current_brk_cont;
4971 	SET_UNUSED(opline->op1);
4972 	if (expr) {
4973 		if (expr->op_type != IS_CONST) {
4974 			zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand is no longer supported", op == ZEND_BRK ? "break" : "continue");
4975 		} else if (Z_TYPE(expr->u.constant) != IS_LONG || Z_LVAL(expr->u.constant) < 1) {
4976 			zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers", op == ZEND_BRK ? "break" : "continue");
4977 		}
4978 		SET_NODE(opline->op2, expr);
4979 	} else {
4980 		LITERAL_LONG(opline->op2, 1);
4981 		opline->op2_type = IS_CONST;
4982 	}
4983 }
4984 /* }}} */
4985 
zend_do_switch_cond(const znode * cond TSRMLS_DC)4986 void zend_do_switch_cond(const znode *cond TSRMLS_DC) /* {{{ */
4987 {
4988 	zend_switch_entry switch_entry;
4989 
4990 	switch_entry.cond = *cond;
4991 	switch_entry.default_case = -1;
4992 	switch_entry.control_var = -1;
4993 	zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
4994 
4995 	do_begin_loop(TSRMLS_C);
4996 
4997 	INC_BPC(CG(active_op_array));
4998 }
4999 /* }}} */
5000 
zend_do_switch_end(const znode * case_list TSRMLS_DC)5001 void zend_do_switch_end(const znode *case_list TSRMLS_DC) /* {{{ */
5002 {
5003 	zend_op *opline;
5004 	zend_switch_entry *switch_entry_ptr;
5005 
5006 	zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
5007 
5008 	/* add code to jmp to default case */
5009 	if (switch_entry_ptr->default_case != -1) {
5010 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5011 		opline->opcode = ZEND_JMP;
5012 		SET_UNUSED(opline->op1);
5013 		SET_UNUSED(opline->op2);
5014 		opline->op1.opline_num = switch_entry_ptr->default_case;
5015 	}
5016 
5017 	if (case_list->op_type != IS_UNUSED) { /* non-empty switch */
5018 		int next_op_number = get_next_op_number(CG(active_op_array));
5019 
5020 		CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
5021 	}
5022 
5023 	/* remember break/continue loop information */
5024 	CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
5025 	CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
5026 
5027 	if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
5028 		/* emit free for the switch condition*/
5029 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5030 		opline->opcode = (switch_entry_ptr->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
5031 		SET_NODE(opline->op1, &switch_entry_ptr->cond);
5032 		SET_UNUSED(opline->op2);
5033 	}
5034 	if (switch_entry_ptr->cond.op_type == IS_CONST) {
5035 		zval_dtor(&switch_entry_ptr->cond.u.constant);
5036 	}
5037 
5038 	zend_stack_del_top(&CG(switch_cond_stack));
5039 
5040 	DEC_BPC(CG(active_op_array));
5041 }
5042 /* }}} */
5043 
zend_do_case_before_statement(const znode * case_list,znode * case_token,const znode * case_expr TSRMLS_DC)5044 void zend_do_case_before_statement(const znode *case_list, znode *case_token, const znode *case_expr TSRMLS_DC) /* {{{ */
5045 {
5046 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5047 	int next_op_number;
5048 	zend_switch_entry *switch_entry_ptr;
5049 	znode result;
5050 
5051 	zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
5052 
5053 	if (switch_entry_ptr->control_var == -1) {
5054 		switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array));
5055 	}
5056 	opline->opcode = ZEND_CASE;
5057 	opline->result.var = switch_entry_ptr->control_var;
5058 	opline->result_type = IS_TMP_VAR;
5059 	SET_NODE(opline->op1, &switch_entry_ptr->cond);
5060 	SET_NODE(opline->op2, case_expr);
5061 	if (opline->op1_type == IS_CONST) {
5062 		zval_copy_ctor(&CONSTANT(opline->op1.constant));
5063 	}
5064 	GET_NODE(&result, opline->result);
5065 
5066 	next_op_number = get_next_op_number(CG(active_op_array));
5067 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5068 	opline->opcode = ZEND_JMPZ;
5069 	SET_NODE(opline->op1, &result);
5070 	SET_UNUSED(opline->op2);
5071 	case_token->u.op.opline_num = next_op_number;
5072 
5073 	if (case_list->op_type==IS_UNUSED) {
5074 		return;
5075 	}
5076 	next_op_number = get_next_op_number(CG(active_op_array));
5077 	CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
5078 }
5079 /* }}} */
5080 
zend_do_case_after_statement(znode * result,const znode * case_token TSRMLS_DC)5081 void zend_do_case_after_statement(znode *result, const znode *case_token TSRMLS_DC) /* {{{ */
5082 {
5083 	int next_op_number = get_next_op_number(CG(active_op_array));
5084 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5085 
5086 	opline->opcode = ZEND_JMP;
5087 	SET_UNUSED(opline->op1);
5088 	SET_UNUSED(opline->op2);
5089 	result->u.op.opline_num = next_op_number;
5090 
5091 	switch (CG(active_op_array)->opcodes[case_token->u.op.opline_num].opcode) {
5092 		case ZEND_JMP:
5093 			CG(active_op_array)->opcodes[case_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
5094 			break;
5095 		case ZEND_JMPZ:
5096 			CG(active_op_array)->opcodes[case_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
5097 			break;
5098 	}
5099 }
5100 /* }}} */
5101 
zend_do_default_before_statement(const znode * case_list,znode * default_token TSRMLS_DC)5102 void zend_do_default_before_statement(const znode *case_list, znode *default_token TSRMLS_DC) /* {{{ */
5103 {
5104 	int next_op_number = get_next_op_number(CG(active_op_array));
5105 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5106 	zend_switch_entry *switch_entry_ptr;
5107 
5108 	zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
5109 
5110 	opline->opcode = ZEND_JMP;
5111 	SET_UNUSED(opline->op1);
5112 	SET_UNUSED(opline->op2);
5113 	default_token->u.op.opline_num = next_op_number;
5114 
5115 	next_op_number = get_next_op_number(CG(active_op_array));
5116 	switch_entry_ptr->default_case = next_op_number;
5117 
5118 	if (case_list->op_type==IS_UNUSED) {
5119 		return;
5120 	}
5121 	CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
5122 }
5123 /* }}} */
5124 
zend_do_begin_class_declaration(const znode * class_token,znode * class_name,const znode * parent_class_name TSRMLS_DC)5125 void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC) /* {{{ */
5126 {
5127 	zend_op *opline;
5128 	int doing_inheritance = 0;
5129 	zend_class_entry *new_class_entry;
5130 	char *lcname;
5131 	int error = 0;
5132 	zval **ns_name, key;
5133 
5134 	if (CG(active_class_entry)) {
5135 		zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
5136 		return;
5137 	}
5138 
5139 	lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
5140 
5141 	if (!(strcmp(lcname, "self") && strcmp(lcname, "parent"))) {
5142 		efree(lcname);
5143 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", Z_STRVAL(class_name->u.constant));
5144 	}
5145 
5146 	/* Class name must not conflict with import names */
5147 	if (CG(current_import) &&
5148 	    zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
5149 		error = 1;
5150 	}
5151 
5152 	if (CG(current_namespace)) {
5153 		/* Prefix class name with name of current namespace */
5154 		znode tmp;
5155 
5156 		tmp.op_type = IS_CONST;
5157 		tmp.u.constant = *CG(current_namespace);
5158 		zval_copy_ctor(&tmp.u.constant);
5159 		zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
5160 		*class_name = tmp;
5161 		efree(lcname);
5162 		lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
5163 	}
5164 
5165 	if (error) {
5166 		char *tmp = zend_str_tolower_dup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
5167 
5168 		if (Z_STRLEN_PP(ns_name) != Z_STRLEN(class_name->u.constant) ||
5169 			memcmp(tmp, lcname, Z_STRLEN(class_name->u.constant))) {
5170 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s because the name is already in use", Z_STRVAL(class_name->u.constant));
5171 		}
5172 		efree(tmp);
5173 	}
5174 
5175 	new_class_entry = emalloc(sizeof(zend_class_entry));
5176 	new_class_entry->type = ZEND_USER_CLASS;
5177 	new_class_entry->name = zend_new_interned_string(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant) + 1, 1 TSRMLS_CC);
5178 	new_class_entry->name_length = Z_STRLEN(class_name->u.constant);
5179 
5180 	zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
5181 	new_class_entry->info.user.filename = zend_get_compiled_filename(TSRMLS_C);
5182 	new_class_entry->info.user.line_start = class_token->u.op.opline_num;
5183 	new_class_entry->ce_flags |= class_token->EA;
5184 
5185 	if (parent_class_name && parent_class_name->op_type != IS_UNUSED) {
5186 		switch (parent_class_name->EA) {
5187 			case ZEND_FETCH_CLASS_SELF:
5188 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'self' as class name as it is reserved");
5189 				break;
5190 			case ZEND_FETCH_CLASS_PARENT:
5191 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved");
5192 				break;
5193 			case ZEND_FETCH_CLASS_STATIC:
5194 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as class name as it is reserved");
5195 				break;
5196 			default:
5197 				break;
5198 		}
5199 		doing_inheritance = 1;
5200 	}
5201 
5202 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5203 	opline->op1_type = IS_CONST;
5204 	build_runtime_defined_function_key(&key, lcname, new_class_entry->name_length TSRMLS_CC);
5205 	opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
5206 	Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
5207 
5208 	opline->op2_type = IS_CONST;
5209 
5210 	if (doing_inheritance) {
5211 		/* Make sure a trait does not try to extend a class */
5212 		if ((new_class_entry->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
5213 			zend_error_noreturn(E_COMPILE_ERROR, "A trait (%s) cannot extend a class. Traits can only be composed from other traits with the 'use' keyword. Error", new_class_entry->name);
5214 		}
5215 
5216 		opline->extended_value = parent_class_name->u.op.var;
5217 		opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
5218 	} else {
5219 		opline->opcode = ZEND_DECLARE_CLASS;
5220 	}
5221 
5222 	LITERAL_STRINGL(opline->op2, lcname, new_class_entry->name_length, 0);
5223 	CALCULATE_LITERAL_HASH(opline->op2.constant);
5224 
5225 	zend_hash_quick_update(CG(class_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &new_class_entry, sizeof(zend_class_entry *), NULL);
5226 	CG(active_class_entry) = new_class_entry;
5227 
5228 	opline->result.var = get_temporary_variable(CG(active_op_array));
5229 	opline->result_type = IS_VAR;
5230 	GET_NODE(&CG(implementing_class), opline->result);
5231 
5232 	if (CG(doc_comment)) {
5233 		CG(active_class_entry)->info.user.doc_comment = CG(doc_comment);
5234 		CG(active_class_entry)->info.user.doc_comment_len = CG(doc_comment_len);
5235 		CG(doc_comment) = NULL;
5236 		CG(doc_comment_len) = 0;
5237 	}
5238 }
5239 /* }}} */
5240 
do_verify_abstract_class(TSRMLS_D)5241 static void do_verify_abstract_class(TSRMLS_D) /* {{{ */
5242 {
5243 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5244 
5245 	opline->opcode = ZEND_VERIFY_ABSTRACT_CLASS;
5246 	SET_NODE(opline->op1, &CG(implementing_class));
5247 	SET_UNUSED(opline->op2);
5248 }
5249 /* }}} */
5250 
zend_do_end_class_declaration(const znode * class_token,const znode * parent_token TSRMLS_DC)5251 void zend_do_end_class_declaration(const znode *class_token, const znode *parent_token TSRMLS_DC) /* {{{ */
5252 {
5253 	zend_class_entry *ce = CG(active_class_entry);
5254 
5255 	if (ce->constructor) {
5256 		ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
5257 		if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
5258 			zend_error_noreturn(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static", ce->name, ce->constructor->common.function_name);
5259 		}
5260 	}
5261 	if (ce->destructor) {
5262 		ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
5263 		if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
5264 			zend_error_noreturn(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static", ce->name, ce->destructor->common.function_name);
5265 		}
5266 	}
5267 	if (ce->clone) {
5268 		ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
5269 		if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
5270 			zend_error_noreturn(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static", ce->name, ce->clone->common.function_name);
5271 		}
5272 	}
5273 
5274 	ce->info.user.line_end = zend_get_compiled_lineno(TSRMLS_C);
5275 
5276 	/* Check for traits and proceed like with interfaces.
5277 	 * The only difference will be a combined handling of them in the end.
5278 	 * Thus, we need another opcode here. */
5279 	if (ce->num_traits > 0) {
5280 		zend_op *opline;
5281 
5282 		ce->traits = NULL;
5283 		ce->num_traits = 0;
5284 		ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS;
5285 
5286 		/* opcode generation: */
5287 		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5288 		opline->opcode = ZEND_BIND_TRAITS;
5289 		SET_NODE(opline->op1, &CG(implementing_class));
5290 	}
5291 
5292 	if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
5293 		&& (parent_token || (ce->num_interfaces > 0))) {
5294 		zend_verify_abstract_class(ce TSRMLS_CC);
5295 		if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) {
5296 			do_verify_abstract_class(TSRMLS_C);
5297 		}
5298 	}
5299 	/* Inherit interfaces; reset number to zero, we need it for above check and
5300 	 * will restore it during actual implementation.
5301 	 * The ZEND_ACC_IMPLEMENT_INTERFACES flag disables double call to
5302 	 * zend_verify_abstract_class() */
5303 	if (ce->num_interfaces > 0) {
5304 		ce->interfaces = NULL;
5305 		ce->num_interfaces = 0;
5306 		ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
5307 	}
5308 
5309 	CG(active_class_entry) = NULL;
5310 }
5311 /* }}} */
5312 
zend_do_implements_interface(znode * interface_name TSRMLS_DC)5313 void zend_do_implements_interface(znode *interface_name TSRMLS_DC) /* {{{ */
5314 {
5315 	zend_op *opline;
5316 
5317 	/* Traits can not implement interfaces */
5318 	if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
5319 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as interface on '%s' since it is a Trait",
5320 							 Z_STRVAL(interface_name->u.constant),
5321 							 CG(active_class_entry)->name);
5322 	}
5323 
5324 	switch (zend_get_class_fetch_type(Z_STRVAL(interface_name->u.constant), Z_STRLEN(interface_name->u.constant))) {
5325 		case ZEND_FETCH_CLASS_SELF:
5326 		case ZEND_FETCH_CLASS_PARENT:
5327 		case ZEND_FETCH_CLASS_STATIC:
5328 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as interface name as it is reserved", Z_STRVAL(interface_name->u.constant));
5329 			break;
5330 		default:
5331 			break;
5332 	}
5333 
5334 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5335 	opline->opcode = ZEND_ADD_INTERFACE;
5336 	SET_NODE(opline->op1, &CG(implementing_class));
5337 	zend_resolve_class_name(interface_name TSRMLS_CC);
5338 	opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;
5339 	opline->op2_type = IS_CONST;
5340 	opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &interface_name->u.constant TSRMLS_CC);
5341 	CG(active_class_entry)->num_interfaces++;
5342 }
5343 /* }}} */
5344 
zend_do_use_trait(znode * trait_name TSRMLS_DC)5345 void zend_do_use_trait(znode *trait_name TSRMLS_DC) /* {{{ */
5346 {
5347 	zend_op *opline;
5348 
5349 	if ((CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
5350 		zend_error_noreturn(E_COMPILE_ERROR,
5351 				"Cannot use traits inside of interfaces. %s is used in %s",
5352 				Z_STRVAL(trait_name->u.constant), CG(active_class_entry)->name);
5353 	}
5354 
5355 
5356 	switch (zend_get_class_fetch_type(Z_STRVAL(trait_name->u.constant), Z_STRLEN(trait_name->u.constant))) {
5357 		case ZEND_FETCH_CLASS_SELF:
5358 		case ZEND_FETCH_CLASS_PARENT:
5359 		case ZEND_FETCH_CLASS_STATIC:
5360 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as trait name as it is reserved", Z_STRVAL(trait_name->u.constant));
5361 			break;
5362 		default:
5363 			break;
5364 	}
5365 
5366 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5367 	opline->opcode = ZEND_ADD_TRAIT;
5368 	SET_NODE(opline->op1, &CG(implementing_class));
5369 	zend_resolve_class_name(trait_name TSRMLS_CC);
5370 	opline->extended_value = ZEND_FETCH_CLASS_TRAIT;
5371 	opline->op2_type = IS_CONST;
5372 	opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &trait_name->u.constant TSRMLS_CC);
5373 	CG(active_class_entry)->num_traits++;
5374 }
5375 /* }}} */
5376 
zend_mangle_property_name(char ** dest,int * dest_length,const char * src1,int src1_length,const char * src2,int src2_length,int internal)5377 ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, const char *src1, int src1_length, const char *src2, int src2_length, int internal) /* {{{ */
5378 {
5379 	char *prop_name;
5380 	int prop_name_length;
5381 
5382 	prop_name_length = 1 + src1_length + 1 + src2_length;
5383 	prop_name = pemalloc(prop_name_length + 1, internal);
5384 	prop_name[0] = '\0';
5385 	memcpy(prop_name + 1, src1, src1_length+1);
5386 	memcpy(prop_name + 1 + src1_length + 1, src2, src2_length+1);
5387 
5388 	*dest = prop_name;
5389 	*dest_length = prop_name_length;
5390 }
5391 /* }}} */
5392 
zend_strnlen(const char * s,int maxlen)5393 static int zend_strnlen(const char* s, int maxlen) /* {{{ */
5394 {
5395 	int len = 0;
5396 	while (*s++ && maxlen--) len++;
5397 	return len;
5398 }
5399 /* }}} */
5400 
zend_unmangle_property_name_ex(const char * mangled_property,int len,const char ** class_name,const char ** prop_name,int * prop_len)5401 ZEND_API int zend_unmangle_property_name_ex(const char *mangled_property, int len, const char **class_name, const char **prop_name, int *prop_len) /* {{{ */
5402 {
5403 	int class_name_len;
5404 
5405 	*class_name = NULL;
5406 
5407 	if (!len || mangled_property[0] != 0) {
5408 		*prop_name = mangled_property;
5409 		if (prop_len) {
5410 			*prop_len = len;
5411 		}
5412 		return SUCCESS;
5413 	}
5414 	if (len < 3 || mangled_property[1]==0) {
5415 		zend_error(E_NOTICE, "Illegal member variable name");
5416 		*prop_name = mangled_property;
5417 		if (prop_len) {
5418 			*prop_len = len;
5419 		}
5420 		return FAILURE;
5421 	}
5422 
5423 	class_name_len = zend_strnlen(mangled_property + 1, --len - 1) + 1;
5424 	if (class_name_len >= len || mangled_property[class_name_len]!=0) {
5425 		zend_error(E_NOTICE, "Corrupt member variable name");
5426 		*prop_name = mangled_property;
5427 		if (prop_len) {
5428 			*prop_len = len + 1;
5429 		}
5430 		return FAILURE;
5431 	}
5432 	*class_name = mangled_property + 1;
5433 	*prop_name = (*class_name) + class_name_len;
5434 	if (prop_len) {
5435 		*prop_len = len - class_name_len;
5436 	}
5437 	return SUCCESS;
5438 }
5439 /* }}} */
5440 
zend_do_declare_property(const znode * var_name,const znode * value,zend_uint access_type TSRMLS_DC)5441 void zend_do_declare_property(const znode *var_name, const znode *value, zend_uint access_type TSRMLS_DC) /* {{{ */
5442 {
5443 	zval *property;
5444 	zend_property_info *existing_property_info;
5445 	char *comment = NULL;
5446 	int comment_len = 0;
5447 
5448 	if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
5449 		zend_error_noreturn(E_COMPILE_ERROR, "Interfaces may not include member variables");
5450 	}
5451 
5452 	if (access_type & ZEND_ACC_ABSTRACT) {
5453 		zend_error_noreturn(E_COMPILE_ERROR, "Properties cannot be declared abstract");
5454 	}
5455 
5456 	if (access_type & ZEND_ACC_FINAL) {
5457 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, the final modifier is allowed only for methods and classes",
5458 				   CG(active_class_entry)->name, Z_STRVAL(var_name->u.constant));
5459 	}
5460 
5461 	if (zend_hash_find(&CG(active_class_entry)->properties_info, Z_STRVAL(var_name->u.constant), Z_STRLEN(var_name->u.constant)+1, (void **) &existing_property_info)==SUCCESS) {
5462 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, Z_STRVAL(var_name->u.constant));
5463 	}
5464 	ALLOC_ZVAL(property);
5465 
5466 	if (value) {
5467 		*property = value->u.constant;
5468 	} else {
5469 		INIT_PZVAL(property);
5470 		Z_TYPE_P(property) = IS_NULL;
5471 	}
5472 
5473 	if (CG(doc_comment)) {
5474 		comment = CG(doc_comment);
5475 		comment_len = CG(doc_comment_len);
5476 		CG(doc_comment) = NULL;
5477 		CG(doc_comment_len) = 0;
5478 	}
5479 
5480 	zend_declare_property_ex(CG(active_class_entry), zend_new_interned_string(Z_STRVAL(var_name->u.constant), Z_STRLEN(var_name->u.constant) + 1, 0 TSRMLS_CC), Z_STRLEN(var_name->u.constant), property, access_type, comment, comment_len TSRMLS_CC);
5481 	efree(Z_STRVAL(var_name->u.constant));
5482 }
5483 /* }}} */
5484 
zend_do_declare_class_constant(znode * var_name,const znode * value TSRMLS_DC)5485 void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_DC) /* {{{ */
5486 {
5487 	zval *property;
5488 	const char *cname = NULL;
5489 	zend_ulong hash;
5490 
5491 	if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
5492 		zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants");
5493 		return;
5494 	}
5495 
5496 	ALLOC_ZVAL(property);
5497 	*property = value->u.constant;
5498 
5499 	cname = zend_new_interned_string(Z_STRVAL(var_name->u.constant), Z_STRLEN(var_name->u.constant)+1, 0 TSRMLS_CC);
5500 	hash = str_hash(cname, Z_STRLEN(var_name->u.constant));
5501 	if (zend_hash_quick_add(&CG(active_class_entry)->constants_table, cname, Z_STRLEN(var_name->u.constant)+1, hash, &property, sizeof(zval *), NULL) == FAILURE) {
5502 		FREE_ZVAL(property);
5503 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name, Z_STRVAL(var_name->u.constant));
5504 	}
5505 	FREE_PNODE(var_name);
5506 
5507 	if (CG(doc_comment)) {
5508 		efree(CG(doc_comment));
5509 		CG(doc_comment) = NULL;
5510 		CG(doc_comment_len) = 0;
5511 	}
5512 }
5513 /* }}} */
5514 
zend_do_fetch_property(znode * result,znode * object,const znode * property TSRMLS_DC)5515 void zend_do_fetch_property(znode *result, znode *object, const znode *property TSRMLS_DC) /* {{{ */
5516 {
5517 	zend_op opline;
5518 	zend_llist *fetch_list_ptr;
5519 
5520 	zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
5521 
5522 	if (object->op_type == IS_CV) {
5523 		if (object->u.op.var == CG(active_op_array)->this_var) {
5524 			object->op_type = IS_UNUSED; /* this means $this for objects */
5525 		}
5526 	} else if (fetch_list_ptr->count == 1) {
5527 		zend_llist_element *le = fetch_list_ptr->head;
5528 		zend_op *opline_ptr = (zend_op *) le->data;
5529 
5530 		if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
5531 			zend_del_literal(CG(active_op_array), opline_ptr->op1.constant);
5532 			SET_UNUSED(opline_ptr->op1); /* this means $this for objects */
5533 			SET_NODE(opline_ptr->op2, property);
5534 			/* if it was usual fetch, we change it to object fetch */
5535 			switch (opline_ptr->opcode) {
5536 				case ZEND_FETCH_W:
5537 					opline_ptr->opcode = ZEND_FETCH_OBJ_W;
5538 					break;
5539 				case ZEND_FETCH_R:
5540 					opline_ptr->opcode = ZEND_FETCH_OBJ_R;
5541 					break;
5542 				case ZEND_FETCH_RW:
5543 					opline_ptr->opcode = ZEND_FETCH_OBJ_RW;
5544 					break;
5545 				case ZEND_FETCH_IS:
5546 					opline_ptr->opcode = ZEND_FETCH_OBJ_IS;
5547 					break;
5548 				case ZEND_FETCH_UNSET:
5549 					opline_ptr->opcode = ZEND_FETCH_OBJ_UNSET;
5550 					break;
5551 				case ZEND_FETCH_FUNC_ARG:
5552 					opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG;
5553 					break;
5554 			}
5555 			if (opline_ptr->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline_ptr->op2.constant)) == IS_STRING) {
5556 				CALCULATE_LITERAL_HASH(opline_ptr->op2.constant);
5557 				GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op2.constant);
5558 			}
5559 			GET_NODE(result, opline_ptr->result);
5560 			return;
5561 		}
5562 	}
5563 
5564 	if (zend_is_function_or_method_call(object)) {
5565 		init_op(&opline TSRMLS_CC);
5566 		opline.opcode = ZEND_SEPARATE;
5567 		SET_NODE(opline.op1, object);
5568 		SET_UNUSED(opline.op2);
5569 		opline.result_type = IS_VAR;
5570 		opline.result.var = opline.op1.var;
5571 		zend_llist_add_element(fetch_list_ptr, &opline);
5572 	}
5573 
5574 	init_op(&opline TSRMLS_CC);
5575 	opline.opcode = ZEND_FETCH_OBJ_W;	/* the backpatching routine assumes W */
5576 	opline.result_type = IS_VAR;
5577 	opline.result.var = get_temporary_variable(CG(active_op_array));
5578 	SET_NODE(opline.op1, object);
5579 	SET_NODE(opline.op2, property);
5580 	if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
5581 		CALCULATE_LITERAL_HASH(opline.op2.constant);
5582 		GET_POLYMORPHIC_CACHE_SLOT(opline.op2.constant);
5583 	}
5584 	GET_NODE(result, opline.result);
5585 
5586 	zend_llist_add_element(fetch_list_ptr, &opline);
5587 }
5588 /* }}} */
5589 
zend_do_halt_compiler_register(TSRMLS_D)5590 void zend_do_halt_compiler_register(TSRMLS_D) /* {{{ */
5591 {
5592 	char *name, *cfilename;
5593 	char haltoff[] = "__COMPILER_HALT_OFFSET__";
5594 	int len, clen;
5595 
5596 	if (CG(has_bracketed_namespaces) && CG(in_namespace)) {
5597 		zend_error_noreturn(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope");
5598 	}
5599 
5600 	cfilename = zend_get_compiled_filename(TSRMLS_C);
5601 	clen = strlen(cfilename);
5602 	zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, cfilename, clen, 0);
5603 	zend_register_long_constant(name, len+1, zend_get_scanned_file_offset(TSRMLS_C), CONST_CS, 0 TSRMLS_CC);
5604 	pefree(name, 0);
5605 
5606 	if (CG(in_namespace)) {
5607 		zend_do_end_namespace(TSRMLS_C);
5608 	}
5609 }
5610 /* }}} */
5611 
zend_do_push_object(const znode * object TSRMLS_DC)5612 void zend_do_push_object(const znode *object TSRMLS_DC) /* {{{ */
5613 {
5614 	zend_stack_push(&CG(object_stack), object, sizeof(znode));
5615 }
5616 /* }}} */
5617 
zend_do_pop_object(znode * object TSRMLS_DC)5618 void zend_do_pop_object(znode *object TSRMLS_DC) /* {{{ */
5619 {
5620 	if (object) {
5621 		znode *tmp;
5622 
5623 		zend_stack_top(&CG(object_stack), (void **) &tmp);
5624 		*object = *tmp;
5625 	}
5626 	zend_stack_del_top(&CG(object_stack));
5627 }
5628 /* }}} */
5629 
zend_do_begin_new_object(znode * new_token,znode * class_type TSRMLS_DC)5630 void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /* {{{ */
5631 {
5632 	zend_op *opline;
5633 
5634 	new_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
5635 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5636 	opline->opcode = ZEND_NEW;
5637 	opline->extended_value = CG(context).nested_calls;
5638 	opline->result_type = IS_VAR;
5639 	opline->result.var = get_temporary_variable(CG(active_op_array));
5640 	SET_NODE(opline->op1, class_type);
5641 	SET_UNUSED(opline->op2);
5642 
5643 	zend_push_function_call_entry(NULL TSRMLS_CC);
5644 	if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
5645 		CG(active_op_array)->nested_calls = CG(context).nested_calls;
5646 	}
5647 }
5648 /* }}} */
5649 
zend_do_end_new_object(znode * result,const znode * new_token TSRMLS_DC)5650 void zend_do_end_new_object(znode *result, const znode *new_token TSRMLS_DC) /* {{{ */
5651 {
5652 	znode ctor_result;
5653 
5654 	zend_do_end_function_call(NULL, &ctor_result, 1, 0 TSRMLS_CC);
5655 	zend_do_free(&ctor_result TSRMLS_CC);
5656 
5657 	CG(active_op_array)->opcodes[new_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
5658 	GET_NODE(result, CG(active_op_array)->opcodes[new_token->u.op.opline_num].result);
5659 }
5660 /* }}} */
5661 
zend_get_ct_const(const zval * const_name,int all_internal_constants_substitution TSRMLS_DC)5662 static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
5663 {
5664 	zend_constant *c = NULL;
5665 
5666 	if (Z_STRVAL_P(const_name)[0] == '\\') {
5667 		if (zend_hash_find(EG(zend_constants), Z_STRVAL_P(const_name)+1, Z_STRLEN_P(const_name), (void **) &c) == FAILURE) {
5668 			char *lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name)+1, Z_STRLEN_P(const_name)-1);
5669 
5670 			if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name), (void **) &c)==SUCCESS) {
5671 				if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
5672 					efree(lookup_name);
5673 					return c;
5674 				}
5675 			}
5676 			efree(lookup_name);
5677 			return NULL;
5678 		}
5679 	} else if (zend_hash_find(EG(zend_constants), Z_STRVAL_P(const_name), Z_STRLEN_P(const_name)+1, (void **) &c) == FAILURE) {
5680 		char *lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name), Z_STRLEN_P(const_name));
5681 
5682 		if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name)+1, (void **) &c)==SUCCESS) {
5683 			if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
5684 				efree(lookup_name);
5685 				return c;
5686 			}
5687 		}
5688 		efree(lookup_name);
5689 		return NULL;
5690 	}
5691 	if (c->flags & CONST_CT_SUBST) {
5692 		return c;
5693 	}
5694 	if (all_internal_constants_substitution &&
5695 	    (c->flags & CONST_PERSISTENT) &&
5696 	    !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
5697 	    !IS_CONSTANT_TYPE(Z_TYPE(c->value))) {
5698 		return c;
5699 	}
5700 	return NULL;
5701 }
5702 /* }}} */
5703 
zend_constant_ct_subst(znode * result,zval * const_name,int all_internal_constants_substitution TSRMLS_DC)5704 static int zend_constant_ct_subst(znode *result, zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
5705 {
5706 	zend_constant *c = zend_get_ct_const(const_name, all_internal_constants_substitution TSRMLS_CC);
5707 
5708 	if (c) {
5709 		zval_dtor(const_name);
5710 		result->op_type = IS_CONST;
5711 		result->u.constant = c->value;
5712 		zval_copy_ctor(&result->u.constant);
5713 		INIT_PZVAL(&result->u.constant);
5714 		return 1;
5715 	}
5716 	return 0;
5717 }
5718 /* }}} */
5719 
zend_do_fetch_constant(znode * result,znode * constant_container,znode * constant_name,int mode,zend_bool check_namespace TSRMLS_DC)5720 void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC) /* {{{ */
5721 {
5722 	znode tmp;
5723 	zend_op *opline;
5724 	int type;
5725 	char *compound;
5726 	ulong fetch_type = 0;
5727 
5728 	if (constant_container) {
5729 		switch (mode) {
5730 			case ZEND_CT:
5731 				/* this is a class constant */
5732 				type = zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant));
5733 
5734 				if (ZEND_FETCH_CLASS_STATIC == type) {
5735 					zend_error(E_ERROR, "\"static::\" is not allowed in compile-time constants");
5736 				} else if (ZEND_FETCH_CLASS_DEFAULT == type) {
5737 					zend_resolve_class_name(constant_container TSRMLS_CC);
5738 				}
5739 				zend_do_build_full_name(NULL, constant_container, constant_name, 1 TSRMLS_CC);
5740 				*result = *constant_container;
5741 				result->u.constant.type = IS_CONSTANT | fetch_type;
5742 				break;
5743 			case ZEND_RT:
5744 				if (constant_container->op_type == IS_CONST &&
5745 				ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant))) {
5746 					zend_resolve_class_name(constant_container TSRMLS_CC);
5747 				} else {
5748 					zend_do_fetch_class(&tmp, constant_container TSRMLS_CC);
5749 					constant_container = &tmp;
5750 				}
5751 				opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5752 				opline->opcode = ZEND_FETCH_CONSTANT;
5753 				opline->result_type = IS_TMP_VAR;
5754 				opline->result.var = get_temporary_variable(CG(active_op_array));
5755 				if (constant_container->op_type == IS_CONST) {
5756 					opline->op1_type = IS_CONST;
5757 					opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), &constant_container->u.constant TSRMLS_CC);
5758 				} else {
5759 					SET_NODE(opline->op1, constant_container);
5760 				}
5761 				SET_NODE(opline->op2, constant_name);
5762 				CALCULATE_LITERAL_HASH(opline->op2.constant);
5763 				if (opline->op1_type == IS_CONST) {
5764 					GET_CACHE_SLOT(opline->op2.constant);
5765 				} else {
5766 					GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
5767 				}
5768 				GET_NODE(result, opline->result);
5769 				break;
5770 		}
5771 		return;
5772 	}
5773 	/* namespace constant */
5774 	/* only one that did not contain \ from the start can be converted to string if unknown */
5775 	switch (mode) {
5776 		case ZEND_CT:
5777 			compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
5778 			/* this is a namespace constant, or an unprefixed constant */
5779 
5780 			if (zend_constant_ct_subst(result, &constant_name->u.constant, 0 TSRMLS_CC)) {
5781 				break;
5782 			}
5783 
5784 			zend_resolve_const_name(constant_name, &check_namespace TSRMLS_CC);
5785 
5786 			if(!compound) {
5787 				fetch_type |= IS_CONSTANT_UNQUALIFIED;
5788 			}
5789 
5790 			*result = *constant_name;
5791 			result->u.constant.type = IS_CONSTANT | fetch_type;
5792 			break;
5793 		case ZEND_RT:
5794 			compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
5795 
5796 			zend_resolve_const_name(constant_name, &check_namespace TSRMLS_CC);
5797 
5798 			if(zend_constant_ct_subst(result, &constant_name->u.constant, 1 TSRMLS_CC)) {
5799 				break;
5800 			}
5801 
5802 			opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5803 			opline->opcode = ZEND_FETCH_CONSTANT;
5804 			opline->result_type = IS_TMP_VAR;
5805 			opline->result.var = get_temporary_variable(CG(active_op_array));
5806 			GET_NODE(result, opline->result);
5807 			SET_UNUSED(opline->op1);
5808 			opline->op2_type = IS_CONST;
5809 			if (compound) {
5810 				/* the name is unambiguous */
5811 				opline->extended_value = 0;
5812 				opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC);
5813 			} else {
5814 				opline->extended_value = IS_CONSTANT_UNQUALIFIED;
5815 				if (check_namespace && CG(current_namespace)) {
5816 					opline->extended_value |= IS_CONSTANT_IN_NAMESPACE;
5817 					opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 1 TSRMLS_CC);
5818 				} else {
5819 					opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC);
5820 				}
5821 			}
5822 			GET_CACHE_SLOT(opline->op2.constant);
5823 			break;
5824 	}
5825 }
5826 /* }}} */
5827 
zend_do_shell_exec(znode * result,const znode * cmd TSRMLS_DC)5828 void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC) /* {{{ */
5829 {
5830 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5831 
5832 	switch (cmd->op_type) {
5833 		case IS_CONST:
5834 		case IS_TMP_VAR:
5835 			opline->opcode = ZEND_SEND_VAL;
5836 			break;
5837 		default:
5838 			opline->opcode = ZEND_SEND_VAR;
5839 			break;
5840 	}
5841 	SET_NODE(opline->op1, cmd);
5842 	opline->op2.opline_num = 1;
5843 	opline->extended_value = ZEND_DO_FCALL;
5844 	SET_UNUSED(opline->op2);
5845 
5846 	/* FIXME: exception support not added to this op2 */
5847 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5848 	opline->opcode = ZEND_DO_FCALL;
5849 	opline->result.var = get_temporary_variable(CG(active_op_array));
5850 	opline->result_type = IS_VAR;
5851 	LITERAL_STRINGL(opline->op1, estrndup("shell_exec", sizeof("shell_exec")-1), sizeof("shell_exec")-1, 0);
5852 	CALCULATE_LITERAL_HASH(opline->op1.constant);
5853 	opline->op1_type = IS_CONST;
5854 	GET_CACHE_SLOT(opline->op1.constant);
5855 	opline->extended_value = 1;
5856 	SET_UNUSED(opline->op2);
5857 	opline->op2.num = CG(context).nested_calls;
5858 	GET_NODE(result, opline->result);
5859 
5860 	if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
5861 		CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
5862 	}
5863 	if (CG(context).used_stack + 2 > CG(active_op_array)->used_stack) {
5864 		CG(active_op_array)->used_stack = CG(context).used_stack + 2;
5865 	}
5866 }
5867 /* }}} */
5868 
zend_do_init_array(znode * result,const znode * expr,const znode * offset,zend_bool is_ref TSRMLS_DC)5869 void zend_do_init_array(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC) /* {{{ */
5870 {
5871 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5872 
5873 	opline->opcode = ZEND_INIT_ARRAY;
5874 	opline->result.var = get_temporary_variable(CG(active_op_array));
5875 	opline->result_type = IS_TMP_VAR;
5876 	GET_NODE(result, opline->result);
5877 	if (expr) {
5878 		SET_NODE(opline->op1, expr);
5879 		if (offset) {
5880 			SET_NODE(opline->op2, offset);
5881 			if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) {
5882 				ulong index;
5883 				int numeric = 0;
5884 
5885 				ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline->op2.constant)), Z_STRLEN(CONSTANT(opline->op2.constant))+1, index, numeric = 1);
5886 				if (numeric) {
5887 					zval_dtor(&CONSTANT(opline->op2.constant));
5888 					ZVAL_LONG(&CONSTANT(opline->op2.constant), index);
5889 				} else {
5890 					CALCULATE_LITERAL_HASH(opline->op2.constant);
5891 				}
5892 			}
5893 		} else {
5894 			SET_UNUSED(opline->op2);
5895 		}
5896 	} else {
5897 		SET_UNUSED(opline->op1);
5898 		SET_UNUSED(opline->op2);
5899 	}
5900 	opline->extended_value = is_ref;
5901 }
5902 /* }}} */
5903 
zend_do_add_array_element(znode * result,const znode * expr,const znode * offset,zend_bool is_ref TSRMLS_DC)5904 void zend_do_add_array_element(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC) /* {{{ */
5905 {
5906 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5907 
5908 	opline->opcode = ZEND_ADD_ARRAY_ELEMENT;
5909 	SET_NODE(opline->result, result);
5910 	SET_NODE(opline->op1, expr);
5911 	if (offset) {
5912 		SET_NODE(opline->op2, offset);
5913 		if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) {
5914 			ulong index;
5915 			int numeric = 0;
5916 
5917 			ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline->op2.constant)), Z_STRLEN(CONSTANT(opline->op2.constant))+1, index, numeric = 1);
5918 			if (numeric) {
5919 				zval_dtor(&CONSTANT(opline->op2.constant));
5920 				ZVAL_LONG(&CONSTANT(opline->op2.constant), index);
5921 			} else {
5922 				CALCULATE_LITERAL_HASH(opline->op2.constant);
5923 			}
5924 		}
5925 	} else {
5926 		SET_UNUSED(opline->op2);
5927 	}
5928 	opline->extended_value = is_ref;
5929 }
5930 /* }}} */
5931 
zend_do_add_static_array_element(zval * result,zval * offset,zval * expr)5932 void zend_do_add_static_array_element(zval *result, zval *offset, zval *expr) /* {{{ */
5933 {
5934 	if (offset) {
5935 		switch (Z_TYPE_P(offset)) {
5936 			case IS_STRING:
5937 				zend_symtable_update(Z_ARRVAL_P(result), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr, sizeof(zval *), NULL);
5938 				zval_dtor(offset);
5939 				break;
5940 			case IS_NULL:
5941 				zend_symtable_update(Z_ARRVAL_P(result), "", 1, &expr, sizeof(zval *), NULL);
5942 				break;
5943 			case IS_RESOURCE:
5944 				zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(offset), Z_LVAL_P(offset));
5945 				/* break missing intentionally */
5946 			case IS_LONG:
5947 			case IS_BOOL:
5948 				zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(offset), &expr, sizeof(zval *), NULL);
5949 				break;
5950 			case IS_DOUBLE:
5951 				zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), &expr, sizeof(zval *), NULL);
5952 				break;
5953 			case IS_ARRAY:
5954 				zend_error(E_ERROR, "Illegal offset type");
5955 				break;
5956 		}
5957 	} else {
5958 		if (zend_hash_next_index_insert(Z_ARRVAL_P(result), &expr, sizeof(zval *), NULL) == FAILURE) {
5959 			zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
5960 			zval_ptr_dtor(&expr);
5961 		}
5962 	}
5963 }
5964 /* }}} */
5965 
zend_do_add_list_element(const znode * element TSRMLS_DC)5966 void zend_do_add_list_element(const znode *element TSRMLS_DC) /* {{{ */
5967 {
5968 	list_llist_element lle;
5969 
5970 	if (element) {
5971 		zend_check_writable_variable(element);
5972 
5973 		lle.var = *element;
5974 		zend_llist_copy(&lle.dimensions, &CG(dimension_llist));
5975 		zend_llist_prepend_element(&CG(list_llist), &lle);
5976 	}
5977 	(*((int *)CG(dimension_llist).tail->data))++;
5978 }
5979 /* }}} */
5980 
zend_do_new_list_begin(TSRMLS_D)5981 void zend_do_new_list_begin(TSRMLS_D) /* {{{ */
5982 {
5983 	int current_dimension = 0;
5984 	zend_llist_add_element(&CG(dimension_llist), &current_dimension);
5985 }
5986 /* }}} */
5987 
zend_do_new_list_end(TSRMLS_D)5988 void zend_do_new_list_end(TSRMLS_D) /* {{{ */
5989 {
5990 	zend_llist_remove_tail(&CG(dimension_llist));
5991 	(*((int *)CG(dimension_llist).tail->data))++;
5992 }
5993 /* }}} */
5994 
zend_do_list_init(TSRMLS_D)5995 void zend_do_list_init(TSRMLS_D) /* {{{ */
5996 {
5997 	zend_stack_push(&CG(list_stack), &CG(list_llist), sizeof(zend_llist));
5998 	zend_stack_push(&CG(list_stack), &CG(dimension_llist), sizeof(zend_llist));
5999 	zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
6000 	zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
6001 	zend_do_new_list_begin(TSRMLS_C);
6002 }
6003 /* }}} */
6004 
zend_do_list_end(znode * result,znode * expr TSRMLS_DC)6005 void zend_do_list_end(znode *result, znode *expr TSRMLS_DC) /* {{{ */
6006 {
6007 	zend_llist_element *le;
6008 	zend_llist_element *dimension;
6009 	zend_op *opline;
6010 	znode last_container;
6011 
6012 	le = CG(list_llist).head;
6013 	while (le) {
6014 		zend_llist *tmp_dimension_llist = &((list_llist_element *)le->data)->dimensions;
6015 		dimension = tmp_dimension_llist->head;
6016 		while (dimension) {
6017 			opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6018 			if (dimension == tmp_dimension_llist->head) { /* first */
6019 				last_container = *expr;
6020 				switch (expr->op_type) {
6021 					case IS_VAR:
6022 					case IS_CV:
6023 						opline->opcode = ZEND_FETCH_DIM_R;
6024 						break;
6025 					case IS_TMP_VAR:
6026 						opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
6027 						break;
6028 					case IS_CONST: /* fetch_dim_tmp_var will handle this bogus fetch */
6029 						zval_copy_ctor(&expr->u.constant);
6030 						opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
6031 						break;
6032 				}
6033 				opline->extended_value |= ZEND_FETCH_ADD_LOCK;
6034 			} else {
6035 				opline->opcode = ZEND_FETCH_DIM_R;
6036 			}
6037 			opline->result_type = IS_VAR;
6038 			opline->result.var = get_temporary_variable(CG(active_op_array));
6039 			SET_NODE(opline->op1, &last_container);
6040 			opline->op2_type = IS_CONST;
6041 			LITERAL_LONG(opline->op2, *((int *) dimension->data));
6042 			GET_NODE(&last_container, opline->result);
6043 			dimension = dimension->next;
6044 		}
6045 		((list_llist_element *) le->data)->value = last_container;
6046 		zend_llist_destroy(&((list_llist_element *) le->data)->dimensions);
6047 		zend_do_assign(result, &((list_llist_element *) le->data)->var, &((list_llist_element *) le->data)->value TSRMLS_CC);
6048 		zend_do_free(result TSRMLS_CC);
6049 		le = le->next;
6050 	}
6051 	zend_llist_destroy(&CG(dimension_llist));
6052 	zend_llist_destroy(&CG(list_llist));
6053 	*result = *expr;
6054 	{
6055 		zend_llist *p;
6056 
6057 		/* restore previous lists */
6058 		zend_stack_top(&CG(list_stack), (void **) &p);
6059 		CG(dimension_llist) = *p;
6060 		zend_stack_del_top(&CG(list_stack));
6061 		zend_stack_top(&CG(list_stack), (void **) &p);
6062 		CG(list_llist) = *p;
6063 		zend_stack_del_top(&CG(list_stack));
6064 	}
6065 }
6066 /* }}} */
6067 
zend_init_list(void * result,void * item TSRMLS_DC)6068 void zend_init_list(void *result, void *item TSRMLS_DC) /* {{{ */
6069 {
6070 	void** list = emalloc(sizeof(void*) * 2);
6071 
6072 	list[0] = item;
6073 	list[1] = NULL;
6074 
6075 	*(void**)result = list;
6076 }
6077 /* }}} */
6078 
zend_add_to_list(void * result,void * item TSRMLS_DC)6079 void zend_add_to_list(void *result, void *item TSRMLS_DC) /* {{{ */
6080 {
6081 	void** list = *(void**)result;
6082 	size_t n = 0;
6083 
6084 	if (list) {
6085 		while (list[n]) {
6086 			n++;
6087 		}
6088 	}
6089 
6090 	list = erealloc(list, sizeof(void*) * (n+2));
6091 
6092 	list[n]   = item;
6093 	list[n+1] = NULL;
6094 
6095 	*(void**)result = list;
6096 }
6097 /* }}} */
6098 
zend_do_fetch_static_variable(znode * varname,const znode * static_assignment,int fetch_type TSRMLS_DC)6099 void zend_do_fetch_static_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
6100 {
6101 	zval *tmp;
6102 	zend_op *opline;
6103 	znode lval;
6104 	znode result;
6105 
6106 	ALLOC_ZVAL(tmp);
6107 
6108 	if (static_assignment) {
6109 		*tmp = static_assignment->u.constant;
6110 	} else {
6111 		INIT_ZVAL(*tmp);
6112 	}
6113 	if (!CG(active_op_array)->static_variables) {
6114 		if (CG(active_op_array)->scope) {
6115 			CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
6116 		}
6117 		ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
6118 		zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
6119 	}
6120 	zend_hash_update(CG(active_op_array)->static_variables, Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant)+1, &tmp, sizeof(zval *), NULL);
6121 
6122 	if (varname->op_type == IS_CONST) {
6123 		if (Z_TYPE(varname->u.constant) != IS_STRING) {
6124 			convert_to_string(&varname->u.constant);
6125 		}
6126 	}
6127 
6128 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6129 	opline->opcode = (fetch_type == ZEND_FETCH_LEXICAL) ? ZEND_FETCH_R : ZEND_FETCH_W;		/* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
6130 	opline->result_type = IS_VAR;
6131 	opline->result.var = get_temporary_variable(CG(active_op_array));
6132 	SET_NODE(opline->op1, varname);
6133 	if (opline->op1_type == IS_CONST) {
6134 		CALCULATE_LITERAL_HASH(opline->op1.constant);
6135 	}
6136 	SET_UNUSED(opline->op2);
6137 	opline->extended_value = ZEND_FETCH_STATIC;
6138 	GET_NODE(&result, opline->result);
6139 
6140 	if (varname->op_type == IS_CONST) {
6141 		zval_copy_ctor(&varname->u.constant);
6142 	}
6143 	fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
6144 
6145 	if (fetch_type == ZEND_FETCH_LEXICAL) {
6146 		znode dummy;
6147 
6148 		zend_do_begin_variable_parse(TSRMLS_C);
6149 		zend_do_assign(&dummy, &lval, &result TSRMLS_CC);
6150 		zend_do_free(&dummy TSRMLS_CC);
6151 	} else {
6152 		zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
6153 	}
6154 	CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result_type |= EXT_TYPE_UNUSED;
6155 }
6156 /* }}} */
6157 
zend_do_fetch_lexical_variable(znode * varname,zend_bool is_ref TSRMLS_DC)6158 void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC) /* {{{ */
6159 {
6160 	znode value;
6161 
6162 	if (Z_STRLEN(varname->u.constant) == sizeof("this") - 1 &&
6163 	    memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1) == 0) {
6164 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
6165 		return;
6166 	}
6167 
6168 	value.op_type = IS_CONST;
6169 	ZVAL_NULL(&value.u.constant);
6170 	Z_TYPE(value.u.constant) |= is_ref ? IS_LEXICAL_REF : IS_LEXICAL_VAR;
6171 	Z_SET_REFCOUNT_P(&value.u.constant, 1);
6172 	Z_UNSET_ISREF_P(&value.u.constant);
6173 
6174 	zend_do_fetch_static_variable(varname, &value, is_ref ? ZEND_FETCH_STATIC : ZEND_FETCH_LEXICAL TSRMLS_CC);
6175 }
6176 /* }}} */
6177 
zend_do_fetch_global_variable(znode * varname,const znode * static_assignment,int fetch_type TSRMLS_DC)6178 void zend_do_fetch_global_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
6179 {
6180 	zend_op *opline;
6181 	znode lval;
6182 	znode result;
6183 
6184 	if (varname->op_type == IS_CONST) {
6185 		if (Z_TYPE(varname->u.constant) != IS_STRING) {
6186 			convert_to_string(&varname->u.constant);
6187 		}
6188 	}
6189 
6190 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6191 	opline->opcode = ZEND_FETCH_W;		/* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
6192 	opline->result_type = IS_VAR;
6193 	opline->result.var = get_temporary_variable(CG(active_op_array));
6194 	SET_NODE(opline->op1, varname);
6195 	if (opline->op1_type == IS_CONST) {
6196 		CALCULATE_LITERAL_HASH(opline->op1.constant);
6197 	}
6198 	SET_UNUSED(opline->op2);
6199 	opline->extended_value = fetch_type;
6200 	GET_NODE(&result, opline->result);
6201 
6202 	if (varname->op_type == IS_CONST) {
6203 		zval_copy_ctor(&varname->u.constant);
6204 	}
6205 	fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
6206 
6207 	zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
6208 	CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result_type |= EXT_TYPE_UNUSED;
6209 }
6210 /* }}} */
6211 
zend_do_cast(znode * result,const znode * expr,int type TSRMLS_DC)6212 void zend_do_cast(znode *result, const znode *expr, int type TSRMLS_DC) /* {{{ */
6213 {
6214 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6215 
6216 	opline->opcode = ZEND_CAST;
6217 	opline->result_type = IS_TMP_VAR;
6218 	opline->result.var = get_temporary_variable(CG(active_op_array));
6219 	SET_NODE(opline->op1, expr);
6220 	SET_UNUSED(opline->op2);
6221 	opline->extended_value = type;
6222 	GET_NODE(result, opline->result);
6223 }
6224 /* }}} */
6225 
zend_do_include_or_eval(int type,znode * result,const znode * op1 TSRMLS_DC)6226 void zend_do_include_or_eval(int type, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */
6227 {
6228 	zend_do_extended_fcall_begin(TSRMLS_C);
6229 	{
6230 		zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6231 
6232 		opline->opcode = ZEND_INCLUDE_OR_EVAL;
6233 		opline->result_type = IS_VAR;
6234 		opline->result.var = get_temporary_variable(CG(active_op_array));
6235 		SET_NODE(opline->op1, op1);
6236 		SET_UNUSED(opline->op2);
6237 		opline->extended_value = type;
6238 		GET_NODE(result, opline->result);
6239 	}
6240 	zend_do_extended_fcall_end(TSRMLS_C);
6241 }
6242 /* }}} */
6243 
zend_do_indirect_references(znode * result,const znode * num_references,znode * variable TSRMLS_DC)6244 void zend_do_indirect_references(znode *result, const znode *num_references, znode *variable TSRMLS_DC) /* {{{ */
6245 {
6246 	int i;
6247 
6248 	zend_do_end_variable_parse(variable, BP_VAR_R, 0 TSRMLS_CC);
6249 	for (i=1; i<Z_LVAL(num_references->u.constant); i++) {
6250 		fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
6251 		*variable = *result;
6252 	}
6253 	zend_do_begin_variable_parse(TSRMLS_C);
6254 	fetch_simple_variable(result, variable, 1 TSRMLS_CC);
6255 	/* there is a chance someone is accessing $this */
6256 	if (CG(active_op_array)->scope && CG(active_op_array)->this_var == -1) {
6257 		CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1, THIS_HASHVAL TSRMLS_CC);
6258 	}
6259 }
6260 /* }}} */
6261 
zend_do_unset(const znode * variable TSRMLS_DC)6262 void zend_do_unset(const znode *variable TSRMLS_DC) /* {{{ */
6263 {
6264 	zend_op *last_op;
6265 
6266 	zend_check_writable_variable(variable);
6267 
6268 	if (variable->op_type == IS_CV) {
6269 		zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6270 		opline->opcode = ZEND_UNSET_VAR;
6271 		SET_NODE(opline->op1, variable);
6272 		SET_UNUSED(opline->op2);
6273 		SET_UNUSED(opline->result);
6274 		opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
6275 	} else {
6276 		last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
6277 
6278 		switch (last_op->opcode) {
6279 			case ZEND_FETCH_UNSET:
6280 				last_op->opcode = ZEND_UNSET_VAR;
6281 				SET_UNUSED(last_op->result);
6282 				break;
6283 			case ZEND_FETCH_DIM_UNSET:
6284 				last_op->opcode = ZEND_UNSET_DIM;
6285 				SET_UNUSED(last_op->result);
6286 				break;
6287 			case ZEND_FETCH_OBJ_UNSET:
6288 				last_op->opcode = ZEND_UNSET_OBJ;
6289 				SET_UNUSED(last_op->result);
6290 				break;
6291 
6292 		}
6293 	}
6294 }
6295 /* }}} */
6296 
zend_do_isset_or_isempty(int type,znode * result,znode * variable TSRMLS_DC)6297 void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC) /* {{{ */
6298 {
6299 	zend_op *last_op;
6300 
6301 	zend_do_end_variable_parse(variable, BP_VAR_IS, 0 TSRMLS_CC);
6302 
6303 	if (zend_is_function_or_method_call(variable)) {
6304 		if (type == ZEND_ISEMPTY) {
6305 			/* empty(func()) can be transformed to !func() */
6306 			zend_do_unary_op(ZEND_BOOL_NOT, result, variable TSRMLS_CC);
6307 		} else {
6308 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use isset() on the result of a function call (you can use \"null !== func()\" instead)");
6309 		}
6310 
6311 		return;
6312 	}
6313 
6314 	if (variable->op_type == IS_CV) {
6315 		last_op = get_next_op(CG(active_op_array) TSRMLS_CC);
6316 		last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
6317 		SET_NODE(last_op->op1, variable);
6318 		SET_UNUSED(last_op->op2);
6319 		last_op->result.var = get_temporary_variable(CG(active_op_array));
6320 		last_op->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
6321 	} else {
6322 		last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
6323 
6324 		switch (last_op->opcode) {
6325 			case ZEND_FETCH_IS:
6326 				last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
6327 				break;
6328 			case ZEND_FETCH_DIM_IS:
6329 				last_op->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
6330 				break;
6331 			case ZEND_FETCH_OBJ_IS:
6332 				last_op->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
6333 				break;
6334 		}
6335 	}
6336 	last_op->result_type = IS_TMP_VAR;
6337 	last_op->extended_value |= type;
6338 
6339 	GET_NODE(result, last_op->result);
6340 }
6341 /* }}} */
6342 
zend_do_instanceof(znode * result,const znode * expr,const znode * class_znode,int type TSRMLS_DC)6343 void zend_do_instanceof(znode *result, const znode *expr, const znode *class_znode, int type TSRMLS_DC) /* {{{ */
6344 {
6345 	int last_op_number = get_next_op_number(CG(active_op_array));
6346 	zend_op *opline;
6347 
6348 	if (last_op_number > 0) {
6349 		opline = &CG(active_op_array)->opcodes[last_op_number-1];
6350 		if (opline->opcode == ZEND_FETCH_CLASS) {
6351 			opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
6352 		}
6353 	}
6354 
6355 	if (expr->op_type == IS_CONST) {
6356 		zend_error_noreturn(E_COMPILE_ERROR, "instanceof expects an object instance, constant given");
6357 	}
6358 
6359 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6360 	opline->opcode = ZEND_INSTANCEOF;
6361 	opline->result_type = IS_TMP_VAR;
6362 	opline->result.var = get_temporary_variable(CG(active_op_array));
6363 	SET_NODE(opline->op1, expr);
6364 
6365 	SET_NODE(opline->op2, class_znode);
6366 
6367 	GET_NODE(result, opline->result);
6368 }
6369 /* }}} */
6370 
zend_do_foreach_begin(znode * foreach_token,znode * open_brackets_token,znode * array,znode * as_token,int variable TSRMLS_DC)6371 void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, znode *as_token, int variable TSRMLS_DC) /* {{{ */
6372 {
6373 	zend_op *opline;
6374 	zend_bool is_variable;
6375 	zend_op dummy_opline;
6376 
6377 	if (variable) {
6378 		if (zend_is_function_or_method_call(array)) {
6379 			is_variable = 0;
6380 		} else {
6381 			is_variable = 1;
6382 		}
6383 		/* save the location of FETCH_W instruction(s) */
6384 		open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
6385 		zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
6386 
6387 		if (zend_is_function_or_method_call(array)) {
6388 			opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6389 			opline->opcode = ZEND_SEPARATE;
6390 			SET_NODE(opline->op1, array);
6391 			SET_UNUSED(opline->op2);
6392 			opline->result_type = IS_VAR;
6393 			opline->result.var = opline->op1.var;
6394 		}
6395 	} else {
6396 		is_variable = 0;
6397 		open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
6398 	}
6399 
6400 	/* save the location of FE_RESET */
6401 	foreach_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
6402 
6403 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6404 
6405 	/* Preform array reset */
6406 	opline->opcode = ZEND_FE_RESET;
6407 	opline->result_type = IS_VAR;
6408 	opline->result.var = get_temporary_variable(CG(active_op_array));
6409 	SET_NODE(opline->op1, array);
6410 	SET_UNUSED(opline->op2);
6411 	opline->extended_value = is_variable ? ZEND_FE_RESET_VARIABLE : 0;
6412 
6413 	COPY_NODE(dummy_opline.result, opline->result);
6414 	zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
6415 
6416 	/* save the location of FE_FETCH */
6417 	as_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
6418 
6419 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6420 	opline->opcode = ZEND_FE_FETCH;
6421 	opline->result_type = IS_VAR;
6422 	opline->result.var = get_temporary_variable(CG(active_op_array));
6423 	COPY_NODE(opline->op1, dummy_opline.result);
6424 	opline->extended_value = 0;
6425 	SET_UNUSED(opline->op2);
6426 
6427 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6428 	opline->opcode = ZEND_OP_DATA;
6429 	SET_UNUSED(opline->op1);
6430 	SET_UNUSED(opline->op2);
6431 	SET_UNUSED(opline->result);
6432 }
6433 /* }}} */
6434 
zend_do_foreach_cont(znode * foreach_token,const znode * open_brackets_token,const znode * as_token,znode * value,znode * key TSRMLS_DC)6435 void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token, const znode *as_token, znode *value, znode *key TSRMLS_DC) /* {{{ */
6436 {
6437 	zend_op *opline;
6438 	znode dummy, value_node;
6439 	zend_bool assign_by_ref=0;
6440 
6441 	opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num];
6442 	if (key->op_type != IS_UNUSED) {
6443 		znode *tmp;
6444 
6445 		/* switch between the key and value... */
6446 		tmp = key;
6447 		key = value;
6448 		value = tmp;
6449 
6450 		/* Mark extended_value in case both key and value are being used */
6451 		opline->extended_value |= ZEND_FE_FETCH_WITH_KEY;
6452 	}
6453 
6454 	if ((key->op_type != IS_UNUSED)) {
6455 		if (key->EA & ZEND_PARSED_REFERENCE_VARIABLE) {
6456 			zend_error_noreturn(E_COMPILE_ERROR, "Key element cannot be a reference");
6457 		}
6458 		if (key->EA & ZEND_PARSED_LIST_EXPR) {
6459 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use list as key element");
6460 		}
6461 	}
6462 
6463 	if (value->EA & ZEND_PARSED_REFERENCE_VARIABLE) {
6464 		assign_by_ref = 1;
6465 
6466 		/* Mark extended_value for assign-by-reference */
6467 		opline->extended_value |= ZEND_FE_FETCH_BYREF;
6468 		CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE;
6469 	} else {
6470 		zend_op *fetch = &CG(active_op_array)->opcodes[foreach_token->u.op.opline_num];
6471 		zend_op	*end = &CG(active_op_array)->opcodes[open_brackets_token->u.op.opline_num];
6472 
6473 		/* Change "write context" into "read context" */
6474 		fetch->extended_value = 0;  /* reset ZEND_FE_RESET_VARIABLE */
6475 		while (fetch != end) {
6476 			--fetch;
6477 			if (fetch->opcode == ZEND_FETCH_DIM_W && fetch->op2_type == IS_UNUSED) {
6478 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
6479 			}
6480 			if (fetch->opcode == ZEND_SEPARATE) {
6481 				MAKE_NOP(fetch);
6482 			} else {
6483 				fetch->opcode -= 3; /* FETCH_W -> FETCH_R */
6484 			}
6485 		}
6486 	}
6487 
6488 	GET_NODE(&value_node, opline->result);
6489 
6490 	if (value->EA & ZEND_PARSED_LIST_EXPR) {
6491 		if (!CG(list_llist).head) {
6492 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
6493 		}
6494 		zend_do_list_end(&dummy, &value_node TSRMLS_CC);
6495 		zend_do_free(&dummy TSRMLS_CC);
6496 	} else {
6497 		if (assign_by_ref) {
6498 			zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
6499 			/* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
6500 			zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
6501 		} else {
6502 			zend_do_assign(&dummy, value, &value_node TSRMLS_CC);
6503 			zend_do_free(&dummy TSRMLS_CC);
6504 		}
6505 	}
6506 
6507 	if (key->op_type != IS_UNUSED) {
6508 		znode key_node;
6509 
6510 		opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num+1];
6511 		opline->result_type = IS_TMP_VAR;
6512 		opline->result.opline_num = get_temporary_variable(CG(active_op_array));
6513 		GET_NODE(&key_node, opline->result);
6514 
6515 		zend_do_assign(&dummy, key, &key_node TSRMLS_CC);
6516 		zend_do_free(&dummy TSRMLS_CC);
6517 	}
6518 
6519 	do_begin_loop(TSRMLS_C);
6520 	INC_BPC(CG(active_op_array));
6521 }
6522 /* }}} */
6523 
zend_do_foreach_end(const znode * foreach_token,const znode * as_token TSRMLS_DC)6524 void zend_do_foreach_end(const znode *foreach_token, const znode *as_token TSRMLS_DC) /* {{{ */
6525 {
6526 	zend_op *container_ptr;
6527 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6528 
6529 	opline->opcode = ZEND_JMP;
6530 	opline->op1.opline_num = as_token->u.op.opline_num;
6531 	SET_UNUSED(opline->op1);
6532 	SET_UNUSED(opline->op2);
6533 
6534 	CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array)); /* FE_RESET */
6535 	CG(active_op_array)->opcodes[as_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array)); /* FE_FETCH */
6536 
6537 	do_end_loop(as_token->u.op.opline_num, 1 TSRMLS_CC);
6538 
6539 	zend_stack_top(&CG(foreach_copy_stack), (void **) &container_ptr);
6540 	generate_free_foreach_copy(container_ptr TSRMLS_CC);
6541 	zend_stack_del_top(&CG(foreach_copy_stack));
6542 
6543 	DEC_BPC(CG(active_op_array));
6544 }
6545 /* }}} */
6546 
zend_do_declare_begin(TSRMLS_D)6547 void zend_do_declare_begin(TSRMLS_D) /* {{{ */
6548 {
6549 	zend_stack_push(&CG(declare_stack), &CG(declarables), sizeof(zend_declarables));
6550 }
6551 /* }}} */
6552 
zend_do_declare_stmt(znode * var,znode * val TSRMLS_DC)6553 void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC) /* {{{ */
6554 {
6555 	if (!zend_binary_strcasecmp(Z_STRVAL(var->u.constant), Z_STRLEN(var->u.constant), "ticks", sizeof("ticks")-1)) {
6556 		convert_to_long(&val->u.constant);
6557 		CG(declarables).ticks = val->u.constant;
6558 	} else if (!zend_binary_strcasecmp(Z_STRVAL(var->u.constant), Z_STRLEN(var->u.constant), "encoding", sizeof("encoding")-1)) {
6559 		if ((Z_TYPE(val->u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
6560 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use constants as encoding");
6561 		}
6562 
6563 		/*
6564 		 * Check that the pragma comes before any opcodes. If the compilation
6565 		 * got as far as this, the previous portion of the script must have been
6566 		 * parseable according to the .ini script_encoding setting. We still
6567 		 * want to tell them to put declare() at the top.
6568 		 */
6569 		{
6570 			int num = CG(active_op_array)->last;
6571 			/* ignore ZEND_EXT_STMT and ZEND_TICKS */
6572 			while (num > 0 &&
6573 			       (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
6574 			        CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
6575 				--num;
6576 			}
6577 
6578 			if (num > 0) {
6579 				zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be the very first statement in the script");
6580 			}
6581 		}
6582 
6583 		if (CG(multibyte)) {
6584 			const zend_encoding *new_encoding, *old_encoding;
6585 			zend_encoding_filter old_input_filter;
6586 
6587 			CG(encoding_declared) = 1;
6588 
6589 			convert_to_string(&val->u.constant);
6590 			new_encoding = zend_multibyte_fetch_encoding(Z_STRVAL(val->u.constant) TSRMLS_CC);
6591 			if (!new_encoding) {
6592 				zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", Z_STRVAL(val->u.constant));
6593 			} else {
6594 				old_input_filter = LANG_SCNG(input_filter);
6595 				old_encoding = LANG_SCNG(script_encoding);
6596 				zend_multibyte_set_filter(new_encoding TSRMLS_CC);
6597 
6598 				/* need to re-scan if input filter changed */
6599 				if (old_input_filter != LANG_SCNG(input_filter) ||
6600 					 (old_input_filter && new_encoding != old_encoding)) {
6601 					zend_multibyte_yyinput_again(old_input_filter, old_encoding TSRMLS_CC);
6602 				}
6603 			}
6604 		} else {
6605 			zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because Zend multibyte feature is turned off by settings");
6606 		}
6607 		zval_dtor(&val->u.constant);
6608 	} else {
6609 		zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", Z_STRVAL(var->u.constant));
6610 		zval_dtor(&val->u.constant);
6611 	}
6612 	zval_dtor(&var->u.constant);
6613 }
6614 /* }}} */
6615 
zend_do_declare_end(const znode * declare_token TSRMLS_DC)6616 void zend_do_declare_end(const znode *declare_token TSRMLS_DC) /* {{{ */
6617 {
6618 	zend_declarables *declarables;
6619 
6620 	zend_stack_top(&CG(declare_stack), (void **) &declarables);
6621 	/* We should restore if there was more than (current - start) - (ticks?1:0) opcodes */
6622 	if ((get_next_op_number(CG(active_op_array)) - declare_token->u.op.opline_num) - ((Z_LVAL(CG(declarables).ticks))?1:0)) {
6623 		CG(declarables) = *declarables;
6624 	}
6625 }
6626 /* }}} */
6627 
zend_do_exit(znode * result,const znode * message TSRMLS_DC)6628 void zend_do_exit(znode *result, const znode *message TSRMLS_DC) /* {{{ */
6629 {
6630 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6631 
6632 	opline->opcode = ZEND_EXIT;
6633 	SET_NODE(opline->op1, message);
6634 	SET_UNUSED(opline->op2);
6635 
6636 	result->op_type = IS_CONST;
6637 	Z_TYPE(result->u.constant) = IS_BOOL;
6638 	Z_LVAL(result->u.constant) = 1;
6639 }
6640 /* }}} */
6641 
zend_do_begin_silence(znode * strudel_token TSRMLS_DC)6642 void zend_do_begin_silence(znode *strudel_token TSRMLS_DC) /* {{{ */
6643 {
6644 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6645 
6646 	opline->opcode = ZEND_BEGIN_SILENCE;
6647 	opline->result_type = IS_TMP_VAR;
6648 	opline->result.var = get_temporary_variable(CG(active_op_array));
6649 	SET_UNUSED(opline->op1);
6650 	SET_UNUSED(opline->op2);
6651 	GET_NODE(strudel_token, opline->result);
6652 }
6653 /* }}} */
6654 
zend_do_end_silence(const znode * strudel_token TSRMLS_DC)6655 void zend_do_end_silence(const znode *strudel_token TSRMLS_DC) /* {{{ */
6656 {
6657 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6658 
6659 	opline->opcode = ZEND_END_SILENCE;
6660 	SET_NODE(opline->op1, strudel_token);
6661 	SET_UNUSED(opline->op2);
6662 }
6663 /* }}} */
6664 
zend_do_jmp_set(const znode * value,znode * jmp_token,znode * colon_token TSRMLS_DC)6665 void zend_do_jmp_set(const znode *value, znode *jmp_token, znode *colon_token TSRMLS_DC) /* {{{ */
6666 {
6667 	int op_number = get_next_op_number(CG(active_op_array));
6668 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6669 
6670 	if (value->op_type == IS_VAR || value->op_type == IS_CV) {
6671 		opline->opcode = ZEND_JMP_SET_VAR;
6672 		opline->result_type = IS_VAR;
6673 	} else {
6674 		opline->opcode = ZEND_JMP_SET;
6675 		opline->result_type = IS_TMP_VAR;
6676 	}
6677 	opline->result.var = get_temporary_variable(CG(active_op_array));
6678 	SET_NODE(opline->op1, value);
6679 	SET_UNUSED(opline->op2);
6680 
6681 	GET_NODE(colon_token, opline->result);
6682 
6683 	jmp_token->u.op.opline_num = op_number;
6684 
6685 	INC_BPC(CG(active_op_array));
6686 }
6687 /* }}} */
6688 
zend_do_jmp_set_else(znode * result,const znode * false_value,const znode * jmp_token,const znode * colon_token TSRMLS_DC)6689 void zend_do_jmp_set_else(znode *result, const znode *false_value, const znode *jmp_token, const znode *colon_token TSRMLS_DC) /* {{{ */
6690 {
6691 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6692 
6693 	SET_NODE(opline->result, colon_token);
6694 	if (colon_token->op_type == IS_TMP_VAR) {
6695 		if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
6696 			CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].opcode = ZEND_JMP_SET_VAR;
6697 			CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].result_type = IS_VAR;
6698 			opline->opcode = ZEND_QM_ASSIGN_VAR;
6699 			opline->result_type = IS_VAR;
6700 		} else {
6701 			opline->opcode = ZEND_QM_ASSIGN;
6702 		}
6703 	} else {
6704 		opline->opcode = ZEND_QM_ASSIGN_VAR;
6705 	}
6706 	opline->extended_value = 0;
6707 	SET_NODE(opline->op1, false_value);
6708 	SET_UNUSED(opline->op2);
6709 
6710 	GET_NODE(result, opline->result);
6711 
6712 	CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
6713 
6714 	DEC_BPC(CG(active_op_array));
6715 }
6716 /* }}} */
6717 
zend_do_begin_qm_op(const znode * cond,znode * qm_token TSRMLS_DC)6718 void zend_do_begin_qm_op(const znode *cond, znode *qm_token TSRMLS_DC) /* {{{ */
6719 {
6720 	int jmpz_op_number = get_next_op_number(CG(active_op_array));
6721 	zend_op *opline;
6722 
6723 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6724 
6725 	opline->opcode = ZEND_JMPZ;
6726 	SET_NODE(opline->op1, cond);
6727 	SET_UNUSED(opline->op2);
6728 	opline->op2.opline_num = jmpz_op_number;
6729 	GET_NODE(qm_token, opline->op2);
6730 
6731 	INC_BPC(CG(active_op_array));
6732 }
6733 /* }}} */
6734 
zend_do_qm_true(const znode * true_value,znode * qm_token,znode * colon_token TSRMLS_DC)6735 void zend_do_qm_true(const znode *true_value, znode *qm_token, znode *colon_token TSRMLS_DC) /* {{{ */
6736 {
6737 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6738 
6739 	CG(active_op_array)->opcodes[qm_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array))+1; /* jmp over the ZEND_JMP */
6740 
6741 	if (true_value->op_type == IS_VAR || true_value->op_type == IS_CV) {
6742 		opline->opcode = ZEND_QM_ASSIGN_VAR;
6743 		opline->result_type = IS_VAR;
6744 	} else {
6745 		opline->opcode = ZEND_QM_ASSIGN;
6746 		opline->result_type = IS_TMP_VAR;
6747 	}
6748 	opline->result.var = get_temporary_variable(CG(active_op_array));
6749 	SET_NODE(opline->op1, true_value);
6750 	SET_UNUSED(opline->op2);
6751 
6752 	GET_NODE(qm_token, opline->result);
6753 	colon_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
6754 
6755 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6756 	opline->opcode = ZEND_JMP;
6757 	SET_UNUSED(opline->op1);
6758 	SET_UNUSED(opline->op2);
6759 }
6760 /* }}} */
6761 
zend_do_qm_false(znode * result,const znode * false_value,const znode * qm_token,const znode * colon_token TSRMLS_DC)6762 void zend_do_qm_false(znode *result, const znode *false_value, const znode *qm_token, const znode *colon_token TSRMLS_DC) /* {{{ */
6763 {
6764 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6765 
6766 	SET_NODE(opline->result, qm_token);
6767 	if (qm_token->op_type == IS_TMP_VAR) {
6768 		if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
6769 			CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].opcode = ZEND_QM_ASSIGN_VAR;
6770 			CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].result_type = IS_VAR;
6771 			opline->opcode = ZEND_QM_ASSIGN_VAR;
6772 			opline->result_type = IS_VAR;
6773 		} else {
6774 			opline->opcode = ZEND_QM_ASSIGN;
6775 		}
6776 	} else {
6777 		opline->opcode = ZEND_QM_ASSIGN_VAR;
6778 	}
6779 	SET_NODE(opline->op1, false_value);
6780 	SET_UNUSED(opline->op2);
6781 
6782 	CG(active_op_array)->opcodes[colon_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
6783 
6784 	GET_NODE(result, opline->result);
6785 
6786 	DEC_BPC(CG(active_op_array));
6787 }
6788 /* }}} */
6789 
zend_do_extended_info(TSRMLS_D)6790 void zend_do_extended_info(TSRMLS_D) /* {{{ */
6791 {
6792 	zend_op *opline;
6793 
6794 	if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
6795 		return;
6796 	}
6797 
6798 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6799 
6800 	opline->opcode = ZEND_EXT_STMT;
6801 	SET_UNUSED(opline->op1);
6802 	SET_UNUSED(opline->op2);
6803 }
6804 /* }}} */
6805 
zend_do_extended_fcall_begin(TSRMLS_D)6806 void zend_do_extended_fcall_begin(TSRMLS_D) /* {{{ */
6807 {
6808 	zend_op *opline;
6809 
6810 	if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
6811 		return;
6812 	}
6813 
6814 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6815 
6816 	opline->opcode = ZEND_EXT_FCALL_BEGIN;
6817 	SET_UNUSED(opline->op1);
6818 	SET_UNUSED(opline->op2);
6819 }
6820 /* }}} */
6821 
zend_do_extended_fcall_end(TSRMLS_D)6822 void zend_do_extended_fcall_end(TSRMLS_D) /* {{{ */
6823 {
6824 	zend_op *opline;
6825 
6826 	if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
6827 		return;
6828 	}
6829 
6830 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6831 
6832 	opline->opcode = ZEND_EXT_FCALL_END;
6833 	SET_UNUSED(opline->op1);
6834 	SET_UNUSED(opline->op2);
6835 }
6836 /* }}} */
6837 
zend_do_ticks(TSRMLS_D)6838 void zend_do_ticks(TSRMLS_D) /* {{{ */
6839 {
6840 	zend_op *opline;
6841 
6842 	/* This prevents a double TICK generated by the parser statement of "declare()" */
6843 	if (CG(active_op_array)->last && CG(active_op_array)->opcodes[CG(active_op_array)->last - 1].opcode == ZEND_TICKS) {
6844 		return;
6845 	}
6846 
6847 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6848 
6849 	opline->opcode = ZEND_TICKS;
6850 	SET_UNUSED(opline->op1);
6851 	SET_UNUSED(opline->op2);
6852 	opline->extended_value = Z_LVAL(CG(declarables).ticks);
6853 }
6854 /* }}} */
6855 
zend_is_auto_global_quick(const char * name,uint name_len,ulong hash TSRMLS_DC)6856 zend_bool zend_is_auto_global_quick(const char *name, uint name_len, ulong hash TSRMLS_DC) /* {{{ */
6857 {
6858 	zend_auto_global *auto_global;
6859 
6860 	if (zend_hash_quick_find(CG(auto_globals), name, name_len+1, hash, (void **) &auto_global)==SUCCESS) {
6861 		if (auto_global->armed) {
6862 			auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
6863 		}
6864 		return 1;
6865 	}
6866 	return 0;
6867 }
6868 /* }}} */
6869 
zend_is_auto_global(const char * name,uint name_len TSRMLS_DC)6870 zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC) /* {{{ */
6871 {
6872 	return zend_is_auto_global_quick(name, name_len, zend_hash_func(name, name_len+1) TSRMLS_CC);
6873 }
6874 /* }}} */
6875 
zend_register_auto_global(const char * name,uint name_len,zend_bool jit,zend_auto_global_callback auto_global_callback TSRMLS_DC)6876 int zend_register_auto_global(const char *name, uint name_len, zend_bool jit, zend_auto_global_callback auto_global_callback TSRMLS_DC) /* {{{ */
6877 {
6878 	zend_auto_global auto_global;
6879 
6880 	auto_global.name = zend_new_interned_string((char*)name, name_len + 1, 0 TSRMLS_CC);
6881 	auto_global.name_len = name_len;
6882 	auto_global.auto_global_callback = auto_global_callback;
6883 	auto_global.jit = jit;
6884 
6885 	return zend_hash_add(CG(auto_globals), name, name_len+1, &auto_global, sizeof(zend_auto_global), NULL);
6886 }
6887 /* }}} */
6888 
zend_auto_global_init(zend_auto_global * auto_global TSRMLS_DC)6889 static int zend_auto_global_init(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */
6890 {
6891 	if (auto_global->jit) {
6892 		auto_global->armed = 1;
6893 	} else if (auto_global->auto_global_callback) {
6894 		auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
6895 	} else {
6896 		auto_global->armed = 0;
6897 	}
6898 	return 0;
6899 }
6900 /* }}} */
6901 
zend_activate_auto_globals(TSRMLS_D)6902 ZEND_API void zend_activate_auto_globals(TSRMLS_D) /* {{{ */
6903 {
6904 	zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_init TSRMLS_CC);
6905 }
6906 /* }}} */
6907 
zendlex(znode * zendlval TSRMLS_DC)6908 int zendlex(znode *zendlval TSRMLS_DC) /* {{{ */
6909 {
6910 	int retval;
6911 
6912 	if (CG(increment_lineno)) {
6913 		CG(zend_lineno)++;
6914 		CG(increment_lineno) = 0;
6915 	}
6916 
6917 again:
6918 	Z_TYPE(zendlval->u.constant) = IS_LONG;
6919 	retval = lex_scan(&zendlval->u.constant TSRMLS_CC);
6920 	switch (retval) {
6921 		case T_COMMENT:
6922 		case T_DOC_COMMENT:
6923 		case T_OPEN_TAG:
6924 		case T_WHITESPACE:
6925 			goto again;
6926 
6927 		case T_CLOSE_TAG:
6928 			if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1] != '>') {
6929 				CG(increment_lineno) = 1;
6930 			}
6931 			if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
6932 				goto again;
6933 			}
6934 			retval = ';'; /* implicit ; */
6935 			break;
6936 		case T_OPEN_TAG_WITH_ECHO:
6937 			retval = T_ECHO;
6938 			break;
6939 	}
6940 
6941 	INIT_PZVAL(&zendlval->u.constant);
6942 	zendlval->op_type = IS_CONST;
6943 	return retval;
6944 }
6945 /* }}} */
6946 
zend_initialize_class_data(zend_class_entry * ce,zend_bool nullify_handlers TSRMLS_DC)6947 ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers TSRMLS_DC) /* {{{ */
6948 {
6949 	zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
6950 	dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR);
6951 
6952 	ce->refcount = 1;
6953 	ce->ce_flags = 0;
6954 
6955 	ce->default_properties_table = NULL;
6956 	ce->default_static_members_table = NULL;
6957 	zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0);
6958 	zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
6959 	zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
6960 
6961 	if (ce->type == ZEND_INTERNAL_CLASS) {
6962 #ifdef ZTS
6963 		int n = zend_hash_num_elements(CG(class_table));
6964 
6965 		if (CG(static_members_table) && n >= CG(last_static_member)) {
6966 			/* Support for run-time declaration: dl() */
6967 			CG(last_static_member) = n+1;
6968 			CG(static_members_table) = realloc(CG(static_members_table), (n+1)*sizeof(zval**));
6969 			CG(static_members_table)[n] = NULL;
6970 		}
6971 		ce->static_members_table = (zval**)(zend_intptr_t)n;
6972 #else
6973 		ce->static_members_table = NULL;
6974 #endif
6975 	} else {
6976 		ce->static_members_table = ce->default_static_members_table;
6977 		ce->info.user.doc_comment = NULL;
6978 		ce->info.user.doc_comment_len = 0;
6979 	}
6980 
6981 	ce->default_properties_count = 0;
6982 	ce->default_static_members_count = 0;
6983 
6984 	if (nullify_handlers) {
6985 		ce->constructor = NULL;
6986 		ce->destructor = NULL;
6987 		ce->clone = NULL;
6988 		ce->__get = NULL;
6989 		ce->__set = NULL;
6990 		ce->__unset = NULL;
6991 		ce->__isset = NULL;
6992 		ce->__call = NULL;
6993 		ce->__callstatic = NULL;
6994 		ce->__tostring = NULL;
6995 		ce->create_object = NULL;
6996 		ce->get_iterator = NULL;
6997 		ce->iterator_funcs.funcs = NULL;
6998 		ce->interface_gets_implemented = NULL;
6999 		ce->get_static_method = NULL;
7000 		ce->parent = NULL;
7001 		ce->num_interfaces = 0;
7002 		ce->interfaces = NULL;
7003 		ce->num_traits = 0;
7004 		ce->traits = NULL;
7005 		ce->trait_aliases = NULL;
7006 		ce->trait_precedences = NULL;
7007 		ce->serialize = NULL;
7008 		ce->unserialize = NULL;
7009 		ce->serialize_func = NULL;
7010 		ce->unserialize_func = NULL;
7011 		ce->__debugInfo = NULL;
7012 		if (ce->type == ZEND_INTERNAL_CLASS) {
7013 			ce->info.internal.module = NULL;
7014 			ce->info.internal.builtin_functions = NULL;
7015 		}
7016 	}
7017 }
7018 /* }}} */
7019 
zend_get_class_fetch_type(const char * class_name,uint class_name_len)7020 int zend_get_class_fetch_type(const char *class_name, uint class_name_len) /* {{{ */
7021 {
7022 	if ((class_name_len == sizeof("self")-1) &&
7023 		!strncasecmp(class_name, "self", sizeof("self")-1)) {
7024 		return ZEND_FETCH_CLASS_SELF;
7025 	} else if ((class_name_len == sizeof("parent")-1) &&
7026 		!strncasecmp(class_name, "parent", sizeof("parent")-1)) {
7027 		return ZEND_FETCH_CLASS_PARENT;
7028 	} else if ((class_name_len == sizeof("static")-1) &&
7029 		!strncasecmp(class_name, "static", sizeof("static")-1)) {
7030 		return ZEND_FETCH_CLASS_STATIC;
7031 	} else {
7032 		return ZEND_FETCH_CLASS_DEFAULT;
7033 	}
7034 }
7035 /* }}} */
7036 
zend_get_compiled_variable_name(const zend_op_array * op_array,zend_uint var,int * name_len)7037 ZEND_API const char* zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var, int* name_len) /* {{{ */
7038 {
7039 	if (name_len) {
7040 		*name_len = op_array->vars[var].name_len;
7041 	}
7042 	return op_array->vars[var].name;
7043 }
7044 /* }}} */
7045 
zend_do_build_namespace_name(znode * result,znode * prefix,znode * name TSRMLS_DC)7046 void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC) /* {{{ */
7047 {
7048 	if (prefix) {
7049 		*result = *prefix;
7050 		if (Z_TYPE(result->u.constant) == IS_STRING &&
7051 		    Z_STRLEN(result->u.constant) == 0) {
7052 			/* namespace\ */
7053 			if (CG(current_namespace)) {
7054 				znode tmp;
7055 
7056 				zval_dtor(&result->u.constant);
7057 				tmp.op_type = IS_CONST;
7058 				tmp.u.constant = *CG(current_namespace);
7059 				zval_copy_ctor(&tmp.u.constant);
7060 				zend_do_build_namespace_name(result, NULL, &tmp TSRMLS_CC);
7061 			}
7062 		}
7063 	} else {
7064 		result->op_type = IS_CONST;
7065 		Z_TYPE(result->u.constant) = IS_STRING;
7066 		Z_STRVAL(result->u.constant) = NULL;
7067 		Z_STRLEN(result->u.constant) = 0;
7068 	}
7069 	/* prefix = result */
7070 	zend_do_build_full_name(NULL, result, name, 0 TSRMLS_CC);
7071 }
7072 /* }}} */
7073 
zend_do_begin_namespace(const znode * name,zend_bool with_bracket TSRMLS_DC)7074 void zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC) /* {{{ */
7075 {
7076 	char *lcname;
7077 
7078 	/* handle mixed syntax declaration or nested namespaces */
7079 	if (!CG(has_bracketed_namespaces)) {
7080 		if (CG(current_namespace)) {
7081 			/* previous namespace declarations were unbracketed */
7082 			if (with_bracket) {
7083 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations with unbracketed namespace declarations");
7084 			}
7085 		}
7086 	} else {
7087 		/* previous namespace declarations were bracketed */
7088 		if (!with_bracket) {
7089 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations with unbracketed namespace declarations");
7090 		} else if (CG(current_namespace) || CG(in_namespace)) {
7091 			zend_error_noreturn(E_COMPILE_ERROR, "Namespace declarations cannot be nested");
7092 		}
7093 	}
7094 
7095 	if (((!with_bracket && !CG(current_namespace)) || (with_bracket && !CG(has_bracketed_namespaces))) && CG(active_op_array)->last > 0) {
7096 		/* ignore ZEND_EXT_STMT and ZEND_TICKS */
7097 		int num = CG(active_op_array)->last;
7098 		while (num > 0 &&
7099 		       (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
7100 		        CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
7101 			--num;
7102 		}
7103 		if (num > 0) {
7104 			zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be the very first statement in the script");
7105 		}
7106 	}
7107 
7108 	CG(in_namespace) = 1;
7109 	if (with_bracket) {
7110 		CG(has_bracketed_namespaces) = 1;
7111 	}
7112 
7113 	if (name) {
7114 		lcname = zend_str_tolower_dup(Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant));
7115 		if (((Z_STRLEN(name->u.constant) == sizeof("self")-1) &&
7116 		      !memcmp(lcname, "self", sizeof("self")-1)) ||
7117 		    ((Z_STRLEN(name->u.constant) == sizeof("parent")-1) &&
7118 	          !memcmp(lcname, "parent", sizeof("parent")-1))) {
7119 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", Z_STRVAL(name->u.constant));
7120 		}
7121 		efree(lcname);
7122 
7123 		if (CG(current_namespace)) {
7124 			zval_dtor(CG(current_namespace));
7125 		} else {
7126 			ALLOC_ZVAL(CG(current_namespace));
7127 		}
7128 		*CG(current_namespace) = name->u.constant;
7129 	} else {
7130 		if (CG(current_namespace)) {
7131 			zval_dtor(CG(current_namespace));
7132 			FREE_ZVAL(CG(current_namespace));
7133 			CG(current_namespace) = NULL;
7134 		}
7135 	}
7136 
7137 	if (CG(current_import)) {
7138 		zend_hash_destroy(CG(current_import));
7139 		efree(CG(current_import));
7140 		CG(current_import) = NULL;
7141 	}
7142 
7143 	if (CG(current_import_function)) {
7144 		zend_hash_destroy(CG(current_import_function));
7145 		efree(CG(current_import_function));
7146 		CG(current_import_function) = NULL;
7147 	}
7148 
7149 	if (CG(current_import_const)) {
7150 		zend_hash_destroy(CG(current_import_const));
7151 		efree(CG(current_import_const));
7152 		CG(current_import_const) = NULL;
7153 	}
7154 
7155 	if (CG(doc_comment)) {
7156 		efree(CG(doc_comment));
7157 		CG(doc_comment) = NULL;
7158 		CG(doc_comment_len) = 0;
7159 	}
7160 }
7161 /* }}} */
7162 
zend_do_use(znode * ns_name,znode * new_name TSRMLS_DC)7163 void zend_do_use(znode *ns_name, znode *new_name TSRMLS_DC) /* {{{ */
7164 {
7165 	char *lcname;
7166 	zval *name, *ns, tmp;
7167 	zend_bool warn = 0;
7168 	zend_class_entry **pce;
7169 
7170 	if (!CG(current_import)) {
7171 		CG(current_import) = emalloc(sizeof(HashTable));
7172 		zend_hash_init(CG(current_import), 0, NULL, ZVAL_PTR_DTOR, 0);
7173 	}
7174 
7175 	MAKE_STD_ZVAL(ns);
7176 	ZVAL_ZVAL(ns, &ns_name->u.constant, 0, 0);
7177 	if (new_name) {
7178 		name = &new_name->u.constant;
7179 	} else {
7180 		const char *p;
7181 
7182 		/* The form "use A\B" is eqivalent to "use A\B as B".
7183 		   So we extract the last part of compound name to use as a new_name */
7184 		name = &tmp;
7185 		p = zend_memrchr(Z_STRVAL_P(ns), '\\', Z_STRLEN_P(ns));
7186 		if (p) {
7187 			ZVAL_STRING(name, p+1, 1);
7188 		} else {
7189 			ZVAL_ZVAL(name, ns, 1, 0);
7190 			warn = !CG(current_namespace);
7191 		}
7192 	}
7193 
7194 	lcname = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
7195 
7196 	if (((Z_STRLEN_P(name) == sizeof("self")-1) &&
7197 				!memcmp(lcname, "self", sizeof("self")-1)) ||
7198 			((Z_STRLEN_P(name) == sizeof("parent")-1) &&
7199 	   !memcmp(lcname, "parent", sizeof("parent")-1))) {
7200 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' is a special class name", Z_STRVAL_P(ns), Z_STRVAL_P(name), Z_STRVAL_P(name));
7201 	}
7202 
7203 	if (CG(current_namespace)) {
7204 		/* Prefix import name with current namespace name to avoid conflicts with classes */
7205 		char *c_ns_name = emalloc(Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) + 1);
7206 
7207 		zend_str_tolower_copy(c_ns_name, Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
7208 		c_ns_name[Z_STRLEN_P(CG(current_namespace))] = '\\';
7209 		memcpy(c_ns_name+Z_STRLEN_P(CG(current_namespace))+1, lcname, Z_STRLEN_P(name)+1);
7210 		if (zend_hash_exists(CG(class_table), c_ns_name, Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name)+1)) {
7211 			char *tmp2 = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
7212 
7213 			if (Z_STRLEN_P(ns) != Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) ||
7214 				memcmp(tmp2, c_ns_name, Z_STRLEN_P(ns))) {
7215 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7216 			}
7217 			efree(tmp2);
7218 		}
7219 		efree(c_ns_name);
7220 	} else if (zend_hash_find(CG(class_table), lcname, Z_STRLEN_P(name)+1, (void**)&pce) == SUCCESS &&
7221 	           (*pce)->type == ZEND_USER_CLASS &&
7222 	           (*pce)->info.user.filename == CG(compiled_filename)) {
7223 		char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
7224 
7225 		if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
7226 			memcmp(c_tmp, lcname, Z_STRLEN_P(ns))) {
7227 			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7228 		}
7229 		efree(c_tmp);
7230 	}
7231 
7232 	if (zend_hash_add(CG(current_import), lcname, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
7233 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7234 	}
7235 	if (warn) {
7236 		if (!strcmp(Z_STRVAL_P(name), "strict")) {
7237 			zend_error_noreturn(E_COMPILE_ERROR, "You seem to be trying to use a different language...");
7238 		}
7239 		zend_error(E_WARNING, "The use statement with non-compound name '%s' has no effect", Z_STRVAL_P(name));
7240 	}
7241 	efree(lcname);
7242 	zval_dtor(name);
7243 }
7244 /* }}} */
7245 
zend_do_use_non_class(znode * ns_name,znode * new_name,int is_function,zend_bool case_sensitive,HashTable * current_import_sub,HashTable * lookup_table TSRMLS_DC)7246 void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_function, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC) /* {{{ */
7247 {
7248 	char *lookup_name;
7249 	zval *name, *ns, tmp;
7250 	zend_bool warn = 0;
7251 
7252 	MAKE_STD_ZVAL(ns);
7253 	ZVAL_ZVAL(ns, &ns_name->u.constant, 0, 0);
7254 	if (new_name) {
7255 		name = &new_name->u.constant;
7256 	} else {
7257 		const char *p;
7258 
7259 		/* The form "use A\B" is eqivalent to "use A\B as B".
7260 		   So we extract the last part of compound name to use as a new_name */
7261 		name = &tmp;
7262 		p = zend_memrchr(Z_STRVAL_P(ns), '\\', Z_STRLEN_P(ns));
7263 		if (p) {
7264 			ZVAL_STRING(name, p+1, 1);
7265 		} else {
7266 			ZVAL_ZVAL(name, ns, 1, 0);
7267 			warn = !CG(current_namespace);
7268 		}
7269 	}
7270 
7271 	if (case_sensitive) {
7272 		lookup_name = estrndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
7273 	} else {
7274 		lookup_name = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
7275 	}
7276 
7277 	if (CG(current_namespace)) {
7278 		/* Prefix import name with current namespace name to avoid conflicts with functions/consts */
7279 		char *c_ns_name = emalloc(Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) + 1);
7280 
7281 		zend_str_tolower_copy(c_ns_name, Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
7282 		c_ns_name[Z_STRLEN_P(CG(current_namespace))] = '\\';
7283 		memcpy(c_ns_name+Z_STRLEN_P(CG(current_namespace))+1, lookup_name, Z_STRLEN_P(name)+1);
7284 		if (zend_hash_exists(lookup_table, c_ns_name, Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name)+1)) {
7285 			char *tmp2 = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
7286 
7287 			if (Z_STRLEN_P(ns) != Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) ||
7288 				memcmp(tmp2, c_ns_name, Z_STRLEN_P(ns))) {
7289 				zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", is_function ? "function" : "const", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7290 			}
7291 			efree(tmp2);
7292 		}
7293 		efree(c_ns_name);
7294 	} else if (is_function) {
7295 		zend_function *function;
7296 
7297 		if (zend_hash_find(lookup_table, lookup_name, Z_STRLEN_P(name)+1, (void **) &function) == SUCCESS && function->type == ZEND_USER_FUNCTION && strcmp(function->op_array.filename, CG(compiled_filename)) == 0) {
7298 			char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
7299 
7300 			if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
7301 				memcmp(c_tmp, lookup_name, Z_STRLEN_P(ns))) {
7302 				zend_error(E_COMPILE_ERROR, "Cannot use function %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7303 			}
7304 			efree(c_tmp);
7305 		}
7306 	} else {
7307 		const char *filename;
7308 
7309 		if (zend_hash_find(lookup_table, lookup_name, Z_STRLEN_P(name)+1, (void **) &filename) == SUCCESS && strcmp(filename, CG(compiled_filename)) == 0) {
7310 			char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
7311 
7312 			if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
7313 				memcmp(c_tmp, lookup_name, Z_STRLEN_P(ns))) {
7314 				zend_error(E_COMPILE_ERROR, "Cannot use const %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7315 			}
7316 			efree(c_tmp);
7317 		}
7318 	}
7319 
7320 	if (zend_hash_add(current_import_sub, lookup_name, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
7321 		zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", is_function ? "function" : "const", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7322 	}
7323 	if (warn) {
7324 		zend_error(E_WARNING, "The use %s statement with non-compound name '%s' has no effect", is_function ? "function" : "const", Z_STRVAL_P(name));
7325 	}
7326 	efree(lookup_name);
7327 	zval_dtor(name);
7328 }
7329 /* }}} */
7330 
zend_do_use_function(znode * ns_name,znode * new_name TSRMLS_DC)7331 void zend_do_use_function(znode *ns_name, znode *new_name TSRMLS_DC) /* {{{ */
7332 {
7333 	if (!CG(current_import_function)) {
7334 		CG(current_import_function) = emalloc(sizeof(HashTable));
7335 		zend_hash_init(CG(current_import_function), 0, NULL, ZVAL_PTR_DTOR, 0);
7336 	}
7337 
7338 	zend_do_use_non_class(ns_name, new_name, 1, 0, CG(current_import_function), CG(function_table) TSRMLS_CC);
7339 }
7340 /* }}} */
7341 
zend_do_use_const(znode * ns_name,znode * new_name TSRMLS_DC)7342 void zend_do_use_const(znode *ns_name, znode *new_name TSRMLS_DC) /* {{{ */
7343 {
7344 	if (!CG(current_import_const)) {
7345 		CG(current_import_const) = emalloc(sizeof(HashTable));
7346 		zend_hash_init(CG(current_import_const), 0, NULL, ZVAL_PTR_DTOR, 0);
7347 	}
7348 
7349 	zend_do_use_non_class(ns_name, new_name, 0, 1, CG(current_import_const), &CG(const_filenames) TSRMLS_CC);
7350 }
7351 /* }}} */
7352 
zend_do_declare_constant(znode * name,znode * value TSRMLS_DC)7353 void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
7354 {
7355 	zend_op *opline;
7356 	zval **ns_name;
7357 
7358 	if (zend_get_ct_const(&name->u.constant, 0 TSRMLS_CC)) {
7359 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", Z_STRVAL(name->u.constant));
7360 	}
7361 
7362 	if (CG(current_namespace)) {
7363 		/* Prefix constant name with name of current namespace, lowercased */
7364 		znode tmp;
7365 
7366 		tmp.op_type = IS_CONST;
7367 		tmp.u.constant = *CG(current_namespace);
7368 		Z_STRVAL(tmp.u.constant) = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), Z_STRLEN(tmp.u.constant));
7369 		zend_do_build_namespace_name(&tmp, &tmp, name TSRMLS_CC);
7370 		*name = tmp;
7371 	}
7372 
7373 	/* Constant name must not conflict with import names */
7374 	if (CG(current_import_const) &&
7375 	    zend_hash_find(CG(current_import_const), Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
7376 
7377 		char *tmp = estrndup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
7378 
7379 		if (Z_STRLEN_PP(ns_name) != Z_STRLEN(name->u.constant) ||
7380 			memcmp(tmp, Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant))) {
7381 			zend_error(E_COMPILE_ERROR, "Cannot declare const %s because the name is already in use", Z_STRVAL(name->u.constant));
7382 		}
7383 		efree(tmp);
7384 	}
7385 
7386 	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
7387 	opline->opcode = ZEND_DECLARE_CONST;
7388 	SET_UNUSED(opline->result);
7389 	SET_NODE(opline->op1, name);
7390 	SET_NODE(opline->op2, value);
7391 
7392 	zend_hash_add(&CG(const_filenames), Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1, CG(compiled_filename), strlen(CG(compiled_filename))+1, NULL);
7393 }
7394 /* }}} */
7395 
zend_verify_namespace(TSRMLS_D)7396 void zend_verify_namespace(TSRMLS_D) /* {{{ */
7397 {
7398 	if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
7399 		zend_error_noreturn(E_COMPILE_ERROR, "No code may exist outside of namespace {}");
7400 	}
7401 }
7402 /* }}} */
7403 
zend_do_end_namespace(TSRMLS_D)7404 void zend_do_end_namespace(TSRMLS_D) /* {{{ */
7405 {
7406 	CG(in_namespace) = 0;
7407 	if (CG(current_namespace)) {
7408 		zval_dtor(CG(current_namespace));
7409 		FREE_ZVAL(CG(current_namespace));
7410 		CG(current_namespace) = NULL;
7411 	}
7412 	if (CG(current_import)) {
7413 		zend_hash_destroy(CG(current_import));
7414 		efree(CG(current_import));
7415 		CG(current_import) = NULL;
7416 	}
7417 	if (CG(current_import_function)) {
7418 		zend_hash_destroy(CG(current_import_function));
7419 		efree(CG(current_import_function));
7420 		CG(current_import_function) = NULL;
7421 	}
7422 	if (CG(current_import_const)) {
7423 		zend_hash_destroy(CG(current_import_const));
7424 		efree(CG(current_import_const));
7425 		CG(current_import_const) = NULL;
7426 	}
7427 }
7428 /* }}} */
7429 
zend_do_end_compilation(TSRMLS_D)7430 void zend_do_end_compilation(TSRMLS_D) /* {{{ */
7431 {
7432 	CG(has_bracketed_namespaces) = 0;
7433 	zend_do_end_namespace(TSRMLS_C);
7434 }
7435 /* }}} */
7436 
zend_do_constant_expression(znode * result,zend_ast * ast TSRMLS_DC)7437 void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
7438 {
7439 	if (ast->kind == ZEND_CONST) {
7440 		result->u.constant = *ast->u.val;
7441 		efree(ast);
7442 	} else if (zend_ast_is_ct_constant(ast)) {
7443 		zend_ast_evaluate(&result->u.constant, ast, NULL TSRMLS_CC);
7444 		zend_ast_destroy(ast);
7445 	} else {
7446 		Z_TYPE(result->u.constant) = IS_CONSTANT_AST;
7447 		Z_AST(result->u.constant) = ast;
7448 	}
7449 }
7450 /* }}} */
7451 
7452 /* {{{ zend_dirname
7453    Returns directory name component of path */
zend_dirname(char * path,size_t len)7454 ZEND_API size_t zend_dirname(char *path, size_t len)
7455 {
7456 	register char *end = path + len - 1;
7457 	unsigned int len_adjust = 0;
7458 
7459 #ifdef PHP_WIN32
7460 	/* Note that on Win32 CWD is per drive (heritage from CP/M).
7461 	 * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
7462 	 */
7463 	if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
7464 		/* Skip over the drive spec (if any) so as not to change */
7465 		path += 2;
7466 		len_adjust += 2;
7467 		if (2 == len) {
7468 			/* Return "c:" on Win32 for dirname("c:").
7469 			 * It would be more consistent to return "c:."
7470 			 * but that would require making the string *longer*.
7471 			 */
7472 			return len;
7473 		}
7474 	}
7475 #elif defined(NETWARE)
7476 	/*
7477 	 * Find the first occurrence of : from the left
7478 	 * move the path pointer to the position just after :
7479 	 * increment the len_adjust to the length of path till colon character(inclusive)
7480 	 * If there is no character beyond : simple return len
7481 	 */
7482 	char *colonpos = NULL;
7483 	colonpos = strchr(path, ':');
7484 	if (colonpos != NULL) {
7485 		len_adjust = ((colonpos - path) + 1);
7486 		path += len_adjust;
7487 		if (len_adjust == len) {
7488 			return len;
7489 		}
7490 	}
7491 #endif
7492 
7493 	if (len == 0) {
7494 		/* Illegal use of this function */
7495 		return 0;
7496 	}
7497 
7498 	/* Strip trailing slashes */
7499 	while (end >= path && IS_SLASH_P(end)) {
7500 		end--;
7501 	}
7502 	if (end < path) {
7503 		/* The path only contained slashes */
7504 		path[0] = DEFAULT_SLASH;
7505 		path[1] = '\0';
7506 		return 1 + len_adjust;
7507 	}
7508 
7509 	/* Strip filename */
7510 	while (end >= path && !IS_SLASH_P(end)) {
7511 		end--;
7512 	}
7513 	if (end < path) {
7514 		/* No slash found, therefore return '.' */
7515 #ifdef NETWARE
7516 		if (len_adjust == 0) {
7517 			path[0] = '.';
7518 			path[1] = '\0';
7519 			return 1; /* only one character */
7520 		} else {
7521 			path[0] = '\0';
7522 			return len_adjust;
7523 		}
7524 #else
7525 		path[0] = '.';
7526 		path[1] = '\0';
7527 		return 1 + len_adjust;
7528 #endif
7529 	}
7530 
7531 	/* Strip slashes which came before the file name */
7532 	while (end >= path && IS_SLASH_P(end)) {
7533 		end--;
7534 	}
7535 	if (end < path) {
7536 		path[0] = DEFAULT_SLASH;
7537 		path[1] = '\0';
7538 		return 1 + len_adjust;
7539 	}
7540 	*(end+1) = '\0';
7541 
7542 	return (size_t)(end + 1 - path) + len_adjust;
7543 }
7544 /* }}} */
7545 
7546 /*
7547  * Local variables:
7548  * tab-width: 4
7549  * c-basic-offset: 4
7550  * indent-tabs-mode: t
7551  * End:
7552  */
7553