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