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 =