1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2009 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: zend_compile.c 290752 2009-11-14 19:17:22Z felipe $ */
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 "tsrm_virtual_cwd.h"
29 :
30 : ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
31 : ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
32 :
33 : #ifndef ZTS
34 : ZEND_API zend_compiler_globals compiler_globals;
35 : ZEND_API zend_executor_globals executor_globals;
36 : #endif
37 :
38 : static void zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */
39 14601 : {
40 14601 : property_info->name.u = eustrndup(property_info->name.u, property_info->name_length);
41 14601 : if (property_info->doc_comment.u) {
42 6 : property_info->doc_comment.u = eustrndup(property_info->doc_comment.u, property_info->doc_comment_len);
43 : }
44 14601 : }
45 : /* }}} */
46 :
47 : static void zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */
48 2687106 : {
49 2687106 : property_info->name.u = zend_ustrndup(property_info->name.u, property_info->name_length);
50 2687106 : }
51 : /* }}} */
52 :
53 : static void zend_destroy_property_info(zend_property_info *property_info) /* {{{ */
54 16512 : {
55 16512 : efree(property_info->name.v);
56 16512 : if (property_info->doc_comment.v) {
57 48 : efree(property_info->doc_comment.v);
58 : }
59 16512 : }
60 : /* }}} */
61 :
62 : static void zend_destroy_property_info_internal(zend_property_info *property_info) /* {{{ */
63 3799569 : {
64 3799569 : free(property_info->name.v);
65 3799569 : }
66 : /* }}} */
67 :
68 : static void build_runtime_defined_function_key(zval *result, zend_uchar type, const zstr name, int name_length TSRMLS_DC) /* {{{ */
69 14278 : {
70 : char char_pos_buf[32];
71 : uint char_pos_len;
72 : char *filename;
73 : uint filename_length;
74 :
75 14278 : char_pos_len = zend_sprintf(char_pos_buf, "%p", LANG_SCNG(yy_text));
76 14278 : if (CG(active_op_array)->filename) {
77 14278 : filename = CG(active_op_array)->filename;
78 : } else {
79 0 : filename = "-";
80 : }
81 :
82 : /* NULL, name length, filename length, last accepting char position length */
83 14278 : filename_length = strlen(filename);
84 14278 : Z_UNILEN_P(result) = 1+name_length+filename_length+char_pos_len;
85 14278 : if (type == IS_UNICODE) {
86 14278 : Z_USTRVAL_P(result) = (UChar *) eumalloc(Z_STRLEN_P(result)+1);
87 14278 : Z_USTRVAL_P(result)[0] = 0;
88 14278 : memcpy(Z_USTRVAL_P(result)+1, name.u, UBYTES(name_length));
89 :
90 : /* UTODO: Support for non-ascii filenames */
91 14278 : u_charsToUChars(filename, Z_USTRVAL_P(result)+1+name_length, filename_length);
92 14278 : u_charsToUChars(char_pos_buf, Z_USTRVAL_P(result)+1+name_length+filename_length, char_pos_len);
93 14278 : Z_USTRVAL_P(result)[1+name_length+filename_length+char_pos_len] = 0;
94 14278 : Z_TYPE_P(result) = IS_UNICODE;
95 : } else {
96 0 : Z_STRVAL_P(result) = (char *) emalloc(Z_STRLEN_P(result)+1);
97 0 : Z_STRVAL_P(result)[0] = '\0';
98 0 : memcpy(Z_STRVAL_P(result)+1, name.s, name_length);
99 0 : memcpy(Z_STRVAL_P(result)+1+name_length, filename, filename_length);
100 0 : memcpy(Z_STRVAL_P(result)+1+name_length+filename_length, char_pos_buf, char_pos_len+1);
101 0 : Z_TYPE_P(result) = IS_STRING;
102 : }
103 14278 : Z_SET_REFCOUNT_P(result, 1);
104 14278 : }
105 : /* }}} */
106 :
107 : ZEND_API int zend_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */
108 153198 : {
109 153198 : auto_global->armed = (auto_global->auto_global_callback ? 1 : 0);
110 153198 : return 0;
111 : }
112 :
113 : ZEND_API int zend_auto_global_arm_by_name(const char *name, zend_uint name_len TSRMLS_DC) /* {{{ */
114 0 : {
115 : zend_auto_global *auto_global;
116 :
117 0 : if (zend_hash_find(CG(auto_globals), name, name_len+1, (void **) &auto_global)==FAILURE) {
118 0 : return FAILURE;
119 : }
120 :
121 0 : auto_global->armed = 1;
122 0 : CG(auto_globals_cache)[auto_global->index] = NULL;
123 :
124 0 : return SUCCESS;
125 : }
126 : /* }}} */
127 :
128 : int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC) /* {{{ */
129 0 : {
130 : zend_auto_global *auto_global;
131 :
132 0 : if (zend_hash_find(CG(auto_globals), varname, varname_length+1, (void **) &auto_global)==FAILURE) {
133 0 : return FAILURE;
134 : }
135 0 : auto_global->armed = 0;
136 0 : return SUCCESS;
137 : }
138 : /* }}} */
139 :
140 : static void init_compiler_declarables(TSRMLS_D) /* {{{ */
141 17022 : {
142 17022 : Z_TYPE(CG(declarables).ticks) = IS_LONG;
143 17022 : Z_LVAL(CG(declarables).ticks) = 0;
144 17022 : }
145 : /* }}} */
146 :
147 : void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
148 17022 : {
149 17022 : zend_stack_init(&CG(bp_stack));
150 17022 : zend_stack_init(&CG(function_call_stack));
151 17022 : zend_stack_init(&CG(switch_cond_stack));
152 17022 : zend_stack_init(&CG(foreach_copy_stack));
153 17022 : zend_stack_init(&CG(object_stack));
154 17022 : zend_stack_init(&CG(declare_stack));
155 17022 : CG(active_class_entry) = NULL;
156 17022 : zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
157 17022 : zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
158 17022 : zend_stack_init(&CG(list_stack));
159 17022 : CG(in_compilation) = 0;
160 17022 : CG(start_lineno) = 0;
161 17022 : init_compiler_declarables(TSRMLS_C);
162 17022 : memset(CG(auto_globals_cache), 0, sizeof(zval**) * zend_hash_num_elements(CG(auto_globals)));
163 17022 : zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_arm TSRMLS_CC);
164 17022 : zend_stack_init(&CG(labels_stack));
165 17022 : CG(labels) = NULL;
166 17022 : CG(current_namespace) = NULL;
167 17022 : CG(in_namespace) = 0;
168 17022 : CG(has_bracketed_namespaces) = 0;
169 17022 : CG(current_import) = NULL;
170 17022 : }
171 : /* }}} */
172 :
173 : ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
174 24343 : {
175 : TSRMLS_FETCH();
176 :
177 24343 : zend_file_handle_dtor(fh TSRMLS_CC);
178 24343 : }
179 : /* }}} */
180 :
181 : void init_compiler(TSRMLS_D) /* {{{ */
182 16993 : {
183 16993 : CG(auto_globals_cache) = emalloc(sizeof(zval**) * zend_hash_num_elements(CG(auto_globals)));
184 16993 : CG(active_op_array) = NULL;
185 16993 : zend_init_compiler_data_structures(TSRMLS_C);
186 16993 : zend_init_rsrc_list(TSRMLS_C);
187 16993 : zend_hash_init(&CG(filenames_table), 5, NULL, (dtor_func_t) free_estring, 0);
188 16993 : zend_hash_init(&CG(script_encodings_table), 5, NULL, (dtor_func_t) free_estring, 0);
189 16993 : zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) file_handle_dtor, 0);
190 16993 : CG(unclean_shutdown) = 0;
191 16993 : }
192 : /* }}} */
193 :
194 : void shutdown_compiler(TSRMLS_D) /* {{{ */
195 17025 : {
196 17025 : efree(CG(auto_globals_cache));
197 17025 : CG(auto_globals_cache) = NULL;
198 17025 : zend_stack_destroy(&CG(bp_stack));
199 17025 : zend_stack_destroy(&CG(function_call_stack));
200 17025 : zend_stack_destroy(&CG(switch_cond_stack));
201 17025 : zend_stack_destroy(&CG(foreach_copy_stack));
202 17025 : zend_stack_destroy(&CG(object_stack));
203 17025 : zend_stack_destroy(&CG(declare_stack));
204 17025 : zend_stack_destroy(&CG(list_stack));
205 17025 : zend_hash_destroy(&CG(script_encodings_table));
206 17025 : zend_hash_destroy(&CG(filenames_table));
207 17025 : zend_llist_destroy(&CG(open_files));
208 17025 : zend_stack_destroy(&CG(labels_stack));
209 17025 : }
210 : /* }}} */
211 :
212 : ZEND_API char *zend_set_compiled_filename(const char *new_compiled_filename TSRMLS_DC) /* {{{ */
213 25345 : {
214 : char **pp, *p;
215 25345 : int length = strlen(new_compiled_filename);
216 :
217 25345 : if (zend_hash_find(&CG(filenames_table), new_compiled_filename, length+1, (void **) &pp) == SUCCESS) {
218 875 : CG(compiled_filename) = *pp;
219 875 : return *pp;
220 : }
221 24470 : p = estrndup(new_compiled_filename, length);
222 24470 : zend_hash_update(&CG(filenames_table), new_compiled_filename, length+1, &p, sizeof(char *), (void **) &pp);
223 24470 : CG(compiled_filename) = p;
224 24470 : return p;
225 : }
226 : /* }}} */
227 :
228 : ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename TSRMLS_DC) /* {{{ */
229 25195 : {
230 25195 : CG(compiled_filename) = original_compiled_filename;
231 25195 : }
232 : /* }}} */
233 :
234 : ZEND_API char *zend_get_compiled_filename(TSRMLS_D) /* {{{ */
235 88453 : {
236 88453 : return CG(compiled_filename);
237 : }
238 : /* }}} */
239 :
240 : ZEND_API int zend_get_compiled_lineno(TSRMLS_D) /* {{{ */
241 53431 : {
242 53431 : return CG(zend_lineno);
243 : }
244 : /* }}} */
245 :
246 : ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */
247 2742053 : {
248 2742053 : return CG(in_compilation);
249 : }
250 : /* }}} */
251 :
252 : ZEND_API char *zend_set_compiled_script_encoding(char *new_script_enc TSRMLS_DC) /* {{{ */
253 25408 : {
254 : char **pp, *p;
255 25408 : int length = strlen(new_script_enc);
256 :
257 25408 : if (zend_hash_find(&CG(script_encodings_table), new_script_enc, length+1, (void **) &pp) == SUCCESS) {
258 8404 : CG(script_encoding) = *pp;
259 8404 : return *pp;
260 : }
261 17004 : p = estrndup(new_script_enc, length);
262 17004 : zend_hash_update(&CG(script_encodings_table), new_script_enc, length+1, &p, sizeof(char *), (void **) &pp);
263 17004 : CG(script_encoding) = p;
264 17004 : return p;
265 : }
266 : /* }}} */
267 :
268 : ZEND_API void zend_restore_compiled_script_encoding(char *original_script_enc TSRMLS_DC) /* {{{ */
269 25195 : {
270 25195 : CG(script_encoding) = original_script_enc;
271 25195 : }
272 : /* }}} */
273 :
274 : ZEND_API char *zend_get_compiled_script_encoding(TSRMLS_D) /* {{{ */
275 48799 : {
276 48799 : return CG(script_encoding);
277 : }
278 : /* }}} */
279 :
280 : static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
281 716185 : {
282 716185 : return (op_array->T)++ * ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable));
283 : }
284 : /* }}} */
285 :
286 : static int lookup_cv(zend_op_array *op_array, zend_uchar type, zstr name, int name_len) /* {{{ */
287 534564 : {
288 534564 : int i = 0;
289 534564 : ulong hash_value = zend_u_inline_hash_func(type, name, name_len+1);
290 :
291 -2141709880 : while (i < op_array->last_var) {
292 -2142462666 : if (op_array->vars[i].hash_value == hash_value &&
293 : op_array->vars[i].name_len == name_len &&
294 : !memcmp(op_array->vars[i].name.v, name.v, USTR_BYTES(type, name_len))) {
295 316342 : efree(name.v);
296 316342 : return i;
297 : }
298 -2142779008 : i++;
299 : }
300 218222 : i = op_array->last_var;
301 218222 : op_array->last_var++;
302 218222 : if (op_array->last_var > op_array->size_var) {
303 39432 : op_array->size_var += 16; /* FIXME */
304 39432 : op_array->vars = erealloc(op_array->vars, op_array->size_var*sizeof(zend_compiled_variable));
305 : }
306 218222 : op_array->vars[i].name = name; /* estrndup(name, name_len); */
307 218222 : op_array->vars[i].name_len = name_len;
308 218222 : op_array->vars[i].hash_value = hash_value;
309 218222 : return i;
310 : }
311 : /* }}} */
312 :
313 : void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
314 67132 : {
315 67132 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
316 :
317 67132 : opline->opcode = op;
318 67132 : opline->result.op_type = IS_TMP_VAR;
319 67132 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
320 67132 : opline->op1 = *op1;
321 67132 : opline->op2 = *op2;
322 67132 : *result = opline->result;
323 67132 : }
324 : /* }}} */
325 :
326 : void zend_do_unary_op(zend_uchar op, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */
327 22778 : {
328 22778 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
329 :
330 22778 : opline->opcode = op;
331 22778 : opline->result.op_type = IS_TMP_VAR;
332 22778 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
333 22778 : opline->op1 = *op1;
334 22778 : *result = opline->result;
335 22778 : SET_UNUSED(opline->op2);
336 22778 : }
337 : /* }}} */
338 :
339 : #define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(znode)); memset(&opline->op1,0,sizeof(znode)); memset(&opline->op2,0,sizeof(znode)); opline->result.op_type=opline->op1.op_type=opline->op2.op_type=IS_UNUSED; }
340 :
341 : static void zend_do_op_data(zend_op *data_op, const znode *value TSRMLS_DC) /* {{{ */
342 7483 : {
343 7483 : data_op->opcode = ZEND_OP_DATA;
344 7483 : data_op->op1 = *value;
345 7483 : SET_UNUSED(data_op->op2);
346 7483 : }
347 : /* }}} */
348 :
349 : void zend_do_binary_assign_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
350 2812 : {
351 2812 : int last_op_number = get_next_op_number(CG(active_op_array));
352 2812 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
353 :
354 2812 : if (last_op_number > 0) {
355 2812 : zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
356 :
357 2812 : switch (last_op->opcode) {
358 : case ZEND_FETCH_OBJ_RW:
359 42 : last_op->opcode = op;
360 42 : last_op->extended_value = ZEND_ASSIGN_OBJ;
361 :
362 42 : zend_do_op_data(opline, op2 TSRMLS_CC);
363 42 : SET_UNUSED(opline->result);
364 42 : *result = last_op->result;
365 42 : return;
366 : case ZEND_FETCH_DIM_RW:
367 31 : last_op->opcode = op;
368 31 : last_op->extended_value = ZEND_ASSIGN_DIM;
369 :
370 31 : zend_do_op_data(opline, op2 TSRMLS_CC);
371 31 : opline->op2.u.var = get_temporary_variable(CG(active_op_array));
372 31 : opline->op2.u.EA.type = 0;
373 31 : opline->op2.op_type = IS_VAR;
374 31 : SET_UNUSED(opline->result);
375 31 : *result = last_op->result;
376 31 : return;
377 : default:
378 : break;
379 : }
380 : }
381 :
382 2739 : opline->opcode = op;
383 2739 : opline->op1 = *op1;
384 2739 : opline->op2 = *op2;
385 2739 : opline->result.op_type = IS_VAR;
386 2739 : opline->result.u.EA.type = 0;
387 2739 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
388 2739 : *result = opline->result;
389 : }
390 : /* }}} */
391 :
392 : void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC) /* {{{ */
393 550869 : {
394 : zend_op opline;
395 : zend_op *opline_ptr;
396 : zend_llist *fetch_list_ptr;
397 550869 : zend_bool is_auto_global = 0;
398 : zend_auto_global *auto_global;
399 :
400 550869 : if (varname->op_type == IS_CONST) {
401 550689 : if (Z_TYPE(varname->u.constant) != IS_STRING &&
402 : Z_TYPE(varname->u.constant) != IS_UNICODE) {
403 0 : convert_to_unicode(&varname->u.constant);
404 : }
405 550689 : is_auto_global = zend_u_is_auto_global_ex(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant), 0, &auto_global TSRMLS_CC);
406 550689 : if (!is_auto_global &&
407 : !(Z_UNILEN(varname->u.constant) == (sizeof("this")-1) &&
408 : ZEND_U_EQUAL(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant), "this", sizeof("this")-1)) &&
409 : (CG(active_op_array)->last == 0 ||
410 : CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
411 532622 : result->op_type = IS_CV;
412 532622 : result->u.var = lookup_cv(CG(active_op_array), Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant));
413 532622 : result->u.EA.type = 0;
414 532622 : return;
415 : }
416 : }
417 :
418 18247 : if (bp) {
419 18233 : opline_ptr = &opline;
420 18233 : init_op(opline_ptr TSRMLS_CC);
421 : } else {
422 14 : opline_ptr = get_next_op(CG(active_op_array) TSRMLS_CC);
423 : }
424 :
425 18247 : opline_ptr->opcode = op;
426 18247 : opline_ptr->result.op_type = IS_VAR;
427 18247 : opline_ptr->result.u.EA.type = 0;
428 18247 : opline_ptr->result.u.var = get_temporary_variable(CG(active_op_array));
429 18247 : opline_ptr->op1 = *varname;
430 18247 : *result = opline_ptr->result;
431 18247 : SET_UNUSED(opline_ptr->op2);
432 :
433 18247 : opline_ptr->op2.u.EA.type = ZEND_FETCH_LOCAL;
434 18247 : if (is_auto_global) {
435 10128 : opline_ptr->op2.u.var = auto_global->index;
436 10128 : opline_ptr->op2.u.EA.type = ZEND_FETCH_AUTO_GLOBAL;
437 : }
438 :
439 18247 : if (bp) {
440 18233 : zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
441 18233 : zend_llist_add_element(fetch_list_ptr, opline_ptr);
442 : }
443 : }
444 : /* }}} */
445 :
446 : void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC) /* {{{ */
447 550859 : {
448 : /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
449 550859 : fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
450 550859 : }
451 : /* }}} */
452 :
453 : void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
454 332 : {
455 : znode class_node;
456 : zend_llist *fetch_list_ptr;
457 : zend_llist_element *le;
458 : zend_op *opline_ptr;
459 : zend_op opline;
460 :
461 332 : zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
462 332 : zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
463 332 : if (result->op_type == IS_CV) {
464 310 : init_op(&opline TSRMLS_CC);
465 :
466 310 : opline.opcode = ZEND_FETCH_W;
467 310 : opline.result.op_type = IS_VAR;
468 310 : opline.result.u.EA.type = 0;
469 310 : opline.result.u.var = get_temporary_variable(CG(active_op_array));
470 310 : opline.op1.op_type = IS_CONST;
471 310 : ZVAL_UNICODEL(&opline.op1.u.constant,
472 : CG(active_op_array)->vars[result->u.var].name.u,
473 : CG(active_op_array)->vars[result->u.var].name_len, 1);
474 310 : SET_UNUSED(opline.op2);
475 310 : opline.op2 = class_node;
476 310 : opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
477 310 : *result = opline.result;
478 :
479 310 : zend_llist_add_element(fetch_list_ptr, &opline);
480 : } else {
481 22 : le = fetch_list_ptr->head;
482 :
483 22 : opline_ptr = (zend_op *)le->data;
484 43 : if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1.op_type == IS_CV) {
485 21 : init_op(&opline TSRMLS_CC);
486 21 : opline.opcode = ZEND_FETCH_W;
487 21 : opline.result.op_type = IS_VAR;
488 21 : opline.result.u.EA.type = 0;
489 21 : opline.result.u.var = get_temporary_variable(CG(active_op_array));
490 21 : opline.op1.op_type = IS_CONST;
491 21 : ZVAL_UNICODEL(&opline.op1.u.constant,
492 : CG(active_op_array)->vars[opline_ptr->op1.u.var].name.u,
493 : CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len, 1);
494 21 : SET_UNUSED(opline.op2);
495 21 : opline.op2 = class_node;
496 21 : opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
497 21 : opline_ptr->op1 = opline.result;
498 :
499 21 : zend_llist_prepend_element(fetch_list_ptr, &opline);
500 : } else {
501 1 : opline_ptr->op2 = class_node;
502 1 : opline_ptr->op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
503 : }
504 : }
505 332 : }
506 : /* }}} */
507 :
508 : void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC) /* {{{ */
509 868 : {
510 868 : fetch_simple_variable(result, varname, 1 TSRMLS_CC);
511 :
512 868 : fetch_array_dim(result, result, first_dim TSRMLS_CC);
513 868 : }
514 : /* }}} */
515 :
516 : void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS_DC) /* {{{ */
517 38867 : {
518 : zend_op opline;
519 : zend_llist *fetch_list_ptr;
520 :
521 38867 : init_op(&opline TSRMLS_CC);
522 38867 : opline.opcode = ZEND_FETCH_DIM_W; /* the backpatching routine assumes W */
523 38867 : opline.result.op_type = IS_VAR;
524 38867 : opline.result.u.EA.type = 0;
525 38867 : opline.result.u.var = get_temporary_variable(CG(active_op_array));
526 38867 : opline.op1 = *parent;
527 38867 : opline.op2 = *dim;
528 38867 : opline.extended_value = ZEND_FETCH_STANDARD;
529 38867 : *result = opline.result;
530 :
531 38867 : zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
532 38867 : zend_llist_add_element(fetch_list_ptr, &opline);
533 38867 : }
534 : /* }}} */
535 :
536 : void fetch_string_offset(znode *result, const znode *parent, const znode *offset TSRMLS_DC) /* {{{ */
537 36 : {
538 36 : fetch_array_dim(result, parent, offset TSRMLS_CC);
539 36 : }
540 : /* }}} */
541 :
542 : void zend_do_print(znode *result, const znode *arg TSRMLS_DC) /* {{{ */
543 2660 : {
544 2660 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
545 :
546 2660 : opline->result.op_type = IS_TMP_VAR;
547 2660 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
548 2660 : opline->opcode = ZEND_PRINT;
549 2660 : opline->op1 = *arg;
550 2660 : SET_UNUSED(opline->op2);
551 2660 : *result = opline->result;
552 2660 : }
553 : /* }}} */
554 :
555 : void zend_do_echo(const znode *arg, zend_bool inline_html TSRMLS_DC) /* {{{ */
556 29126 : {
557 29126 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
558 :
559 29126 : opline->opcode = ZEND_ECHO;
560 29126 : opline->op1 = *arg;
561 29126 : opline->extended_value = inline_html;
562 29126 : SET_UNUSED(opline->op2);
563 29126 : }
564 : /* }}} */
565 :
566 : void zend_do_abstract_method(const znode *function_name, znode *modifiers, const znode *body TSRMLS_DC) /* {{{ */
567 15251 : {
568 : char *method_type;
569 :
570 15251 : if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
571 69 : Z_LVAL(modifiers->u.constant) |= ZEND_ACC_ABSTRACT;
572 69 : method_type = "Interface";
573 : } else {
574 15182 : method_type = "Abstract";
575 : }
576 :
577 15251 : if (Z_LVAL(modifiers->u.constant) & ZEND_ACC_ABSTRACT) {
578 103 : if(Z_LVAL(modifiers->u.constant) & ZEND_ACC_PRIVATE) {
579 1 : zend_error(E_COMPILE_ERROR, "%s function %v::%R() cannot be declared private", method_type, CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant));
580 : }
581 102 : if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
582 101 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
583 :
584 101 : opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
585 101 : SET_UNUSED(opline->op1);
586 101 : SET_UNUSED(opline->op2);
587 : } else {
588 : /* we had code in the function body */
589 1 : zend_error(E_COMPILE_ERROR, "%s function %v::%R() cannot contain body", method_type, CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant));
590 : }
591 : } else {
592 15148 : if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
593 1 : zend_error(E_COMPILE_ERROR, "Non-abstract method %v::%R() must contain body", CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant));
594 : }
595 : }
596 15248 : }
597 : /* }}} */
598 :
599 : static zend_bool opline_is_fetch_this(const zend_op *opline TSRMLS_DC) /* {{{ */
600 75856 : {
601 75856 : if ((opline->opcode == ZEND_FETCH_W) && (opline->op1.op_type == IS_CONST)
602 : && (Z_TYPE(opline->op1.u.constant) == IS_STRING ||
603 : Z_TYPE(opline->op1.u.constant) == IS_UNICODE)
604 : && (Z_UNILEN(opline->op1.u.constant) == (sizeof("this")-1))
605 : && ZEND_U_EQUAL(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), "this", sizeof("this")-1)) {
606 3670 : return 1;
607 : } else {
608 72186 : return 0;
609 : }
610 : }
611 : /* }}} */
612 :
613 : void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC) /* {{{ */
614 126478 : {
615 : int last_op_number;
616 : zend_op *opline;
617 :
618 126478 : if (value->op_type == IS_CV) {
619 : zend_llist *fetch_list_ptr;
620 :
621 3960 : zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
622 3960 : if (fetch_list_ptr && fetch_list_ptr->head) {
623 1590 : opline = (zend_op *)fetch_list_ptr->head->data;
624 :
625 1590 : if (opline->opcode == ZEND_FETCH_DIM_W &&
626 : opline->op1.op_type == IS_CV &&
627 : opline->op1.u.var == value->u.var) {
628 :
629 12 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
630 12 : opline->opcode = ZEND_FETCH_R;
631 12 : opline->result.op_type = IS_VAR;
632 12 : opline->result.u.EA.type = 0;
633 12 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
634 12 : opline->op1.op_type = IS_CONST;
635 12 : ZVAL_UNICODEL(&opline->op1.u.constant,
636 : CG(active_op_array)->vars[value->u.var].name.u,
637 : CG(active_op_array)->vars[value->u.var].name_len, 1);
638 12 : SET_UNUSED(opline->op2);
639 12 : opline->op2.u.EA.type = ZEND_FETCH_LOCAL;
640 12 : value = &opline->result;
641 : }
642 : }
643 : }
644 :
645 126478 : zend_do_end_variable_parse(variable, BP_VAR_W, 0 TSRMLS_CC);
646 :
647 126478 : last_op_number = get_next_op_number(CG(active_op_array));
648 126478 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
649 :
650 126478 : if (variable->op_type == IS_CV) {
651 118898 : if (variable->u.var == CG(active_op_array)->this_var) {
652 2 : zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
653 : }
654 7580 : } else if (variable->op_type == IS_VAR) {
655 7580 : int n = 0;
656 :
657 15160 : while (last_op_number - n > 0) {
658 : zend_op *last_op;
659 :
660 7580 : last_op = &CG(active_op_array)->opcodes[last_op_number-n-1];
661 :
662 7580 : if (last_op->result.op_type == IS_VAR &&
663 : last_op->result.u.var == variable->u.var) {
664 7580 : if (last_op->opcode == ZEND_FETCH_OBJ_W) {
665 1509 : if (n > 0) {
666 0 : int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
667 0 : *opline = *last_op;
668 0 : MAKE_NOP(last_op);
669 : /* last_op = opline; */
670 0 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
671 : /* get_next_op can realloc, we need to move last_op */
672 0 : last_op = &CG(active_op_array)->opcodes[opline_no];
673 : }
674 1509 : last_op->opcode = ZEND_ASSIGN_OBJ;
675 1509 : zend_do_op_data(opline, value TSRMLS_CC);
676 1509 : SET_UNUSED(opline->result);
677 1509 : *result = last_op->result;
678 1509 : return;
679 6071 : } else if (last_op->opcode == ZEND_FETCH_DIM_W) {
680 5901 : if (n > 0) {
681 0 : int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
682 0 : *opline = *last_op;
683 0 : MAKE_NOP(last_op);
684 : /* last_op = opline; */
685 0 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
686 : /* get_next_op can realloc, we need to move last_op */
687 0 : last_op = &CG(active_op_array)->opcodes[opline_no];
688 : }
689 5901 : last_op->opcode = ZEND_ASSIGN_DIM;
690 5901 : zend_do_op_data(opline, value TSRMLS_CC);
691 5901 : opline->op2.u.var = get_temporary_variable(CG(active_op_array));
692 5901 : opline->op2.u.EA.type = 0;
693 5901 : opline->op2.op_type = IS_VAR;
694 5901 : SET_UNUSED(opline->result);
695 5901 : *result = last_op->result;
696 5901 : return;
697 170 : } else if (opline_is_fetch_this(last_op TSRMLS_CC)) {
698 0 : zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
699 : } else {
700 170 : break;
701 : }
702 : }
703 0 : n++;
704 : }
705 : }
706 :
707 119066 : opline->opcode = ZEND_ASSIGN;
708 119066 : opline->op1 = *variable;
709 119066 : opline->op2 = *value;
710 119066 : opline->result.op_type = IS_VAR;
711 119066 : opline->result.u.EA.type = 0;
712 119066 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
713 119066 : *result = opline->result;
714 : }
715 : /* }}} */
716 :
717 : static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
718 232207 : {
719 232207 : zend_uint type = variable->u.EA.type;
720 :
721 232207 : return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
722 : }
723 : /* }}} */
724 :
725 : void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRMLS_DC) /* {{{ */
726 5813 : {
727 : zend_op *opline;
728 :
729 5813 : if (lvar->op_type == IS_CV) {
730 5645 : if (lvar->u.var == CG(active_op_array)->this_var) {
731 1 : zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
732 : }
733 168 : } else if (lvar->op_type == IS_VAR) {
734 168 : int last_op_number = get_next_op_number(CG(active_op_array));
735 :
736 168 : if (last_op_number > 0) {
737 168 : opline = &CG(active_op_array)->opcodes[last_op_number-1];
738 168 : if (opline_is_fetch_this(opline TSRMLS_CC)) {
739 0 : zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
740 : }
741 : }
742 : }
743 :
744 5812 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
745 5812 : opline->opcode = ZEND_ASSIGN_REF;
746 5812 : if (zend_is_function_or_method_call(rvar)) {
747 40 : opline->extended_value = ZEND_RETURNS_FUNCTION;
748 5772 : } else if (rvar->u.EA.type & ZEND_PARSED_NEW) {
749 10 : opline->extended_value = ZEND_RETURNS_NEW;
750 : } else {
751 5762 : opline->extended_value = 0;
752 : }
753 5812 : if (result) {
754 369 : opline->result.op_type = IS_VAR;
755 369 : opline->result.u.EA.type = 0;
756 369 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
757 369 : *result = opline->result;
758 : } else {
759 : /* SET_UNUSED(opline->result); */
760 5443 : opline->result.u.EA.type |= EXT_TYPE_UNUSED;
761 : }
762 5812 : opline->op1 = *lvar;
763 5812 : opline->op2 = *rvar;
764 5812 : }
765 : /* }}} */
766 :
767 : static inline void do_begin_loop(TSRMLS_D) /* {{{ */
768 12176 : {
769 : zend_brk_cont_element *brk_cont_element;
770 : int parent;
771 :
772 12176 : parent = CG(active_op_array)->current_brk_cont;
773 12176 : CG(active_op_array)->current_brk_cont = CG(active_op_array)->last_brk_cont;
774 12176 : brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
775 12176 : brk_cont_element->start = get_next_op_number(CG(active_op_array));
776 12176 : brk_cont_element->parent = parent;
777 12176 : }
778 : /* }}} */
779 :
780 : static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{ */
781 11740 : {
782 11740 : if (!has_loop_var) {
783 : /* The start fileld is used to free temporary variables in case of exceptions.
784 : * We won't try to free something of we don't have loop variable.
785 : */
786 2834 : CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].start = -1;
787 : }
788 11740 : CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = cont_addr;
789 11740 : CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
790 11740 : CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
791 11740 : }
792 : /* }}} */
793 :
794 : void zend_do_while_cond(const znode *expr, znode *close_bracket_token TSRMLS_DC) /* {{{ */
795 731 : {
796 731 : int while_cond_op_number = get_next_op_number(CG(active_op_array));
797 731 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
798 :
799 731 : opline->opcode = ZEND_JMPZ;
800 731 : opline->op1 = *expr;
801 731 : close_bracket_token->u.opline_num = while_cond_op_number;
802 731 : SET_UNUSED(opline->op2);
803 :
804 731 : do_begin_loop(TSRMLS_C);
805 731 : INC_BPC(CG(active_op_array));
806 731 : }
807 : /* }}} */
808 :
809 : void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC) /* {{{ */
810 731 : {
811 731 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
812 :
813 : /* add unconditional jump */
814 731 : opline->opcode = ZEND_JMP;
815 731 : opline->op1.u.opline_num = while_token->u.opline_num;
816 731 : SET_UNUSED(opline->op1);
817 731 : SET_UNUSED(opline->op2);
818 :
819 : /* update while's conditional jmp */
820 731 : CG(active_op_array)->opcodes[close_bracket_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
821 :
822 731 : do_end_loop(while_token->u.opline_num, 0 TSRMLS_CC);
823 :
824 731 : DEC_BPC(CG(active_op_array));
825 731 : }
826 : /* }}} */
827 :
828 : void zend_do_for_cond(const znode *expr, znode *second_semicolon_token TSRMLS_DC) /* {{{ */
829 1837 : {
830 1837 : int for_cond_op_number = get_next_op_number(CG(active_op_array));
831 1837 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
832 :
833 1837 : opline->opcode = ZEND_JMPZNZ;
834 1837 : opline->op1 = *expr; /* the conditional expression */
835 1837 : second_semicolon_token->u.opline_num = for_cond_op_number;
836 1837 : SET_UNUSED(opline->op2);
837 1837 : }
838 : /* }}} */
839 :
840 : void zend_do_for_before_statement(const znode *cond_start, const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
841 1837 : {
842 1837 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
843 :
844 1837 : opline->opcode = ZEND_JMP;
845 1837 : opline->op1.u.opline_num = cond_start->u.opline_num;
846 1837 : CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
847 1837 : SET_UNUSED(opline->op1);
848 1837 : SET_UNUSED(opline->op2);
849 :
850 1837 : do_begin_loop(TSRMLS_C);
851 :
852 1837 : INC_BPC(CG(active_op_array));
853 1837 : }
854 : /* }}} */
855 :
856 : void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
857 1837 : {
858 1837 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
859 :
860 1837 : opline->opcode = ZEND_JMP;
861 1837 : opline->op1.u.opline_num = second_semicolon_token->u.opline_num+1;
862 1837 : CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
863 1837 : SET_UNUSED(opline->op1);
864 1837 : SET_UNUSED(opline->op2);
865 :
866 1837 : do_end_loop(second_semicolon_token->u.opline_num+1, 0 TSRMLS_CC);
867 :
868 1837 : DEC_BPC(CG(active_op_array));
869 1837 : }
870 : /* }}} */
871 :
872 : void zend_do_pre_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
873 409 : {
874 409 : int last_op_number = get_next_op_number(CG(active_op_array));
875 : zend_op *opline;
876 :
877 409 : if (last_op_number > 0) {
878 409 : zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
879 :
880 409 : if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
881 9 : last_op->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
882 9 : last_op->result.op_type = IS_VAR;
883 9 : last_op->result.u.EA.type = 0;
884 9 : last_op->result.u.var = get_temporary_variable(CG(active_op_array));
885 9 : *result = last_op->result;
886 9 : return;
887 : }
888 : }
889 :
890 400 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
891 400 : opline->opcode = op;
892 400 : opline->op1 = *op1;
893 400 : SET_UNUSED(opline->op2);
894 400 : opline->result.op_type = IS_VAR;
895 400 : opline->result.u.EA.type = 0;
896 400 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
897 400 : *result = opline->result;
898 : }
899 : /* }}} */
900 :
901 : void zend_do_post_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
902 5207 : {
903 5207 : int last_op_number = get_next_op_number(CG(active_op_array));
904 : zend_op *opline;
905 :
906 5207 : if (last_op_number > 0) {
907 5207 : zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
908 :
909 5207 : if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
910 33 : last_op->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
911 33 : last_op->result.op_type = IS_TMP_VAR;
912 33 : last_op->result.u.var = get_temporary_variable(CG(active_op_array));
913 33 : *result = last_op->result;
914 33 : return;
915 : }
916 : }
917 :
918 5174 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
919 5174 : opline->opcode = op;
920 5174 : opline->op1 = *op1;
921 5174 : SET_UNUSED(opline->op2);
922 5174 : opline->result.op_type = IS_TMP_VAR;
923 5174 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
924 5174 : *result = opline->result;
925 : }
926 : /* }}} */
927 :
928 : void zend_do_if_cond(const znode *cond, znode *closing_bracket_token TSRMLS_DC) /* {{{ */
929 55729 : {
930 55729 : int if_cond_op_number = get_next_op_number(CG(active_op_array));
931 55729 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
932 :
933 55729 : opline->opcode = ZEND_JMPZ;
934 55729 : opline->op1 = *cond;
935 55729 : closing_bracket_token->u.opline_num = if_cond_op_number;
936 55729 : SET_UNUSED(opline->op2);
937 55729 : INC_BPC(CG(active_op_array));
938 55729 : }
939 : /* }}} */
940 :
941 : void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned char initialize TSRMLS_DC) /* {{{ */
942 55726 : {
943 55726 : int if_end_op_number = get_next_op_number(CG(active_op_array));
944 55726 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
945 : zend_llist *jmp_list_ptr;
946 :
947 55726 : opline->opcode = ZEND_JMP;
948 : /* save for backpatching */
949 55726 : if (initialize) {
950 : zend_llist jmp_list;
951 :
952 54184 : zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
953 54184 : zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
954 : }
955 55726 : zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
956 55726 : zend_llist_add_element(jmp_list_ptr, &if_end_op_number);
957 :
958 55726 : CG(active_op_array)->opcodes[closing_bracket_token->u.opline_num].op2.u.opline_num = if_end_op_number+1;
959 55726 : SET_UNUSED(opline->op1);
960 55726 : SET_UNUSED(opline->op2);
961 55726 : }
962 : /* }}} */
963 :
964 : void zend_do_if_end(TSRMLS_D) /* {{{ */
965 55930 : {
966 55930 : int next_op_number = get_next_op_number(CG(active_op_array));
967 : zend_llist *jmp_list_ptr;
968 : zend_llist_element *le;
969 :
970 55930 : zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
971 115156 : for (le=jmp_list_ptr->head; le; le = le->next) {
972 59226 : CG(active_op_array)->opcodes[*((int *) le->data)].op1.u.opline_num = next_op_number;
973 : }
974 55930 : zend_llist_destroy(jmp_list_ptr);
975 55930 : zend_stack_del_top(&CG(bp_stack));
976 55930 : DEC_BPC(CG(active_op_array));
977 55930 : }
978 : /* }}} */
979 :
980 : void zend_check_writable_variable(const znode *variable) /* {{{ */
981 144242 : {
982 144242 : zend_uint type = variable->u.EA.type;
983 :
984 144242 : if (type & ZEND_PARSED_METHOD_CALL) {
985 1 : zend_error(E_COMPILE_ERROR, "Can't use method return value in write context");
986 : }
987 144241 : if (type == ZEND_PARSED_FUNCTION_CALL) {
988 1 : zend_error(E_COMPILE_ERROR, "Can't use function return value in write context");
989 : }
990 144240 : }
991 : /* }}} */
992 :
993 : void zend_do_begin_variable_parse(TSRMLS_D) /* {{{ */
994 684004 : {
995 : zend_llist fetch_list;
996 :
997 684004 : zend_llist_init(&fetch_list, sizeof(zend_op), NULL, 0);
998 684004 : zend_stack_push(&CG(bp_stack), (void *) &fetch_list, sizeof(zend_llist));
999 684004 : }
1000 : /* }}} */
1001 :
1002 : void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC) /* {{{ */
1003 683985 : {
1004 : zend_llist *fetch_list_ptr;
1005 : zend_llist_element *le;
1006 683985 : zend_op *opline = NULL;
1007 : zend_op *opline_ptr;
1008 683985 : zend_uint this_var = -1;
1009 :
1010 683985 : zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
1011 :
1012 683985 : le = fetch_list_ptr->head;
1013 :
1014 : /* TODO: $foo->x->y->z = 1 should fetch "x" and "y" for R or RW, not just W */
1015 :
1016 683985 : if (le) {
1017 70593 : opline_ptr = (zend_op *)le->data;
1018 70593 : if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
1019 : /* convert to FETCH_?(this) into IS_CV */
1020 442 : if (CG(active_op_array)->last == 0 ||
1021 : CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
1022 :
1023 221 : this_var = opline_ptr->result.u.var;
1024 221 : if (CG(active_op_array)->this_var == -1) {
1025 188 : CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_TYPE(opline_ptr->op1.u.constant), Z_UNIVAL(opline_ptr->op1.u.constant), Z_UNILEN(opline_ptr->op1.u.constant));
1026 : } else {
1027 33 : efree(Z_STRVAL(opline_ptr->op1.u.constant));
1028 : }
1029 221 : le = le->next;
1030 221 : if (variable->op_type == IS_VAR &&
1031 : variable->u.var == this_var) {
1032 217 : variable->op_type = IS_CV;
1033 217 : variable->u.var = CG(active_op_array)->this_var;
1034 : }
1035 0 : } else if (CG(active_op_array)->this_var == -1) {
1036 0 : CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_TYPE(opline_ptr->op1.u.constant), ezstrndup(Z_TYPE(opline_ptr->op1.u.constant), Z_UNIVAL(opline_ptr->op1.u.constant), Z_UNILEN(opline_ptr->op1.u.constant)), Z_UNILEN(opline_ptr->op1.u.constant));
1037 : }
1038 : }
1039 :
1040 226322 : while (le) {
1041 85140 : opline_ptr = (zend_op *)le->data;
1042 85140 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1043 85140 : memcpy(opline, opline_ptr, sizeof(zend_op));
1044 85140 : if (opline->op1.op_type == IS_VAR &&
1045 : opline->op1.u.var == this_var) {
1046 4 : opline->op1.op_type = IS_CV;
1047 4 : opline->op1.u.var = CG(active_op_array)->this_var;
1048 : }
1049 85140 : switch (type) {
1050 : case BP_VAR_R:
1051 60949 : if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
1052 2 : zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
1053 : }
1054 60947 : opline->opcode -= 3;
1055 60947 : break;
1056 : case BP_VAR_W:
1057 12338 : break;
1058 : case BP_VAR_RW:
1059 1179 : opline->opcode += 3;
1060 1179 : break;
1061 : case BP_VAR_IS:
1062 9976 : if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
1063 1 : zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
1064 : }
1065 9975 : opline->opcode += 6; /* 3+3 */
1066 9975 : break;
1067 : case BP_VAR_FUNC_ARG:
1068 366 : opline->opcode += 9; /* 3+3+3 */
1069 366 : opline->extended_value = arg_offset;
1070 366 : break;
1071 : case BP_VAR_UNSET:
1072 332 : if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
1073 1 : zend_error(E_COMPILE_ERROR, "Cannot use [] for unsetting");
1074 : }
1075 331 : opline->opcode += 12; /* 3+3+3+3 */
1076 : break;
1077 : }
1078 85136 : le = le->next;
1079 : }
1080 70589 : if (opline && type == BP_VAR_W && arg_offset) {
1081 108 : opline->extended_value = ZEND_FETCH_MAKE_REF;
1082 : }
1083 : }
1084 683981 : zend_llist_destroy(fetch_list_ptr);
1085 683981 : zend_stack_del_top(&CG(bp_stack));
1086 683981 : }
1087 : /* }}} */
1088 :
1089 : void zend_do_add_string(znode *result, const znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
1090 19168 : {
1091 : zend_op *opline;
1092 :
1093 19168 : if (Z_UNILEN(op2->u.constant) > 1) {
1094 14968 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1095 14968 : opline->opcode = ZEND_ADD_STRING;
1096 4200 : } else if (Z_UNILEN(op2->u.constant) == 1) {
1097 4194 : int ch = (Z_TYPE(op2->u.constant) == IS_UNICODE) ? *Z_USTRVAL(op2->u.constant) : *Z_STRVAL(op2->u.constant);
1098 :
1099 : /* Free memory and use ZEND_ADD_CHAR in case of 1 character strings */
1100 4194 : efree(Z_UNIVAL(op2->u.constant).v);
1101 4194 : ZVAL_LONG(&op2->u.constant, ch);
1102 4194 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1103 4194 : opline->opcode = ZEND_ADD_CHAR;
1104 : } else { /* String can be empty after a variable at the end of a heredoc */
1105 6 : efree(Z_UNIVAL(op2->u.constant).v);
1106 6 : return;
1107 : }
1108 :
1109 19162 : if (op1) {
1110 12016 : opline->op1 = *op1;
1111 12016 : opline->result = *op1;
1112 : } else {
1113 7146 : SET_UNUSED(opline->op1);
1114 7146 : opline->result.op_type = IS_TMP_VAR;
1115 7146 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
1116 : }
1117 19162 : opline->op2 = *op2;
1118 19162 : opline->extended_value = CG(literal_type);
1119 19162 : *result = opline->result;
1120 : }
1121 : /* }}} */
1122 :
1123 : void zend_do_add_variable(znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
1124 15951 : {
1125 15951 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1126 :
1127 15951 : opline->opcode = ZEND_ADD_VAR;
1128 :
1129 15951 : if (op1) {
1130 12390 : opline->op1 = *op1;
1131 12390 : opline->result = *op1;
1132 : } else {
1133 3561 : SET_UNUSED(opline->op1);
1134 3561 : opline->result.op_type = IS_TMP_VAR;
1135 3561 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
1136 : }
1137 15951 : opline->op2 = *op2;
1138 15951 : opline->extended_value = CG(literal_type);
1139 15951 : *result = opline->result;
1140 15951 : }
1141 : /* }}} */
1142 :
1143 : void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
1144 247194 : {
1145 247194 : if (op1->op_type==IS_TMP_VAR) {
1146 9250 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1147 :
1148 9250 : opline->opcode = ZEND_FREE;
1149 9250 : opline->op1 = *op1;
1150 9250 : SET_UNUSED(opline->op2);
1151 237944 : } else if (op1->op_type==IS_VAR) {
1152 226612 : zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
1153 :
1154 461979 : while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END || opline->opcode == ZEND_OP_DATA) {
1155 8755 : opline--;
1156 : }
1157 453043 : if (opline->result.op_type == IS_VAR
1158 : && opline->result.u.var == op1->u.var) {
1159 226431 : opline->result.u.EA.type |= EXT_TYPE_UNUSED;
1160 : } else {
1161 732 : while (opline>CG(active_op_array)->opcodes) {
1162 551 : if (opline->opcode == ZEND_FETCH_DIM_TMP_VAR
1163 : && opline->op1.op_type == IS_VAR
1164 : && opline->op1.u.var == op1->u.var) {
1165 : /* This should the end of a list() construct
1166 : * Mark its result as unused
1167 : */
1168 38 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1169 :
1170 38 : opline->opcode = ZEND_SWITCH_FREE;
1171 38 : opline->extended_value = 0;
1172 38 : opline->op1 = *op1;
1173 38 : SET_UNUSED(opline->op2);
1174 38 : break;
1175 513 : } else if (opline->result.op_type==IS_VAR
1176 : && opline->result.u.var == op1->u.var) {
1177 143 : if (opline->opcode == ZEND_NEW) {
1178 143 : opline->result.u.EA.type |= EXT_TYPE_UNUSED;
1179 : }
1180 143 : break;
1181 : }
1182 370 : opline--;
1183 : }
1184 : }
1185 11332 : } else if (op1->op_type == IS_CONST) {
1186 11064 : zval_dtor(&op1->u.constant);
1187 : }
1188 247194 : }
1189 : /* }}} */
1190 :
1191 : int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier) /* {{{ */
1192 504 : {
1193 504 : if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_PPP_MASK)
1194 : && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_PPP_MASK)) {
1195 4 : zend_error(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
1196 : }
1197 500 : if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_ABSTRACT)
1198 : && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_ABSTRACT)) {
1199 1 : zend_error(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
1200 : }
1201 499 : if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_STATIC)
1202 : && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_STATIC)) {
1203 1 : zend_error(E_COMPILE_ERROR, "Multiple static modifiers are not allowed");
1204 : }
1205 498 : if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_FINAL)
1206 : && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_FINAL)) {
1207 1 : zend_error(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
1208 : }
1209 497 : 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)) {
1210 4 : zend_error(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class member");
1211 : }
1212 493 : return (Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant));
1213 : }
1214 : /* }}} */
1215 :
1216 : void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC) /* {{{ */
1217 23501 : {
1218 : zend_op_array op_array;
1219 23501 : zstr name = Z_UNIVAL(function_name->u.constant);
1220 23501 : int name_len = Z_UNILEN(function_name->u.constant);
1221 23501 : int function_begin_line = function_token->u.opline_num;
1222 : zend_uint fn_flags;
1223 : unsigned int lcname_len;
1224 : zstr lcname;
1225 : zend_bool orig_interactive;
1226 :
1227 23501 : if (is_method) {
1228 15276 : if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
1229 72 : if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
1230 1 : zend_error(E_COMPILE_ERROR, "Access type for interface method %v::%R() must be omitted", CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant));
1231 : }
1232 71 : Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
1233 : }
1234 15275 : fn_flags = Z_LVAL(fn_flags_znode->u.constant); /* must be done *after* the above check */
1235 : } else {
1236 8225 : fn_flags = 0;
1237 : }
1238 23500 : if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
1239 3 : zend_error(E_COMPILE_ERROR, "Static function %v%s%R() cannot be abstract", is_method ? CG(active_class_entry)->name : EMPTY_ZSTR, is_method ? "::" : "", Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant));
1240 : }
1241 :
1242 23497 : function_token->u.op_array = CG(active_op_array);
1243 23497 : lcname = zend_u_str_case_fold(Z_TYPE(function_name->u.constant), name, name_len, 0, &lcname_len);
1244 :
1245 23497 : orig_interactive = CG(interactive);
1246 23497 : CG(interactive) = 0;
1247 23497 : init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
1248 23497 : CG(interactive) = orig_interactive;
1249 :
1250 23497 : op_array.function_name = name;
1251 23497 : op_array.return_reference = return_reference;
1252 23497 : op_array.fn_flags |= fn_flags;
1253 23497 : op_array.pass_rest_by_reference = 0;
1254 :
1255 23497 : op_array.scope = is_method?CG(active_class_entry):NULL;
1256 23497 : op_array.prototype = NULL;
1257 :
1258 23497 : op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
1259 :
1260 23497 : if (is_method) {
1261 15272 : if (zend_u_hash_add(&CG(active_class_entry)->function_table, Z_TYPE(function_name->u.constant), lcname, lcname_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
1262 1 : zend_error(E_COMPILE_ERROR, "Cannot redeclare %v::%R()", CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), name);
1263 : }
1264 :
1265 15271 : if (fn_flags & ZEND_ACC_ABSTRACT) {
1266 106 : CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
1267 : }
1268 :
1269 15271 : if (!(fn_flags & ZEND_ACC_PPP_MASK)) {
1270 0 : fn_flags |= ZEND_ACC_PUBLIC;
1271 : }
1272 :
1273 15271 : if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
1274 71 : if ((lcname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1275 1 : if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1276 1 : zend_error(E_COMPILE_ERROR, "The magic method __call() must have public visibility and cannot be static");
1277 : }
1278 70 : } else if ((lcname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
1279 1 : if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
1280 1 : zend_error(E_COMPILE_ERROR, "The magic method __callStatic() must have public visibility and be static");
1281 : }
1282 69 : } else if ((lcname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
1283 0 : if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1284 0 : zend_error(E_COMPILE_ERROR, "The magic method __get() must have public visibility and cannot be static");
1285 : }
1286 69 : } else if ((lcname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
1287 0 : if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1288 0 : zend_error(E_COMPILE_ERROR, "The magic method __set() must have public visibility and cannot be static");
1289 : }
1290 69 : } else if ((lcname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
1291 0 : if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1292 0 : zend_error(E_COMPILE_ERROR, "The magic method __unset() must have public visibility and cannot be static");
1293 : }
1294 69 : } else if ((lcname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
1295 0 : if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1296 0 : zend_error(E_COMPILE_ERROR, "The magic method __isset() must have public visibility and cannot be static");
1297 : }
1298 69 : } else if ((lcname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
1299 0 : if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1300 0 : zend_error(E_COMPILE_ERROR, "The magic method __toString() must have public visibility and cannot be static");
1301 : }
1302 : }
1303 : } else {
1304 : zstr short_class_name;
1305 : unsigned int short_class_name_length;
1306 : zstr short_class_lcname;
1307 :
1308 15200 : if ((short_class_name.u = u_memrchr(CG(active_class_entry)->name.u, '\\', CG(active_class_entry)->name_length))) {
1309 58 : short_class_name_length = CG(active_class_entry)->name_length - (short_class_name.u - CG(active_class_entry)->name.u) - 1;
1310 58 : short_class_name.u++;
1311 : } else {
1312 15142 : short_class_name = CG(active_class_entry)->name;
1313 15142 : short_class_name_length = CG(active_class_entry)->name_length;
1314 : }
1315 15200 : short_class_lcname = zend_u_str_case_fold(IS_UNICODE, short_class_name, short_class_name_length, 0, &short_class_name_length);
1316 : /* Improve after RC: cache the lowercase class name */
1317 :
1318 15419 : if ((short_class_name_length == name_len) && (!memcmp(short_class_lcname.v, lcname.v, UBYTES(lcname_len)))) {
1319 220 : if (CG(active_class_entry)->constructor) {
1320 8 : zend_error(E_STRICT, "Redefining already defined constructor for class %v", CG(active_class_entry)->name);
1321 : } else {
1322 212 : CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
1323 : }
1324 16388 : } else if ((lcname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1))) {
1325 1408 : if (CG(active_class_entry)->constructor) {
1326 5 : zend_error(E_STRICT, "Redefining already defined constructor for class %v", CG(active_class_entry)->name);
1327 : }
1328 1408 : CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
1329 13701 : } else if ((lcname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1))) {
1330 129 : CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
1331 13463 : } else if ((lcname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1))) {
1332 20 : CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
1333 13474 : } else if ((lcname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1334 53 : if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1335 2 : zend_error(E_COMPILE_ERROR, "The magic method __call() must have public visibility and cannot be static");
1336 : }
1337 51 : CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
1338 13388 : } else if ((lcname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
1339 19 : if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
1340 1 : zend_error(E_COMPILE_ERROR, "The magic method __callStatic() must have public visibility and be static");
1341 : }
1342 18 : CG(active_class_entry)->__callstatic = (zend_function *) CG(active_op_array);
1343 13405 : } else if ((lcname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
1344 54 : if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1345 0 : zend_error(E_COMPILE_ERROR, "The magic method __get() must have public visibility and cannot be static");
1346 : }
1347 54 : CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
1348 13350 : } else if ((lcname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
1349 55 : if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1350 2 : zend_error(E_COMPILE_ERROR, "The magic method __set() must have public visibility and cannot be static");
1351 : }
1352 53 : CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
1353 13255 : } else if ((lcname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
1354 16 : if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1355 3 : zend_error(E_COMPILE_ERROR, "The magic method __unset() must have public visibility and cannot be static");
1356 : }
1357 13 : CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
1358 13239 : } else if ((lcname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
1359 13 : if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1360 0 : zend_error(E_COMPILE_ERROR, "The magic method __isset() must have public visibility and cannot be static");
1361 : }
1362 13 : CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
1363 13887 : } else if ((lcname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
1364 675 : if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1365 1 : zend_error(E_COMPILE_ERROR, "The magic method __toString() must have public visibility and cannot be static");
1366 : }
1367 674 : CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array);
1368 12538 : } else if (!(fn_flags & ZEND_ACC_STATIC)) {
1369 6553 : CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
1370 : }
1371 15190 : efree(short_class_lcname.v);
1372 : }
1373 :
1374 15259 : efree(lcname.v);
1375 : } else {
1376 8225 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1377 :
1378 8225 : if (CG(current_namespace)) {
1379 : /* Prefix function name with current namespcae name */
1380 : znode tmp;
1381 :
1382 71 : tmp.u.constant = *CG(current_namespace);
1383 71 : zval_copy_ctor(&tmp.u.constant);
1384 71 : zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
1385 71 : op_array.function_name = Z_UNIVAL(tmp.u.constant);
1386 71 : efree(lcname.v);
1387 71 : lcname = zend_u_str_case_fold(Z_TYPE(tmp.u.constant), Z_UNIVAL(tmp.u.constant), Z_UNILEN(tmp.u.constant), 0, &lcname_len);
1388 : }
1389 :
1390 8225 : opline->opcode = ZEND_DECLARE_FUNCTION;
1391 8225 : opline->op1.op_type = IS_CONST;
1392 8225 : build_runtime_defined_function_key(&opline->op1.u.constant, Z_TYPE(function_name->u.constant), lcname, lcname_len TSRMLS_CC);
1393 8225 : opline->op2.op_type = IS_CONST;
1394 8225 : Z_TYPE(opline->op2.u.constant) = Z_TYPE(function_name->u.constant);
1395 8225 : Z_UNIVAL(opline->op2.u.constant) = lcname;
1396 8225 : Z_UNILEN(opline->op2.u.constant) = lcname_len;
1397 8225 : Z_SET_REFCOUNT(opline->op2.u.constant, 1);
1398 8225 : opline->extended_value = ZEND_DECLARE_FUNCTION;
1399 8225 : zend_u_hash_update(CG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
1400 : }
1401 :
1402 23484 : if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
1403 0 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1404 :
1405 0 : opline->opcode = ZEND_EXT_NOP;
1406 0 : opline->lineno = function_begin_line;
1407 0 : SET_UNUSED(opline->op1);
1408 0 : SET_UNUSED(opline->op2);
1409 : }
1410 :
1411 : {
1412 : /* Push a seperator to the switch and foreach stacks */
1413 : zend_switch_entry switch_entry;
1414 :
1415 23484 : switch_entry.cond.op_type = IS_UNUSED;
1416 23484 : switch_entry.default_case = 0;
1417 23484 : switch_entry.control_var = 0;
1418 :
1419 23484 : zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
1420 :
1421 : {
1422 : /* Foreach stack separator */
1423 : zend_op dummy_opline;
1424 :
1425 23484 : dummy_opline.result.op_type = IS_UNUSED;
1426 23484 : dummy_opline.op1.op_type = IS_UNUSED;
1427 :
1428 23484 : zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
1429 : }
1430 : }
1431 :
1432 23484 : if (CG(doc_comment).v) {
1433 1926 : CG(active_op_array)->doc_comment = CG(doc_comment);
1434 1926 : CG(active_op_array)->doc_comment_len = CG(doc_comment_len);
1435 1926 : CG(doc_comment) = NULL_ZSTR;
1436 1926 : CG(doc_comment_len) = 0;
1437 : }
1438 :
1439 23484 : zend_stack_push(&CG(labels_stack), (void *) &CG(labels), sizeof(HashTable*));
1440 23484 : CG(labels) = NULL;
1441 23484 : }
1442 : /* }}} */
1443 :
1444 : void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC) /* {{{ */
1445 98 : {
1446 : znode function_name;
1447 98 : zend_op_array *current_op_array = CG(active_op_array);
1448 98 : int current_op_number = get_next_op_number(CG(active_op_array));
1449 : zend_op *current_op;
1450 :
1451 98 : function_name.op_type = IS_CONST;
1452 98 : ZVAL_ASCII_STRING(&function_name.u.constant, "{closure}", ZSTR_DUPLICATE);
1453 :
1454 98 : zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC);
1455 :
1456 98 : result->op_type = IS_TMP_VAR;
1457 98 : result->u.var = get_temporary_variable(current_op_array);
1458 :
1459 98 : current_op = ¤t_op_array->opcodes[current_op_number];
1460 98 : current_op->opcode = ZEND_DECLARE_LAMBDA_FUNCTION;
1461 98 : zval_dtor(¤t_op->op2.u.constant);
1462 98 : ZVAL_LONG(¤t_op->op2.u.constant, zend_u_get_hash_value(Z_TYPE(current_op->op1.u.constant), Z_UNIVAL(current_op->op1.u.constant), Z_UNILEN(current_op->op1.u.constant)));
1463 98 : current_op->result = *result;
1464 98 : if (is_static) {
1465 1 : CG(active_op_array)->fn_flags |= ZEND_ACC_STATIC;
1466 : }
1467 98 : CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE;
1468 98 : }
1469 : /* }}} */
1470 :
1471 : void zend_do_handle_exception(TSRMLS_D) /* {{{ */
1472 0 : {
1473 0 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1474 :
1475 0 : opline->opcode = ZEND_HANDLE_EXCEPTION;
1476 0 : SET_UNUSED(opline->op1);
1477 0 : SET_UNUSED(opline->op2);
1478 0 : }
1479 : /* }}} */
1480 :
1481 : void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC) /* {{{ */
1482 23472 : {
1483 : unsigned int lcname_len;
1484 : zstr lcname;
1485 : char lcname_buf[16];
1486 : int name_len;
1487 :
1488 23472 : zend_do_extended_info(TSRMLS_C);
1489 23472 : zend_do_return(NULL, 0 TSRMLS_CC);
1490 :
1491 23472 : pass_two(CG(active_op_array) TSRMLS_CC);
1492 :
1493 23472 : zend_release_labels(TSRMLS_C);
1494 :
1495 23472 : if (CG(active_class_entry)) {
1496 15277 : zend_check_magic_method_implementation(CG(active_class_entry), (zend_function*)CG(active_op_array), E_COMPILE_ERROR TSRMLS_CC);
1497 : } else {
1498 : zend_uchar utype;
1499 :
1500 : /* we don't care if the function name is longer, in fact lowercasing only
1501 : * the beginning of the name speeds up the check process */
1502 8195 : utype = IS_UNICODE;
1503 8195 : name_len = u_strlen(CG(active_op_array)->function_name.u);
1504 8195 : lcname = zend_u_str_case_fold(utype, CG(active_op_array)->function_name, name_len, 0, &lcname_len);
1505 8195 : if (lcname_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 &&
1506 : ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1) &&
1507 : CG(active_op_array)->num_args != 1) {
1508 1 : zend_error(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
1509 : }
1510 8194 : if (lcname.s != lcname_buf) {
1511 8194 : efree(lcname.s);
1512 : }
1513 : }
1514 :
1515 23455 : CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
1516 23455 : CG(active_op_array) = function_token->u.op_array;
1517 :
1518 :
1519 : /* Pop the switch and foreach seperators */
1520 23455 : zend_stack_del_top(&CG(switch_cond_stack));
1521 23455 : zend_stack_del_top(&CG(foreach_copy_stack));
1522 23455 : }
1523 : /* }}} */
1524 :
1525 : void zend_do_receive_arg(zend_uchar op, const znode *var, const znode *offset, const znode *initialization, znode *class_type, const znode *varname, zend_uchar pass_by_reference TSRMLS_DC) /* {{{ */
1526 110178 : {
1527 : zend_op *opline;
1528 : zend_arg_info *cur_arg_info;
1529 :
1530 110178 : if (class_type->op_type == IS_CONST &&
1531 : Z_TYPE(class_type->u.constant) == IS_UNICODE &&
1532 : Z_UNILEN(class_type->u.constant) == 0) {
1533 : /* Usage of namespace as class name not in namespace */
1534 0 : zval_dtor(&class_type->u.constant);
1535 0 : zend_error(E_COMPILE_ERROR, "Cannot use 'namespace' as a class name");
1536 0 : return;
1537 : }
1538 :
1539 110178 : if (var->op_type == IS_CV &&
1540 : var->u.var == CG(active_op_array)->this_var &&
1541 : (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
1542 0 : zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
1543 110178 : } else if (var->op_type == IS_VAR &&
1544 : CG(active_op_array)->scope &&
1545 : ((CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) &&
1546 : (Z_TYPE(varname->u.constant) == IS_STRING || Z_TYPE(varname->u.constant) == IS_UNICODE) &&
1547 : Z_UNILEN(varname->u.constant) == (sizeof("this")-1) &&
1548 : ZEND_U_EQUAL(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant), "this", sizeof("this")-1)) {
1549 1 : zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
1550 : }
1551 :
1552 110177 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1553 110177 : CG(active_op_array)->num_args++;
1554 110177 : opline->opcode = op;
1555 110177 : opline->result = *var;
1556 110177 : opline->op1 = *offset;
1557 110177 : if (op == ZEND_RECV_INIT) {
1558 10938 : opline->op2 = *initialization;
1559 : } else {
1560 99239 : CG(active_op_array)->required_num_args = CG(active_op_array)->num_args;
1561 99239 : SET_UNUSED(opline->op2);
1562 : }
1563 110177 : CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
1564 110177 : cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
1565 110177 : if (Z_TYPE(varname->u.constant) == IS_UNICODE) {
1566 110177 : cur_arg_info->name.u = eustrndup(Z_USTRVAL(varname->u.constant), Z_USTRLEN(varname->u.constant));
1567 : } else {
1568 0 : cur_arg_info->name.s = estrndup(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant));
1569 : }
1570 110177 : cur_arg_info->name_len = Z_UNILEN(varname->u.constant);
1571 110177 : cur_arg_info->array_type_hint = 0;
1572 110177 : cur_arg_info->allow_null = 1;
1573 110177 : cur_arg_info->pass_by_reference = pass_by_reference;
1574 110177 : cur_arg_info->class_name = NULL_ZSTR;
1575 110177 : cur_arg_info->class_name_len = 0;
1576 :
1577 110177 : if (class_type->op_type != IS_UNUSED) {
1578 310 : cur_arg_info->allow_null = 0;
1579 439 : if (Z_TYPE(class_type->u.constant) == IS_STRING || Z_TYPE(class_type->u.constant) == IS_UNICODE) {
1580 131 : if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_TYPE(class_type->u.constant), Z_UNIVAL(class_type->u.constant), Z_UNILEN(class_type->u.constant))) {
1581 127 : zend_resolve_class_name(class_type, &opline->extended_value, 1 TSRMLS_CC);
1582 : }
1583 130 : cur_arg_info->class_name = Z_UNIVAL(class_type->u.constant);
1584 130 : cur_arg_info->class_name_len = Z_UNILEN(class_type->u.constant);
1585 130 : if (op == ZEND_RECV_INIT) {
1586 29 : if (Z_TYPE(initialization->u.constant) == IS_NULL ||
1587 : (Z_TYPE(initialization->u.constant) == IS_CONSTANT &&
1588 : Z_UNILEN(initialization->u.constant) == sizeof("null") - 1 &&
1589 : ZEND_U_CASE_EQUAL(IS_UNICODE, Z_UNIVAL(initialization->u.constant), Z_UNILEN(initialization->u.constant), "null", sizeof("null")-1))) {
1590 14 : cur_arg_info->allow_null = 1;
1591 : } else {
1592 1 : zend_error(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
1593 : }
1594 : }
1595 : } else {
1596 179 : cur_arg_info->array_type_hint = 1;
1597 179 : cur_arg_info->class_name = NULL_ZSTR;
1598 179 : cur_arg_info->class_name_len = 0;
1599 179 : if (op == ZEND_RECV_INIT) {
1600 11 : if (Z_TYPE(initialization->u.constant) == IS_NULL ||
1601 : (Z_TYPE(initialization->u.constant) == IS_CONSTANT &&
1602 : Z_UNILEN(initialization->u.constant) == sizeof("null") - 1 &&
1603 : ZEND_U_CASE_EQUAL(IS_UNICODE, Z_UNIVAL(initialization->u.constant), Z_UNILEN(initialization->u.constant), "null", sizeof("null")-1))) {
1604 3 : cur_arg_info->allow_null = 1;
1605 5 : } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) {
1606 1 : zend_error(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
1607 : }
1608 : }
1609 : }
1610 : }
1611 110174 : opline->result.u.EA.type |= EXT_TYPE_UNUSED;
1612 : }
1613 : /* }}} */
1614 :
1615 : int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
1616 217894 : {
1617 : zend_function *function;
1618 : unsigned int lcname_len;
1619 : zstr lcname;
1620 : zstr is_compound;
1621 :
1622 217894 : if(Z_TYPE(function_name->u.constant) == IS_UNICODE) {
1623 217894 : is_compound.u = u_memchr(Z_USTRVAL(function_name->u.constant), '\\', Z_USTRLEN(function_name->u.constant));
1624 : } else {
1625 0 : is_compound.s = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
1626 : }
1627 :
1628 217894 : zend_resolve_non_class_name(function_name, check_namespace TSRMLS_CC);
1629 :
1630 217894 : if (check_namespace && CG(current_namespace) && !is_compound.v) {
1631 : /* We assume we call function from the current namespace
1632 : if it is not prefixed. */
1633 : /* In run-time PHP will check for function with full name and
1634 : internal function with short name */
1635 270 : zend_do_begin_dynamic_function_call(function_name, 1 TSRMLS_CC);
1636 270 : return 1;
1637 : }
1638 :
1639 217624 : lcname = zend_u_str_case_fold(Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant), Z_UNILEN(function_name->u.constant), 0, &lcname_len);
1640 217624 : if ((zend_u_hash_find(CG(function_table), Z_TYPE(function_name->u.constant), lcname, lcname_len+1, (void **) &function)==FAILURE) ||
1641 : ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
1642 : (function->type == ZEND_INTERNAL_FUNCTION))) {
1643 2689 : zend_do_begin_dynamic_function_call(function_name, 0 TSRMLS_CC);
1644 2689 : efree(lcname.v);
1645 2689 : return 1; /* Dynamic */
1646 : }
1647 214935 : efree(Z_UNIVAL(function_name->u.constant).v);
1648 214935 : Z_UNIVAL(function_name->u.constant) = lcname;
1649 214935 : Z_UNILEN(function_name->u.constant) = lcname_len;
1650 :
1651 214935 : zend_stack_push(&CG(function_call_stack), (void *) &function, sizeof(zend_function *));
1652 214935 : zend_do_extended_fcall_begin(TSRMLS_C);
1653 214935 : return 0;
1654 : }
1655 : /* }}} */
1656 :
1657 : void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
1658 23078 : {
1659 : zend_op *last_op;
1660 : int last_op_number;
1661 : unsigned int len;
1662 23078 : unsigned char *ptr = NULL;
1663 :
1664 23078 : zend_do_end_variable_parse(left_bracket, BP_VAR_R, 0 TSRMLS_CC);
1665 23078 : zend_do_begin_variable_parse(TSRMLS_C);
1666 :
1667 23078 : last_op_number = get_next_op_number(CG(active_op_array))-1;
1668 23078 : last_op = &CG(active_op_array)->opcodes[last_op_number];
1669 :
1670 23078 : if (last_op->op2.op_type == IS_CONST &&
1671 : (Z_TYPE(last_op->op2.u.constant) == IS_STRING ||
1672 : Z_TYPE(last_op->op2.u.constant) == IS_UNICODE) &&
1673 : Z_UNILEN(last_op->op2.u.constant) == sizeof(ZEND_CLONE_FUNC_NAME)-1) {
1674 : zstr lcname;
1675 : unsigned int lcname_len;
1676 :
1677 2265 : lcname = zend_u_str_case_fold(Z_TYPE(last_op->op2.u.constant), Z_UNIVAL(last_op->op2.u.constant), Z_UNILEN(last_op->op2.u.constant), 0, &lcname_len);
1678 2265 : if (ZEND_U_EQUAL(Z_TYPE(last_op->op2.u.constant), lcname, lcname_len, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1)) {
1679 1 : efree(lcname.v);
1680 1 : zend_error(E_COMPILE_ERROR, "Cannot call __clone() method on objects - use 'clone $obj' instead");
1681 : }
1682 2264 : efree(lcname.v);
1683 : }
1684 :
1685 23077 : if (last_op->opcode == ZEND_FETCH_OBJ_R) {
1686 23072 : last_op->opcode = ZEND_INIT_METHOD_CALL;
1687 23072 : SET_UNUSED(last_op->result);
1688 23072 : Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
1689 : } else {
1690 5 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1691 5 : opline->opcode = ZEND_INIT_FCALL_BY_NAME;
1692 5 : opline->op2 = *left_bracket;
1693 5 : if (opline->op2.op_type == IS_CONST) {
1694 0 : opline->op1.op_type = IS_CONST;
1695 0 : Z_TYPE(opline->op1.u.constant) = Z_TYPE(opline->op2.u.constant);
1696 0 : Z_UNIVAL(opline->op1.u.constant) = zend_u_str_case_fold(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), 0, &len);
1697 0 : Z_UNILEN(opline->op1.u.constant) = len;
1698 0 : opline->extended_value = zend_u_get_hash_value(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant) + 1);
1699 : } else {
1700 5 : opline->extended_value = 0;
1701 5 : SET_UNUSED(opline->op1);
1702 : }
1703 : }
1704 :
1705 23077 : zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
1706 23077 : zend_do_extended_fcall_begin(TSRMLS_C);
1707 23077 : }
1708 : /* }}} */
1709 :
1710 : void zend_do_clone(znode *result, const znode *expr TSRMLS_DC) /* {{{ */
1711 76 : {
1712 76 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1713 :
1714 76 : opline->opcode = ZEND_CLONE;
1715 76 : opline->op1 = *expr;
1716 76 : SET_UNUSED(opline->op2);
1717 76 : opline->result.op_type = IS_VAR;
1718 76 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
1719 76 : *result = opline->result;
1720 76 : }
1721 : /* }}} */
1722 :
1723 : void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC) /* {{{ */
1724 4782 : {
1725 4782 : unsigned char *ptr = NULL;
1726 : unsigned int len;
1727 : zend_op *opline, *opline2;
1728 :
1729 4782 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1730 :
1731 4782 : if (ns_call) {
1732 : zstr slash;
1733 : unsigned int prefix_len, name_len;
1734 : int type;
1735 : /* In run-time PHP will check for function with full name and
1736 : internal function with short name */
1737 270 : opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
1738 270 : opline->op2 = *function_name;
1739 270 : opline->extended_value = 0;
1740 270 : opline->op1.op_type = IS_CONST;
1741 270 : type = Z_TYPE(opline->op1.u.constant) = Z_TYPE(opline->op2.u.constant);
1742 270 : Z_UNIVAL(opline->op1.u.constant) = zend_u_str_case_fold(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), 0, &len);
1743 270 : Z_UNILEN(opline->op1.u.constant) = len;
1744 270 : opline->extended_value = zend_u_get_hash_value(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant) + 1);
1745 270 : if(Z_TYPE(opline->op1.u.constant) == IS_UNICODE) {
1746 270 : slash.u = u_memrchr(Z_USTRVAL(opline->op1.u.constant), '\\', Z_USTRLEN(opline->op1.u.constant));
1747 270 : if(!slash.u) {
1748 0 : zend_error(E_CORE_ERROR, "Namespaced name %R should contain slash", Z_UNIVAL(opline->op1.u.constant));
1749 : }
1750 270 : slash.u++;
1751 270 : prefix_len = slash.u-Z_USTRVAL(opline->op1.u.constant);
1752 270 : name_len = Z_USTRLEN(opline->op1.u.constant)-prefix_len;
1753 : } else {
1754 0 : slash.s = zend_memrchr(Z_STRVAL(opline->op1.u.constant), '\\', Z_STRLEN(opline->op1.u.constant));
1755 0 : if(!slash.s) {
1756 0 : zend_error(E_CORE_ERROR, "Namespaced name %R should contain slash", Z_UNIVAL(opline->op1.u.constant));
1757 : }
1758 0 : slash.s++;
1759 0 : prefix_len = slash.s-Z_STRVAL(opline->op1.u.constant);
1760 0 : name_len = Z_STRLEN(opline->op1.u.constant)-prefix_len;
1761 : }
1762 270 : opline2 = get_next_op(CG(active_op_array) TSRMLS_CC);
1763 270 : opline2->opcode = ZEND_OP_DATA;
1764 270 : opline2->op1.op_type = IS_CONST;
1765 : /* this is the length of namespace prefix */
1766 270 : Z_LVAL(opline2->op1.u.constant) = prefix_len;
1767 : /* this is the hash of the non-prefixed part, lowercased */
1768 270 : opline2->extended_value = zend_u_get_hash_value(type, slash, name_len+1);
1769 270 : SET_UNUSED(opline2->op2);
1770 : } else {
1771 4512 : opline->opcode = ZEND_INIT_FCALL_BY_NAME;
1772 4512 : opline->op2 = *function_name;
1773 4512 : if (opline->op2.op_type == IS_CONST) {
1774 2689 : opline->op1.op_type = IS_CONST;
1775 2689 : Z_TYPE(opline->op1.u.constant) = Z_TYPE(opline->op2.u.constant);
1776 2689 : Z_UNIVAL(opline->op1.u.constant) = zend_u_str_case_fold(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), 0, &len);
1777 2689 : Z_UNILEN(opline->op1.u.constant) = len;
1778 2689 : opline->extended_value = zend_u_get_hash_value(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant) + 1);
1779 : } else {
1780 1823 : opline->extended_value = 0;
1781 1823 : SET_UNUSED(opline->op1);
1782 : }
1783 : }
1784 :
1785 4782 : zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
1786 4782 : zend_do_extended_fcall_begin(TSRMLS_C);
1787 4782 : }
1788 : /* }}} */
1789 :
1790 : void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace TSRMLS_DC)
1791 275408 : {
1792 : znode tmp;
1793 : int len;
1794 : zval **ns;
1795 : zstr lcname;
1796 : zstr compound;
1797 : unsigned int lcname_len;
1798 :
1799 275408 : if (Z_TYPE(element_name->u.constant) == IS_UNICODE) {
1800 275408 : compound.u = u_memchr(Z_USTRVAL(element_name->u.constant), '\\', Z_USTRLEN(element_name->u.constant));
1801 : } else {
1802 0 : compound.s = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
1803 : }
1804 :
1805 275408 : if (Z_TYPE(element_name->u.constant) == IS_UNICODE && Z_USTRVAL(element_name->u.constant)[0] == '\\') {
1806 : /* name starts with \ so it is known and unambiguos, nothing to do here but shorten it */
1807 58 : memmove(Z_USTRVAL(element_name->u.constant), Z_USTRVAL(element_name->u.constant)+1, UBYTES(Z_USTRLEN(element_name->u.constant)));
1808 58 : --Z_USTRLEN(element_name->u.constant);
1809 58 : return;
1810 275350 : } else if (Z_TYPE(element_name->u.constant) == IS_STRING && Z_STRVAL(element_name->u.constant)[0] == '\\') {
1811 : /* name starts with \ so it is known and unambiguos, nothing to do here but shorten it */
1812 0 : memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+1, Z_STRLEN(element_name->u.constant));
1813 0 : --Z_STRLEN(element_name->u.constant);
1814 0 : return;
1815 : }
1816 :
1817 275350 : if(!check_namespace) {
1818 14 : return;
1819 : }
1820 :
1821 275336 : if (compound.v != NULL && CG(current_import)) {
1822 27 : if (Z_TYPE(element_name->u.constant) == IS_UNICODE) {
1823 27 : len = compound.u - Z_USTRVAL(element_name->u.constant);
1824 : } else {
1825 0 : len = compound.s - Z_STRVAL(element_name->u.constant);
1826 : }
1827 27 : lcname = zend_u_str_case_fold(Z_TYPE(element_name->u.constant), Z_UNIVAL(element_name->u.constant), len , 0, &lcname_len);
1828 : /* Check if first part of compound name is an import name */
1829 27 : if (zend_u_hash_find(CG(current_import), Z_TYPE(element_name->u.constant), lcname, lcname_len+1, (void**)&ns) == SUCCESS) {
1830 : /* Substitute import name */
1831 12 : tmp.op_type = IS_CONST;
1832 12 : tmp.u.constant = **ns;
1833 12 : zval_copy_ctor(&tmp.u.constant);
1834 12 : len += 1;
1835 12 : Z_UNILEN(element_name->u.constant) -= len;
1836 12 : if (Z_TYPE(element_name->u.constant) == IS_UNICODE) {
1837 12 : memmove(Z_USTRVAL(element_name->u.constant), Z_USTRVAL(element_name->u.constant)+len, UBYTES(Z_USTRLEN(element_name->u.constant)+1));
1838 : } else {
1839 0 : memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+len, Z_STRLEN(element_name->u.constant)+1);
1840 : }
1841 12 : zend_do_build_namespace_name(&tmp, &tmp, element_name TSRMLS_CC);
1842 12 : *element_name = tmp;
1843 12 : efree(lcname.v);
1844 12 : return;
1845 : }
1846 15 : efree(lcname.v);
1847 : }
1848 :
1849 275324 : if (CG(current_namespace)) {
1850 353 : tmp.op_type = IS_CONST;
1851 353 : tmp.u.constant = *CG(current_namespace);
1852 353 : zval_copy_ctor(&tmp.u.constant);
1853 353 : zend_do_build_namespace_name(&tmp, &tmp, element_name TSRMLS_CC);
1854 353 : *element_name = tmp;
1855 : }
1856 : }
1857 :
1858 : void zend_resolve_class_name(znode *class_name, ulong *fetch_type, int check_ns_name TSRMLS_DC) /* {{{ */
1859 23904 : {
1860 : zstr compound;
1861 : unsigned int lcname_len;
1862 : zstr lcname;
1863 : zval **ns;
1864 : znode tmp;
1865 : int len;
1866 :
1867 23904 : if (Z_TYPE(class_name->u.constant) == IS_UNICODE) {
1868 23904 : compound.u = u_memchr(Z_USTRVAL(class_name->u.constant), '\\', Z_USTRLEN(class_name->u.constant));
1869 : } else {
1870 0 : compound.s = memchr(Z_STRVAL(class_name->u.constant), '\\', Z_STRLEN(class_name->u.constant));
1871 : }
1872 23904 : if (compound.v) {
1873 : /* This is a compound class name that cotains namespace prefix */
1874 230 : if (Z_TYPE(class_name->u.constant) == IS_UNICODE &&
1875 : Z_USTRVAL(class_name->u.constant)[0] == '\\') {
1876 : /* The unicode name has \ prefix */
1877 103 : Z_USTRLEN(class_name->u.constant) -= 1;
1878 103 : memmove(Z_USTRVAL(class_name->u.constant), Z_USTRVAL(class_name->u.constant)+1, UBYTES(Z_USTRLEN(class_name->u.constant)+1));
1879 103 : Z_USTRVAL(class_name->u.constant) = eurealloc(
1880 : Z_USTRVAL(class_name->u.constant),
1881 : Z_USTRLEN(class_name->u.constant) + 1);
1882 103 : if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant))) {
1883 1 : zend_error(E_COMPILE_ERROR, "'\\%R' is an invalid class name", Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant));
1884 : }
1885 25 : } else if (Z_TYPE(class_name->u.constant) == IS_STRING &&
1886 : Z_STRVAL(class_name->u.constant)[0] == '\\') {
1887 : /* The STRING name has \ prefix */
1888 0 : Z_STRLEN(class_name->u.constant) -= 1;
1889 0 : memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+1, Z_STRLEN(class_name->u.constant)+1);
1890 0 : Z_STRVAL(class_name->u.constant) = erealloc(
1891 : Z_STRVAL(class_name->u.constant),
1892 : Z_STRLEN(class_name->u.constant) + 1);
1893 0 : if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant))) {
1894 0 : zend_error(E_COMPILE_ERROR, "'\\%R' is an invalid class name", Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant));
1895 : }
1896 : } else {
1897 25 : if (CG(current_import)) {
1898 21 : if (Z_TYPE(class_name->u.constant) == IS_UNICODE) {
1899 21 : len = compound.u - Z_USTRVAL(class_name->u.constant);
1900 : } else {
1901 0 : len = compound.s - Z_STRVAL(class_name->u.constant);
1902 : }
1903 21 : lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), len, 0, &lcname_len);
1904 : /* Check if first part of compound name is an import name */
1905 21 : if (zend_u_hash_find(CG(current_import), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&ns) == SUCCESS) {
1906 : /* Substitute import name */
1907 14 : tmp.op_type = IS_CONST;
1908 14 : tmp.u.constant = **ns;
1909 14 : zval_copy_ctor(&tmp.u.constant);
1910 14 : len += 1;
1911 14 : Z_UNILEN(class_name->u.constant) -= len;
1912 14 : if (Z_TYPE(class_name->u.constant) == IS_UNICODE) {
1913 14 : memmove(Z_USTRVAL(class_name->u.constant), Z_USTRVAL(class_name->u.constant)+len, UBYTES(Z_USTRLEN(class_name->u.constant)+1));
1914 : } else {
1915 0 : memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+len, Z_STRLEN(class_name->u.constant)+1);
1916 : }
1917 14 : zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
1918 14 : *class_name = tmp;
1919 14 : efree(lcname.v);
1920 14 : return;
1921 : }
1922 7 : efree(lcname.v);
1923 : }
1924 :
1925 : /* Here name is not prefixed with \ and not imported */
1926 11 : if (CG(current_namespace)) {
1927 7 : tmp.op_type = IS_CONST;
1928 7 : tmp.u.constant = *CG(current_namespace);
1929 7 : zval_copy_ctor(&tmp.u.constant);
1930 7 : zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
1931 7 : *class_name = tmp;
1932 : }
1933 : }
1934 23776 : } else if (CG(current_import) || CG(current_namespace)) {
1935 : /* this is a plain name (without \) */
1936 148 : lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant), 0, &lcname_len);
1937 :
1938 188 : if (CG(current_import) &&
1939 : zend_u_hash_find(CG(current_import), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&ns) == SUCCESS) {
1940 : /* The given name is an import name. Substitute it. */
1941 40 : zval_dtor(&class_name->u.constant);
1942 40 : class_name->u.constant = **ns;
1943 40 : zval_copy_ctor(&class_name->u.constant);
1944 108 : } else if (CG(current_namespace)) {
1945 106 : tmp.op_type = IS_CONST;
1946 106 : tmp.u.constant = *CG(current_namespace);
1947 106 : zval_copy_ctor(&tmp.u.constant);
1948 106 : zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
1949 106 : *class_name = tmp;
1950 : }
1951 148 : efree(lcname.v);
1952 : }
1953 : }
1954 : /* }}} */
1955 :
1956 : void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
1957 17804 : {
1958 : long fetch_class_op_number;
1959 : zend_op *opline;
1960 :
1961 17804 : if (class_name->op_type == IS_CONST &&
1962 : Z_TYPE(class_name->u.constant) == IS_UNICODE &&
1963 : Z_UNILEN(class_name->u.constant) == 0) {
1964 : /* Usage of namespace as class name not in namespace */
1965 0 : zval_dtor(&class_name->u.constant);
1966 0 : zend_error(E_COMPILE_ERROR, "Cannot use 'namespace' as a class name");
1967 0 : return;
1968 : }
1969 :
1970 17804 : fetch_class_op_number = get_next_op_number(CG(active_op_array));
1971 17804 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1972 :
1973 17804 : opline->opcode = ZEND_FETCH_CLASS;
1974 17804 : SET_UNUSED(opline->op1);
1975 17804 : opline->extended_value = ZEND_FETCH_CLASS_GLOBAL;
1976 17804 : CG(catch_begin) = fetch_class_op_number;
1977 17804 : if (class_name->op_type == IS_CONST) {
1978 : int fetch_type;
1979 :
1980 16695 : fetch_type = zend_get_class_fetch_type(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant));
1981 16695 : switch (fetch_type) {
1982 : case ZEND_FETCH_CLASS_SELF:
1983 : case ZEND_FETCH_CLASS_PARENT:
1984 : case ZEND_FETCH_CLASS_STATIC:
1985 3851 : SET_UNUSED(opline->op2);
1986 3851 : opline->extended_value = fetch_type;
1987 3851 : zval_dtor(&class_name->u.constant);
1988 3851 : break;
1989 : default: {
1990 12844 : zend_resolve_class_name(class_name, &opline->extended_value, 0 TSRMLS_CC);
1991 12844 : opline->op2 = *class_name;
1992 : break;
1993 : }
1994 : }
1995 : } else {
1996 1109 : opline->op2 = *class_name;
1997 : }
1998 17804 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
1999 17804 : opline->result.u.EA.type = opline->extended_value;
2000 17804 : opline->result.op_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
2001 17804 : *result = opline->result;
2002 : }
2003 : /* }}} */
2004 :
2005 : void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_class_member TSRMLS_DC) /* {{{ */
2006 1257 : {
2007 : zend_uint length;
2008 :
2009 1257 : if (!result) {
2010 1257 : result = prefix;
2011 : } else {
2012 0 : *result = *prefix;
2013 : }
2014 :
2015 1257 : if(is_class_member) {
2016 118 : length = sizeof("::")-1 + Z_UNILEN(result->u.constant) + Z_UNILEN(name->u.constant);
2017 118 : if (Z_TYPE(result->u.constant) == IS_UNICODE) {
2018 118 : Z_USTRVAL(result->u.constant) = erealloc(Z_USTRVAL(result->u.constant), UBYTES(length+1));
2019 118 : Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant)] = ':';
2020 118 : Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant)+1] = ':';
2021 118 : memcpy(&Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant) + sizeof("::")-1], Z_STRVAL(name->u.constant), UBYTES(Z_USTRLEN(name->u.constant)+1));
2022 118 : STR_FREE(Z_USTRVAL(name->u.constant));
2023 : } else {
2024 0 : Z_STRVAL(result->u.constant) = erealloc(Z_STRVAL(result->u.constant), length+1);
2025 0 : memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)], "::", sizeof("::")-1);
2026 0 : memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant) + sizeof("::")-1], Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1);
2027 0 : STR_FREE(Z_STRVAL(name->u.constant));
2028 : }
2029 118 : Z_UNILEN(result->u.constant) = length;
2030 : } else {
2031 1139 : length = sizeof("\\")-1 + Z_UNILEN(result->u.constant) + Z_UNILEN(name->u.constant);
2032 1139 : if (Z_TYPE(result->u.constant) == IS_UNICODE) {
2033 1139 : Z_USTRVAL(result->u.constant) = erealloc(Z_USTRVAL(result->u.constant), UBYTES(length+1));
2034 1139 : Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant)] = '\\';
2035 1139 : memcpy(&Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant) + sizeof("\\")-1], Z_USTRVAL(name->u.constant), UBYTES(Z_USTRLEN(name->u.constant)+1));
2036 1139 : STR_FREE(Z_USTRVAL(name->u.constant));
2037 : } else {
2038 0 : Z_STRVAL(result->u.constant) = erealloc(Z_STRVAL(result->u.constant), length+1);
2039 0 : memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)], "\\", sizeof("\\")-1);
2040 0 : memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant) + sizeof("\\")-1], Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1);
2041 0 : STR_FREE(Z_STRVAL(name->u.constant));
2042 : }
2043 1139 : Z_UNILEN(result->u.constant) = length;
2044 : }
2045 1257 : }
2046 : /* }}} */
2047 :
2048 : int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
2049 6491 : {
2050 : znode class_node;
2051 6491 : unsigned char *ptr = NULL;
2052 : zend_op *opline;
2053 6491 : ulong fetch_type = 0;
2054 :
2055 6491 : if (method_name->op_type == IS_CONST) {
2056 : zstr lcname;
2057 : unsigned int lcname_len;
2058 :
2059 6457 : lcname = zend_u_str_case_fold(Z_TYPE(method_name->u.constant), Z_UNIVAL(method_name->u.constant), Z_UNILEN(method_name->u.constant), 0, &lcname_len);
2060 :
2061 6457 : if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_UNILEN(method_name->u.constant) &&
2062 : ZEND_U_EQUAL(Z_TYPE(method_name->u.constant), lcname, Z_UNILEN(method_name->u.constant), ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1)) {
2063 907 : zval_dtor(&method_name->u.constant);
2064 907 : SET_UNUSED(*method_name);
2065 : }
2066 6457 : efree(lcname.v);
2067 : }
2068 :
2069 9288 : if (class_name->op_type == IS_CONST &&
2070 : ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant))) {
2071 2797 : fetch_type = ZEND_FETCH_CLASS_GLOBAL;
2072 2797 : zend_resolve_class_name(class_name, &fetch_type, 1 TSRMLS_CC);
2073 2797 : class_node = *class_name;
2074 : } else {
2075 3694 : zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
2076 : }
2077 6491 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2078 6491 : opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
2079 6491 : opline->op1 = class_node;
2080 6491 : opline->op2 = *method_name;
2081 :
2082 6491 : zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
2083 6491 : zend_do_extended_fcall_begin(TSRMLS_C);
2084 6491 : return 1; /* Dynamic */
2085 : }
2086 : /* }}} */
2087 :
2088 : void zend_do_end_function_call(znode *function_name, znode *result, const znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */
2089 259227 : {
2090 : zend_op *opline;
2091 :
2092 259227 : if (is_method && function_name && function_name->op_type == IS_UNUSED) {
2093 : /* clone */
2094 0 : if (Z_LVAL(argument_list->u.constant) != 0) {
2095 0 : zend_error(E_WARNING, "Clone method does not require arguments");
2096 : }
2097 0 : opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
2098 : } else {
2099 259227 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2100 474150 : if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
2101 214923 : opline->opcode = ZEND_DO_FCALL;
2102 214923 : opline->op1 = *function_name;
2103 214923 : ZVAL_LONG(&opline->op2.u.constant, zend_u_get_hash_value(Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant), Z_UNILEN(function_name->u.constant) + 1));
2104 : } else {
2105 44304 : opline->opcode = ZEND_DO_FCALL_BY_NAME;
2106 44304 : SET_UNUSED(opline->op1);
2107 : }
2108 : }
2109 :
2110 259227 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
2111 259227 : opline->result.op_type = IS_VAR;
2112 259227 : *result = opline->result;
2113 259227 : SET_UNUSED(opline->op2);
2114 :
2115 259227 : zend_stack_del_top(&CG(function_call_stack));
2116 259227 : opline->extended_value = Z_LVAL(argument_list->u.constant);
2117 259227 : }
2118 : /* }}} */
2119 :
2120 : void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{{ */
2121 443666 : {
2122 : zend_op *opline;
2123 443666 : int original_op=op;
2124 : zend_function **function_ptr_ptr, *function_ptr;
2125 : int send_by_reference;
2126 443666 : int send_function = 0;
2127 :
2128 443666 : zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
2129 443666 : function_ptr = *function_ptr_ptr;
2130 :
2131 443666 : if (original_op==ZEND_SEND_REF) {
2132 31 : if (function_ptr &&
2133 : function_ptr->common.function_name.v &&
2134 : function_ptr->common.type == ZEND_USER_FUNCTION &&
2135 : !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
2136 0 : zend_error(E_DEPRECATED,
2137 : "Call-time pass-by-reference has been deprecated; "
2138 : "if you would like to pass argument by reference, modify the declaration of %R().",
2139 : IS_UNICODE,
2140 : function_ptr->common.function_name.v);
2141 : } else{
2142 31 : zend_error(E_DEPRECATED,
2143 : "Call-time pass-by-reference has been deprecated");
2144 : }
2145 31 : send_by_reference = 1;
2146 443635 : } else if (function_ptr) {
2147 386634 : if (ARG_MAY_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
2148 348 : if (param->op_type & (IS_VAR|IS_CV)) {
2149 313 : send_by_reference = 1;
2150 313 : if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
2151 : /* Method call */
2152 2 : op = ZEND_SEND_VAR_NO_REF;
2153 2 : send_function = ZEND_ARG_SEND_FUNCTION | ZEND_ARG_SEND_SILENT;
2154 : }
2155 : } else {
2156 35 : op = ZEND_SEND_VAL;
2157 35 : send_by_reference = 0;
2158 : }
2159 : } else {
2160 386286 : send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset) ? ZEND_ARG_SEND_BY_REF : 0;
2161 : }
2162 : } else {
2163 57001 : send_by_reference = 0;
2164 : }
2165 :
2166 488466 : if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
2167 : /* Method call */
2168 44800 : op = ZEND_SEND_VAR_NO_REF;
2169 44800 : send_function = ZEND_ARG_SEND_FUNCTION;
2170 398866 : } else if (op == ZEND_SEND_VAL && (param->op_type & (IS_VAR|IS_CV))) {
2171 2215 : op = ZEND_SEND_VAR_NO_REF;
2172 : }
2173 :
2174 443666 : if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference==ZEND_ARG_SEND_BY_REF) {
2175 : /* change to passing by reference */
2176 6598 : switch (param->op_type) {
2177 : case IS_VAR:
2178 : case IS_CV:
2179 6592 : op = ZEND_SEND_REF;
2180 6592 : break;
2181 : default:
2182 6 : zend_error(E_COMPILE_ERROR, "Only variables can be passed by reference");
2183 : break;
2184 : }
2185 : }
2186 :
2187 443660 : if (original_op == ZEND_SEND_VAR) {
2188 199884 : switch (op) {
2189 : case ZEND_SEND_VAR_NO_REF:
2190 44802 : zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
2191 44802 : break;
2192 : case ZEND_SEND_VAR:
2193 148521 : if (function_ptr) {
2194 122478 : zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
2195 : } else {
2196 26043 : zend_do_end_variable_parse(param, BP_VAR_FUNC_ARG, offset TSRMLS_CC);
2197 : }
2198 148520 : break;
2199 : case ZEND_SEND_REF:
2200 6561 : zend_do_end_variable_parse(param, BP_VAR_W, 0 TSRMLS_CC);
2201 : break;
2202 : }
2203 : }
2204 :
2205 443659 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2206 :
2207 443659 : if (op == ZEND_SEND_VAR_NO_REF) {
2208 47017 : if (function_ptr) {
2209 45663 : opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference | send_function;
2210 : } else {
2211 1354 : opline->extended_value = send_function;
2212 : }
2213 : } else {
2214 396642 : if (function_ptr) {
2215 340985 : opline->extended_value = ZEND_DO_FCALL;
2216 : } else {
2217 55657 : opline->extended_value = ZEND_DO_FCALL_BY_NAME;
2218 : }
2219 : }
2220 443659 : opline->opcode = op;
2221 443659 : opline->op1 = *param;
2222 443659 : opline->op2.u.opline_num = offset;
2223 443659 : SET_UNUSED(opline->op2);
2224 443659 : }
2225 : /* }}} */
2226 :
2227 : static int generate_free_switch_expr(const zend_switch_entry *switch_entry TSRMLS_DC) /* {{{ */
2228 51114 : {
2229 : zend_op *opline;
2230 :
2231 51114 : if (switch_entry->cond.op_type != IS_VAR && switch_entry->cond.op_type != IS_TMP_VAR) {
2232 51089 : return (switch_entry->cond.op_type == IS_UNUSED);
2233 : }
2234 :
2235 25 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2236 :
2237 25 : opline->opcode = (switch_entry->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2238 25 : opline->op1 = switch_entry->cond;
2239 25 : SET_UNUSED(opline->op2);
2240 25 : opline->extended_value = 0;
2241 25 : return 0;
2242 : }
2243 : /* }}} */
2244 :
2245 : static int generate_free_foreach_copy(const zend_op *foreach_copy TSRMLS_DC) /* {{{ */
2246 60949 : {
2247 : zend_op *opline;
2248 :
2249 : /* If we reach the seperator then stop applying the stack */
2250 60949 : if (foreach_copy->result.op_type == IS_UNUSED && foreach_copy->op1.op_type == IS_UNUSED) {
2251 50995 : return 1;
2252 : }
2253 :
2254 9954 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2255 :
2256 9954 : opline->opcode = (foreach_copy->result.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2257 9954 : opline->op1 = foreach_copy->result;
2258 9954 : SET_UNUSED(opline->op2);
2259 9954 : opline->extended_value = 1;
2260 :
2261 9954 : if (foreach_copy->op1.op_type != IS_UNUSED) {
2262 3 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2263 :
2264 3 : opline->opcode = (foreach_copy->op1.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2265 3 : opline->op1 = foreach_copy->op1;
2266 3 : SET_UNUSED(opline->op2);
2267 3 : opline->extended_value = 0;
2268 : }
2269 :
2270 9954 : return 0;
2271 : }
2272 : /* }}} */
2273 :
2274 : void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
2275 76578 : {
2276 : zend_op *opline;
2277 : int start_op_number, end_op_number;
2278 :
2279 76578 : if (do_end_vparse) {
2280 17495 : if (CG(active_op_array)->return_reference && !zend_is_function_or_method_call(expr)) {
2281 26 : zend_do_end_variable_parse(expr, BP_VAR_W, 0 TSRMLS_CC);
2282 : } else {
2283 17443 : zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
2284 : }
2285 : }
2286 :
2287 76578 : start_op_number = get_next_op_number(CG(active_op_array));
2288 :
2289 : #ifdef ZTS
2290 : zend_stack_apply_with_argument(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_switch_expr TSRMLS_CC);
2291 : zend_stack_apply_with_argument(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_foreach_copy TSRMLS_CC);
2292 : #else
2293 76578 : zend_stack_apply(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_switch_expr);
2294 76578 : zend_stack_apply(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_foreach_copy);
2295 : #endif
2296 :
2297 76578 : end_op_number = get_next_op_number(CG(active_op_array));
2298 154229 : while (start_op_number < end_op_number) {
2299 1073 : CG(active_op_array)->opcodes[start_op_number].op1.u.EA.type = EXT_TYPE_FREE_ON_RETURN;
2300 1073 : start_op_number++;
2301 : }
2302 :
2303 76578 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2304 :
2305 76578 : opline->opcode = ZEND_RETURN;
2306 :
2307 76578 : if (expr) {
2308 52079 : opline->op1 = *expr;
2309 :
2310 52079 : if (do_end_vparse) {
2311 17469 : if (zend_is_function_or_method_call(expr)) {
2312 8024 : opline->extended_value = ZEND_RETURNS_FUNCTION;
2313 : }
2314 34610 : } else if (CG(active_op_array)->return_reference &&
2315 : expr->u.EA.type == ZEND_PARSED_NEW) {
2316 0 : opline->extended_value = ZEND_RETURNS_NEW;
2317 0 : zend_error(E_DEPRECATED, "Returning the return value of new by reference is deprecated");
2318 : }
2319 : } else {
2320 24499 : opline->op1.op_type = IS_CONST;
2321 24499 : INIT_ZVAL(opline->op1.u.constant);
2322 : }
2323 :
2324 76578 : SET_UNUSED(opline->op2);
2325 76578 : }
2326 : /* }}} */
2327 :
2328 : static int zend_add_try_element(zend_uint try_op TSRMLS_DC) /* {{{ */
2329 1747 : {
2330 1747 : int try_catch_offset = CG(active_op_array)->last_try_catch++;
2331 :
2332 1747 : CG(active_op_array)->try_catch_array = erealloc(CG(active_op_array)->try_catch_array, sizeof(zend_try_catch_element)*CG(active_op_array)->last_try_catch);
2333 1747 : CG(active_op_array)->try_catch_array[try_catch_offset].try_op = try_op;
2334 1747 : return try_catch_offset;
2335 : }
2336 : /* }}} */
2337 :
2338 : static void zend_add_catch_element(int offset, zend_uint catch_op TSRMLS_DC) /* {{{ */
2339 1747 : {
2340 1747 : CG(active_op_array)->try_catch_array[offset].catch_op = catch_op;
2341 1747 : }
2342 : /* }}} */
2343 :
2344 : void zend_do_first_catch(znode *open_parentheses TSRMLS_DC) /* {{{ */
2345 1747 : {
2346 1747 : open_parentheses->u.opline_num = get_next_op_number(CG(active_op_array));
2347 1747 : }
2348 : /* }}} */
2349 :
2350 : void zend_initialize_try_catch_element(const znode *try_token TSRMLS_DC) /* {{{ */
2351 1747 : {
2352 1747 : int jmp_op_number = get_next_op_number(CG(active_op_array));
2353 1747 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2354 : zend_llist jmp_list;
2355 : zend_llist *jmp_list_ptr;
2356 :
2357 1747 : opline->opcode = ZEND_JMP;
2358 1747 : SET_UNUSED(opline->op1);
2359 1747 : SET_UNUSED(opline->op2);
2360 : /* save for backpatching */
2361 :
2362 1747 : zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
2363 1747 : zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
2364 1747 : zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
2365 1747 : zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
2366 :
2367 1747 : zend_add_catch_element(try_token->u.opline_num, get_next_op_number(CG(active_op_array)) TSRMLS_CC);
2368 1747 : }
2369 : /* }}} */
2370 :
2371 : void zend_do_mark_last_catch(const znode *first_catch, const znode *last_additional_catch TSRMLS_DC) /* {{{ */
2372 1747 : {
2373 1747 : CG(active_op_array)->last--;
2374 1747 : zend_do_if_end(TSRMLS_C);
2375 1747 : if (last_additional_catch->u.opline_num == -1) {
2376 1740 : CG(active_op_array)->opcodes[first_catch->u.opline_num].op1.u.EA.type = 1;
2377 1740 : CG(active_op_array)->opcodes[first_catch->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
2378 : } else {
2379 7 : CG(active_op_array)->opcodes[last_additional_catch->u.opline_num].op1.u.EA.type = 1;
2380 7 : CG(active_op_array)->opcodes[last_additional_catch->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
2381 : }
2382 1747 : DEC_BPC(CG(active_op_array));
2383 1747 : }
2384 : /* }}} */
2385 :
2386 : void zend_do_try(znode *try_token TSRMLS_DC) /* {{{ */
2387 1747 : {
2388 1747 : try_token->u.opline_num = zend_add_try_element(get_next_op_number(CG(active_op_array)) TSRMLS_CC);
2389 1747 : INC_BPC(CG(active_op_array));
2390 1747 : }
2391 : /* }}} */
2392 :
2393 : void zend_do_begin_catch(znode *try_token, znode *class_name, const znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */
2394 1754 : {
2395 : long catch_op_number;
2396 : zend_op *opline;
2397 : znode catch_class;
2398 :
2399 1754 : zend_do_fetch_class(&catch_class, class_name TSRMLS_CC);
2400 :
2401 1754 : catch_op_number = get_next_op_number(CG(active_op_array));
2402 1754 : if (catch_op_number > 0) {
2403 1754 : opline = &CG(active_op_array)->opcodes[catch_op_number-1];
2404 1754 : if (opline->opcode == ZEND_FETCH_CLASS) {
2405 1754 : opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
2406 : }
2407 : }
2408 :
2409 1754 : if (first_catch) {
2410 1747 : first_catch->u.opline_num = catch_op_number;
2411 : }
2412 :
2413 1754 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2414 1754 : opline->opcode = ZEND_CATCH;
2415 1754 : opline->op1 = catch_class;
2416 : /* SET_UNUSED(opline->op1); */ /* FIXME: Define IS_CLASS or something like that */
2417 1754 : opline->op2.op_type = IS_CV;
2418 1754 : opline->op2.u.var = lookup_cv(CG(active_op_array), Z_TYPE(catch_var->u.constant), Z_UNIVAL(catch_var->u.constant), Z_UNILEN(catch_var->u.constant));
2419 1754 : opline->op2.u.EA.type = 0;
2420 1754 : opline->op1.u.EA.type = 0; /* 1 means it's the last catch in the block */
2421 :
2422 1754 : try_token->u.opline_num = catch_op_number;
2423 1754 : }
2424 : /* }}} */
2425 :
2426 : void zend_do_end_catch(const znode *try_token TSRMLS_DC) /* {{{ */
2427 1754 : {
2428 1754 : int jmp_op_number = get_next_op_number(CG(active_op_array));
2429 1754 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2430 : zend_llist *jmp_list_ptr;
2431 :
2432 1754 : opline->opcode = ZEND_JMP;
2433 1754 : SET_UNUSED(opline->op1);
2434 1754 : SET_UNUSED(opline->op2);
2435 : /* save for backpatching */
2436 :
2437 1754 : zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
2438 1754 : zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
2439 :
2440 1754 : CG(active_op_array)->opcodes[try_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
2441 1754 : }
2442 : /* }}} */
2443 :
2444 : void zend_do_throw(const znode *expr TSRMLS_DC) /* {{{ */
2445 229 : {
2446 : zend_op *opline;
2447 :
2448 229 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2449 229 : opline->opcode = ZEND_THROW;
2450 229 : opline->op1 = *expr;
2451 229 : SET_UNUSED(opline->op2);
2452 229 : }
2453 : /* }}} */
2454 :
2455 : ZEND_API void function_add_ref(zend_function *function TSRMLS_DC) /* {{{ */
2456 18236923 : {
2457 18236923 : if (function->type == ZEND_USER_FUNCTION) {
2458 1025 : zend_op_array *op_array = &function->op_array;
2459 :
2460 1025 : (*op_array->refcount)++;
2461 1025 : if (op_array->static_variables) {
2462 1 : HashTable *static_variables = op_array->static_variables;
2463 : zval *tmp_zval;
2464 :
2465 1 : ALLOC_HASHTABLE(op_array->static_variables);
2466 1 : zend_u_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
2467 1 : zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
2468 : }
2469 18235898 : } else if (function->type == ZEND_INTERNAL_FUNCTION) {
2470 18235898 : zend_internal_function *func = &function->internal_function;
2471 :
2472 18235898 : func->function_name.u = zend_ustrndup(func->function_name.u, u_strlen(func->function_name.u));
2473 18235898 : if (func->arg_info) {
2474 : zend_arg_info *args;
2475 14358567 : int n = func->num_args;
2476 :
2477 14358567 : args = malloc((n + 1) * sizeof(zend_arg_info));
2478 14358567 : memcpy(args, func->arg_info, (n + 1) * sizeof(zend_arg_info));
2479 39078214 : while (n > 0) {
2480 10361080 : --n;
2481 10361080 : if (args[n].name.u) {
2482 10361079 : args[n].name.u = zend_ustrndup(args[n].name.u, u_strlen(args[n].name.u));
2483 : }
2484 10361080 : if (args[n].class_name.s) {
2485 1836835 : args[n].class_name.u = zend_ustrndup(args[n].class_name.u, u_strlen(args[n].class_name.u));
2486 : }
2487 : }
2488 14358567 : func->arg_info = args;
2489 : }
2490 : }
2491 18236923 : }
2492 : /* }}} */
2493 :
2494 : static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC) /* {{{ */
2495 1090360 : {
2496 1090360 : if (!ce->parent) {
2497 0 : return;
2498 : }
2499 :
2500 : /* You cannot change create_object */
2501 1090360 : ce->create_object = ce->parent->create_object;
2502 :
2503 : /* Inherit special functions if needed */
2504 1090360 : if (!ce->get_iterator) {
2505 699050 : ce->get_iterator = ce->parent->get_iterator;
2506 : }
2507 1090360 : if (!ce->iterator_funcs.funcs) {
2508 699082 : ce->iterator_funcs.funcs = ce->parent->iterator_funcs.funcs;
2509 : }
2510 1090360 : if (!ce->__get) {
2511 1090356 : ce->__get = ce->parent->__get;
2512 : }
2513 1090360 : if (!ce->__set) {
2514 1090354 : ce->__set = ce->parent->__set;
2515 : }
2516 1090360 : if (!ce->__unset) {
2517 1090356 : ce->__unset = ce->parent->__unset;
2518 : }
2519 1090360 : if (!ce->__isset) {
2520 1090356 : ce->__isset = ce->parent->__isset;
2521 : }
2522 1090360 : if (!ce->__call) {
2523 1090350 : ce->__call = ce->parent->__call;
2524 : }
2525 1090360 : if (!ce->__callstatic) {
2526 1090359 : ce->__callstatic = ce->parent->__callstatic;
2527 : }
2528 1090360 : if (!ce->__tostring) {
2529 988312 : ce->__tostring = ce->parent->__tostring;
2530 : }
2531 1090360 : if (!ce->clone) {
2532 1090356 : ce->clone = ce->parent->clone;
2533 : }
2534 1090360 : if(!ce->serialize) {
2535 903193 : ce->serialize = ce->parent->serialize;
2536 : }
2537 1090360 : if(!ce->unserialize) {
2538 903193 : ce->unserialize = ce->parent->unserialize;
2539 : }
2540 1090360 : if (!ce->destructor) {
2541 1039286 : ce->destructor = ce->parent->destructor;
2542 : }
2543 1090360 : if (ce->constructor) {
2544 596270 : if (ce->parent->constructor && ce->parent->constructor->common.fn_flags & ZEND_ACC_FINAL) {
2545 2 : zend_error(E_ERROR, "Cannot override final %v::%v() with %v::%v()",
2546 : ce->parent->name, ce->parent->constructor->common.function_name,
2547 : ce->name, ce->constructor->common.function_name
2548 : );
2549 : }
2550 596268 : return;
2551 494090 : } else if (ce->parent->constructor) {
2552 374377 : ce->constructor = ce->parent->constructor;
2553 374377 : if (!zend_ascii_hash_exists(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
2554 : unsigned int lc_parent_class_name_len;
2555 : zend_function *function;
2556 25 : zstr lc_parent_class_name = zend_u_str_case_fold(IS_UNICODE, ce->parent->name, ce->parent->name_length, 0, &lc_parent_class_name_len);
2557 :
2558 25 : if (!zend_u_hash_exists(&ce->function_table, IS_UNICODE, lc_parent_class_name, ce->parent->name_length+1) &&
2559 : zend_u_hash_find(&ce->parent->function_table, IS_UNICODE, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
2560 0 : if (function->common.fn_flags & ZEND_ACC_CTOR) {
2561 : /* inherit parent's constructor */
2562 0 : zend_u_hash_update(&ce->function_table, IS_UNICODE, lc_parent_class_name, ce->parent->name_length+1, function, sizeof(zend_function), NULL);
2563 0 : function_add_ref(function TSRMLS_CC);
2564 : }
2565 : }
2566 25 : efree(lc_parent_class_name.v);
2567 : }
2568 : }
2569 : }
2570 : /* }}} */
2571 :
2572 : char *zend_visibility_string(zend_uint fn_flags) /* {{{ */
2573 53 : {
2574 53 : if (fn_flags & ZEND_ACC_PRIVATE) {
2575 19 : return "private";
2576 : }
2577 34 : if (fn_flags & ZEND_ACC_PROTECTED) {
2578 24 : return "protected";
2579 : }
2580 10 : if (fn_flags & ZEND_ACC_PUBLIC) {
2581 10 : return "public";
2582 : }
2583 0 : return "";
2584 : }
2585 : /* }}} */
2586 :
2587 : static void do_inherit_method(zend_function *function) /* {{{ */
2588 18236868 : {
2589 : /* The class entry of the derived function intentionally remains the same
2590 : * as that of the parent class. That allows us to know in which context
2591 : * we're running, and handle private method calls properly.
2592 : */
2593 : TSRMLS_FETCH();
2594 18236868 : function_add_ref(function TSRMLS_CC);
2595 18236868 : }
2596 : /* }}} */
2597 :
2598 : static zend_bool zend_do_perform_implementation_check(const zend_function *fe, const zend_function *proto TSRMLS_DC) /* {{{ */
2599 4909259 : {
2600 : zend_uint i;
2601 :
2602 : /* If it's a user function then arg_info == NULL means we don't have any parameters but we still need to do the arg number checks. We are only willing to ignore this for internal functions because extensions don't always define arg_info. */
2603 4909259 : if (!proto || (!proto->common.arg_info && proto->common.type != ZEND_USER_FUNCTION)) {
2604 2925504 : return 1;
2605 : }
2606 :
2607 : /* Checks for constructors only if they are declared in an interface */
2608 1983755 : if ((fe->common.fn_flags & ZEND_ACC_CTOR) && !(proto->common.scope->ce_flags & ZEND_ACC_INTERFACE)) {
2609 420875 : return 1;
2610 : }
2611 :
2612 : /* check number of arguments */
2613 1562880 : if (proto->common.required_num_args < fe->common.required_num_args
2614 : || proto->common.num_args > fe->common.num_args) {
2615 25 : return 0;
2616 : }
2617 :
2618 1562855 : if (proto->common.pass_rest_by_reference
2619 : && !fe->common.pass_rest_by_reference) {
2620 0 : return 0;
2621 : }
2622 :
2623 1562855 : if (fe->common.return_reference != proto->common.return_reference) {
2624 1 : return 0;
2625 : }
2626 :
2627 2396595 : for (i=0; i < proto->common.num_args; i++) {
2628 833749 : if (ZEND_LOG_XOR(fe->common.arg_info[i].class_name.v, proto->common.arg_info[i].class_name.v)) {
2629 : /* Only one has a type hint and the other one doesn't */
2630 3 : return 0;
2631 : }
2632 833746 : if (fe->common.arg_info[i].class_name.v &&
2633 : (fe->common.arg_info[i].class_name_len != proto->common.arg_info[i].class_name_len ||
2634 : (zend_u_binary_strcasecmp(fe->common.arg_info[i].class_name.u, fe->common.arg_info[i].class_name_len, proto->common.arg_info[i].class_name.u, proto->common.arg_info[i].class_name_len) != 0))) {
2635 : zstr colon;
2636 :
2637 1 : if (fe->common.type != ZEND_USER_FUNCTION ||
2638 : ((u_strchr(proto->common.arg_info[i].class_name.u, ':') != NULL ||
2639 : (colon.u = u_memrchr(fe->common.arg_info[i].class_name.u, ':', fe->common.arg_info[i].class_name_len)) == NULL ||
2640 : fe->common.arg_info[i].class_name_len - (colon.u + 1 - fe->common.arg_info[i].class_name.u) != proto->common.arg_info[i].class_name_len ||
2641 : zend_u_binary_strcasecmp(colon.u + 1, proto->common.arg_info[i].class_name_len, proto->common.arg_info[i].class_name.u, proto->common.arg_info[i].class_name_len) != 0) &&
2642 : (strchr(proto->common.arg_info[i].class_name.s, ':') != NULL ||
2643 : (colon.s = zend_memrchr(fe->common.arg_info[i].class_name.s, ':', fe->common.arg_info[i].class_name_len)) == NULL ||
2644 : fe->common.arg_info[i].class_name_len - (colon.s + 1 - fe->common.arg_info[i].class_name.s) != proto->common.arg_info[i].class_name_len ||
2645 : zend_binary_strcasecmp(colon.s + 1, proto->common.arg_info[i].class_name_len, proto->common.arg_info[i].class_name.s, proto->common.arg_info[i].class_name_len) != 0))) {
2646 1 : return 0;
2647 : }
2648 : }
2649 833745 : if (fe->common.arg_info[i].array_type_hint != proto->common.arg_info[i].array_type_hint) {
2650 : /* Only one has an array type hint and the other one doesn't */
2651 2 : return 0;
2652 : }
2653 833743 : if (fe->common.arg_info[i].pass_by_reference != proto->common.arg_info[i].pass_by_reference) {
2654 2 : return 0;
2655 : }
2656 : }
2657 :
2658 1562846 : if (proto->common.pass_rest_by_reference) {
2659 0 : for (i=proto->common.num_args; i < fe->common.num_args; i++) {
2660 0 : if (!fe->common.arg_info[i].pass_by_reference) {
2661 0 : return 0;
2662 : }
2663 : }
2664 : }
2665 1562846 : return 1;
2666 : }
2667 : /* }}} */
2668 :
2669 : static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, const zend_hash_key *hash_key, zend_class_entry *child_ce) /* {{{ */
2670 23153538 : {
2671 : zend_uint child_flags;
2672 23153538 : zend_uint parent_flags = parent->common.fn_flags;
2673 : zend_function *child;
2674 : TSRMLS_FETCH();
2675 :
2676 23153538 : if (zend_u_hash_quick_find(child_function_table, hash_key->type, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
2677 18236868 : if (parent_flags & (ZEND_ACC_ABSTRACT)) {
2678 272146 : child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2679 : }
2680 18236868 : return 1; /* method doesn't exist in child, copy from parent */
2681 : }
2682 :
2683 4916670 : if (parent->common.fn_flags & ZEND_ACC_ABSTRACT
2684 : && parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
2685 : && child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
2686 4 : zend_error(E_COMPILE_ERROR, "Can't inherit abstract function %v::%v() (previously declared abstract in %v)",
2687 : parent->common.scope->name,
2688 : child->common.function_name,
2689 : child->common.prototype ? child->common.prototype->common.scope->name : child->common.scope->name);
2690 : }
2691 :
2692 4916666 : if (parent_flags & ZEND_ACC_FINAL) {
2693 3 : zend_error(E_COMPILE_ERROR, "Cannot override final method %v::%v()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name.v);
2694 : }
2695 :
2696 4916663 : child_flags = child->common.fn_flags;
2697 : /* You cannot change from static to non static and vice versa.
2698 : */
2699 4916663 : if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) {
2700 2 : if (child->common.fn_flags & ZEND_ACC_STATIC) {
2701 1 : zend_error(E_COMPILE_ERROR, "Cannot make non static method %v::%v() static in class %v", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
2702 : } else {
2703 1 : zend_error(E_COMPILE_ERROR, "Cannot make static method %v::%v() non static in class %v", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
2704 : }
2705 : }
2706 :
2707 : /* Disallow making an inherited method abstract. */
2708 4916661 : if ((child_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_ABSTRACT)) {
2709 0 : zend_error(E_COMPILE_ERROR, "Cannot make non abstract method %v::%v() abstract in class %v", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
2710 : }
2711 :
2712 4916661 : if (parent_flags & ZEND_ACC_CHANGED) {
2713 0 : child->common.fn_flags |= ZEND_ACC_CHANGED;
2714 : } else {
2715 : /* Prevent derived classes from restricting access that was available in parent classes
2716 : */
2717 4916661 : if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) {
2718 7 : zend_error(E_COMPILE_ERROR, "Access level to %v::%v() must be %s (as in class %v)%s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
2719 4916654 : } else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
2720 : && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
2721 15 : child->common.fn_flags |= ZEND_ACC_CHANGED;
2722 : }
2723 : }
2724 :
2725 4916654 : if (parent_flags & ZEND_ACC_PRIVATE) {
2726 39 : child->common.prototype = NULL;
2727 4916615 : } else if (parent_flags & ZEND_ACC_ABSTRACT) {
2728 3521027 : child->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
2729 3521027 : child->common.prototype = parent;
2730 1395588 : } else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) {
2731 : /* ctors only have a prototype if it comes from an interface */
2732 970310 : child->common.prototype = parent->common.prototype ? parent->common.prototype : parent;
2733 : }
2734 :
2735 9118126 : if (child->common.prototype && (child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) {
2736 4201475 : if (!zend_do_perform_implementation_check(child, child->common.prototype TSRMLS_CC)) {
2737 3 : zend_error(E_COMPILE_ERROR, "Declaration of %v::%v() must be compatible with that of %v::%v()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(child->common.prototype), child->common.prototype->common.function_name);
2738 : }
2739 715179 : } else if (EG(error_reporting) & E_STRICT || EG(user_error_handler)) { /* Check E_STRICT (or custom error handler) before the check so that we save some time */
2740 707784 : if (!zend_do_perform_implementation_check(child, parent TSRMLS_CC)) {
2741 31 : zend_error(E_STRICT, "Declaration of %v::%v() should be compatible with that of %v::%v()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(parent), parent->common.function_name);
2742 : }
2743 : }
2744 :
2745 4916651 : return 0;
2746 : }
2747 : /* }}} */
2748 :
2749 : static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_property_info *parent_info, const zend_hash_key *hash_key, zend_class_entry *ce) /* {{{ */
2750 2701852 : {
2751 : zend_property_info *child_info;
2752 2701852 : zend_class_entry *parent_ce = ce->parent;
2753 : zend_uchar utype;
2754 : TSRMLS_FETCH();
2755 :
2756 2701852 : utype = IS_UNICODE;
2757 2701852 : if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
2758 1122659 : if (zend_u_hash_quick_find(&ce->properties_info, hash_key->type, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
2759 54 : child_info->flags |= ZEND_ACC_CHANGED;
2760 : } else {
2761 1122605 : zend_u_hash_quick_update(&ce->properties_info, hash_key->type, hash_key->arKey, hash_key->nKeyLength, hash_key->h, parent_info, sizeof(zend_property_info), (void **) &child_info);
2762 1122605 : if(ce->type & ZEND_INTERNAL_CLASS) {
2763 1122462 : zend_duplicate_property_info_internal(child_info);
2764 : } else {
2765 143 : zend_duplicate_property_info(child_info);
2766 : }
2767 1122605 : child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */
2768 1122605 : child_info->flags |= ZEND_ACC_SHADOW; /* but it's a shadow of private */
2769 : }
2770 1122659 : return 0; /* don't copy access information to child */
2771 : }
2772 :
2773 1579193 : if (zend_u_hash_quick_find(&ce->properties_info, hash_key->type, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
2774 91 : if ((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC)) {
2775 12 : zend_error(E_COMPILE_ERROR, "Cannot redeclare %s%v::$%R as %s%v::$%R",
2776 : (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->type, hash_key->arKey,
2777 : (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->type, hash_key->arKey);
2778 : }
2779 :
2780 79 : if(parent_info->flags & ZEND_ACC_CHANGED) {
2781 1 : child_info->flags |= ZEND_ACC_CHANGED;
2782 : }
2783 :
2784 79 : if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
2785 7 : zend_error(E_COMPILE_ERROR, "Access level to %v::$%R must be %s (as in class %v)%s", ce->name, hash_key->type, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
2786 72 : } else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
2787 0 : if (!(parent_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
2788 : /* Explicitly copy the default value from the parent (if it has one) */
2789 : zval **pvalue;
2790 :
2791 0 : if (zend_u_hash_quick_find(&parent_ce->default_properties, utype, parent_info->name, parent_info->name_length+1, parent_info->h, (void **) &pvalue) == SUCCESS) {
2792 0 : Z_ADDREF_PP(pvalue);
2793 0 : zend_u_hash_quick_del(&ce->default_properties, utype, child_info->name, child_info->name_length+1, parent_info->h);
2794 0 : zend_u_hash_quick_update(&ce->default_properties, utype, parent_info->name, parent_info->name_length+1, parent_info->h, pvalue, sizeof(zval *), NULL);
2795 : }
2796 : }
2797 0 : return 1; /* Inherit from the parent */
2798 72 : } else if ((child_info->flags & ZEND_ACC_PUBLIC) && (parent_info->flags & ZEND_ACC_PROTECTED)) {
2799 : zstr prot_name;
2800 : int prot_name_length;
2801 :
2802 7 : zend_u_mangle_property_name(&prot_name, &prot_name_length, utype, ZSTR("*"), 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS);
2803 7 : if (child_info->flags & ZEND_ACC_STATIC) {
2804 : zval **prop;
2805 : HashTable *ht;
2806 :
2807 4 : if (parent_ce->type != ce->type) {
2808 : /* User class extends internal class */
2809 0 : ht = CE_STATIC_MEMBERS(parent_ce);
2810 : } else {
2811 4 : ht = &parent_ce->default_static_members;
2812 : }
2813 4 : if (zend_u_hash_find(ht, utype, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
2814 4 : zend_u_hash_del(&ce->default_static_members, utype, prot_name, prot_name_length+1);
2815 : }
2816 : } else {
2817 3 : zend_u_hash_del(&ce->default_properties, utype, prot_name, prot_name_length+1);
2818 : }
2819 7 : pefree(prot_name.v, ce->type & ZEND_INTERNAL_CLASS);
2820 : }
2821 72 : return 0; /* Don't copy from parent */
2822 : } else {
2823 1579102 : return 1; /* Copy from parent */
2824 : }
2825 : }
2826 : /* }}} */
2827 :
2828 : static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
2829 2773237 : {
2830 2773237 : if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce TSRMLS_CC) == FAILURE) {
2831 0 : zend_error(E_CORE_ERROR, "Class %v could not implement interface %v", ce->name, iface->name);
2832 : }
2833 2773236 : if (ce == iface) {
2834 1 : zend_error(E_ERROR, "Interface %v cannot implement itself", ce->name);
2835 : }
2836 2773235 : }
2837 : /* }}} */
2838 :
2839 : ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC) /* {{{ */
2840 2094083 : {
2841 : /* expects interface to be contained in ce's interface list already */
2842 2094083 : zend_uint i, ce_num, if_num = iface->num_interfaces;
2843 : zend_class_entry *entry;
2844 :
2845 2094083 : if (if_num==0) {
2846 1124358 : return;
2847 : }
2848 969725 : ce_num = ce->num_interfaces;
2849 :
2850 969725 : if (ce->type == ZEND_INTERNAL_CLASS) {
2851 969399 : ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
2852 : } else {
2853 326 : ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
2854 : }
2855 :
2856 : /* Inherit the interfaces, only if they're not already inherited by the class */
2857 4066183 : while (if_num--) {
2858 2126733 : entry = iface->interfaces[if_num];
2859 2926235 : for (i = 0; i < ce_num; i++) {
2860 1156690 : if (ce->interfaces[i] == entry) {
2861 357188 : break;
2862 : }
2863 : }
2864 2126733 : if (i == ce_num) {
2865 1769545 : ce->interfaces[ce->num_interfaces++] = entry;
2866 : }
2867 : }
2868 :
2869 : /* and now call the implementing handlers */
2870 3708995 : while (ce_num < ce->num_interfaces) {
2871 1769545 : do_implement_interface(ce, ce->interfaces[ce_num++] TSRMLS_CC);
2872 : }
2873 : }
2874 : /* }}} */
2875 :
2876 : static int inherit_static_prop(zval **p TSRMLS_DC, int num_args, va_list args, const zend_hash_key *key) /* {{{ */
2877 129 : {
2878 129 : HashTable *target = va_arg(args, HashTable*);
2879 :
2880 129 : if (!zend_u_hash_quick_exists(target, key->type, key->arKey, key->nKeyLength, key->h)) {
2881 106 : SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
2882 106 : if (zend_u_hash_quick_add(target, key->type, key->arKey, key->nKeyLength, key->h, p, sizeof(zval*), NULL) == SUCCESS) {
2883 106 : Z_ADDREF_PP(p);
2884 : }
2885 : }
2886 129 : return ZEND_HASH_APPLY_KEEP;
2887 : }
2888 : /* }}} */
2889 :
2890 : ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
2891 1090394 : {
2892 1090394 : if ((ce->ce_flags & ZEND_ACC_INTERFACE)
2893 : && !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
2894 0 : zend_error(E_COMPILE_ERROR, "Interface %v may not inherit from class (%v)", ce->name, parent_ce->name);
2895 : }
2896 1090394 : if (parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
2897 1 : zend_error(E_COMPILE_ERROR, "Class %v may not inherit from final class (%v)", ce->name, parent_ce->name);
2898 : }
2899 :
2900 1090393 : ce->parent = parent_ce;
2901 : /* Transfer parent custom callbacks, if any */
2902 1090393 : if (!ce->serialize) {
2903 1090393 : ce->serialize = parent_ce->serialize;
2904 : }
2905 1090393 : if (!ce->unserialize) {
2906 1090393 : ce->unserialize = parent_ce->unserialize;
2907 : }
2908 : /* Inherit interfaces */
2909 1090393 : zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);
2910 :
2911 : /* Inherit properties */
2912 1090393 : zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0);
2913 1090393 : if (parent_ce->type != ce->type) {
2914 : /* User class extends internal class */
2915 1145 : zend_update_class_constants(parent_ce TSRMLS_CC);
2916 1145 : zend_hash_apply_with_arguments(CE_STATIC_MEMBERS(parent_ce) TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);
2917 : } else {
2918 1089248 : zend_hash_apply_with_arguments(&parent_ce->default_static_members TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);
2919 : }
2920 1090393 : zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce);
2921 :
2922 1090374 : zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0);
2923 1090374 : zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce);
2924 1090360 : do_inherit_parent_constructor(ce TSRMLS_CC);
2925 :
2926 1124372 : if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
2927 34014 : ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
2928 1056344 : } else if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES)) {
2929 : /* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */
2930 1056309 : zend_verify_abstract_class(ce TSRMLS_CC);
2931 : }
2932 1090357 : }
2933 : /* }}} */
2934 :
2935 : static zend_bool do_inherit_constant_check(HashTable *child_constants_table, const zval **parent_constant, const zend_hash_key *hash_key, const zend_class_entry *iface) /* {{{ */
2936 14 : {
2937 : zval **old_constant;
2938 :
2939 14 : if (zend_u_hash_quick_find(child_constants_table, hash_key->type, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**)&old_constant) == SUCCESS) {
2940 6 : if (*old_constant != *parent_constant) {
2941 5 : zend_error(E_COMPILE_ERROR, "Cannot inherit previously-inherited constant %R from interface %v", hash_key->type, hash_key->arKey, iface->name);
2942 : }
2943 1 : return 0;
2944 : }
2945 8 : return 1;
2946 : }
2947 : /* }}} */
2948 :
2949 : ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
2950 1003707 : {
2951 1003707 : zend_uint i, ignore = 0;
2952 1003707 : zend_uint current_iface_num = ce->num_interfaces;
2953 1003707 : zend_uint parent_iface_num = ce->parent ? ce->parent->num_interfaces : 0;
2954 :
2955 2823551 : for (i = 0; i < ce->num_interfaces; i++) {
2956 1819847 : if (ce->interfaces[i] == NULL) {
2957 0 : memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i));
2958 0 : i--;
2959 1819847 : } else if (ce->interfaces[i] == iface) {
2960 5 : if (i < parent_iface_num) {
2961 2 : ignore = 1;
2962 : } else {
2963 3 : zend_error(E_COMPILE_ERROR, "Class %v cannot implement previously implemented interface %v", ce->name, iface->name);
2964 : }
2965 : }
2966 : }
2967 1003704 : if (!ignore) {
2968 1003702 : if (ce->num_interfaces >= current_iface_num) {
2969 1003702 : if (ce->type == ZEND_INTERNAL_CLASS) {
2970 1003413 : ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
2971 : } else {
2972 289 : ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
2973 : }
2974 : }
2975 1003702 : ce->interfaces[ce->num_interfaces++] = iface;
2976 :
2977 1003702 : zend_hash_merge_ex(&ce->constants_table, &iface->constants_table, (copy_ctor_func_t) zval_add_ref, sizeof(zval *), (merge_checker_func_t) do_inherit_constant_check, iface);
2978 1003697 : zend_hash_merge_ex(&ce->function_table, &iface->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce);
2979 :
2980 1003692 : do_implement_interface(ce, iface TSRMLS_CC);
2981 1003690 : zend_do_inherit_interfaces(ce, iface TSRMLS_CC);
2982 : }
2983 1003692 : }
2984 : /* }}} */
2985 :
2986 : ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
2987 6922 : {
2988 : zend_function *function;
2989 :
2990 6922 : zend_u_hash_find(function_table, Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (void *) &function);
2991 6922 : if (zend_u_hash_add(function_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, function, sizeof(zend_function), NULL)==FAILURE) {
2992 0 : int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
2993 : zend_function *old_function;
2994 :
2995 0 : if (zend_u_hash_find(function_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void *) &old_function)==SUCCESS) {
2996 0 : if (old_function->type == ZEND_USER_FUNCTION &&
2997 : old_function->op_array.last > 0) {
2998 0 : zend_error(error_level, "Cannot redeclare %v() (previously declared in %s:%d)",
2999 : function->common.function_name,
3000 : old_function->op_array.filename,
3001 : old_function->op_array.opcodes[0].lineno);
3002 0 : } else if (old_function->type == ZEND_INTERNAL_FUNCTION &&
3003 : old_function->internal_function.module) {
3004 0 : zend_error(error_level, "Cannot redeclare %v() (internal function exists in module %s)",
3005 : function->common.function_name,
3006 : old_function->internal_function.module->name);
3007 : }
3008 : }
3009 0 : zend_error(error_level, "Cannot redeclare %v()", function->common.function_name);
3010 0 : return FAILURE;
3011 : } else {
3012 6922 : (*function->op_array.refcount)++;
3013 6922 : function->op_array.static_variables = NULL; /* NULL out the unbound function */
3014 6922 : return SUCCESS;
3015 : }
3016 : }
3017 : /* }}} */
3018 :
3019 : ZEND_API zend_class_entry *do_bind_class(const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
3020 4021 : {
3021 : zend_class_entry *ce, **pce;
3022 :
3023 4021 : if (zend_u_hash_find(class_table, Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (void **) &pce)==FAILURE) {
3024 0 : zend_error(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %R", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
3025 0 : return NULL;
3026 : } else {
3027 4021 : ce = *pce;
3028 : }
3029 4021 : ce->refcount++;
3030 4021 : if (zend_u_hash_add(class_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
3031 4 : ce->refcount--;
3032 4 : if (!compile_time) {
3033 : /* If we're in compile time, in practice, it's quite possible
3034 : * that we'll never reach this class declaration at runtime,
3035 : * so we shut up about it. This allows the if (!defined('FOO')) { return; }
3036 : * approach to work.
3037 : */
3038 2 : zend_error(E_COMPILE_ERROR, "Cannot redeclare class %v", ce->name);
3039 : }
3040 2 : return NULL;
3041 : } else {
3042 4017 : if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES))) {
3043 3673 : zend_verify_abstract_class(ce TSRMLS_CC);
3044 : }
3045 4017 : return ce;
3046 : }
3047 : }
3048 : /* }}} */
3049 :
3050 : ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC) /* {{{ */
3051 1947 : {
3052 : zend_class_entry *ce, **pce;
3053 : int found_ce;
3054 :
3055 1947 : found_ce = zend_u_hash_find(class_table, Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (void **) &pce);
3056 :
3057 1947 : if (found_ce == FAILURE) {
3058 0 : if (!compile_time) {
3059 : /* If we're in compile time, in practice, it's quite possible
3060 : * that we'll never reach this class declaration at runtime,
3061 : * so we shut up about it. This allows the if (!defined('FOO')) { return; }
3062 : * approach to work.
3063 : */
3064 0 : zend_error(E_COMPILE_ERROR, "Cannot redeclare class %R", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
3065 : }
3066 0 : return NULL;
3067 : } else {
3068 1947 : ce = *pce;
3069 : }
3070 :
3071 1947 : if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
3072 1 : zend_error(E_COMPILE_ERROR, "Class %v cannot extend from interface %v", ce->name, parent_ce->name);
3073 : }
3074 :
3075 1946 : zend_do_inheritance(ce, parent_ce TSRMLS_CC);
3076 :
3077 1909 : ce->refcount++;
3078 :
3079 : /* Register the derived class */
3080 1909 : if (zend_u_hash_add(class_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
3081 0 : zend_error(E_COMPILE_ERROR, "Cannot redeclare class %v", ce->name);
3082 : }
3083 1909 : return ce;
3084 : }
3085 : /* }}} */
3086 :
3087 : void zend_do_early_binding(TSRMLS_D) /* {{{ */
3088 10141 : {
3089 10141 : zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
3090 : HashTable *table;
3091 :
3092 20282 : while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) {
3093 0 : opline--;
3094 : }
3095 :
3096 10141 : switch (opline->opcode) {
3097 : case ZEND_DECLARE_FUNCTION:
3098 4994 : if (do_bind_function(opline, CG(function_table), 1) == FAILURE) {
3099 0 : return;
3100 : }
3101 4994 : table = CG(function_table);
3102 4994 : break;
3103 : case ZEND_DECLARE_CLASS:
3104 3782 : if (do_bind_class(opline, CG(class_table), 1 TSRMLS_CC) == NULL) {
3105 2 : return;
3106 : }
3107 3780 : table = CG(class_table);
3108 3780 : break;
3109 : case ZEND_DECLARE_INHERITED_CLASS:
3110 : {
3111 1096 : zend_op *fetch_class_opline = opline-1;
3112 1096 : zval *parent_name = &fetch_class_opline->op2.u.constant;
3113 : zend_class_entry **pce;
3114 :
3115 1096 : if ((zend_u_lookup_class(Z_TYPE_P(parent_name), Z_UNIVAL_P(parent_name), Z_UNILEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) ||
3116 : ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
3117 : ((*pce)->type == ZEND_INTERNAL_CLASS))) {
3118 249 : if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
3119 0 : zend_uint *opline_num = &CG(active_op_array)->early_binding;
3120 :
3121 0 : while (*opline_num != -1) {
3122 0 : opline_num = &CG(active_op_array)->opcodes[*opline_num].result.u.opline_num;
3123 : }
3124 0 : *opline_num = opline - CG(active_op_array)->opcodes;
3125 0 : opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
3126 0 : opline->result.op_type = IS_UNUSED;
3127 0 : opline->result.u.opline_num = -1;
3128 : }
3129 249 : return;
3130 : }
3131 847 : if (do_bind_inherited_class(opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
3132 0 : return;
3133 : }
3134 : /* clear unnecessary ZEND_FETCH_CLASS opcode */
3135 811 : zval_dtor(&fetch_class_opline->op2.u.constant);
3136 811 : MAKE_NOP(fetch_class_opline);
3137 :
3138 811 : table = CG(class_table);
3139 811 : break;
3140 : }
3141 : case ZEND_VERIFY_ABSTRACT_CLASS:
3142 : case ZEND_ADD_INTERFACE:
3143 : /* We currently don't early-bind classes that implement interfaces */
3144 269 : return;
3145 : default:
3146 0 : zend_error(E_COMPILE_ERROR, "Invalid binding type");
3147 0 : return;
3148 : }
3149 :
3150 9585 : zend_u_hash_del(table, Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant));
3151 9585 : zval_dtor(&opline->op1.u.constant);
3152 9585 : zval_dtor(&opline->op2.u.constant);
3153 9585 : MAKE_NOP(opline);
3154 : }
3155 : /* }}} */
3156 :
3157 : ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS_DC) /* {{{ */
3158 0 : {
3159 0 : if (op_array->early_binding != -1) {
3160 0 : zend_bool orig_in_compilation = CG(in_compilation);
3161 0 : zend_uint opline_num = op_array->early_binding;
3162 : zend_class_entry **pce;
3163 :
3164 0 : CG(in_compilation) = 1;
3165 0 : while (opline_num != -1) {
3166 0 : if (zend_u_lookup_class(Z_TYPE(op_array->opcodes[opline_num-1].op2.u.constant), Z_UNIVAL(op_array->opcodes[opline_num-1].op2.u.constant), Z_UNILEN(op_array->opcodes[opline_num-1].op2.u.constant), &pce TSRMLS_CC) == SUCCESS) {
3167 0 : do_bind_inherited_class(&op_array->opcodes[opline_num], EG(class_table), *pce, 1 TSRMLS_CC);
3168 : }
3169 0 : opline_num = op_array->opcodes[opline_num].result.u.opline_num;
3170 : }
3171 0 : CG(in_compilation) = orig_in_compilation;
3172 : }
3173 0 : }
3174 : /* }}} */
3175 :
3176 : void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
3177 2597 : {
3178 2597 : int next_op_number = get_next_op_number(CG(active_op_array));
3179 2597 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3180 :
3181 2597 : opline->opcode = ZEND_JMPNZ_EX;
3182 2597 : if (expr1->op_type == IS_TMP_VAR) {
3183 1910 : opline->result = *expr1;
3184 : } else {
3185 687 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
3186 687 : opline->result.op_type = IS_TMP_VAR;
3187 : }
3188 2597 : opline->op1 = *expr1;
3189 2597 : SET_UNUSED(opline->op2);
3190 :
3191 2597 : op_token->u.opline_num = next_op_number;
3192 :
3193 2597 : *expr1 = opline->result;
3194 2597 : }
3195 : /* }}} */
3196 :
3197 : void zend_do_boolean_or_end(znode *result, const znode *expr1, const znode *expr2, znode *op_token TSRMLS_DC) /* {{{ */
3198 2597 : {
3199 2597 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3200 :
3201 2597 : *result = *expr1; /* we saved the original result in expr1 */
3202 2597 : opline->opcode = ZEND_BOOL;
3203 2597 : opline->result = *result;
3204 2597 : opline->op1 = *expr2;
3205 2597 : SET_UNUSED(opline->op2);
3206 :
3207 2597 : CG(active_op_array)->opcodes[op_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
3208 2597 : }
3209 : /* }}} */
3210 :
3211 : void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
3212 3711 : {
3213 3711 : int next_op_number = get_next_op_number(CG(active_op_array));
3214 3711 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3215 :
3216 3711 : opline->opcode = ZEND_JMPZ_EX;
3217 3711 : if (expr1->op_type == IS_TMP_VAR) {
3218 2326 : opline->result = *expr1;
3219 : } else {
3220 1385 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
3221 1385 : opline->result.op_type = IS_TMP_VAR;
3222 : }
3223 3711 : opline->op1 = *expr1;
3224 3711 : SET_UNUSED(opline->op2);
3225 :
3226 3711 : op_token->u.opline_num = next_op_number;
3227 :
3228 3711 : *expr1 = opline->result;
3229 3711 : }
3230 : /* }}} */
3231 :
3232 : void zend_do_boolean_and_end(znode *result, const znode *expr1, const znode *expr2, const znode *op_token TSRMLS_DC) /* {{{ */
3233 3711 : {
3234 3711 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3235 :
3236 3711 : *result = *expr1; /* we saved the original result in expr1 */
3237 3711 : opline->opcode = ZEND_BOOL;
3238 3711 : opline->result = *result;
3239 3711 : opline->op1 = *expr2;
3240 3711 : SET_UNUSED(opline->op2);
3241 :
3242 3711 : CG(active_op_array)->opcodes[op_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
3243 3711 : }
3244 : /* }}} */
3245 :
3246 : void zend_do_do_while_begin(TSRMLS_D) /* {{{ */
3247 266 : {
3248 266 : do_begin_loop(TSRMLS_C);
3249 266 : INC_BPC(CG(active_op_array));
3250 266 : }
3251 : /* }}} */
3252 :
3253 : void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket, const znode *expr TSRMLS_DC) /* {{{ */
3254 266 : {
3255 266 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3256 :
3257 266 : opline->opcode = ZEND_JMPNZ;
3258 266 : opline->op1 = *expr;
3259 266 : opline->op2.u.opline_num = do_token->u.opline_num;
3260 266 : SET_UNUSED(opline->op2);
3261 :
3262 266 : do_end_loop(expr_open_bracket->u.opline_num, 0 TSRMLS_CC);
3263 :
3264 266 : DEC_BPC(CG(active_op_array));
3265 266 : }
3266 : /* }}} */
3267 :
3268 : void zend_do_brk_cont(zend_uchar op, const znode *expr TSRMLS_DC) /* {{{ */
3269 1832 : {
3270 1832 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3271 :
3272 1832 : opline->opcode = op;
3273 1832 : opline->op1.u.opline_num = CG(active_op_array)->current_brk_cont;
3274 1832 : SET_UNUSED(opline->op1);
3275 1832 : if (expr) {
3276 11 : if (expr->op_type != IS_CONST) {
3277 0 : zend_error(E_COMPILE_ERROR, "'%s' operator with non-constant operand is no longer supported", op == ZEND_BRK ? "break" : "continue");
3278 11 : } else if (Z_TYPE(expr->u.constant) != IS_LONG || Z_LVAL(expr->u.constant) < 1) {
3279 0 : zend_error(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers", op == ZEND_BRK ? "break" : "continue");
3280 : }
3281 11 : opline->op2 = *expr;
3282 : } else {
3283 1821 : Z_TYPE(opline->op2.u.constant) = IS_LONG;
3284 1821 : Z_LVAL(opline->op2.u.constant) = 1;
3285 1821 : INIT_PZVAL(&opline->op2.u.constant);
3286 1821 : opline->op2.op_type = IS_CONST;
3287 : }
3288 1832 : }
3289 : /* }}} */
3290 :
3291 : void zend_do_switch_cond(const znode *cond TSRMLS_DC) /* {{{ */
3292 436 : {
3293 : zend_switch_entry switch_entry;
3294 :
3295 436 : switch_entry.cond = *cond;
3296 436 : switch_entry.default_case = -1;
3297 436 : switch_entry.control_var = -1;
3298 436 : zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
3299 :
3300 436 : do_begin_loop(TSRMLS_C);
3301 :
3302 436 : INC_BPC(CG(active_op_array));
3303 436 : }
3304 : /* }}} */
3305 :
3306 : void zend_do_switch_end(const znode *case_list TSRMLS_DC) /* {{{ */
3307 436 : {
3308 : zend_op *opline;
3309 : zend_switch_entry *switch_entry_ptr;
3310 :
3311 436 : zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
3312 :
3313 : /* add code to jmp to default case */
3314 436 : if (switch_entry_ptr->default_case != -1) {
3315 260 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3316 260 : opline->opcode = ZEND_JMP;
3317 260 : SET_UNUSED(opline->op1);
3318 260 : SET_UNUSED(opline->op2);
3319 260 : opline->op1.u.opline_num = switch_entry_ptr->default_case;
3320 : }
3321 :
3322 436 : if (case_list->op_type != IS_UNUSED) { /* non-empty switch */
3323 436 : int next_op_number = get_next_op_number(CG(active_op_array));
3324 :
3325 436 : CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
3326 : }
3327 :
3328 : /* remember break/continue loop information */
3329 436 : CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
3330 436 : CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
3331 :
3332 436 : if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
3333 : /* emit free for the switch condition*/
3334 95 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3335 95 : opline->opcode = (switch_entry_ptr->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
3336 95 : opline->op1 = switch_entry_ptr->cond;
3337 95 : SET_UNUSED(opline->op2);
3338 : }
3339 436 : if (switch_entry_ptr->cond.op_type == IS_CONST) {
3340 5 : zval_dtor(&switch_entry_ptr->cond.u.constant);
3341 : }
3342 :
3343 436 : zend_stack_del_top(&CG(switch_cond_stack));
3344 :
3345 436 : DEC_BPC(CG(active_op_array));
3346 436 : }
3347 : /* }}} */
3348 :
3349 : void zend_do_case_before_statement(const znode *case_list, znode *case_token, const znode *case_expr TSRMLS_DC) /* {{{ */
3350 1467 : {
3351 1467 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3352 : int next_op_number;
3353 : zend_switch_entry *switch_entry_ptr;
3354 : znode result;
3355 :
3356 1467 : zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
3357 :
3358 1467 : if (switch_entry_ptr->control_var == -1) {
3359 435 : switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array));
3360 : }
3361 1467 : opline->opcode = ZEND_CASE;
3362 1467 : opline->result.u.var = switch_entry_ptr->control_var;
3363 1467 : opline->result.op_type = IS_TMP_VAR;
3364 1467 : opline->op1 = switch_entry_ptr->cond;
3365 1467 : opline->op2 = *case_expr;
3366 1467 : if (opline->op1.op_type == IS_CONST) {
3367 8 : zval_copy_ctor(&opline->op1.u.constant);
3368 : }
3369 1467 : result = opline->result;
3370 :
3371 1467 : next_op_number = get_next_op_number(CG(active_op_array));
3372 1467 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3373 1467 : opline->opcode = ZEND_JMPZ;
3374 1467 : opline->op1 = result;
3375 1467 : SET_UNUSED(opline->op2);
3376 1467 : case_token->u.opline_num = next_op_number;
3377 :
3378 1467 : if (case_list->op_type==IS_UNUSED) {
3379 292 : return;
3380 : }
3381 1175 : next_op_number = get_next_op_number(CG(active_op_array));
3382 1175 : CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
3383 : }
3384 : /* }}} */
3385 :
3386 : void zend_do_case_after_statement(znode *result, const znode *case_token TSRMLS_DC) /* {{{ */
3387 1729 : {
3388 1729 : int next_op_number = get_next_op_number(CG(active_op_array));
3389 1729 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3390 :
3391 1729 : opline->opcode = ZEND_JMP;
3392 1729 : SET_UNUSED(opline->op1);
3393 1729 : SET_UNUSED(opline->op2);
3394 1729 : result->u.opline_num = next_op_number;
3395 :
3396 1729 : switch (CG(active_op_array)->opcodes[case_token->u.opline_num].opcode) {
3397 : case ZEND_JMP:
3398 262 : CG(active_op_array)->opcodes[case_token->u.opline_num].op1.u.opline_num = get_next_op_number(CG(active_op_array));
3399 262 : break;
3400 : case ZEND_JMPZ:
3401 1467 : CG(active_op_array)->opcodes[case_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
3402 : break;
3403 : }
3404 1729 : }
3405 : /* }}} */
3406 :
3407 : void zend_do_default_before_statement(const znode *case_list, znode *default_token TSRMLS_DC) /* {{{ */
3408 262 : {
3409 262 : int next_op_number = get_next_op_number(CG(active_op_array));
3410 262 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3411 : zend_switch_entry *switch_entry_ptr;
3412 :
3413 262 : zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
3414 :
3415 262 : opline->opcode = ZEND_JMP;
3416 262 : SET_UNUSED(opline->op1);
3417 262 : SET_UNUSED(opline->op2);
3418 262 : default_token->u.opline_num = next_op_number;
3419 :
3420 262 : next_op_number = get_next_op_number(CG(active_op_array));
3421 262 : switch_entry_ptr->default_case = next_op_number;
3422 :
3423 262 : if (case_list->op_type==IS_UNUSED) {
3424 144 : return;
3425 : }
3426 118 : CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
3427 : }
3428 : /* }}} */
3429 :
3430 : void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC) /* {{{ */
3431 6059 : {
3432 : zend_op *opline;
3433 6059 : int doing_inheritance = 0;
3434 : zend_class_entry *new_class_entry;
3435 : unsigned int lcname_len;
3436 : zstr lcname;
3437 6059 : int error = 0;
3438 : zval **ns_name;
3439 :
3440 6059 : if (CG(active_class_entry)) {
3441 1 : zend_error(E_COMPILE_ERROR, "Class declarations may not be nested");
3442 0 : return;
3443 : }
3444 :
3445 6058 : lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant), 0, &lcname_len);
3446 :
3447 6058 : if ((lcname_len == sizeof("self")-1 &&
3448 : ZEND_U_EQUAL(Z_TYPE(class_name->u.constant), lcname, lcname_len, "self", sizeof("self")-1)) ||
3449 : (lcname_len == sizeof("parent")-1 &&
3450 : ZEND_U_EQUAL(Z_TYPE(class_name->u.constant), lcname, lcname_len, "parent", sizeof("parent")-1))) {
3451 2 : efree(lcname.v);
3452 2 : zend_error(E_COMPILE_ERROR, "Cannot use '%R' as class name as it is reserved", Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant));
3453 : }
3454 :
3455 : /* Class name must not conflict with import names */
3456 6056 : if (CG(current_import) &&
3457 : zend_u_hash_find(CG(current_import), Z_TYPE(class_name->u.constant), lcname, lcname_len+1, (void**)&ns_name) == SUCCESS) {
3458 2 : error = 1;
3459 : }
3460 :
3461 6056 : if (CG(current_namespace)) {
3462 : /* Prefix class name with name of current namespace */
3463 : znode tmp;
3464 :
3465 87 : tmp.u.constant = *CG(current_namespace);
3466 87 : zval_copy_ctor(&tmp.u.constant);
3467 87 : zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
3468 87 : class_name = &tmp;
3469 87 : efree(lcname.v);
3470 87 : lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant), 0, &lcname_len);
3471 : }
3472 :
3473 6056 : if (error) {
3474 : unsigned int tmp_len;
3475 2 : zstr tmp = zend_u_str_case_fold(Z_TYPE_PP(ns_name), Z_UNIVAL_PP(ns_name), Z_UNILEN_PP(ns_name), 0, &tmp_len);
3476 :
3477 2 : if (tmp_len != lcname_len ||
3478 : memcmp(tmp.v, lcname.v, UBYTES(lcname_len))) {
3479 1 : zend_error(E_COMPILE_ERROR, "Cannot declare class %R because the name is already in use", Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant));
3480 : }
3481 1 : efree(tmp.v);
3482 : }
3483 :
3484 6055 : new_class_entry = emalloc(sizeof(zend_class_entry));
3485 6055 : new_class_entry->type = ZEND_USER_CLASS;
3486 6055 : new_class_entry->name = Z_UNIVAL(class_name->u.constant);
3487 6055 : new_class_entry->name_length = Z_UNILEN(class_name->u.constant);
3488 :
3489 6055 : zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
3490 6055 : new_class_entry->filename = zend_get_compiled_filename(TSRMLS_C);
3491 6055 : new_class_entry->line_start = class_token->u.opline_num;
3492 6055 : new_class_entry->ce_flags |= class_token->u.EA.type;
3493 :
3494 6055 : if (parent_class_name && parent_class_name->op_type != IS_UNUSED) {
3495 1960 : switch (parent_class_name->u.EA.type) {
3496 : case ZEND_FETCH_CLASS_SELF:
3497 1 : zend_error(E_COMPILE_ERROR, "Cannot use 'self' as class name as it is reserved");
3498 0 : break;
3499 : case ZEND_FETCH_CLASS_PARENT:
3500 1 : zend_error(E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved");
3501 0 : break;
3502 : case ZEND_FETCH_CLASS_STATIC:
3503 0 : zend_error(E_COMPILE_ERROR, "Cannot use 'static' as class name as it is reserved");
3504 : break;
3505 : default:
3506 : break;
3507 : }
3508 1958 : doing_inheritance = 1;
3509 : }
3510 :
3511 6053 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3512 6053 : opline->op1.op_type = IS_CONST;
3513 6053 : build_runtime_defined_function_key(&opline->op1.u.constant, Z_TYPE(class_name->u.constant), lcname, lcname_len TSRMLS_CC);
3514 :
3515 6053 : opline->op2.op_type = IS_CONST;
3516 6053 : Z_TYPE(opline->op2.u.constant) = Z_TYPE(class_name->u.constant);
3517 6053 : Z_SET_REFCOUNT(opline->op2.u.constant, 1);
3518 :
3519 6053 : if (doing_inheritance) {
3520 1958 : opline->extended_value = parent_class_name->u.var;
3521 1958 : opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
3522 : } else {
3523 4095 : opline->opcode = ZEND_DECLARE_CLASS;
3524 : }
3525 :
3526 6053 : ZVAL_ZSTRL(&opline->op2.u.constant, Z_TYPE(opline->op2.u.constant), lcname, lcname_len, 0);
3527 :
3528 6053 : zend_u_hash_update(CG(class_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), &new_class_entry, sizeof(zend_class_entry *), NULL);
3529 6053 : CG(active_class_entry) = new_class_entry;
3530 :
3531 6053 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
3532 6053 : opline->result.op_type = IS_VAR;
3533 6053 : CG(implementing_class) = opline->result;
3534 :
3535 6053 : if (CG(doc_comment).v) {
3536 11 : CG(active_class_entry)->doc_comment = CG(doc_comment);
3537 11 : CG(active_class_entry)->doc_comment_len = CG(doc_comment_len);
3538 11 : CG(doc_comment) = NULL_ZSTR;
3539 11 : CG(doc_comment_len) = 0;
3540 : }
3541 : }
3542 : /* }}} */
3543 :
3544 : static void do_verify_abstract_class(TSRMLS_D) /* {{{ */
3545 233 : {
3546 233 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3547 :
3548 233 : opline->opcode = ZEND_VERIFY_ABSTRACT_CLASS;
3549 233 : opline->op1 = CG(implementing_class);
3550 233 : SET_UNUSED(opline->op2);
3551 233 : }
3552 : /* }}} */
3553 :
3554 : void zend_do_end_class_declaration(const znode *class_token, const znode *parent_token TSRMLS_DC) /* {{{ */
3555 5984 : {
3556 5984 : zend_class_entry *ce = CG(active_class_entry);
3557 :
3558 5984 : if (ce->constructor) {
3559 1613 : ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
3560 1613 : if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
3561 1 : zend_error(E_COMPILE_ERROR, "Constructor %v::%v() cannot be static", ce->name, ce->constructor->common.function_name);
3562 : }
3563 : }
3564 5983 : if (ce->destructor) {
3565 128 : ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
3566 128 : if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
3567 1 : zend_error(E_COMPILE_ERROR, "Destructor %v::%v() cannot be static", ce->name, ce->destructor->common.function_name);
3568 : }
3569 : }
3570 5982 : if (ce->clone) {
3571 19 : ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
3572 19 : if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
3573 1 : zend_error(E_COMPILE_ERROR, "Clone method %v::%v() cannot be static", ce->name, ce->clone->common.function_name);
3574 : }
3575 : }
3576 :
3577 5981 : ce->line_end = zend_get_compiled_lineno(TSRMLS_C);
3578 :
3579 5981 : if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
3580 : && ((parent_token->op_type != IS_UNUSED) || (ce->num_interfaces > 0))) {
3581 5774 : zend_verify_abstract_class(ce TSRMLS_CC);
3582 5771 : if (ce->num_interfaces) {
3583 233 : do_verify_abstract_class(TSRMLS_C);
3584 : }
3585 : }
3586 : /* Inherit interfaces; reset number to zero, we need it for above check and
3587 : * will restore it during actual implementation.
3588 : * The ZEND_ACC_IMPLEMENT_INTERFACES flag disables double call to
3589 : * zend_verify_abstract_class() */
3590 5978 : if (ce->num_interfaces > 0) {
3591 272 : ce->interfaces = NULL;
3592 272 : ce->num_interfaces = 0;
3593 272 : ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
3594 : }
3595 5978 : CG(active_class_entry) = NULL;
3596 5978 : }
3597 : /* }}} */
3598 :
3599 : void zend_do_implements_interface(znode *interface_name TSRMLS_DC) /* {{{ */
3600 309 : {
3601 : zend_op *opline;
3602 :
3603 309 : switch (zend_get_class_fetch_type(Z_TYPE(interface_name->u.constant), Z_UNIVAL(interface_name->u.constant), Z_UNILEN(interface_name->u.constant))) {
3604 : case ZEND_FETCH_CLASS_SELF:
3605 : case ZEND_FETCH_CLASS_PARENT:
3606 : case ZEND_FETCH_CLASS_STATIC:
3607 2 : zend_error(E_COMPILE_ERROR, "Cannot use '%R' as interface name as it is reserved", Z_TYPE(interface_name->u.constant), Z_UNIVAL(interface_name->u.constant));
3608 : break;
3609 : default:
3610 : break;
3611 : }
3612 :
3613 307 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3614 307 : opline->opcode = ZEND_ADD_INTERFACE;
3615 307 : opline->op1 = CG(implementing_class);
3616 307 : zend_resolve_class_name(interface_name, &opline->extended_value, 0 TSRMLS_CC);
3617 307 : opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;
3618 307 : opline->op2 = *interface_name;
3619 307 : CG(active_class_entry)->num_interfaces++;
3620 307 : }
3621 : /* }}} */
3622 :
3623 : ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, const char *src1, int src1_length, const char *src2, int src2_length, int internal) /* {{{ */
3624 346 : {
3625 : char *prop_name;
3626 : int prop_name_length;
3627 :
3628 346 : prop_name_length = 1 + src1_length + 1 + src2_length;
3629 346 : prop_name = pemalloc(prop_name_length + 1, internal);
3630 346 : prop_name[0] = '\0';
3631 346 : memcpy(prop_name + 1, src1, src1_length+1);
3632 346 : memcpy(prop_name + 1 + src1_length + 1, src2, src2_length+1);
3633 :
3634 346 : *dest = prop_name;
3635 346 : *dest_length = prop_name_length;
3636 346 : }
3637 : /* }}} */
3638 :
3639 : ZEND_API void zend_u_mangle_property_name(zstr *dest, int *dest_length, zend_uchar type, const zstr src1, int src1_length, const zstr src2, int src2_length, int internal) /* {{{ */
3640 273131 : {
3641 273131 : if (type == IS_UNICODE) {
3642 : UChar *prop_name;
3643 : int prop_name_length;
3644 :
3645 273131 : prop_name_length = 1 + src1_length + 1 + src2_length;
3646 273131 : prop_name = pemalloc(UBYTES(prop_name_length + 1), internal);
3647 273131 : prop_name[0] = 0;
3648 494589 : if (src1_length == 1 && src1.s[0] == '*') {
3649 221458 : prop_name[1] = '*';
3650 221458 : prop_name[2] = 0;
3651 : } else {
3652 51673 : memcpy(prop_name + 1, src1.s, UBYTES(src1_length+1));
3653 : }
3654 273131 : memcpy(prop_name + 1 + src1_length + 1, src2.s, UBYTES(src2_length+1));
3655 :
3656 273131 : dest->u = prop_name;
3657 273131 : *dest_length = prop_name_length;
3658 : } else {
3659 0 : zend_mangle_property_name(&dest->s, dest_length, src1.s, src1_length, src2.s, src2_length, internal);
3660 : }
3661 273131 : }
3662 : /* }}} */
3663 :
3664 : static int zend_strnlen(const char* s, int maxlen) /* {{{ */
3665 2 : {
3666 2 : int len = 0;
3667 2 : while (*s++ && maxlen--) len++;
3668 2 : return len;
3669 : }
3670 : /* }}} */
3671 :
3672 : static int zend_u_strnlen(const UChar* s, int maxlen) /* {{{ */
3673 2065 : {
3674 2065 : int len = 0;
3675 2065 : while (*s++ && maxlen--) len++;
3676 2065 : return len;
3677 : }
3678 : /* }}} */
3679 :
3680 : ZEND_API int zend_unmangle_property_name(char *mangled_property, int len, char **class_name, char **prop_name) /* {{{ */
3681 100 : {
3682 : int class_name_len;
3683 :
3684 100 : *class_name = NULL;
3685 :
3686 100 : if (mangled_property[0]!=0) {
3687 98 : *prop_name = mangled_property;
3688 98 : return SUCCESS;
3689 : }
3690 2 : if (len < 3 || mangled_property[1]==0) {
3691 0 : zend_error(E_NOTICE, "Illegal member variable name");
3692 0 : *prop_name = mangled_property;
3693 0 : return FAILURE;
3694 : }
3695 :
3696 2 : class_name_len = zend_strnlen(mangled_property+1, --len - 1) + 1;
3697 2 : if (class_name_len >= len || mangled_property[class_name_len]!=0) {
3698 0 : zend_error(E_NOTICE, "Corrupt member variable name");
3699 0 : *prop_name = mangled_property;
3700 0 : return FAILURE;
3701 : }
3702 2 : *class_name = mangled_property+1;
3703 2 : *prop_name = (*class_name)+class_name_len;
3704 2 : return SUCCESS;
3705 : }
3706 : /* }}} */
3707 :
3708 : ZEND_API int zend_u_unmangle_property_name(zend_uchar type, zstr mangled_property, int len, zstr *class_name, zstr *prop_name) /* {{{ */
3709 8834 : {
3710 8834 : if (type == IS_UNICODE) {
3711 : int class_name_len;
3712 :
3713 8792 : class_name->v = NULL;
3714 :
3715 8792 : if ((mangled_property.u)[0]!=0) {
3716 6727 : *prop_name = mangled_property;
3717 6727 : return SUCCESS;
3718 : }
3719 2065 : if (len < 3 || mangled_property.u[1]==0) {
3720 0 : zend_error(E_NOTICE, "Illegal member variable name");
3721 0 : *prop_name = mangled_property;
3722 0 : return FAILURE;
3723 : }
3724 :
3725 2065 : class_name_len = zend_u_strnlen(mangled_property.u+1, --len - 1) + 1;
3726 2065 : if (class_name_len >= len || mangled_property.u[class_name_len]!=0) {
3727 0 : zend_error(E_NOTICE, "Corrupt member variable name");
3728 0 : *prop_name = mangled_property;
3729 0 : return FAILURE;
3730 : }
3731 :
3732 2065 : class_name->u = mangled_property.u + 1;
3733 2065 : prop_name->u = class_name->u + class_name_len;
3734 2065 : if (class_name->u[0] == '*') {
3735 797 : class_name->s = "*";
3736 : }
3737 2065 : return SUCCESS;
3738 : } else {
3739 42 : return zend_unmangle_property_name(mangled_property.s, len, &class_name->s, &prop_name->s);
3740 : }
3741 : }
3742 : /* }}} */
3743 :
3744 : void zend_do_declare_property(const znode *var_name, const znode *value, zend_uint access_type TSRMLS_DC) /* {{{ */
3745 1881 : {
3746 : zval *property;
3747 : zend_property_info *existing_property_info;
3748 1881 : zstr comment = NULL_ZSTR;
3749 1881 : int comment_len = 0;
3750 :
3751 1881 : if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
3752 1 : zend_error(E_COMPILE_ERROR, "Interfaces may not include member variables");
3753 : }
3754 :
3755 1880 : if (access_type & ZEND_ACC_ABSTRACT) {
3756 1 : zend_error(E_COMPILE_ERROR, "Properties cannot be declared abstract");
3757 : }
3758 :
3759 1879 : if (access_type & ZEND_ACC_FINAL) {
3760 1 : zend_error(E_COMPILE_ERROR, "Cannot declare property %v::$%R final, the final modifier is allowed only for methods and classes",
3761 : CG(active_class_entry)->name, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant));
3762 : }
3763 :
3764 1878 : if (zend_u_hash_find(&CG(active_class_entry)->properties_info, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant), Z_UNILEN(var_name->u.constant)+1, (void **) &existing_property_info)==SUCCESS) {
3765 1 : if (!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
3766 1 : zend_error(E_COMPILE_ERROR, "Cannot redeclare %v::$%R", CG(active_class_entry)->name, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant));
3767 : }
3768 : }
3769 1877 : ALLOC_ZVAL(property);
3770 :
3771 1877 : if (value) {
3772 1037 : *property = value->u.constant;
3773 : } else {
3774 840 : INIT_PZVAL(property);
3775 840 : Z_TYPE_P(property) = IS_NULL;
3776 : }
3777 :
3778 1877 : if (CG(doc_comment).v) {
3779 42 : comment = CG(doc_comment);
3780 42 : comment_len = CG(doc_comment_len);
3781 42 : CG(doc_comment) = NULL_ZSTR;
3782 42 : CG(doc_comment_len) = 0;
3783 : }
3784 :
3785 1877 : zend_u_declare_property_ex(CG(active_class_entry), Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant), Z_UNILEN(var_name->u.constant), property, access_type, comment, comment_len TSRMLS_CC);
3786 1877 : efree(Z_STRVAL(var_name->u.constant));
3787 1877 : }
3788 : /* }}} */
3789 :
3790 : void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_DC) /* {{{ */
3791 193 : {
3792 : zval *property;
3793 :
3794 193 : if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) {
3795 2 : zend_error(E_COMPILE_ERROR, "Arrays are not allowed in class constants");
3796 : }
3797 :
3798 191 : ALLOC_ZVAL(property);
3799 191 : *property = value->u.constant;
3800 :
3801 191 : if (zend_u_hash_add(&CG(active_class_entry)->constants_table, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant), Z_UNILEN(var_name->u.constant)+1, &property, sizeof(zval *), NULL)==FAILURE) {
3802 2 : FREE_ZVAL(property);
3803 2 : zend_error(E_COMPILE_ERROR, "Cannot redefine class constant %v::%R", CG(active_class_entry)->name, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant));
3804 : }
3805 189 : FREE_PNODE(var_name);
3806 :
3807 189 : if (CG(doc_comment).v) {
3808 2 : efree(CG(doc_comment).v);
3809 2 : CG(doc_comment) = NULL_ZSTR;
3810 2 : CG(doc_comment_len) = 0;
3811 : }
3812 189 : }
3813 : /* }}} */
3814 :
3815 : void zend_do_fetch_property(znode *result, znode *object, const znode *property TSRMLS_DC) /* {{{ */
3816 31379 : {
3817 : zend_op opline;
3818 : zend_llist *fetch_list_ptr;
3819 :
3820 31379 : zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
3821 :
3822 31379 : if (object->op_type == IS_CV) {
3823 26067 : if (object->u.var == CG(active_op_array)->this_var) {
3824 0 : SET_UNUSED(*object); /* this means $this for objects */
3825 : }
3826 5312 : } else if (fetch_list_ptr->count == 1) {
3827 4925 : zend_llist_element *le = fetch_list_ptr->head;
3828 4925 : zend_op *opline_ptr = (zend_op *) le->data;
3829 :
3830 4925 : if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
3831 3449 : efree(Z_STRVAL(opline_ptr->op1.u.constant));
3832 3449 : SET_UNUSED(opline_ptr->op1); /* this means $this for objects */
3833 3449 : opline_ptr->op2 = *property;
3834 : /* if it was usual fetch, we change it to object fetch */
3835 3449 : switch (opline_ptr->opcode) {
3836 : case ZEND_FETCH_W:
3837 3449 : opline_ptr->opcode = ZEND_FETCH_OBJ_W;
3838 3449 : break;
3839 : case ZEND_FETCH_R:
3840 0 : opline_ptr->opcode = ZEND_FETCH_OBJ_R;
3841 0 : break;
3842 : case ZEND_FETCH_RW:
3843 0 : opline_ptr->opcode = ZEND_FETCH_OBJ_RW;
3844 0 : break;
3845 : case ZEND_FETCH_IS:
3846 0 : opline_ptr->opcode = ZEND_FETCH_OBJ_IS;
3847 0 : break;
3848 : case ZEND_FETCH_UNSET:
3849 0 : opline_ptr->opcode = ZEND_FETCH_OBJ_UNSET;
3850 0 : break;
3851 : case ZEND_FETCH_FUNC_ARG:
3852 0 : opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG;
3853 : break;
3854 : }
3855 3449 : *result = opline_ptr->result;
3856 3449 : return;
3857 : }
3858 : }
3859 :
3860 27930 : init_op(&opline TSRMLS_CC);
3861 27930 : opline.opcode = ZEND_FETCH_OBJ_W; /* the backpatching routine assumes W */
3862 27930 : opline.result.op_type = IS_VAR;
3863 27930 : opline.result.u.EA.type = 0;
3864 27930 : opline.result.u.var = get_temporary_variable(CG(active_op_array));
3865 27930 : opline.op1 = *object;
3866 27930 : opline.op2 = *property;
3867 27930 : *result = opline.result;
3868 :
3869 27930 : zend_llist_add_element(fetch_list_ptr, &opline);
3870 : }
3871 : /* }}} */
3872 :
3873 : void zend_do_halt_compiler_register(TSRMLS_D) /* {{{ */
3874 270 : {
3875 : char *name, *cfilename;
3876 : int len, clen;
3877 270 : cfilename = zend_get_compiled_filename(TSRMLS_C);
3878 270 : clen = strlen(cfilename);
3879 270 : zend_mangle_property_name(&name, &len, ZEND_HALT_CONSTANT_NAME,
3880 : sizeof(ZEND_HALT_CONSTANT_NAME)-1, cfilename, clen, 0);
3881 270 : zend_register_long_constant(name, len+1, zend_get_scanned_file_offset(TSRMLS_C), CONST_CS, 0 TSRMLS_CC);
3882 270 : pefree(name, 0);
3883 270 : }
3884 : /* }}} */
3885 :
3886 : void zend_do_declare_implicit_property(TSRMLS_D) /* {{{ */
3887 8242 : {
3888 : /* Fixes bug #26182. Not sure why we needed to do this in the first place.
3889 : Has to be checked with Zeev.
3890 : */
3891 : #if ANDI_0
3892 : zend_op *opline_ptr;
3893 : zend_llist_element *le;
3894 : zend_llist *fetch_list_ptr;
3895 :
3896 :
3897 : zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
3898 :
3899 : if (fetch_list_ptr->count != 1) {
3900 : return;
3901 : }
3902 :
3903 : le = fetch_list_ptr->head;
3904 : opline_ptr = (zend_op *) le->data;
3905 :
3906 : if (opline_ptr->op1.op_type == IS_UNUSED
3907 : && CG(active_class_entry)
3908 : && opline_ptr->op2.op_type == IS_CONST
3909 : && !zend_u_hash_exists(&CG(active_class_entry)->properties_info, Z_TYPE(opline_ptr->op2.u.constant), Z_UNIVAL(opline_ptr->op2.u.constant), Z_UNILEN(opline_ptr->op2.u.constant)+1)) {
3910 : znode property;
3911 :
3912 : property = opline_ptr->op2;
3913 : if (Z_TYPE(opline_ptr->op2.u.constant) == IS_UNICODE) {
3914 : Z_USTRVAL(property.u.constant) = eustrndup(Z_USTRVAL(opline_ptr->op2.u.constant), Z_USTRLEN(opline_ptr->op2.u.constant));
3915 : } else {
3916 : Z_STRVAL(property.u.constant) = estrndup(Z_STRVAL(opline_ptr->op2.u.constant), Z_STRLEN(opline_ptr->op2.u.constant));
3917 : }
3918 : zend_do_declare_property(&property, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_IMPLICIT_PUBLIC TSRMLS_CC);
3919 : }
3920 : #endif
3921 8242 : }
3922 : /* }}} */
3923 :
3924 : void zend_do_push_object(const znode *object TSRMLS_DC) /* {{{ */
3925 84594 : {
3926 84594 : zend_stack_push(&CG(object_stack), object, sizeof(znode));
3927 84594 : }
3928 : /* }}} */
3929 :
3930 : void zend_do_pop_object(znode *object TSRMLS_DC) /* {{{ */
3931 84594 : {
3932 84594 : if (object) {
3933 : znode *tmp;
3934 :
3935 84594 : zend_stack_top(&CG(object_stack), (void **) &tmp);
3936 84594 : *object = *tmp;
3937 : }
3938 84594 : zend_stack_del_top(&CG(object_stack));
3939 84594 : }
3940 : /* }}} */
3941 :
3942 : void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /* {{{ */
3943 9955 : {
3944 : zend_op *opline;
3945 9955 : unsigned char *ptr = NULL;
3946 :
3947 9955 : new_token->u.opline_num = get_next_op_number(CG(active_op_array));
3948 9955 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3949 9955 : opline->opcode = ZEND_NEW;
3950 9955 : opline->result.op_type = IS_VAR;
3951 9955 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
3952 9955 : opline->op1 = *class_type;
3953 9955 : SET_UNUSED(opline->op2);
3954 :
3955 9955 : zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *));
3956 9955 : }
3957 : /* }}} */
3958 :
3959 : void zend_do_end_new_object(znode *result, const znode *new_token, const znode *argument_list TSRMLS_DC) /* {{{ */
3960 9955 : {
3961 : znode ctor_result;
3962 :
3963 9955 : zend_do_end_function_call(NULL, &ctor_result, argument_list, 1, 0 TSRMLS_CC);
3964 9955 : zend_do_free(&ctor_result TSRMLS_CC);
3965 :
3966 9955 : CG(active_op_array)->opcodes[new_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
3967 9955 : *result = CG(active_op_array)->opcodes[new_token->u.opline_num].result;
3968 9955 : }
3969 : /* }}} */
3970 :
3971 : static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
3972 61808 : {
3973 61808 : zend_constant *c = NULL;
3974 : zstr lookup_name;
3975 :
3976 61808 : lookup_name.v = NULL;
3977 61835 : if(Z_TYPE_P(const_name) == IS_UNICODE && Z_USTRVAL_P(const_name)[0] == '\\') {
3978 27 : lookup_name.u = Z_USTRVAL_P(const_name)+1;
3979 61781 : } else if(Z_TYPE_P(const_name) == IS_STRING && Z_STRVAL_P(const_name)[0] == '\\') {
3980 0 : lookup_name.s = Z_STRVAL_P(const_name)+1;
3981 : }
3982 61808 : if(lookup_name.v != NULL) {
3983 27 : if (zend_u_hash_find(EG(zend_constants), Z_TYPE_P(const_name), lookup_name, Z_UNILEN_P(const_name), (void **) &c) == FAILURE) {
3984 : unsigned int lookup_name_len;
3985 26 : lookup_name = zend_u_str_case_fold(Z_TYPE_P(const_name), lookup_name, Z_UNILEN_P(const_name)-1, 1, &lookup_name_len);
3986 :
3987 26 : if (zend_u_hash_find(EG(zend_constants), Z_TYPE_P(const_name), lookup_name, lookup_name_len+1, (void **) &c)==SUCCESS) {
3988 0 : if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
3989 0 : efree(lookup_name.v);
3990 0 : return c;
3991 : }
3992 : }
3993 26 : efree(lookup_name.v);
3994 26 : return NULL;
3995 : }
3996 61781 : } else if (zend_u_hash_find(EG(zend_constants), Z_TYPE_P(const_name), Z_UNIVAL_P(const_name), Z_UNILEN_P(const_name)+1, (void **) &c) == FAILURE) {
3997 : unsigned int lookup_name_len;
3998 17848 : lookup_name = zend_u_str_case_fold(Z_TYPE_P(const_name), Z_UNIVAL_P(const_name), Z_UNILEN_P(const_name), 1, &lookup_name_len);
3999 :
4000 17848 : if (zend_u_hash_find(EG(zend_constants), Z_TYPE_P(const_name), lookup_name, lookup_name_len+1, (void **) &c)==SUCCESS) {
4001 15337 : if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
4002 15106 : efree(lookup_name.v);
4003 15106 : return c;
4004 : }
4005 : }
4006 2742 : efree(lookup_name.v);
4007 2742 : return NULL;
4008 : }
4009 43934 : if (c->flags & CONST_CT_SUBST) {
4010 36822 : return c;
4011 : }
4012 7112 : if (all_internal_constants_substitution &&
4013 : (c->flags & CONST_PERSISTENT) &&
4014 : !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
4015 : Z_TYPE(c->value) != IS_CONSTANT &&
4016 : Z_TYPE(c->value) != IS_CONSTANT_ARRAY) {
4017 6996 : return c;
4018 : }
4019 116 : return NULL;
4020 : }
4021 : /* }}} */
4022 :
4023 : static int zend_constant_ct_subst(znode *result, zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
4024 61775 : {
4025 61775 : zend_constant *c = zend_get_ct_const(const_name, all_internal_constants_substitution TSRMLS_CC);
4026 :
4027 61775 : if (c) {
4028 58923 : zval_dtor(const_name);
4029 58923 : result->op_type = IS_CONST;
4030 58923 : result->u.constant = c->value;
4031 58923 : zval_copy_ctor(&result->u.constant);
4032 58923 : INIT_PZVAL(&result->u.constant);
4033 58923 : return 1;
4034 : }
4035 2852 : return 0;
4036 : }
4037 : /* }}} */
4038 :
4039 : void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC) /* {{{ */
4040 69695 : {
4041 69695 : ulong fetch_type = 0;
4042 : znode tmp;
4043 : zend_op *opline;
4044 : int type;
4045 : zstr compound;
4046 :
4047 69695 : if (constant_container) {
4048 7920 : switch (mode) {
4049 : case ZEND_CT:
4050 118 : type = zend_get_class_fetch_type(Z_TYPE(constant_container->u.constant), Z_UNIVAL(constant_container->u.constant), Z_UNILEN(constant_container->u.constant));
4051 :
4052 118 : if (ZEND_FETCH_CLASS_STATIC == type) {
4053 0 : zend_error(E_ERROR, "\"static::\" is not allowed in compile-time constants");
4054 118 : } else if (ZEND_FETCH_CLASS_DEFAULT == type) {
4055 76 : zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC);
4056 : }
4057 118 : zend_do_build_full_name(NULL, constant_container, constant_name, 1 TSRMLS_CC);
4058 118 : *result = *constant_container;
4059 118 : result->u.constant.type = IS_CONSTANT | fetch_type;
4060 118 : break;
4061 : case ZEND_RT:
4062 15555 : if (constant_container->op_type == IS_CONST &&
4063 : ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_TYPE(constant_container->u.constant), Z_UNIVAL(constant_container->u.constant), Z_UNILEN(constant_container->u.constant))) {
4064 7753 : zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC);
4065 : } else {
4066 49 : zend_do_fetch_class(&tmp, constant_container TSRMLS_CC);
4067 49 : constant_container = &tmp;
4068 : }
4069 7802 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4070 7802 : opline->opcode = ZEND_FETCH_CONSTANT;
4071 7802 : opline->extended_value = fetch_type;
4072 7802 : opline->result.op_type = IS_TMP_VAR;
4073 7802 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
4074 7802 : opline->op1 = *constant_container;
4075 7802 : opline->op2 = *constant_name;
4076 7802 : *result = opline->result;
4077 : break;
4078 : }
4079 7920 : return;
4080 : }
4081 : /* namespace constant */
4082 : /* only one that did not contain \ from the start can be converted to string if unknown */
4083 61775 : switch (mode) {
4084 : case ZEND_CT:
4085 4373 : if(Z_TYPE(constant_name->u.constant) == IS_UNICODE) {
4086 4373 : compound.u = u_memchr(Z_USTRVAL(constant_name->u.constant), '\\', Z_USTRLEN(constant_name->u.constant));
4087 : } else {
4088 0 : compound.s = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
4089 : }
4090 : /* this is a namespace constant, or an unprefixed constant */
4091 :
4092 4373 : if (zend_constant_ct_subst(result, &constant_name->u.constant, 0 TSRMLS_CC)) {
4093 4261 : break;
4094 : }
4095 :
4096 112 : zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC);
4097 :
4098 112 : if(!compound.v) {
4099 70 : fetch_type |= IS_CONSTANT_UNQUALIFIED;
4100 : }
4101 :
4102 112 : *result = *constant_name;
4103 112 : result->u.constant.type = IS_CONSTANT | fetch_type;
4104 112 : break;
4105 : case ZEND_RT:
4106 57402 : if(Z_TYPE(constant_name->u.constant) == IS_UNICODE) {
4107 57402 : compound.u = u_memchr(Z_USTRVAL(constant_name->u.constant), '\\', Z_USTRLEN(constant_name->u.constant));
4108 : } else {
4109 0 : compound.s = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
4110 : }
4111 :
4112 57402 : zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC);
4113 :
4114 57402 : if(zend_constant_ct_subst(result, &constant_name->u.constant, 1 TSRMLS_CC)) {
4115 54662 : break;
4116 : }
4117 :
4118 2740 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4119 2740 : opline->opcode = ZEND_FETCH_CONSTANT;
4120 2740 : opline->result.op_type = IS_TMP_VAR;
4121 2740 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
4122 2740 : *result = opline->result;
4123 2740 : SET_UNUSED(opline->op1);
4124 2740 : if(compound.v != NULL) {
4125 : /* the name is unambiguous */
4126 48 : opline->extended_value = 0;
4127 : } else {
4128 2692 : opline->extended_value = IS_CONSTANT_UNQUALIFIED;
4129 : }
4130 2740 : opline->op2 = *constant_name;
4131 : break;
4132 : }
4133 :
4134 : }
4135 : /* }}} */
4136 :
4137 : void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC) /* {{{ */
4138 105 : {
4139 105 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4140 :
4141 105 : switch (cmd->op_type) {
4142 : case IS_CONST:
4143 : case IS_TMP_VAR:
4144 105 : opline->opcode = ZEND_SEND_VAL;
4145 105 : break;
4146 : default:
4147 0 : opline->opcode = ZEND_SEND_VAR;
4148 : break;
4149 : }
4150 105 : opline->op1 = *cmd;
4151 105 : opline->op2.u.opline_num = 0;
4152 105 : opline->extended_value = ZEND_DO_FCALL;
4153 105 : SET_UNUSED(opline->op2);
4154 :
4155 : /* FIXME: exception support not added to this op2 */
4156 105 : opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4157 105 : opline->opcode = ZEND_DO_FCALL;
4158 105 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
4159 105 : opline->result.op_type = IS_VAR;
4160 105 : Z_STRVAL(opline->op1.u.constant) = estrndup("shell_exec", sizeof("shell_exec")-1);
4161 105 : Z_STRLEN(opline->op1.u.constant) = sizeof("shell_exec")-1;
4162 105 : INIT_PZVAL(&opline->op1.u.constant);
4163 105 : Z_TYPE(opline->op1.u.constant) = IS_STRING;
4164 105 : opline->op1.op_type = IS_CONST;
4165 105 : opline->extended_value = 1;
4166 105 : SET_UNUSED(opline->op2);
4167 105 : ZVAL_LONG(&opline->op2.u.constant, zend_u_get_hash_value(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant)+1));
4168 105 : *result = opline->result;
4169 105 : }
4170 : /* }}} */
4171 :
4172 : void zend_do_init_array(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC) /* {{{ */
4173 19458 : {
4174 19458 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4175 :
4176 19458 : opline->opcode = ZEND_INIT_ARRAY;
4177 19458 : opline->result.u.var = get_temporary_variable(CG(active_op_array));
4178 19458 : opline->result.op_type = IS_TMP_VAR;
4179 19458 : *result = opline->result;
4180 19458 : if (expr) {
4181 17342 : opline->op1 = *expr;
4182 17342 : if (offset) {
4183 6285 : opline->op2 = *offset;
4184 : } else {
4185 11057 : SET_UNUSED(opline->op2);
4186 : }
4187 : } else {
4188 2116 : SET_UNUSED(opline->op1);
4189 2116 : SET_UNUSED(opline->op2);
4190 : }
4191 19458 : opline->extended_value = is_ref;
4192 19458 : }
4193 : /* }}} */
4194 :
4195 : void zend_do_add_array_element(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC) /* {{{ */
4196 61062 : {
4197 61062 : zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4198 :
4199 61062 : opline->opcode = ZEND_ADD_ARRAY_ELEMENT;
4200 61062 : opline->result = *result;
4201 61062 : opline->op1 = *expr;
4202 61062 : if (offset) {
4203 17559 : opline->op2 = *offset;
4204 : } else {
4205 43503 : SET_UNUSED(opline->op2);
4206 : }
4207 61062 : opline->extended_value = is_ref;
4208 61062 : }
4209 : /* }}} */
4210 :
4211 : void zend_do_add_static_array_element(znode *result, znode *offset, const znode *expr) /* {{{ */
4212 2697 : {
4213 : zval *element;
4214 :
4215 2697 : ALLOC_ZVAL(element);
4216 2697 : *element = expr->u.constant;
4217 2697 : if (offset) {
4218 130 : zend_uchar utype = Z_TYPE(offset->u.constant);
4219 :
4220 130 : switch (Z_TYPE(offset->u.constant) & IS_CONSTANT_TYPE_MASK) {
4221 : case IS_CONSTANT:
4222 : /* Ugly hack to denote that this value has a constant index */
4223 76 : Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
4224 :
4225 76 : Z_USTRVAL(offset->u.constant) = eurealloc(Z_USTRVAL(offset->u.constant), Z_USTRLEN(offset->u.constant)+3);
4226 76 : Z_USTRVAL(offset->u.constant)[Z_USTRLEN(offset->u.constant)+1] = Z_TYPE(offset->u.constant);
4227 76 : Z_USTRVAL(offset->u.constant)[Z_USTRLEN(offset->u.constant)+2] = 0;
4228 :
4229 76 : zend_u_symtable_update(result->u.constant.value.ht, IS_UNICODE, Z_UNIVAL(offset->u.constant), Z_UNILEN(offset->u.constant)+3, &element, sizeof(zval *), NULL);
4230 76 : zval_dtor(&offset->u.constant);
4231 76 : break;
4232 : case IS_STRING:
4233 : case IS_UNICODE:
4234 36 : zend_u_symtable_update(Z_ARRVAL(result->u.constant), utype, Z_UNIVAL(offset->u.constant), Z_UNILEN(offset->u.constant)+1, &element, sizeof(zval *), NULL);
4235 36 : zval_dtor(&offset->u.constant);
4236 36 : break;
4237 : case IS_NULL:
4238 0 : zend_u_symtable_update(Z_ARRVAL(result->u.constant), IS_UNICODE, EMPTY_ZSTR, 1, &element, sizeof(zval *), NULL);
4239 0 : break;
4240 : case IS_LONG:
4241 : case IS_BOOL:
4242 18 : zend_hash_index_update(Z_ARRVAL(result->u.constant), Z_LVAL(offset->u.constant), &element, sizeof(zval *), NULL);
4243 18 : break;
4244 : case IS_DOUBLE:
4245 0 : |