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