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