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