This source file includes following definitions.
- zend_push_function_call_entry
- zend_duplicate_property_info
- zend_duplicate_property_info_internal
- zend_destroy_property_info
- zend_destroy_property_info_internal
- build_runtime_defined_function_key
- init_compiler_declarables
- zend_init_compiler_context
- zend_init_compiler_data_structures
- file_handle_dtor
- init_compiler
- shutdown_compiler
- zend_set_compiled_filename
- zend_restore_compiled_filename
- zend_get_compiled_filename
- zend_get_compiled_lineno
- zend_is_compiling
- get_temporary_variable
- lookup_cv
- zend_del_literal
- zend_insert_literal
- zend_add_literal
- zend_append_individual_literal
- zend_add_func_name_literal
- zend_add_ns_func_name_literal
- zend_add_class_name_literal
- zend_add_const_name_literal
- zend_is_function_or_method_call
- zend_do_binary_op
- zend_do_unary_op
- zend_do_op_data
- zend_do_binary_assign_op
- fetch_simple_variable_ex
- fetch_simple_variable
- zend_do_fetch_static_member
- fetch_array_begin
- fetch_array_dim
- fetch_string_offset
- zend_do_print
- zend_do_echo
- zend_do_abstract_method
- opline_is_fetch_this
- zend_do_assign
- zend_do_assign_ref
- do_begin_loop
- do_end_loop
- zend_do_while_cond
- zend_do_while_end
- zend_do_for_cond
- zend_do_for_before_statement
- zend_do_for_end
- zend_do_pre_incdec
- zend_do_post_incdec
- zend_do_if_cond
- zend_do_if_after_statement
- zend_do_if_end
- zend_check_writable_variable
- zend_do_begin_variable_parse
- zend_do_end_variable_parse
- zend_do_add_string
- zend_do_add_variable
- zend_do_free
- zend_do_verify_access_types
- zend_do_begin_function_declaration
- zend_do_begin_lambda_function_declaration
- zend_do_handle_exception
- zend_do_end_function_declaration
- zend_do_receive_param
- zend_do_begin_function_call
- zend_do_begin_method_call
- zend_do_clone
- zend_do_begin_dynamic_function_call
- zend_resolve_non_class_name
- zend_resolve_function_name
- zend_resolve_const_name
- zend_do_resolve_class_name
- zend_resolve_class_name
- zend_do_fetch_class
- zend_do_label
- zend_resolve_goto_label
- zend_do_goto
- zend_release_labels
- zend_do_build_full_name
- zend_do_begin_class_member_function_call
- zend_do_end_function_call
- zend_do_pass_param
- zend_do_unpack_params
- generate_free_switch_expr
- generate_free_foreach_copy
- zend_do_return
- zend_do_yield
- zend_add_try_element
- zend_add_catch_element
- zend_do_first_catch
- zend_initialize_try_catch_element
- zend_do_mark_last_catch
- zend_do_try
- zend_do_finally
- zend_do_begin_catch
- zend_do_end_catch
- zend_do_bind_catch
- zend_do_end_finally
- zend_do_throw
- function_add_ref
- do_inherit_parent_constructor
- zend_visibility_string
- do_inherit_method
- zend_do_perform_implementation_check
- zend_get_function_declaration
- do_inheritance_check_on_method
- do_inherit_method_check
- do_inherit_property_access_check
- do_implement_interface
- zend_do_inherit_interfaces
- zval_internal_ctor
- zend_do_inheritance
- do_inherit_constant_check
- do_interface_constant_check
- zend_do_implement_interface
- zend_do_implement_trait
- zend_traits_method_compatibility_check
- zend_add_magic_methods
- zend_add_trait_method
- zend_fixup_trait_method
- zend_traits_copy_functions
- zend_check_trait_usage
- zend_traits_init_trait_structures
- zend_traits_compile_exclude_table
- zend_do_traits_method_binding
- find_first_definition
- zend_do_traits_property_binding
- zend_do_check_for_inconsistent_traits_aliasing
- zend_do_bind_traits
- do_bind_function
- zend_prepare_reference
- zend_add_trait_alias
- zend_add_trait_precedence
- do_bind_class
- do_bind_inherited_class
- zend_do_early_binding
- zend_do_delayed_early_binding
- zend_do_boolean_or_begin
- zend_do_boolean_or_end
- zend_do_boolean_and_begin
- zend_do_boolean_and_end
- zend_do_do_while_begin
- zend_do_do_while_end
- zend_do_brk_cont
- zend_do_switch_cond
- zend_do_switch_end
- zend_do_case_before_statement
- zend_do_case_after_statement
- zend_do_default_before_statement
- zend_do_begin_class_declaration
- do_verify_abstract_class
- zend_do_end_class_declaration
- zend_do_implements_interface
- zend_do_use_trait
- zend_mangle_property_name
- zend_strnlen
- zend_unmangle_property_name_ex
- zend_do_declare_property
- zend_do_declare_class_constant
- zend_do_fetch_property
- zend_do_halt_compiler_register
- zend_do_push_object
- zend_do_pop_object
- zend_do_begin_new_object
- zend_do_end_new_object
- zend_get_ct_const
- zend_constant_ct_subst
- zend_do_fetch_constant
- zend_do_shell_exec
- zend_do_init_array
- zend_do_add_array_element
- zend_do_add_static_array_element
- zend_do_add_list_element
- zend_do_new_list_begin
- zend_do_new_list_end
- zend_do_list_init
- zend_do_list_end
- zend_init_list
- zend_add_to_list
- zend_do_fetch_static_variable
- zend_do_fetch_lexical_variable
- zend_do_fetch_global_variable
- zend_do_cast
- zend_do_include_or_eval
- zend_do_indirect_references
- zend_do_unset
- zend_do_isset_or_isempty
- zend_do_instanceof
- zend_do_foreach_begin
- zend_do_foreach_cont
- zend_do_foreach_end
- zend_do_declare_begin
- zend_do_declare_stmt
- zend_do_declare_end
- zend_do_exit
- zend_do_begin_silence
- zend_do_end_silence
- zend_do_jmp_set
- zend_do_jmp_set_else
- zend_do_begin_qm_op
- zend_do_qm_true
- zend_do_qm_false
- zend_do_extended_info
- zend_do_extended_fcall_begin
- zend_do_extended_fcall_end
- zend_do_ticks
- zend_is_auto_global_quick
- zend_is_auto_global
- zend_register_auto_global
- zend_auto_global_init
- zend_activate_auto_globals
- zendlex
- zend_initialize_class_data
- zend_get_class_fetch_type
- zend_get_compiled_variable_name
- zend_do_build_namespace_name
- zend_do_begin_namespace
- zend_do_use
- zend_do_use_non_class
- zend_do_use_function
- zend_do_use_const
- zend_do_declare_constant
- zend_verify_namespace
- zend_do_end_namespace
- zend_do_end_compilation
- zend_do_constant_expression
- zend_dirname
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <zend_language_parser.h>
23 #include "zend.h"
24 #include "zend_compile.h"
25 #include "zend_constants.h"
26 #include "zend_llist.h"
27 #include "zend_API.h"
28 #include "zend_exceptions.h"
29 #include "zend_virtual_cwd.h"
30 #include "zend_multibyte.h"
31 #include "zend_language_scanner.h"
32
33 #define CONSTANT_EX(op_array, op) \
34 (op_array)->literals[op].constant
35
36 #define CONSTANT(op) \
37 CONSTANT_EX(CG(active_op_array), op)
38
39 #define SET_NODE(target, src) do { \
40 target ## _type = (src)->op_type; \
41 if ((src)->op_type == IS_CONST) { \
42 target.constant = zend_add_literal(CG(active_op_array), &(src)->u.constant TSRMLS_CC); \
43 } else { \
44 target = (src)->u.op; \
45 } \
46 } while (0)
47
48 #define GET_NODE(target, src) do { \
49 (target)->op_type = src ## _type; \
50 if ((target)->op_type == IS_CONST) { \
51 (target)->u.constant = CONSTANT(src.constant); \
52 } else { \
53 (target)->u.op = src; \
54 (target)->EA = 0; \
55 } \
56 } while (0)
57
58 #define COPY_NODE(target, src) do { \
59 target ## _type = src ## _type; \
60 target = src; \
61 } while (0)
62
63 #define CALCULATE_LITERAL_HASH(num) do { \
64 zval *c = &CONSTANT(num); \
65 Z_HASH_P(c) = str_hash(Z_STRVAL_P(c), Z_STRLEN_P(c)); \
66 } while (0)
67
68 #define GET_CACHE_SLOT(literal) do { \
69 CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot++; \
70 if ((CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) && CG(active_op_array)->run_time_cache) { \
71 CG(active_op_array)->run_time_cache = erealloc(CG(active_op_array)->run_time_cache, CG(active_op_array)->last_cache_slot * sizeof(void*)); \
72 CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 1] = NULL; \
73 } \
74 } while (0)
75
76 #define POLYMORPHIC_CACHE_SLOT_SIZE 2
77
78 #define GET_POLYMORPHIC_CACHE_SLOT(literal) do { \
79 CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot; \
80 CG(active_op_array)->last_cache_slot += POLYMORPHIC_CACHE_SLOT_SIZE; \
81 if ((CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) && CG(active_op_array)->run_time_cache) { \
82 CG(active_op_array)->run_time_cache = erealloc(CG(active_op_array)->run_time_cache, CG(active_op_array)->last_cache_slot * sizeof(void*)); \
83 CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 1] = NULL; \
84 CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 2] = NULL; \
85 } \
86 } while (0)
87
88 #define FREE_POLYMORPHIC_CACHE_SLOT(literal) do { \
89 if (CG(active_op_array)->literals[literal].cache_slot != -1 && \
90 CG(active_op_array)->literals[literal].cache_slot == \
91 CG(active_op_array)->last_cache_slot - POLYMORPHIC_CACHE_SLOT_SIZE) { \
92 CG(active_op_array)->literals[literal].cache_slot = -1; \
93 CG(active_op_array)->last_cache_slot -= POLYMORPHIC_CACHE_SLOT_SIZE; \
94 } \
95 } while (0)
96
97 ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
98 ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
99
100 #ifndef ZTS
101 ZEND_API zend_compiler_globals compiler_globals;
102 ZEND_API zend_executor_globals executor_globals;
103 #endif
104
105 static void zend_push_function_call_entry(zend_function *fbc TSRMLS_DC)
106 {
107 zend_function_call_entry fcall = { fbc };
108 zend_stack_push(&CG(function_call_stack), &fcall, sizeof(zend_function_call_entry));
109 }
110
111
112 static void zend_duplicate_property_info(zend_property_info *property_info)
113 {
114 property_info->name = str_estrndup(property_info->name, property_info->name_length);
115 if (property_info->doc_comment) {
116 property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len);
117 }
118 }
119
120
121 static void zend_duplicate_property_info_internal(zend_property_info *property_info)
122 {
123 property_info->name = str_strndup(property_info->name, property_info->name_length);
124 }
125
126
127 static void zend_destroy_property_info(zend_property_info *property_info)
128 {
129 str_efree(property_info->name);
130 if (property_info->doc_comment) {
131 efree((char*)property_info->doc_comment);
132 }
133 }
134
135
136 static void zend_destroy_property_info_internal(zend_property_info *property_info)
137 {
138 str_free((char*)property_info->name);
139 }
140
141
142 static void build_runtime_defined_function_key(zval *result, const char *name, int name_length TSRMLS_DC)
143 {
144 char char_pos_buf[32];
145 uint char_pos_len;
146 const char *filename;
147
148 char_pos_len = zend_sprintf(char_pos_buf, "%p", LANG_SCNG(yy_text));
149 if (CG(active_op_array)->filename) {
150 filename = CG(active_op_array)->filename;
151 } else {
152 filename = "-";
153 }
154
155
156 Z_STRLEN_P(result) = 1+name_length+strlen(filename)+char_pos_len;
157
158
159 Z_STRVAL_P(result) = (char *) safe_emalloc(Z_STRLEN_P(result), 1, 1);
160 Z_STRVAL_P(result)[0] = '\0';
161 sprintf(Z_STRVAL_P(result)+1, "%s%s%s", name, filename, char_pos_buf);
162
163 result->type = IS_STRING;
164 Z_SET_REFCOUNT_P(result, 1);
165 }
166
167
168 static void init_compiler_declarables(TSRMLS_D)
169 {
170 Z_TYPE(CG(declarables).ticks) = IS_LONG;
171 Z_LVAL(CG(declarables).ticks) = 0;
172 }
173
174
175 void zend_init_compiler_context(TSRMLS_D)
176 {
177 CG(context).opcodes_size = (CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) ? INITIAL_INTERACTIVE_OP_ARRAY_SIZE : INITIAL_OP_ARRAY_SIZE;
178 CG(context).vars_size = 0;
179 CG(context).literals_size = 0;
180 CG(context).current_brk_cont = -1;
181 CG(context).backpatch_count = 0;
182 CG(context).nested_calls = 0;
183 CG(context).used_stack = 0;
184 CG(context).in_finally = 0;
185 CG(context).labels = NULL;
186 }
187
188
189 void zend_init_compiler_data_structures(TSRMLS_D)
190 {
191 zend_stack_init(&CG(bp_stack));
192 zend_stack_init(&CG(function_call_stack));
193 zend_stack_init(&CG(switch_cond_stack));
194 zend_stack_init(&CG(foreach_copy_stack));
195 zend_stack_init(&CG(object_stack));
196 zend_stack_init(&CG(declare_stack));
197 CG(active_class_entry) = NULL;
198 zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
199 zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
200 zend_stack_init(&CG(list_stack));
201 CG(in_compilation) = 0;
202 CG(start_lineno) = 0;
203 CG(current_namespace) = NULL;
204 CG(in_namespace) = 0;
205 CG(has_bracketed_namespaces) = 0;
206 CG(current_import) = NULL;
207 CG(current_import_function) = NULL;
208 CG(current_import_const) = NULL;
209 zend_hash_init(&CG(const_filenames), 0, NULL, NULL, 0);
210 init_compiler_declarables(TSRMLS_C);
211 zend_stack_init(&CG(context_stack));
212
213 CG(encoding_declared) = 0;
214 }
215
216
217 ZEND_API void file_handle_dtor(zend_file_handle *fh)
218 {
219 TSRMLS_FETCH();
220
221 zend_file_handle_dtor(fh TSRMLS_CC);
222 }
223
224
225 void init_compiler(TSRMLS_D)
226 {
227 CG(active_op_array) = NULL;
228 memset(&CG(context), 0, sizeof(CG(context)));
229 zend_init_compiler_data_structures(TSRMLS_C);
230 zend_init_rsrc_list(TSRMLS_C);
231 zend_hash_init(&CG(filenames_table), 5, NULL, (dtor_func_t) free_estring, 0);
232 zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) file_handle_dtor, 0);
233 CG(unclean_shutdown) = 0;
234 }
235
236
237 void shutdown_compiler(TSRMLS_D)
238 {
239 zend_stack_destroy(&CG(bp_stack));
240 zend_stack_destroy(&CG(function_call_stack));
241 zend_stack_destroy(&CG(switch_cond_stack));
242 zend_stack_destroy(&CG(foreach_copy_stack));
243 zend_stack_destroy(&CG(object_stack));
244 zend_stack_destroy(&CG(declare_stack));
245 zend_stack_destroy(&CG(list_stack));
246 zend_hash_destroy(&CG(filenames_table));
247 zend_llist_destroy(&CG(open_files));
248 zend_hash_destroy(&CG(const_filenames));
249 zend_stack_destroy(&CG(context_stack));
250 }
251
252
253 ZEND_API char *zend_set_compiled_filename(const char *new_compiled_filename TSRMLS_DC)
254 {
255 char **pp, *p;
256 int length = strlen(new_compiled_filename);
257
258 if (zend_hash_find(&CG(filenames_table), new_compiled_filename, length+1, (void **) &pp) == SUCCESS) {
259 CG(compiled_filename) = *pp;
260 return *pp;
261 }
262 p = estrndup(new_compiled_filename, length);
263 zend_hash_update(&CG(filenames_table), new_compiled_filename, length+1, &p, sizeof(char *), (void **) &pp);
264 CG(compiled_filename) = p;
265 return p;
266 }
267
268
269 ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename TSRMLS_DC)
270 {
271 CG(compiled_filename) = original_compiled_filename;
272 }
273
274
275 ZEND_API char *zend_get_compiled_filename(TSRMLS_D)
276 {
277 return CG(compiled_filename);
278 }
279
280
281 ZEND_API int zend_get_compiled_lineno(TSRMLS_D)
282 {
283 return CG(zend_lineno);
284 }
285
286
287 ZEND_API zend_bool zend_is_compiling(TSRMLS_D)
288 {
289 return CG(in_compilation);
290 }
291
292
293 static zend_uint get_temporary_variable(zend_op_array *op_array)
294 {
295 return (zend_uint)(zend_uintptr_t)EX_TMP_VAR_NUM(0, (op_array->T)++);
296 }
297
298
299 static int lookup_cv(zend_op_array *op_array, char* name, int name_len, ulong hash TSRMLS_DC)
300 {
301 int i = 0;
302 ulong hash_value = hash ? hash : zend_inline_hash_func(name, name_len+1);
303
304 while (i < op_array->last_var) {
305 if (op_array->vars[i].name == name ||
306 (op_array->vars[i].hash_value == hash_value &&
307 op_array->vars[i].name_len == name_len &&
308 memcmp(op_array->vars[i].name, name, name_len) == 0)) {
309 str_efree(name);
310 return i;
311 }
312 i++;
313 }
314 i = op_array->last_var;
315 op_array->last_var++;
316 if (op_array->last_var > CG(context).vars_size) {
317 CG(context).vars_size += 16;
318 op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_compiled_variable));
319 }
320 op_array->vars[i].name = zend_new_interned_string(name, name_len + 1, 1 TSRMLS_CC);
321 op_array->vars[i].name_len = name_len;
322 op_array->vars[i].hash_value = hash_value;
323 return i;
324 }
325
326
327 void zend_del_literal(zend_op_array *op_array, int n)
328 {
329 zval_dtor(&CONSTANT_EX(op_array, n));
330 if (n + 1 == op_array->last_literal) {
331 op_array->last_literal--;
332 } else {
333 Z_TYPE(CONSTANT_EX(op_array, n)) = IS_NULL;
334 }
335 }
336
337
338
339 static inline void zend_insert_literal(zend_op_array *op_array, const zval *zv, int literal_position TSRMLS_DC)
340 {
341 if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) {
342 zval *z = (zval*)zv;
343 Z_STRVAL_P(z) = (char*)zend_new_interned_string(Z_STRVAL_P(zv), Z_STRLEN_P(zv) + 1, 1 TSRMLS_CC);
344 }
345 CONSTANT_EX(op_array, literal_position) = *zv;
346 Z_SET_REFCOUNT(CONSTANT_EX(op_array, literal_position), 2);
347 Z_SET_ISREF(CONSTANT_EX(op_array, literal_position));
348 op_array->literals[literal_position].hash_value = 0;
349 op_array->literals[literal_position].cache_slot = -1;
350 }
351
352
353
354
355
356 int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC)
357 {
358 int i = op_array->last_literal;
359 op_array->last_literal++;
360 if (i >= CG(context).literals_size) {
361 while (i >= CG(context).literals_size) {
362 CG(context).literals_size += 16;
363 }
364 op_array->literals = (zend_literal*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zend_literal));
365 }
366 zend_insert_literal(op_array, zv, i TSRMLS_CC);
367 return i;
368 }
369
370
371
372
373 int zend_append_individual_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC)
374 {
375 int i = op_array->last_literal;
376 op_array->last_literal++;
377 op_array->literals = (zend_literal*)erealloc(op_array->literals, (i + 1) * sizeof(zend_literal));
378 zend_insert_literal(op_array, zv, i TSRMLS_CC);
379 return i;
380 }
381
382
383 int zend_add_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC)
384 {
385 int ret;
386 char *lc_name;
387 zval c;
388 int lc_literal;
389
390 if (op_array->last_literal > 0 &&
391 &op_array->literals[op_array->last_literal - 1].constant == zv &&
392 op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
393
394 ret = op_array->last_literal - 1;
395 } else {
396 ret = zend_add_literal(op_array, zv TSRMLS_CC);
397 }
398
399 lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
400 ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0);
401 lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
402 CALCULATE_LITERAL_HASH(lc_literal);
403
404 return ret;
405 }
406
407
408 int zend_add_ns_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC)
409 {
410 int ret;
411 char *lc_name;
412 const char *ns_separator;
413 int lc_len;
414 zval c;
415 int lc_literal;
416
417 if (op_array->last_literal > 0 &&
418 &op_array->literals[op_array->last_literal - 1].constant == zv &&
419 op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
420
421 ret = op_array->last_literal - 1;
422 } else {
423 ret = zend_add_literal(op_array, zv TSRMLS_CC);
424 }
425
426 lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
427 ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0);
428 lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
429 CALCULATE_LITERAL_HASH(lc_literal);
430
431 ns_separator = (const char*)zend_memrchr(Z_STRVAL_P(zv), '\\', Z_STRLEN_P(zv));
432
433 if (ns_separator != NULL) {
434 ns_separator += 1;
435 lc_len = Z_STRLEN_P(zv) - (ns_separator - Z_STRVAL_P(zv));
436 lc_name = zend_str_tolower_dup(ns_separator, lc_len);
437 ZVAL_STRINGL(&c, lc_name, lc_len, 0);
438 lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
439 CALCULATE_LITERAL_HASH(lc_literal);
440 }
441
442 return ret;
443 }
444
445
446 int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC)
447 {
448 int ret;
449 char *lc_name;
450 int lc_len;
451 zval c;
452 int lc_literal;
453
454 if (op_array->last_literal > 0 &&
455 &op_array->literals[op_array->last_literal - 1].constant == zv &&
456 op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
457
458 ret = op_array->last_literal - 1;
459 } else {
460 ret = zend_add_literal(op_array, zv TSRMLS_CC);
461 }
462
463 if (Z_STRVAL_P(zv)[0] == '\\') {
464 lc_len = Z_STRLEN_P(zv) - 1;
465 lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv) + 1, lc_len);
466 } else {
467 lc_len = Z_STRLEN_P(zv);
468 lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), lc_len);
469 }
470 ZVAL_STRINGL(&c, lc_name, lc_len, 0);
471 lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
472 CALCULATE_LITERAL_HASH(lc_literal);
473
474 GET_CACHE_SLOT(ret);
475
476 return ret;
477 }
478
479
480 int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unqualified TSRMLS_DC)
481 {
482 int ret, tmp_literal;
483 char *name, *tmp_name;
484 const char *ns_separator;
485 int name_len, ns_len;
486 zval c;
487
488 if (op_array->last_literal > 0 &&
489 &op_array->literals[op_array->last_literal - 1].constant == zv &&
490 op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
491
492 ret = op_array->last_literal - 1;
493 } else {
494 ret = zend_add_literal(op_array, zv TSRMLS_CC);
495 }
496
497
498 if (Z_STRVAL_P(zv)[0] == '\\') {
499 name_len = Z_STRLEN_P(zv) - 1;
500 name = Z_STRVAL_P(zv) + 1;
501 } else {
502 name_len = Z_STRLEN_P(zv);
503 name = Z_STRVAL_P(zv);
504 }
505 ns_separator = zend_memrchr(name, '\\', name_len);
506 if (ns_separator) {
507 ns_len = ns_separator - name;
508 } else {
509 ns_len = 0;
510 }
511
512 if (ns_len) {
513
514 tmp_name = estrndup(name, name_len);
515 zend_str_tolower(tmp_name, ns_len);
516 ZVAL_STRINGL(&c, tmp_name, name_len, 0);
517 tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
518 CALCULATE_LITERAL_HASH(tmp_literal);
519
520
521 tmp_name = zend_str_tolower_dup(name, name_len);
522 ZVAL_STRINGL(&c, tmp_name, name_len, 0);
523 tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
524 CALCULATE_LITERAL_HASH(tmp_literal);
525 }
526
527 if (ns_len) {
528 if (!unqualified) {
529 return ret;
530 }
531 ns_len++;
532 name += ns_len;
533 name_len -= ns_len;
534 }
535
536
537 tmp_name = estrndup(name, name_len);
538 ZVAL_STRINGL(&c, tmp_name, name_len, 0);
539 tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
540 CALCULATE_LITERAL_HASH(tmp_literal);
541
542
543 tmp_name = zend_str_tolower_dup(name, name_len);
544 ZVAL_STRINGL(&c, tmp_name, name_len, 0);
545 tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
546 CALCULATE_LITERAL_HASH(tmp_literal);
547
548 return ret;
549 }
550
551
552 #define LITERAL_STRINGL(op, str, len, copy) do { \
553 zval _c; \
554 ZVAL_STRINGL(&_c, str, len, copy); \
555 op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
556 } while (0)
557
558 #define LITERAL_LONG(op, val) do { \
559 zval _c; \
560 ZVAL_LONG(&_c, val); \
561 op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
562 } while (0)
563
564 #define LITERAL_LONG_EX(op_array, op, val) do { \
565 zval _c; \
566 ZVAL_LONG(&_c, val); \
567 op.constant = zend_add_literal(op_array, &_c TSRMLS_CC); \
568 } while (0)
569
570 #define LITERAL_NULL(op) do { \
571 zval _c; \
572 INIT_ZVAL( _c); \
573 op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
574 } while (0)
575
576 static inline zend_bool zend_is_function_or_method_call(const znode *variable)
577 {
578 zend_uint type = variable->EA;
579
580 return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
581 }
582
583
584 void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC)
585 {
586 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
587
588 opline->opcode = op;
589 opline->result_type = IS_TMP_VAR;
590 opline->result.var = get_temporary_variable(CG(active_op_array));
591 SET_NODE(opline->op1, op1);
592 SET_NODE(opline->op2, op2);
593 GET_NODE(result, opline->result);
594 }
595
596
597 void zend_do_unary_op(zend_uchar op, znode *result, const znode *op1 TSRMLS_DC)
598 {
599 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
600
601 opline->opcode = op;
602 opline->result_type = IS_TMP_VAR;
603 opline->result.var = get_temporary_variable(CG(active_op_array));
604 SET_NODE(opline->op1, op1);
605 GET_NODE(result, opline->result);
606 SET_UNUSED(opline->op2);
607 }
608
609
610 #define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(opline->result)); memset(&opline->op1,0,sizeof(opline->op1)); memset(&opline->op2,0,sizeof(opline->op2)); opline->result_type=opline->op1_type=opline->op2_type=IS_UNUSED; }
611
612 static void zend_do_op_data(zend_op *data_op, const znode *value TSRMLS_DC)
613 {
614 data_op->opcode = ZEND_OP_DATA;
615 SET_NODE(data_op->op1, value);
616 SET_UNUSED(data_op->op2);
617 }
618
619
620 void zend_do_binary_assign_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC)
621 {
622 int last_op_number = get_next_op_number(CG(active_op_array));
623 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
624
625 if (last_op_number > 0) {
626 zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
627
628 switch (last_op->opcode) {
629 case ZEND_FETCH_OBJ_RW:
630 last_op->opcode = op;
631 last_op->extended_value = ZEND_ASSIGN_OBJ;
632
633 zend_do_op_data(opline, op2 TSRMLS_CC);
634 SET_UNUSED(opline->result);
635 GET_NODE(result, last_op->result);
636 return;
637 case ZEND_FETCH_DIM_RW:
638 last_op->opcode = op;
639 last_op->extended_value = ZEND_ASSIGN_DIM;
640
641 zend_do_op_data(opline, op2 TSRMLS_CC);
642 opline->op2.var = get_temporary_variable(CG(active_op_array));
643 opline->op2_type = IS_VAR;
644 SET_UNUSED(opline->result);
645 GET_NODE(result,last_op->result);
646 return;
647 default:
648 break;
649 }
650 }
651
652 opline->opcode = op;
653 SET_NODE(opline->op1, op1);
654 SET_NODE(opline->op2, op2);
655 opline->result_type = IS_VAR;
656 opline->result.var = get_temporary_variable(CG(active_op_array));
657 GET_NODE(result, opline->result);
658 }
659
660
661 void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC)
662 {
663 zend_op opline;
664 zend_op *opline_ptr;
665 zend_llist *fetch_list_ptr;
666
667 if (varname->op_type == IS_CONST) {
668 ulong hash;
669
670 if (Z_TYPE(varname->u.constant) != IS_STRING) {
671 convert_to_string(&varname->u.constant);
672 }
673
674 hash = str_hash(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant));
675 if (!zend_is_auto_global_quick(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), hash TSRMLS_CC) &&
676 !(Z_STRLEN(varname->u.constant) == (sizeof("this")-1) &&
677 !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1)) &&
678 (CG(active_op_array)->last == 0 ||
679 CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
680 result->op_type = IS_CV;
681 result->u.op.var = lookup_cv(CG(active_op_array), Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), hash TSRMLS_CC);
682 Z_STRVAL(varname->u.constant) = (char*)CG(active_op_array)->vars[result->u.op.var].name;
683 result->EA = 0;
684 return;
685 }
686 }
687
688 if (bp) {
689 opline_ptr = &opline;
690 init_op(opline_ptr TSRMLS_CC);
691 } else {
692 opline_ptr = get_next_op(CG(active_op_array) TSRMLS_CC);
693 }
694
695 opline_ptr->opcode = op;
696 opline_ptr->result_type = IS_VAR;
697 opline_ptr->result.var = get_temporary_variable(CG(active_op_array));
698 SET_NODE(opline_ptr->op1, varname);
699 GET_NODE(result, opline_ptr->result);
700 SET_UNUSED(opline_ptr->op2);
701 opline_ptr->extended_value = ZEND_FETCH_LOCAL;
702
703 if (varname->op_type == IS_CONST) {
704 CALCULATE_LITERAL_HASH(opline_ptr->op1.constant);
705 if (zend_is_auto_global_quick(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), Z_HASH_P(&CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC)) {
706 opline_ptr->extended_value = ZEND_FETCH_GLOBAL;
707 }
708 }
709
710 if (bp) {
711 zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
712 zend_llist_add_element(fetch_list_ptr, opline_ptr);
713 }
714 }
715
716
717 void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC)
718 {
719
720 fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
721 }
722
723
724 void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC)
725 {
726 znode class_node;
727 zend_llist *fetch_list_ptr;
728 zend_llist_element *le;
729 zend_op *opline_ptr;
730 zend_op opline;
731
732 if (class_name->op_type == IS_CONST &&
733 ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
734 zend_resolve_class_name(class_name TSRMLS_CC);
735 class_node = *class_name;
736 } else {
737 zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
738 }
739 zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
740 if (result->op_type == IS_CV) {
741 init_op(&opline TSRMLS_CC);
742
743 opline.opcode = ZEND_FETCH_W;
744 opline.result_type = IS_VAR;
745 opline.result.var = get_temporary_variable(CG(active_op_array));
746 opline.op1_type = IS_CONST;
747 LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[result->u.op.var].name), CG(active_op_array)->vars[result->u.op.var].name_len, 0);
748 CALCULATE_LITERAL_HASH(opline.op1.constant);
749 GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
750 if (class_node.op_type == IS_CONST) {
751 opline.op2_type = IS_CONST;
752 opline.op2.constant =
753 zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
754 } else {
755 SET_NODE(opline.op2, &class_node);
756 }
757 GET_NODE(result,opline.result);
758 opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
759 opline_ptr = &opline;
760
761 zend_llist_add_element(fetch_list_ptr, &opline);
762 } else {
763 le = fetch_list_ptr->head;
764
765 opline_ptr = (zend_op *)le->data;
766 if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1_type == IS_CV) {
767 init_op(&opline TSRMLS_CC);
768 opline.opcode = ZEND_FETCH_W;
769 opline.result_type = IS_VAR;
770 opline.result.var = get_temporary_variable(CG(active_op_array));
771 opline.op1_type = IS_CONST;
772 LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[opline_ptr->op1.var].name), CG(active_op_array)->vars[opline_ptr->op1.var].name_len, 0);
773 CALCULATE_LITERAL_HASH(opline.op1.constant);
774 GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
775 if (class_node.op_type == IS_CONST) {
776 opline.op2_type = IS_CONST;
777 opline.op2.constant =
778 zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
779 } else {
780 SET_NODE(opline.op2, &class_node);
781 }
782 opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
783 COPY_NODE(opline_ptr->op1, opline.result);
784
785 zend_llist_prepend_element(fetch_list_ptr, &opline);
786 } else {
787 if (opline_ptr->op1_type == IS_CONST) {
788 GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op1.constant);
789 }
790 if (class_node.op_type == IS_CONST) {
791 opline_ptr->op2_type = IS_CONST;
792 opline_ptr->op2.constant =
793 zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
794 } else {
795 SET_NODE(opline_ptr->op2, &class_node);
796 }
797 opline_ptr->extended_value |= ZEND_FETCH_STATIC_MEMBER;
798 }
799 }
800 }
801
802
803 void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC)
804 {
805 fetch_simple_variable(result, varname, 1 TSRMLS_CC);
806
807 fetch_array_dim(result, result, first_dim TSRMLS_CC);
808 }
809
810
811 void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS_DC)
812 {
813 zend_op opline;
814 zend_llist *fetch_list_ptr;
815
816 zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
817
818 if (zend_is_function_or_method_call(parent)) {
819 init_op(&opline TSRMLS_CC);
820 opline.opcode = ZEND_SEPARATE;
821 SET_NODE(opline.op1, parent);
822 SET_UNUSED(opline.op2);
823 opline.result_type = IS_VAR;
824 opline.result.var = opline.op1.var;
825 zend_llist_add_element(fetch_list_ptr, &opline);
826 }
827
828 init_op(&opline TSRMLS_CC);
829 opline.opcode = ZEND_FETCH_DIM_W;
830 opline.result_type = IS_VAR;
831 opline.result.var = get_temporary_variable(CG(active_op_array));
832 SET_NODE(opline.op1, parent);
833 SET_NODE(opline.op2, dim);
834 if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
835 ulong index;
836 int numeric = 0;
837
838 ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline.op2.constant)), Z_STRLEN(CONSTANT(opline.op2.constant))+1, index, numeric = 1);
839 if (numeric) {
840 zval_dtor(&CONSTANT(opline.op2.constant));
841 ZVAL_LONG(&CONSTANT(opline.op2.constant), index);
842 } else {
843 CALCULATE_LITERAL_HASH(opline.op2.constant);
844 }
845 }
846
847 GET_NODE(result, opline.result);
848
849 zend_llist_add_element(fetch_list_ptr, &opline);
850 }
851
852
853 void fetch_string_offset(znode *result, const znode *parent, const znode *offset TSRMLS_DC)
854 {
855 fetch_array_dim(result, parent, offset TSRMLS_CC);
856 }
857
858
859 void zend_do_print(znode *result, const znode *arg TSRMLS_DC)
860 {
861 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
862
863 opline->result_type = IS_TMP_VAR;
864 opline->result.var = get_temporary_variable(CG(active_op_array));
865 opline->opcode = ZEND_PRINT;
866 SET_NODE(opline->op1, arg);
867 SET_UNUSED(opline->op2);
868 GET_NODE(result, opline->result);
869 }
870
871
872 void zend_do_echo(const znode *arg TSRMLS_DC)
873 {
874 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
875
876 opline->opcode = ZEND_ECHO;
877 SET_NODE(opline->op1, arg);
878 SET_UNUSED(opline->op2);
879 }
880
881
882 void zend_do_abstract_method(const znode *function_name, znode *modifiers, const znode *body TSRMLS_DC)
883 {
884 char *method_type;
885
886 if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
887 Z_LVAL(modifiers->u.constant) |= ZEND_ACC_ABSTRACT;
888 method_type = "Interface";
889 } else {
890 method_type = "Abstract";
891 }
892
893 if (Z_LVAL(modifiers->u.constant) & ZEND_ACC_ABSTRACT) {
894 if(Z_LVAL(modifiers->u.constant) & ZEND_ACC_PRIVATE) {
895 zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private", method_type, CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
896 }
897 if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
898 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
899
900 opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
901 SET_UNUSED(opline->op1);
902 SET_UNUSED(opline->op2);
903 } else {
904
905 zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body", method_type, CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
906 }
907 } else {
908 if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
909 zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body", CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
910 }
911 }
912 }
913
914
915 static zend_bool opline_is_fetch_this(const zend_op *opline TSRMLS_DC)
916 {
917 if ((opline->opcode == ZEND_FETCH_W) && (opline->op1_type == IS_CONST)
918 && (Z_TYPE(CONSTANT(opline->op1.constant)) == IS_STRING)
919 && ((opline->extended_value & ZEND_FETCH_STATIC_MEMBER) != ZEND_FETCH_STATIC_MEMBER)
920 && (Z_HASH_P(&CONSTANT(opline->op1.constant)) == THIS_HASHVAL)
921 && (Z_STRLEN(CONSTANT(opline->op1.constant)) == (sizeof("this")-1))
922 && !memcmp(Z_STRVAL(CONSTANT(opline->op1.constant)), "this", sizeof("this") - 1)) {
923 return 1;
924 } else {
925 return 0;
926 }
927 }
928
929
930 void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC)
931 {
932 int last_op_number;
933 zend_op *opline;
934
935 if (value->op_type == IS_CV) {
936 zend_llist *fetch_list_ptr;
937
938 zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
939 if (fetch_list_ptr && fetch_list_ptr->head) {
940 opline = (zend_op *)fetch_list_ptr->head->data;
941
942 if (opline->opcode == ZEND_FETCH_DIM_W &&
943 opline->op1_type == IS_CV &&
944 opline->op1.var == value->u.op.var) {
945
946 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
947 opline->opcode = ZEND_FETCH_R;
948 opline->result_type = IS_VAR;
949 opline->result.var = get_temporary_variable(CG(active_op_array));
950 opline->op1_type = IS_CONST;
951 LITERAL_STRINGL(opline->op1,
952 CG(active_op_array)->vars[value->u.op.var].name,
953 CG(active_op_array)->vars[value->u.op.var].name_len, 1);
954 CALCULATE_LITERAL_HASH(opline->op1.constant);
955 SET_UNUSED(opline->op2);
956 opline->extended_value = ZEND_FETCH_LOCAL;
957 GET_NODE(value, opline->result);
958 }
959 }
960 }
961
962 zend_do_end_variable_parse(variable, BP_VAR_W, 0 TSRMLS_CC);
963
964 last_op_number = get_next_op_number(CG(active_op_array));
965 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
966
967 if (variable->op_type == IS_CV) {
968 if (variable->u.op.var == CG(active_op_array)->this_var) {
969 zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
970 }
971 } else if (variable->op_type == IS_VAR) {
972 int n = 0;
973
974 while (last_op_number - n > 0) {
975 zend_op *last_op;
976
977 last_op = &CG(active_op_array)->opcodes[last_op_number-n-1];
978
979 if (last_op->result_type == IS_VAR &&
980 last_op->result.var == variable->u.op.var) {
981 if (last_op->opcode == ZEND_FETCH_OBJ_W) {
982 if (n > 0) {
983 int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
984 *opline = *last_op;
985 MAKE_NOP(last_op);
986
987 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
988
989 last_op = &CG(active_op_array)->opcodes[opline_no];
990 }
991 last_op->opcode = ZEND_ASSIGN_OBJ;
992 zend_do_op_data(opline, value TSRMLS_CC);
993 SET_UNUSED(opline->result);
994 GET_NODE(result, last_op->result);
995 return;
996 } else if (last_op->opcode == ZEND_FETCH_DIM_W) {
997 if (n > 0) {
998 int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
999 *opline = *last_op;
1000 MAKE_NOP(last_op);
1001
1002
1003 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1004
1005 last_op = &CG(active_op_array)->opcodes[opline_no];
1006 }
1007 last_op->opcode = ZEND_ASSIGN_DIM;
1008 zend_do_op_data(opline, value TSRMLS_CC);
1009 opline->op2.var = get_temporary_variable(CG(active_op_array));
1010 opline->op2_type = IS_VAR;
1011 SET_UNUSED(opline->result);
1012 GET_NODE(result, last_op->result);
1013 return;
1014 } else if (opline_is_fetch_this(last_op TSRMLS_CC)) {
1015 zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
1016 } else {
1017 break;
1018 }
1019 }
1020 n++;
1021 }
1022 }
1023
1024 opline->opcode = ZEND_ASSIGN;
1025 SET_NODE(opline->op1, variable);
1026 SET_NODE(opline->op2, value);
1027 opline->result_type = IS_VAR;
1028 opline->result.var = get_temporary_variable(CG(active_op_array));
1029 GET_NODE(result, opline->result);
1030 }
1031
1032
1033 void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRMLS_DC)
1034 {
1035 zend_op *opline;
1036
1037 if (lvar->op_type == IS_CV) {
1038 if (lvar->u.op.var == CG(active_op_array)->this_var) {
1039 zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
1040 }
1041 } else if (lvar->op_type == IS_VAR) {
1042 int last_op_number = get_next_op_number(CG(active_op_array));
1043
1044 if (last_op_number > 0) {
1045 opline = &CG(active_op_array)->opcodes[last_op_number-1];
1046 if (opline_is_fetch_this(opline TSRMLS_CC)) {
1047 zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
1048 }
1049 }
1050 }
1051
1052 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1053 opline->opcode = ZEND_ASSIGN_REF;
1054 if (zend_is_function_or_method_call(rvar)) {
1055 opline->extended_value = ZEND_RETURNS_FUNCTION;
1056 } else if (rvar->EA & ZEND_PARSED_NEW) {
1057 opline->extended_value = ZEND_RETURNS_NEW;
1058 } else {
1059 opline->extended_value = 0;
1060 }
1061 if (result) {
1062 opline->result_type = IS_VAR;
1063 opline->result.var = get_temporary_variable(CG(active_op_array));
1064 GET_NODE(result, opline->result);
1065 } else {
1066 opline->result_type = IS_UNUSED | EXT_TYPE_UNUSED;
1067 }
1068 SET_NODE(opline->op1, lvar);
1069 SET_NODE(opline->op2, rvar);
1070 }
1071
1072
1073 static inline void do_begin_loop(TSRMLS_D)
1074 {
1075 zend_brk_cont_element *brk_cont_element;
1076 int parent;
1077
1078 parent = CG(context).current_brk_cont;
1079 CG(context).current_brk_cont = CG(active_op_array)->last_brk_cont;
1080 brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
1081 brk_cont_element->start = get_next_op_number(CG(active_op_array));
1082 brk_cont_element->parent = parent;
1083 }
1084
1085
1086 static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC)
1087 {
1088 if (!has_loop_var) {
1089
1090
1091
1092 CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].start = -1;
1093 }
1094 CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = cont_addr;
1095 CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
1096 CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
1097 }
1098
1099
1100 void zend_do_while_cond(const znode *expr, znode *close_bracket_token TSRMLS_DC)
1101 {
1102 int while_cond_op_number = get_next_op_number(CG(active_op_array));
1103 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1104
1105 opline->opcode = ZEND_JMPZ;
1106 SET_NODE(opline->op1, expr);
1107 close_bracket_token->u.op.opline_num = while_cond_op_number;
1108 SET_UNUSED(opline->op2);
1109
1110 do_begin_loop(TSRMLS_C);
1111 INC_BPC(CG(active_op_array));
1112 }
1113
1114
1115 void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC)
1116 {
1117 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1118
1119
1120 opline->opcode = ZEND_JMP;
1121 opline->op1.opline_num = while_token->u.op.opline_num;
1122 SET_UNUSED(opline->op1);
1123 SET_UNUSED(opline->op2);
1124
1125
1126 CG(active_op_array)->opcodes[close_bracket_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
1127
1128 do_end_loop(while_token->u.op.opline_num, 0 TSRMLS_CC);
1129
1130 DEC_BPC(CG(active_op_array));
1131 }
1132
1133
1134 void zend_do_for_cond(const znode *expr, znode *second_semicolon_token TSRMLS_DC)
1135 {
1136 int for_cond_op_number = get_next_op_number(CG(active_op_array));
1137 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1138
1139 opline->opcode = ZEND_JMPZNZ;
1140 SET_NODE(opline->op1, expr);
1141 second_semicolon_token->u.op.opline_num = for_cond_op_number;
1142 SET_UNUSED(opline->op2);
1143 }
1144
1145
1146 void zend_do_for_before_statement(const znode *cond_start, const znode *second_semicolon_token TSRMLS_DC)
1147 {
1148 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1149
1150 opline->opcode = ZEND_JMP;
1151 opline->op1.opline_num = cond_start->u.op.opline_num;
1152 CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
1153 SET_UNUSED(opline->op1);
1154 SET_UNUSED(opline->op2);
1155
1156 do_begin_loop(TSRMLS_C);
1157
1158 INC_BPC(CG(active_op_array));
1159 }
1160
1161
1162 void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC)
1163 {
1164 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1165
1166 opline->opcode = ZEND_JMP;
1167 opline->op1.opline_num = second_semicolon_token->u.op.opline_num+1;
1168 CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
1169 SET_UNUSED(opline->op1);
1170 SET_UNUSED(opline->op2);
1171
1172 do_end_loop(second_semicolon_token->u.op.opline_num+1, 0 TSRMLS_CC);
1173
1174 DEC_BPC(CG(active_op_array));
1175 }
1176
1177
1178 void zend_do_pre_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC)
1179 {
1180 int last_op_number = get_next_op_number(CG(active_op_array));
1181 zend_op *opline;
1182
1183 if (last_op_number > 0) {
1184 zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
1185
1186 if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
1187 last_op->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
1188 last_op->result_type = IS_VAR;
1189 last_op->result.var = get_temporary_variable(CG(active_op_array));
1190 GET_NODE(result, last_op->result);
1191 return;
1192 }
1193 }
1194
1195 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1196 opline->opcode = op;
1197 SET_NODE(opline->op1, op1);
1198 SET_UNUSED(opline->op2);
1199 opline->result_type = IS_VAR;
1200 opline->result.var = get_temporary_variable(CG(active_op_array));
1201 GET_NODE(result, opline->result);
1202 }
1203
1204
1205 void zend_do_post_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC)
1206 {
1207 int last_op_number = get_next_op_number(CG(active_op_array));
1208 zend_op *opline;
1209
1210 if (last_op_number > 0) {
1211 zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
1212
1213 if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
1214 last_op->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
1215 last_op->result_type = IS_TMP_VAR;
1216 last_op->result.var = get_temporary_variable(CG(active_op_array));
1217 GET_NODE(result, last_op->result);
1218 return;
1219 }
1220 }
1221
1222 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1223 opline->opcode = op;
1224 SET_NODE(opline->op1, op1);
1225 SET_UNUSED(opline->op2);
1226 opline->result_type = IS_TMP_VAR;
1227 opline->result.var = get_temporary_variable(CG(active_op_array));
1228 GET_NODE(result, opline->result);
1229 }
1230
1231
1232 void zend_do_if_cond(const znode *cond, znode *closing_bracket_token TSRMLS_DC)
1233 {
1234 int if_cond_op_number = get_next_op_number(CG(active_op_array));
1235 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1236
1237 opline->opcode = ZEND_JMPZ;
1238 SET_NODE(opline->op1, cond);
1239 closing_bracket_token->u.op.opline_num = if_cond_op_number;
1240 SET_UNUSED(opline->op2);
1241 INC_BPC(CG(active_op_array));
1242 }
1243
1244
1245 void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned char initialize TSRMLS_DC)
1246 {
1247 int if_end_op_number = get_next_op_number(CG(active_op_array));
1248 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1249 zend_llist *jmp_list_ptr;
1250
1251 opline->opcode = ZEND_JMP;
1252
1253 if (initialize) {
1254 zend_llist jmp_list;
1255
1256 zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
1257 zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
1258 }
1259 zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
1260 zend_llist_add_element(jmp_list_ptr, &if_end_op_number);
1261
1262 CG(active_op_array)->opcodes[closing_bracket_token->u.op.opline_num].op2.opline_num = if_end_op_number+1;
1263 SET_UNUSED(opline->op1);
1264 SET_UNUSED(opline->op2);
1265 }
1266
1267
1268 void zend_do_if_end(TSRMLS_D)
1269 {
1270 int next_op_number = get_next_op_number(CG(active_op_array));
1271 zend_llist *jmp_list_ptr;
1272 zend_llist_element *le;
1273
1274 zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
1275 for (le=jmp_list_ptr->head; le; le = le->next) {
1276 CG(active_op_array)->opcodes[*((int *) le->data)].op1.opline_num = next_op_number;
1277 }
1278 zend_llist_destroy(jmp_list_ptr);
1279 zend_stack_del_top(&CG(bp_stack));
1280 DEC_BPC(CG(active_op_array));
1281 }
1282
1283
1284 void zend_check_writable_variable(const znode *variable)
1285 {
1286 zend_uint type = variable->EA;
1287
1288 if (type & ZEND_PARSED_METHOD_CALL) {
1289 zend_error_noreturn(E_COMPILE_ERROR, "Can't use method return value in write context");
1290 }
1291 if (type == ZEND_PARSED_FUNCTION_CALL) {
1292 zend_error_noreturn(E_COMPILE_ERROR, "Can't use function return value in write context");
1293 }
1294 }
1295
1296
1297 void zend_do_begin_variable_parse(TSRMLS_D)
1298 {
1299 zend_llist fetch_list;
1300
1301 zend_llist_init(&fetch_list, sizeof(zend_op), NULL, 0);
1302 zend_stack_push(&CG(bp_stack), (void *) &fetch_list, sizeof(zend_llist));
1303 }
1304
1305
1306 void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC)
1307 {
1308 zend_llist *fetch_list_ptr;
1309 zend_llist_element *le;
1310 zend_op *opline = NULL;
1311 zend_op *opline_ptr;
1312 zend_uint this_var = -1;
1313
1314 zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
1315
1316 le = fetch_list_ptr->head;
1317
1318
1319
1320 if (le) {
1321 opline_ptr = (zend_op *)le->data;
1322 if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
1323
1324 if (CG(active_op_array)->last == 0 ||
1325 CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
1326
1327 this_var = opline_ptr->result.var;
1328 if (CG(active_op_array)->this_var == -1) {
1329 CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(CONSTANT(opline_ptr->op1.constant)), Z_STRLEN(CONSTANT(opline_ptr->op1.constant)), Z_HASH_P(&CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC);
1330 Z_TYPE(CONSTANT(opline_ptr->op1.constant)) = IS_NULL;
1331 } else {
1332 zend_del_literal(CG(active_op_array), opline_ptr->op1.constant);
1333 }
1334 le = le->next;
1335 if (variable->op_type == IS_VAR &&
1336 variable->u.op.var == this_var) {
1337 variable->op_type = IS_CV;
1338 variable->u.op.var = CG(active_op_array)->this_var;
1339 }
1340 } else if (CG(active_op_array)->this_var == -1) {
1341 CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1, THIS_HASHVAL TSRMLS_CC);
1342 }
1343 }
1344
1345 while (le) {
1346 opline_ptr = (zend_op *)le->data;
1347 if (opline_ptr->opcode == ZEND_SEPARATE) {
1348 if (type != BP_VAR_R && type != BP_VAR_IS) {
1349 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1350 memcpy(opline, opline_ptr, sizeof(zend_op));
1351 }
1352 le = le->next;
1353 continue;
1354 }
1355 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1356 memcpy(opline, opline_ptr, sizeof(zend_op));
1357 if (opline->op1_type == IS_VAR &&
1358 opline->op1.var == this_var) {
1359 opline->op1_type = IS_CV;
1360 opline->op1.var = CG(active_op_array)->this_var;
1361 }
1362 switch (type) {
1363 case BP_VAR_R:
1364 if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
1365 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
1366 }
1367 opline->opcode -= 3;
1368 break;
1369 case BP_VAR_W:
1370 break;
1371 case BP_VAR_RW:
1372 opline->opcode += 3;
1373 break;
1374 case BP_VAR_IS:
1375 if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
1376 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
1377 }
1378 opline->opcode += 6;
1379 break;
1380 case BP_VAR_FUNC_ARG:
1381 opline->opcode += 9;
1382 opline->extended_value |= arg_offset;
1383 break;
1384 case BP_VAR_UNSET:
1385 if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
1386 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
1387 }
1388 opline->opcode += 12;
1389 break;
1390 }
1391 le = le->next;
1392 }
1393 if (opline && type == BP_VAR_W && arg_offset) {
1394 opline->extended_value |= ZEND_FETCH_MAKE_REF;
1395 }
1396 }
1397 zend_llist_destroy(fetch_list_ptr);
1398 zend_stack_del_top(&CG(bp_stack));
1399 }
1400
1401
1402 void zend_do_add_string(znode *result, const znode *op1, znode *op2 TSRMLS_DC)
1403 {
1404 zend_op *opline;
1405
1406 if (Z_STRLEN(op2->u.constant) > 1) {
1407 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1408 opline->opcode = ZEND_ADD_STRING;
1409 } else if (Z_STRLEN(op2->u.constant) == 1) {
1410 int ch = *Z_STRVAL(op2->u.constant);
1411
1412
1413 efree(Z_STRVAL(op2->u.constant));
1414 ZVAL_LONG(&op2->u.constant, ch);
1415 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1416 opline->opcode = ZEND_ADD_CHAR;
1417 } else {
1418 efree(Z_STRVAL(op2->u.constant));
1419 return;
1420 }
1421
1422 if (op1) {
1423 SET_NODE(opline->op1, op1);
1424 SET_NODE(opline->result, op1);
1425 } else {
1426 SET_UNUSED(opline->op1);
1427 opline->result_type = IS_TMP_VAR;
1428 opline->result.var = get_temporary_variable(CG(active_op_array));
1429 }
1430 SET_NODE(opline->op2, op2);
1431 GET_NODE(result, opline->result);
1432 }
1433
1434
1435 void zend_do_add_variable(znode *result, const znode *op1, const znode *op2 TSRMLS_DC)
1436 {
1437 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1438
1439 opline->opcode = ZEND_ADD_VAR;
1440
1441 if (op1) {
1442 SET_NODE(opline->op1, op1);
1443 SET_NODE(opline->result, op1);
1444 } else {
1445 SET_UNUSED(opline->op1);
1446 opline->result_type = IS_TMP_VAR;
1447 opline->result.var = get_temporary_variable(CG(active_op_array));
1448 }
1449 SET_NODE(opline->op2, op2);
1450 GET_NODE(result, opline->result);
1451 }
1452
1453
1454 void zend_do_free(znode *op1 TSRMLS_DC)
1455 {
1456 if (op1->op_type==IS_TMP_VAR) {
1457 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1458
1459 opline->opcode = ZEND_FREE;
1460 SET_NODE(opline->op1, op1);
1461 SET_UNUSED(opline->op2);
1462 } else if (op1->op_type==IS_VAR) {
1463 zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
1464
1465 while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END || opline->opcode == ZEND_OP_DATA) {
1466 opline--;
1467 }
1468 if (opline->result_type == IS_VAR
1469 && opline->result.var == op1->u.op.var) {
1470 if (opline->opcode == ZEND_FETCH_R ||
1471 opline->opcode == ZEND_FETCH_DIM_R ||
1472 opline->opcode == ZEND_FETCH_OBJ_R ||
1473 opline->opcode == ZEND_QM_ASSIGN_VAR) {
1474
1475
1476
1477 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1478 opline->opcode = ZEND_FREE;
1479 SET_NODE(opline->op1, op1);
1480 SET_UNUSED(opline->op2);
1481 } else {
1482 opline->result_type |= EXT_TYPE_UNUSED;
1483 }
1484 } else {
1485 while (opline>CG(active_op_array)->opcodes) {
1486 if (opline->opcode == ZEND_FETCH_DIM_R
1487 && opline->op1_type == IS_VAR
1488 && opline->op1.var == op1->u.op.var) {
1489
1490
1491
1492 opline->extended_value = ZEND_FETCH_STANDARD;
1493 break;
1494 } else if (opline->result_type==IS_VAR
1495 && opline->result.var == op1->u.op.var) {
1496 if (opline->opcode == ZEND_NEW) {
1497 opline->result_type |= EXT_TYPE_UNUSED;
1498 }
1499 break;
1500 }
1501 opline--;
1502 }
1503 }
1504 } else if (op1->op_type == IS_CONST) {
1505 zval_dtor(&op1->u.constant);
1506 }
1507 }
1508
1509
1510 int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier)
1511 {
1512 if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_PPP_MASK)
1513 && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_PPP_MASK)) {
1514 zend_error_noreturn(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
1515 }
1516 if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_ABSTRACT)
1517 && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_ABSTRACT)) {
1518 zend_error_noreturn(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
1519 }
1520 if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_STATIC)
1521 && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_STATIC)) {
1522 zend_error_noreturn(E_COMPILE_ERROR, "Multiple static modifiers are not allowed");
1523 }
1524 if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_FINAL)
1525 && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_FINAL)) {
1526 zend_error_noreturn(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
1527 }
1528 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)) {
1529 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class member");
1530 }
1531 return (Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant));
1532 }
1533
1534
1535 void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC)
1536 {
1537 zend_op_array op_array;
1538 char *name = Z_STRVAL(function_name->u.constant);
1539 int name_len = Z_STRLEN(function_name->u.constant);
1540 int function_begin_line = function_token->u.op.opline_num;
1541 zend_uint fn_flags;
1542 const char *lcname;
1543 zend_bool orig_interactive;
1544 ALLOCA_FLAG(use_heap)
1545
1546 if (is_method) {
1547 if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
1548 if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
1549 zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method %s::%s() must be omitted", CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
1550 }
1551 Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT;
1552 }
1553 fn_flags = Z_LVAL(fn_flags_znode->u.constant);
1554 } else {
1555 fn_flags = 0;
1556 }
1557 if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
1558 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));
1559 }
1560
1561 function_token->u.op_array = CG(active_op_array);
1562
1563 orig_interactive = CG(interactive);
1564 CG(interactive) = 0;
1565 init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
1566 CG(interactive) = orig_interactive;
1567
1568 op_array.function_name = name;
1569 if (return_reference) {
1570 op_array.fn_flags |= ZEND_ACC_RETURN_REFERENCE;
1571 }
1572 op_array.fn_flags |= fn_flags;
1573
1574 op_array.scope = is_method?CG(active_class_entry):NULL;
1575 op_array.prototype = NULL;
1576
1577 op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
1578
1579 if (is_method) {
1580 zend_ulong hash;
1581
1582 lcname = zend_new_interned_string(zend_str_tolower_dup(name, name_len), name_len + 1, 1 TSRMLS_CC);
1583 hash = str_hash(lcname, name_len);
1584 if (zend_hash_quick_add(&CG(active_class_entry)->function_table, lcname, name_len+1, hash, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
1585 zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
1586 }
1587
1588 zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
1589 zend_init_compiler_context(TSRMLS_C);
1590
1591 if (fn_flags & ZEND_ACC_ABSTRACT) {
1592 CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
1593 }
1594
1595 if (!(fn_flags & ZEND_ACC_PPP_MASK)) {
1596 fn_flags |= ZEND_ACC_PUBLIC;
1597 }
1598
1599 if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
1600 if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1601 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1602 zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
1603 }
1604 } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
1605 if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
1606 zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
1607 }
1608 } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
1609 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1610 zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
1611 }
1612 } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
1613 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1614 zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
1615 }
1616 } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
1617 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1618 zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
1619 }
1620 } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
1621 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1622 zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
1623 }
1624 } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
1625 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1626 zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
1627 }
1628 } else if ((name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1))) {
1629 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1630 zend_error(E_WARNING, "The magic method __invoke() must have public visibility and cannot be static");
1631 }
1632
1633 } else if ((name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1))) {
1634 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1635 zend_error(E_WARNING, "The magic method __debugInfo() must have public visibility and cannot be static");
1636 }
1637 }
1638 } else {
1639 char *class_lcname;
1640
1641 class_lcname = do_alloca(CG(active_class_entry)->name_length + 1, use_heap);
1642 zend_str_tolower_copy(class_lcname, CG(active_class_entry)->name, CG(active_class_entry)->name_length);
1643
1644
1645 if ((CG(active_class_entry)->name_length == name_len) && ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT) && (!memcmp(class_lcname, lcname, name_len))) {
1646 if (!CG(active_class_entry)->constructor) {
1647 CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
1648 }
1649 } else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) {
1650 if (CG(active_class_entry)->constructor) {
1651 zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
1652 }
1653 CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
1654 } else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1))) {
1655 CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
1656 } else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1))) {
1657 CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
1658 } else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1659 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1660 zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
1661 }
1662 CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
1663 } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
1664 if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
1665 zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
1666 }
1667 CG(active_class_entry)->__callstatic = (zend_function *) CG(active_op_array);
1668 } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
1669 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1670 zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
1671 }
1672 CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
1673 } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
1674 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1675 zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
1676 }
1677 CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
1678 } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
1679 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1680 zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
1681 }
1682 CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
1683 } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
1684 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1685 zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
1686 }
1687 CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
1688 } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
1689 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1690 zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
1691 }
1692 CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array);
1693 } else if ((name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1))) {
1694 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1695 zend_error(E_WARNING, "The magic method __invoke() must have public visibility and cannot be static");
1696 }
1697 } else if ((name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1))) {
1698 if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1699 zend_error(E_WARNING, "The magic method __debugInfo() must have public visibility and cannot be static");
1700 }
1701 CG(active_class_entry)->__debugInfo = (zend_function *) CG(active_op_array);
1702 } else if (!(fn_flags & ZEND_ACC_STATIC)) {
1703 CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
1704 }
1705 free_alloca(class_lcname, use_heap);
1706 }
1707
1708 str_efree(lcname);
1709 } else {
1710 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1711 zval key;
1712 zval **ns_name;
1713
1714 if (CG(current_namespace)) {
1715
1716 znode tmp;
1717
1718 tmp.u.constant = *CG(current_namespace);
1719 zval_copy_ctor(&tmp.u.constant);
1720 zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
1721 op_array.function_name = Z_STRVAL(tmp.u.constant);
1722 name_len = Z_STRLEN(tmp.u.constant);
1723 lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
1724 } else {
1725 lcname = zend_str_tolower_dup(name, name_len);
1726 }
1727
1728
1729 if (CG(current_import_function) &&
1730 zend_hash_find(CG(current_import_function), lcname, Z_STRLEN(function_name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
1731
1732 char *tmp = zend_str_tolower_dup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
1733
1734 if (Z_STRLEN_PP(ns_name) != Z_STRLEN(function_name->u.constant) ||
1735 memcmp(tmp, lcname, Z_STRLEN(function_name->u.constant))) {
1736 zend_error(E_COMPILE_ERROR, "Cannot declare function %s because the name is already in use", Z_STRVAL(function_name->u.constant));
1737 }
1738 efree(tmp);
1739 }
1740
1741 opline->opcode = ZEND_DECLARE_FUNCTION;
1742 opline->op1_type = IS_CONST;
1743 build_runtime_defined_function_key(&key, lcname, name_len TSRMLS_CC);
1744 opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
1745 Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
1746 opline->op2_type = IS_CONST;
1747 LITERAL_STRINGL(opline->op2, lcname, name_len, 1);
1748 CALCULATE_LITERAL_HASH(opline->op2.constant);
1749 opline->extended_value = ZEND_DECLARE_FUNCTION;
1750 zend_hash_quick_update(CG(function_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
1751 zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
1752 zend_init_compiler_context(TSRMLS_C);
1753 str_efree(lcname);
1754 }
1755
1756 if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
1757 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1758
1759 opline->opcode = ZEND_EXT_NOP;
1760 opline->lineno = function_begin_line;
1761 SET_UNUSED(opline->op1);
1762 SET_UNUSED(opline->op2);
1763 }
1764
1765 {
1766
1767 zend_switch_entry switch_entry;
1768
1769 switch_entry.cond.op_type = IS_UNUSED;
1770 switch_entry.default_case = 0;
1771 switch_entry.control_var = 0;
1772
1773 zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
1774 }
1775
1776 {
1777
1778 zend_op dummy_opline;
1779
1780 dummy_opline.result_type = IS_UNUSED;
1781
1782 zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
1783 }
1784
1785 if (CG(doc_comment)) {
1786 CG(active_op_array)->doc_comment = CG(doc_comment);
1787 CG(active_op_array)->doc_comment_len = CG(doc_comment_len);
1788 CG(doc_comment) = NULL;
1789 CG(doc_comment_len) = 0;
1790 }
1791 }
1792
1793
1794 void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC)
1795 {
1796 znode function_name;
1797 zend_op_array *current_op_array = CG(active_op_array);
1798 int current_op_number = get_next_op_number(CG(active_op_array));
1799 zend_op *current_op;
1800
1801 function_name.op_type = IS_CONST;
1802 ZVAL_STRINGL(&function_name.u.constant, "{closure}", sizeof("{closure}")-1, 1);
1803
1804 zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC);
1805
1806 result->op_type = IS_TMP_VAR;
1807 result->u.op.var = get_temporary_variable(current_op_array);
1808
1809 current_op = ¤t_op_array->opcodes[current_op_number];
1810 current_op->opcode = ZEND_DECLARE_LAMBDA_FUNCTION;
1811 zend_del_literal(current_op_array, current_op->op2.constant);
1812 SET_UNUSED(current_op->op2);
1813 SET_NODE(current_op->result, result);
1814 if (is_static) {
1815 CG(active_op_array)->fn_flags |= ZEND_ACC_STATIC;
1816 }
1817 CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE;
1818 }
1819
1820
1821 void zend_do_handle_exception(TSRMLS_D)
1822 {
1823 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1824
1825 opline->opcode = ZEND_HANDLE_EXCEPTION;
1826 SET_UNUSED(opline->op1);
1827 SET_UNUSED(opline->op2);
1828 }
1829
1830
1831 void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC)
1832 {
1833 char lcname[16];
1834 int name_len;
1835
1836 zend_do_extended_info(TSRMLS_C);
1837 zend_do_return(NULL, 0 TSRMLS_CC);
1838
1839 pass_two(CG(active_op_array) TSRMLS_CC);
1840 zend_release_labels(0 TSRMLS_CC);
1841
1842 if (CG(active_class_entry)) {
1843 zend_check_magic_method_implementation(CG(active_class_entry), (zend_function*)CG(active_op_array), E_COMPILE_ERROR TSRMLS_CC);
1844 } else {
1845
1846
1847 name_len = strlen(CG(active_op_array)->function_name);
1848 zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1));
1849 lcname[sizeof(lcname)-1] = '\0';
1850 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) {
1851 zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
1852 }
1853 }
1854
1855 CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
1856 CG(active_op_array) = function_token->u.op_array;
1857
1858
1859
1860 zend_stack_del_top(&CG(switch_cond_stack));
1861 zend_stack_del_top(&CG(foreach_copy_stack));
1862 }
1863
1864
1865 void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initialization, znode *class_type, zend_uchar pass_by_reference, zend_bool is_variadic TSRMLS_DC)
1866 {
1867 zend_op *opline;
1868 zend_arg_info *cur_arg_info;
1869 znode var;
1870
1871 if (zend_is_auto_global(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant) TSRMLS_CC)) {
1872 zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s", Z_STRVAL(varname->u.constant));
1873 } else {
1874 var.op_type = IS_CV;
1875 var.u.op.var = lookup_cv(CG(active_op_array), Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), 0 TSRMLS_CC);
1876 Z_STRVAL(varname->u.constant) = (char*)CG(active_op_array)->vars[var.u.op.var].name;
1877 var.EA = 0;
1878 if (CG(active_op_array)->vars[var.u.op.var].hash_value == THIS_HASHVAL &&
1879 Z_STRLEN(varname->u.constant) == sizeof("this")-1 &&
1880 !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")-1)) {
1881 if (CG(active_op_array)->scope &&
1882 (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
1883 zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
1884 }
1885 CG(active_op_array)->this_var = var.u.op.var;
1886 }
1887 }
1888
1889 if (CG(active_op_array)->fn_flags & ZEND_ACC_VARIADIC) {
1890 zend_error_noreturn(E_COMPILE_ERROR, "Only the last parameter can be variadic");
1891 }
1892
1893 if (is_variadic) {
1894 if (op == ZEND_RECV_INIT) {
1895 zend_error_noreturn(E_COMPILE_ERROR, "Variadic parameter cannot have a default value");
1896 }
1897
1898 op = ZEND_RECV_VARIADIC;
1899 CG(active_op_array)->fn_flags |= ZEND_ACC_VARIADIC;
1900 }
1901
1902 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1903 CG(active_op_array)->num_args++;
1904 opline->opcode = op;
1905 SET_NODE(opline->result, &var);
1906 opline->op1_type = IS_UNUSED;
1907 opline->op1.num = CG(active_op_array)->num_args;
1908 if (op == ZEND_RECV_INIT) {
1909 SET_NODE(opline->op2, initialization);
1910 } else {
1911 SET_UNUSED(opline->op2);
1912 if (!is_variadic) {
1913 CG(active_op_array)->required_num_args = CG(active_op_array)->num_args;
1914 }
1915 }
1916 CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
1917 cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
1918 cur_arg_info->name = zend_new_interned_string(estrndup(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant)), Z_STRLEN(varname->u.constant) + 1, 1 TSRMLS_CC);
1919 cur_arg_info->name_len = Z_STRLEN(varname->u.constant);
1920 cur_arg_info->type_hint = 0;
1921 cur_arg_info->pass_by_reference = pass_by_reference;
1922 cur_arg_info->allow_null = 1;
1923 cur_arg_info->is_variadic = is_variadic;
1924 cur_arg_info->class_name = NULL;
1925 cur_arg_info->class_name_len = 0;
1926
1927 if (class_type->op_type != IS_UNUSED) {
1928 cur_arg_info->allow_null = 0;
1929
1930 if (class_type->u.constant.type != IS_NULL) {
1931 if (class_type->u.constant.type == IS_ARRAY) {
1932 cur_arg_info->type_hint = IS_ARRAY;
1933 if (op == ZEND_RECV_INIT) {
1934 if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
1935 cur_arg_info->allow_null = 1;
1936 } else if (IS_CONSTANT_TYPE(Z_TYPE(initialization->u.constant))) {
1937
1938 cur_arg_info->allow_null = 0;
1939 } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY) {
1940 zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
1941 }
1942 }
1943 } else if (class_type->u.constant.type == IS_CALLABLE) {
1944 cur_arg_info->type_hint = IS_CALLABLE;
1945 if (op == ZEND_RECV_INIT) {
1946 if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
1947 cur_arg_info->allow_null = 1;
1948 } else if (IS_CONSTANT_TYPE(Z_TYPE(initialization->u.constant))) {
1949
1950 cur_arg_info->allow_null = 0;
1951 } else {
1952 zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with callable type hint can only be NULL");
1953 }
1954 }
1955 } else {
1956 cur_arg_info->type_hint = IS_OBJECT;
1957 if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
1958 zend_resolve_class_name(class_type TSRMLS_CC);
1959 }
1960 Z_STRVAL(class_type->u.constant) = (char*)zend_new_interned_string(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant) + 1, 1 TSRMLS_CC);
1961 cur_arg_info->class_name = Z_STRVAL(class_type->u.constant);
1962 cur_arg_info->class_name_len = Z_STRLEN(class_type->u.constant);
1963 if (op == ZEND_RECV_INIT) {
1964 if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
1965 cur_arg_info->allow_null = 1;
1966 } else if (IS_CONSTANT_TYPE(Z_TYPE(initialization->u.constant))) {
1967
1968 cur_arg_info->allow_null = 0;
1969 } else {
1970 zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
1971 }
1972 }
1973 }
1974 }
1975 }
1976 }
1977
1978
1979 int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC)
1980 {
1981 zend_function *function;
1982 char *lcname;
1983 char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
1984
1985 zend_resolve_function_name(function_name, &check_namespace TSRMLS_CC);
1986
1987 if (check_namespace && CG(current_namespace) && !is_compound) {
1988
1989
1990
1991
1992
1993 zend_do_begin_dynamic_function_call(function_name, 1 TSRMLS_CC);
1994 return 1;
1995 }
1996
1997 lcname = zend_str_tolower_dup(Z_STRVAL(function_name->u.constant), Z_STRLEN(function_name->u.constant));
1998 if ((zend_hash_find(CG(function_table), lcname, Z_STRLEN(function_name->u.constant)+1, (void **) &function)==FAILURE) ||
1999 ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
2000 (function->type == ZEND_INTERNAL_FUNCTION))) {
2001 zend_do_begin_dynamic_function_call(function_name, 0 TSRMLS_CC);
2002 efree(lcname);
2003 return 1;
2004 }
2005 efree(Z_STRVAL(function_name->u.constant));
2006 Z_STRVAL(function_name->u.constant) = lcname;
2007
2008 zend_push_function_call_entry(function TSRMLS_CC);
2009 if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
2010 CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
2011 }
2012 zend_do_extended_fcall_begin(TSRMLS_C);
2013 return 0;
2014 }
2015
2016
2017 void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC)
2018 {
2019 zend_op *last_op;
2020 int last_op_number;
2021
2022 zend_do_end_variable_parse(left_bracket, BP_VAR_R, 0 TSRMLS_CC);
2023 zend_do_begin_variable_parse(TSRMLS_C);
2024
2025 last_op_number = get_next_op_number(CG(active_op_array))-1;
2026 last_op = &CG(active_op_array)->opcodes[last_op_number];
2027
2028 if ((last_op->op2_type == IS_CONST) && (Z_TYPE(CONSTANT(last_op->op2.constant)) == IS_STRING) && (Z_STRLEN(CONSTANT(last_op->op2.constant)) == sizeof(ZEND_CLONE_FUNC_NAME)-1)
2029 && !zend_binary_strcasecmp(Z_STRVAL(CONSTANT(last_op->op2.constant)), Z_STRLEN(CONSTANT(last_op->op2.constant)), ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1)) {
2030 zend_error_noreturn(E_COMPILE_ERROR, "Cannot call __clone() method on objects - use 'clone $obj' instead");
2031 }
2032
2033 if (last_op->opcode == ZEND_FETCH_OBJ_R) {
2034 if (last_op->op2_type == IS_CONST) {
2035 zval name;
2036 name = CONSTANT(last_op->op2.constant);
2037 if (Z_TYPE(name) != IS_STRING) {
2038 zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
2039 }
2040 Z_STRVAL(name) = str_estrndup(Z_STRVAL(name), Z_STRLEN(name));
2041 FREE_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
2042 last_op->op2.constant =
2043 zend_add_func_name_literal(CG(active_op_array), &name TSRMLS_CC);
2044 GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
2045 }
2046 last_op->opcode = ZEND_INIT_METHOD_CALL;
2047 last_op->result_type = IS_UNUSED;
2048 last_op->result.num = CG(context).nested_calls;
2049 Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
2050 } else {
2051 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2052 opline->opcode = ZEND_INIT_FCALL_BY_NAME;
2053 opline->result.num = CG(context).nested_calls;
2054 SET_UNUSED(opline->op1);
2055 if (left_bracket->op_type == IS_CONST) {
2056 opline->op2_type = IS_CONST;
2057 opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &left_bracket->u.constant TSRMLS_CC);
2058 GET_CACHE_SLOT(opline->op2.constant);
2059 } else {
2060 SET_NODE(opline->op2, left_bracket);
2061 }
2062 }
2063
2064 zend_push_function_call_entry(NULL TSRMLS_CC);
2065 if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
2066 CG(active_op_array)->nested_calls = CG(context).nested_calls;
2067 }
2068 zend_do_extended_fcall_begin(TSRMLS_C);
2069 }
2070
2071
2072 void zend_do_clone(znode *result, const znode *expr TSRMLS_DC)
2073 {
2074 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2075
2076 opline->opcode = ZEND_CLONE;
2077 SET_NODE(opline->op1, expr);
2078 SET_UNUSED(opline->op2);
2079 opline->result_type = IS_VAR;
2080 opline->result.var = get_temporary_variable(CG(active_op_array));
2081 GET_NODE(result, opline->result);
2082 }
2083
2084
2085 void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC)
2086 {
2087 zend_op *opline;
2088
2089 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2090 if (ns_call) {
2091
2092
2093 opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
2094 opline->result.num = CG(context).nested_calls;
2095 SET_UNUSED(opline->op1);
2096 opline->op2_type = IS_CONST;
2097 opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
2098 GET_CACHE_SLOT(opline->op2.constant);
2099 } else {
2100 opline->opcode = ZEND_INIT_FCALL_BY_NAME;
2101 opline->result.num = CG(context).nested_calls;
2102 SET_UNUSED(opline->op1);
2103 if (function_name->op_type == IS_CONST) {
2104 opline->op2_type = IS_CONST;
2105 opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
2106 GET_CACHE_SLOT(opline->op2.constant);
2107 } else {
2108 SET_NODE(opline->op2, function_name);
2109 }
2110 }
2111
2112 zend_push_function_call_entry(NULL TSRMLS_CC);
2113 if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
2114 CG(active_op_array)->nested_calls = CG(context).nested_calls;
2115 }
2116 zend_do_extended_fcall_begin(TSRMLS_C);
2117 }
2118
2119
2120 void zend_resolve_non_class_name(znode *element_name, zend_bool *check_namespace, zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC)
2121 {
2122 znode tmp;
2123 int len;
2124 zval **ns;
2125 char *lookup_name, *compound = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
2126
2127 if (Z_STRVAL(element_name->u.constant)[0] == '\\') {
2128
2129 memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+1, Z_STRLEN(element_name->u.constant));
2130 --Z_STRLEN(element_name->u.constant);
2131 return;
2132 }
2133
2134 if(!*check_namespace) {
2135 return;
2136 }
2137
2138 if (current_import_sub) {
2139 len = Z_STRLEN(element_name->u.constant)+1;
2140 if (case_sensitive) {
2141 lookup_name = estrndup(Z_STRVAL(element_name->u.constant), len);
2142 } else {
2143 lookup_name = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
2144 }
2145
2146 if (zend_hash_find(current_import_sub, lookup_name, len, (void**)&ns) == SUCCESS) {
2147 zval_dtor(&element_name->u.constant);
2148 element_name->u.constant = **ns;
2149 zval_copy_ctor(&element_name->u.constant);
2150 efree(lookup_name);
2151 *check_namespace = 0;
2152 return;
2153 }
2154 efree(lookup_name);
2155 }
2156
2157 if (compound && CG(current_import)) {
2158 len = compound - Z_STRVAL(element_name->u.constant);
2159
2160 lookup_name = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
2161
2162 if (zend_hash_find(CG(current_import), lookup_name, len+1, (void**)&ns) == SUCCESS) {
2163
2164 tmp.op_type = IS_CONST;
2165 tmp.u.constant = **ns;
2166 zval_copy_ctor(&tmp.u.constant);
2167 len += 1;
2168 Z_STRLEN(element_name->u.constant) -= len;
2169 memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+len, Z_STRLEN(element_name->u.constant)+1);
2170 zend_do_build_namespace_name(&tmp, &tmp, element_name TSRMLS_CC);
2171 *element_name = tmp;
2172 efree(lookup_name);
2173 *check_namespace = 0;
2174 return;
2175 }
2176 efree(lookup_name);
2177 }
2178
2179 if (CG(current_namespace)) {
2180 tmp = *element_name;
2181 Z_STRLEN(tmp.u.constant) = sizeof("\\")-1 + Z_STRLEN(element_name->u.constant) + Z_STRLEN_P(CG(current_namespace));
2182 Z_STRVAL(tmp.u.constant) = (char *) emalloc(Z_STRLEN(tmp.u.constant)+1);
2183 memcpy(Z_STRVAL(tmp.u.constant), Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
2184 memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN_P(CG(current_namespace))]), "\\", sizeof("\\")-1);
2185 memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN_P(CG(current_namespace)) + sizeof("\\")-1]), Z_STRVAL(element_name->u.constant), Z_STRLEN(element_name->u.constant)+1);
2186 str_efree(Z_STRVAL(element_name->u.constant));
2187 *element_name = tmp;
2188 }
2189 }
2190
2191
2192 void zend_resolve_function_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC)
2193 {
2194 zend_resolve_non_class_name(element_name, check_namespace, 0, CG(current_import_function) TSRMLS_CC);
2195 }
2196
2197
2198 void zend_resolve_const_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC)
2199 {
2200 zend_resolve_non_class_name(element_name, check_namespace, 1, CG(current_import_const) TSRMLS_CC);
2201 }
2202
2203
2204 void zend_do_resolve_class_name(znode *result, znode *class_name, int is_static TSRMLS_DC)
2205 {
2206 char *lcname;
2207 int lctype;
2208 znode constant_name;
2209
2210 lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
2211 lctype = zend_get_class_fetch_type(lcname, strlen(lcname));
2212 switch (lctype) {
2213 case ZEND_FETCH_CLASS_SELF:
2214 if (!CG(active_class_entry)) {
2215 zend_error_noreturn(E_COMPILE_ERROR, "Cannot access self::class when no class scope is active");
2216 }
2217 if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
2218 zval_dtor(&class_name->u.constant);
2219 constant_name.op_type = IS_CONST;
2220 ZVAL_STRINGL(&constant_name.u.constant, "__CLASS__", sizeof("__CLASS__")-1, 1);
2221 if (is_static) {
2222 *result = constant_name;
2223 result->u.constant.type = IS_CONSTANT;
2224 } else {
2225 zend_do_fetch_constant(result, NULL, &constant_name, ZEND_RT, 1 TSRMLS_CC);
2226 }
2227 break;
2228 }
2229 zval_dtor(&class_name->u.constant);
2230 class_name->op_type = IS_CONST;
2231 ZVAL_STRINGL(&class_name->u.constant, CG(active_class_entry)->name, CG(active_class_entry)->name_length, 1);
2232 *result = *class_name;
2233 break;
2234 case ZEND_FETCH_CLASS_STATIC:
2235 case ZEND_FETCH_CLASS_PARENT:
2236 if (is_static) {
2237 zend_error_noreturn(E_COMPILE_ERROR,
2238 "%s::class cannot be used for compile-time class name resolution",
2239 lctype == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
2240 );
2241 }
2242 if (!CG(active_class_entry)) {
2243 zend_error_noreturn(E_COMPILE_ERROR,
2244 "Cannot access %s::class when no class scope is active",
2245 lctype == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
2246 );
2247 }
2248 constant_name.op_type = IS_CONST;
2249 ZVAL_STRINGL(&constant_name.u.constant, "class", sizeof("class")-1, 1);
2250 zend_do_fetch_constant(result, class_name, &constant_name, ZEND_RT, 1 TSRMLS_CC);
2251 break;
2252 case ZEND_FETCH_CLASS_DEFAULT:
2253 zend_resolve_class_name(class_name TSRMLS_CC);
2254 *result = *class_name;
2255 break;
2256 }
2257
2258 efree(lcname);
2259
2260 }
2261
2262
2263 void zend_resolve_class_name(znode *class_name TSRMLS_DC)
2264 {
2265 char *compound;
2266 char *lcname;
2267 zval **ns;
2268 znode tmp;
2269 int len;
2270
2271 compound = memchr(Z_STRVAL(class_name->u.constant), '\\', Z_STRLEN(class_name->u.constant));
2272 if (compound) {
2273
2274 if (Z_STRVAL(class_name->u.constant)[0] == '\\') {
2275
2276 Z_STRLEN(class_name->u.constant) -= 1;
2277 memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+1, Z_STRLEN(class_name->u.constant)+1);
2278 Z_STRVAL(class_name->u.constant) = erealloc(
2279 Z_STRVAL(class_name->u.constant),
2280 Z_STRLEN(class_name->u.constant) + 1);
2281
2282 if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
2283 zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", Z_STRVAL(class_name->u.constant));
2284 }
2285 } else {
2286 if (CG(current_import)) {
2287 len = compound - Z_STRVAL(class_name->u.constant);
2288 lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), len);
2289
2290 if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
2291
2292 tmp.op_type = IS_CONST;
2293 tmp.u.constant = **ns;
2294 zval_copy_ctor(&tmp.u.constant);
2295 len += 1;
2296 Z_STRLEN(class_name->u.constant) -= len;
2297 memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+len, Z_STRLEN(class_name->u.constant)+1);
2298 zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
2299 *class_name = tmp;
2300 efree(lcname);
2301 return;
2302 }
2303 efree(lcname);
2304 }
2305
2306 if (CG(current_namespace)) {
2307 tmp.op_type = IS_CONST;
2308 tmp.u.constant = *CG(current_namespace);
2309 zval_copy_ctor(&tmp.u.constant);
2310 zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
2311 *class_name = tmp;
2312 }
2313 }
2314 } else if (CG(current_import) || CG(current_namespace)) {
2315
2316 lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
2317
2318 if (CG(current_import) &&
2319 zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns) == SUCCESS) {
2320
2321 zval_dtor(&class_name->u.constant);
2322 class_name->u.constant = **ns;
2323 zval_copy_ctor(&class_name->u.constant);
2324 } else if (CG(current_namespace)) {
2325
2326 tmp.op_type = IS_CONST;
2327 tmp.u.constant = *CG(current_namespace);
2328 zval_copy_ctor(&tmp.u.constant);
2329 zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
2330 *class_name = tmp;
2331 }
2332 efree(lcname);
2333 }
2334 }
2335
2336
2337 void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC)
2338 {
2339 long fetch_class_op_number;
2340 zend_op *opline;
2341
2342 fetch_class_op_number = get_next_op_number(CG(active_op_array));
2343 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2344
2345 opline->opcode = ZEND_FETCH_CLASS;
2346 SET_UNUSED(opline->op1);
2347 opline->extended_value = ZEND_FETCH_CLASS_DEFAULT;
2348 CG(catch_begin) = fetch_class_op_number;
2349 if (class_name->op_type == IS_CONST) {
2350 int fetch_type;
2351
2352 fetch_type = zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
2353 switch (fetch_type) {
2354 case ZEND_FETCH_CLASS_SELF:
2355 case ZEND_FETCH_CLASS_PARENT:
2356 case ZEND_FETCH_CLASS_STATIC:
2357 SET_UNUSED(opline->op2);
2358 opline->extended_value = fetch_type;
2359 zval_dtor(&class_name->u.constant);
2360 break;
2361 default:
2362 zend_resolve_class_name(class_name TSRMLS_CC);
2363 opline->op2_type = IS_CONST;
2364 opline->op2.constant =
2365 zend_add_class_name_literal(CG(active_op_array), &class_name->u.constant TSRMLS_CC);
2366 break;
2367 }
2368 } else {
2369 SET_NODE(opline->op2, class_name);
2370 }
2371 opline->result.var = get_temporary_variable(CG(active_op_array));
2372 opline->result_type = IS_VAR;
2373 GET_NODE(result, opline->result);
2374 result->EA = opline->extended_value;
2375 }
2376
2377
2378 void zend_do_label(znode *label TSRMLS_DC)
2379 {
2380 zend_label dest;
2381
2382 if (!CG(context).labels) {
2383 ALLOC_HASHTABLE(CG(context).labels);
2384 zend_hash_init(CG(context).labels, 4, NULL, NULL, 0);
2385 }
2386
2387 dest.brk_cont = CG(context).current_brk_cont;
2388 dest.opline_num = get_next_op_number(CG(active_op_array));
2389
2390 if (zend_hash_add(CG(context).labels, Z_STRVAL(label->u.constant), Z_STRLEN(label->u.constant) + 1, (void**)&dest, sizeof(zend_label), NULL) == FAILURE) {
2391 zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", Z_STRVAL(label->u.constant));
2392 }
2393
2394
2395 zval_dtor(&label->u.constant);
2396 }
2397
2398
2399 void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC)
2400 {
2401 zend_label *dest;
2402 long current, distance;
2403 zval *label;
2404
2405 if (pass2) {
2406 label = opline->op2.zv;
2407 } else {
2408 label = &CONSTANT_EX(op_array, opline->op2.constant);
2409 }
2410 if (CG(context).labels == NULL ||
2411 zend_hash_find(CG(context).labels, Z_STRVAL_P(label), Z_STRLEN_P(label)+1, (void**)&dest) == FAILURE) {
2412
2413 if (pass2) {
2414 CG(in_compilation) = 1;
2415 CG(active_op_array) = op_array;
2416 CG(zend_lineno) = opline->lineno;
2417 zend_error_noreturn(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL_P(label));
2418 } else {
2419
2420 INC_BPC(op_array);
2421 return;
2422 }
2423 }
2424
2425 opline->op1.opline_num = dest->opline_num;
2426 zval_dtor(label);
2427 Z_TYPE_P(label) = IS_NULL;
2428
2429
2430 current = opline->extended_value;
2431 for (distance = 0; current != dest->brk_cont; distance++) {
2432 if (current == -1) {
2433 if (pass2) {
2434 CG(in_compilation) = 1;
2435 CG(active_op_array) = op_array;
2436 CG(zend_lineno) = opline->lineno;
2437 }
2438 zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
2439 }
2440 current = op_array->brk_cont_array[current].parent;
2441 }
2442
2443 if (distance == 0) {
2444
2445 opline->opcode = ZEND_JMP;
2446 opline->extended_value = 0;
2447 SET_UNUSED(opline->op2);
2448 } else {
2449
2450 ZVAL_LONG(label, distance);
2451 }
2452
2453 if (pass2) {
2454 DEC_BPC(op_array);
2455 }
2456 }
2457
2458
2459 void zend_do_goto(const znode *label TSRMLS_DC)
2460 {
2461 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2462
2463 opline->opcode = ZEND_GOTO;
2464 opline->extended_value = CG(context).current_brk_cont;
2465 SET_UNUSED(opline->op1);
2466 SET_NODE(opline->op2, label);
2467 zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC);
2468 }
2469
2470
2471 void zend_release_labels(int temporary TSRMLS_DC)
2472 {
2473 if (CG(context).labels) {
2474 zend_hash_destroy(CG(context).labels);
2475 FREE_HASHTABLE(CG(context).labels);
2476 CG(context).labels = NULL;
2477 }
2478 if (!temporary && !zend_stack_is_empty(&CG(context_stack))) {
2479 zend_compiler_context *ctx;
2480
2481 zend_stack_top(&CG(context_stack), (void**)&ctx);
2482 CG(context) = *ctx;
2483 zend_stack_del_top(&CG(context_stack));
2484 }
2485 }
2486
2487
2488 void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_class_member TSRMLS_DC)
2489 {
2490 zend_uint length;
2491
2492 if (!result) {
2493 result = prefix;
2494 } else {
2495 *result = *prefix;
2496 }
2497
2498 if (is_class_member) {
2499 length = sizeof("::")-1 + Z_STRLEN(result->u.constant) + Z_STRLEN(name->u.constant);
2500 Z_STRVAL(result->u.constant) = str_erealloc(Z_STRVAL(result->u.constant), length+1);
2501 memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)], "::", sizeof("::")-1);
2502 memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant) + sizeof("::")-1], Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1);
2503 str_efree(Z_STRVAL(name->u.constant));
2504 Z_STRLEN(result->u.constant) = length;
2505 } else {
2506 length = sizeof("\\")-1 + Z_STRLEN(result->u.constant) + Z_STRLEN(name->u.constant);
2507 Z_STRVAL(result->u.constant) = str_erealloc(Z_STRVAL(result->u.constant), length+1);
2508 memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)], "\\", sizeof("\\")-1);
2509 memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant) + sizeof("\\")-1], Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1);
2510 str_efree(Z_STRVAL(name->u.constant));
2511 Z_STRLEN(result->u.constant) = length;
2512 }
2513 }
2514
2515
2516 int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC)
2517 {
2518 znode class_node;
2519 zend_op *opline;
2520
2521 if (method_name->op_type == IS_CONST) {
2522 char *lcname;
2523 if (Z_TYPE(method_name->u.constant) != IS_STRING) {
2524 zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
2525 }
2526 lcname = zend_str_tolower_dup(Z_STRVAL(method_name->u.constant), Z_STRLEN(method_name->u.constant));
2527 if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(method_name->u.constant) &&
2528 memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
2529 zval_dtor(&method_name->u.constant);
2530 method_name->op_type = IS_UNUSED;
2531 }
2532 efree(lcname);
2533 }
2534
2535 if (class_name->op_type == IS_CONST &&
2536 ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
2537 zend_resolve_class_name(class_name TSRMLS_CC);
2538 class_node = *class_name;
2539 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2540 } else {
2541 zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
2542 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2543 opline->extended_value = class_node.EA ;
2544 }
2545 opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
2546 opline->result.num = CG(context).nested_calls;
2547 if (class_node.op_type == IS_CONST) {
2548 opline->op1_type = IS_CONST;
2549 opline->op1.constant =
2550 zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
2551 } else {
2552 SET_NODE(opline->op1, &class_node);
2553 }
2554 if (method_name->op_type == IS_CONST) {
2555 opline->op2_type = IS_CONST;
2556 opline->op2.constant =
2557 zend_add_func_name_literal(CG(active_op_array), &method_name->u.constant TSRMLS_CC);
2558 if (opline->op1_type == IS_CONST) {
2559 GET_CACHE_SLOT(opline->op2.constant);
2560 } else {
2561 GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
2562 }
2563 } else {
2564 SET_NODE(opline->op2, method_name);
2565 }
2566
2567 zend_push_function_call_entry(NULL TSRMLS_CC);
2568 if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
2569 CG(active_op_array)->nested_calls = CG(context).nested_calls;
2570 }
2571 zend_do_extended_fcall_begin(TSRMLS_C);
2572 return 1;
2573 }
2574
2575
2576 void zend_do_end_function_call(znode *function_name, znode *result, int is_method, int is_dynamic_fcall TSRMLS_DC)
2577 {
2578 zend_op *opline;
2579 zend_function_call_entry *fcall;
2580 zend_stack_top(&CG(function_call_stack), (void **) &fcall);
2581
2582 if (is_method && function_name && function_name->op_type == IS_UNUSED) {
2583
2584 if (fcall->arg_num != 0) {
2585 zend_error(E_WARNING, "Clone method does not require arguments");
2586 }
2587 opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
2588 } else {
2589 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2590 if (fcall->fbc) {
2591 opline->opcode = ZEND_DO_FCALL;
2592 SET_NODE(opline->op1, function_name);
2593 SET_UNUSED(opline->op2);
2594 opline->op2.num = CG(context).nested_calls;
2595 CALCULATE_LITERAL_HASH(opline->op1.constant);
2596 GET_CACHE_SLOT(opline->op1.constant);
2597 } else {
2598 opline->opcode = ZEND_DO_FCALL_BY_NAME;
2599 SET_UNUSED(opline->op1);
2600 SET_UNUSED(opline->op2);
2601 opline->op2.num = --CG(context).nested_calls;
2602
2603
2604
2605
2606 if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
2607 zval_dtor(&function_name->u.constant);
2608 }
2609 }
2610 }
2611
2612 opline->result.var = get_temporary_variable(CG(active_op_array));
2613 opline->result_type = IS_VAR;
2614 GET_NODE(result, opline->result);
2615 opline->extended_value = fcall->arg_num;
2616
2617 if (CG(context).used_stack + 1 > CG(active_op_array)->used_stack) {
2618 CG(active_op_array)->used_stack = CG(context).used_stack + 1;
2619 }
2620 CG(context).used_stack -= fcall->arg_num;
2621 zend_stack_del_top(&CG(function_call_stack));
2622 }
2623
2624
2625 void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC)
2626 {
2627 zend_op *opline;
2628 int original_op = op;
2629 zend_function_call_entry *fcall;
2630 zend_function *function_ptr;
2631 int send_by_reference = 0;
2632 int send_function = 0;
2633
2634 zend_stack_top(&CG(function_call_stack), (void **) &fcall);
2635 function_ptr = fcall->fbc;
2636 fcall->arg_num++;
2637
2638 if (fcall->uses_argument_unpacking) {
2639 zend_error_noreturn(E_COMPILE_ERROR,
2640 "Cannot use positional argument after argument unpacking");
2641 }
2642
2643 if (original_op == ZEND_SEND_REF) {
2644 if (function_ptr &&
2645 function_ptr->common.function_name &&
2646 function_ptr->common.type == ZEND_USER_FUNCTION &&
2647 !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
2648 zend_error_noreturn(E_COMPILE_ERROR,
2649 "Call-time pass-by-reference has been removed; "
2650 "If you would like to pass argument by reference, modify the declaration of %s().",
2651 function_ptr->common.function_name);
2652 } else {
2653 zend_error_noreturn(E_COMPILE_ERROR, "Call-time pass-by-reference has been removed");
2654 }
2655 return;
2656 }
2657
2658 if (function_ptr) {
2659 if (ARG_MAY_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
2660 if (op == ZEND_SEND_VAR && param->op_type & (IS_VAR|IS_CV)) {
2661 send_by_reference = ZEND_ARG_SEND_BY_REF;
2662 if (zend_is_function_or_method_call(param)) {
2663
2664 op = ZEND_SEND_VAR_NO_REF;
2665 send_function = ZEND_ARG_SEND_FUNCTION | ZEND_ARG_SEND_SILENT;
2666 }
2667 } else {
2668 op = ZEND_SEND_VAL;
2669 }
2670 } else if (ARG_SHOULD_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
2671 send_by_reference = ZEND_ARG_SEND_BY_REF;
2672 }
2673 }
2674
2675 if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
2676
2677 op = ZEND_SEND_VAR_NO_REF;
2678 send_function = ZEND_ARG_SEND_FUNCTION;
2679 } else if (op == ZEND_SEND_VAL && (param->op_type & (IS_VAR|IS_CV))) {
2680 op = ZEND_SEND_VAR_NO_REF;
2681 }
2682
2683 if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference==ZEND_ARG_SEND_BY_REF) {
2684
2685 switch (param->op_type) {
2686 case IS_VAR:
2687 case IS_CV:
2688 op = ZEND_SEND_REF;
2689 break;
2690 default:
2691 zend_error_noreturn(E_COMPILE_ERROR, "Only variables can be passed by reference");
2692 break;
2693 }
2694 }
2695
2696 if (original_op == ZEND_SEND_VAR) {
2697 switch (op) {
2698 case ZEND_SEND_VAR_NO_REF:
2699 zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
2700 break;
2701 case ZEND_SEND_VAR:
2702 if (function_ptr) {
2703 zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
2704 } else {
2705 zend_do_end_variable_parse(param, BP_VAR_FUNC_ARG, fcall->arg_num TSRMLS_CC);
2706 }
2707 break;
2708 case ZEND_SEND_REF:
2709 zend_do_end_variable_parse(param, BP_VAR_W, 0 TSRMLS_CC);
2710 break;
2711 }
2712 }
2713
2714 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2715
2716 if (op == ZEND_SEND_VAR_NO_REF) {
2717 if (function_ptr) {
2718 opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference | send_function;
2719 } else {
2720 opline->extended_value = send_function;
2721 }
2722 } else {
2723 if (function_ptr) {
2724 opline->extended_value = ZEND_DO_FCALL;
2725 } else {
2726 opline->extended_value = ZEND_DO_FCALL_BY_NAME;
2727 }
2728 }
2729 opline->opcode = op;
2730 SET_NODE(opline->op1, param);
2731 opline->op2.opline_num = fcall->arg_num;
2732 SET_UNUSED(opline->op2);
2733
2734 if (++CG(context).used_stack > CG(active_op_array)->used_stack) {
2735 CG(active_op_array)->used_stack = CG(context).used_stack;
2736 }
2737 }
2738
2739
2740 void zend_do_unpack_params(znode *params TSRMLS_DC)
2741 {
2742 zend_op *opline;
2743 zend_function_call_entry *fcall;
2744
2745 zend_stack_top(&CG(function_call_stack), (void **) &fcall);
2746 fcall->uses_argument_unpacking = 1;
2747
2748 if (fcall->fbc) {
2749
2750
2751
2752 zval func_name;
2753 ZVAL_STRING(&func_name, fcall->fbc->common.function_name, 1);
2754
2755 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2756 opline->opcode = ZEND_INIT_FCALL_BY_NAME;
2757 opline->result.num = CG(context).nested_calls;
2758 SET_UNUSED(opline->op1);
2759 opline->op2_type = IS_CONST;
2760 opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &func_name TSRMLS_CC);
2761 GET_CACHE_SLOT(opline->op2.constant);
2762
2763 ++CG(context).nested_calls;
2764 fcall->fbc = NULL;
2765 }
2766
2767 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2768 opline->opcode = ZEND_SEND_UNPACK;
2769 SET_NODE(opline->op1, params);
2770 SET_UNUSED(opline->op2);
2771 opline->op2.num = fcall->arg_num;
2772 }
2773
2774
2775 static int generate_free_switch_expr(const zend_switch_entry *switch_entry TSRMLS_DC)
2776 {
2777 zend_op *opline;
2778
2779 if (switch_entry->cond.op_type != IS_VAR && switch_entry->cond.op_type != IS_TMP_VAR) {
2780 return (switch_entry->cond.op_type == IS_UNUSED);
2781 }
2782
2783 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2784
2785 opline->opcode = (switch_entry->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2786 SET_NODE(opline->op1, &switch_entry->cond);
2787 SET_UNUSED(opline->op2);
2788
2789 return 0;
2790 }
2791
2792
2793 static int generate_free_foreach_copy(const zend_op *foreach_copy TSRMLS_DC)
2794 {
2795 zend_op *opline;
2796
2797
2798 if (foreach_copy->result_type == IS_UNUSED) {
2799 return 1;
2800 }
2801
2802 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2803
2804 opline->opcode = (foreach_copy->result_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2805 COPY_NODE(opline->op1, foreach_copy->result);
2806 SET_UNUSED(opline->op2);
2807
2808 return 0;
2809 }
2810
2811
2812 void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC)
2813 {
2814 zend_op *opline;
2815 int start_op_number, end_op_number;
2816 zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
2817
2818
2819
2820 if (do_end_vparse) {
2821 if (returns_reference && !zend_is_function_or_method_call(expr)) {
2822 zend_do_end_variable_parse(expr, BP_VAR_W, 0 TSRMLS_CC);
2823 } else {
2824 zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
2825 }
2826 }
2827
2828 start_op_number = get_next_op_number(CG(active_op_array));
2829
2830 #ifdef ZTS
2831 zend_stack_apply_with_argument(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_switch_expr TSRMLS_CC);
2832 zend_stack_apply_with_argument(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_foreach_copy TSRMLS_CC);
2833 #else
2834 zend_stack_apply(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_switch_expr);
2835 zend_stack_apply(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_foreach_copy);
2836 #endif
2837
2838 end_op_number = get_next_op_number(CG(active_op_array));
2839 while (start_op_number < end_op_number) {
2840 CG(active_op_array)->opcodes[start_op_number].extended_value |= EXT_TYPE_FREE_ON_RETURN;
2841 start_op_number++;
2842 }
2843
2844 if (CG(context).in_finally) {
2845 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2846 opline->opcode = ZEND_DISCARD_EXCEPTION;
2847 SET_UNUSED(opline->op1);
2848 SET_UNUSED(opline->op2);
2849 }
2850
2851 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2852
2853 opline->opcode = returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN;
2854
2855 if (expr) {
2856 SET_NODE(opline->op1, expr);
2857
2858 if (!do_end_vparse) {
2859 opline->extended_value = ZEND_RETURNS_VALUE;
2860 } else if (zend_is_function_or_method_call(expr)) {
2861 opline->extended_value = ZEND_RETURNS_FUNCTION;
2862 }
2863 } else {
2864 opline->op1_type = IS_CONST;
2865 LITERAL_NULL(opline->op1);
2866 }
2867
2868 SET_UNUSED(opline->op2);
2869 }
2870
2871
2872 void zend_do_yield(znode *result, znode *value, const znode *key, zend_bool is_variable TSRMLS_DC)
2873 {
2874 zend_op *opline;
2875
2876 if (!CG(active_op_array)->function_name) {
2877 zend_error_noreturn(E_COMPILE_ERROR, "The \"yield\" expression can only be used inside a function");
2878 }
2879
2880 CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR;
2881
2882 if (is_variable) {
2883 if ((CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) && !zend_is_function_or_method_call(value)) {
2884 zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
2885 } else {
2886 zend_do_end_variable_parse(value, BP_VAR_R, 0 TSRMLS_CC);
2887 }
2888 }
2889
2890 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2891
2892 opline->opcode = ZEND_YIELD;
2893
2894 if (value) {
2895 SET_NODE(opline->op1, value);
2896
2897 if (is_variable && zend_is_function_or_method_call(value)) {
2898 opline->extended_value = ZEND_RETURNS_FUNCTION;
2899 }
2900 } else {
2901 SET_UNUSED(opline->op1);
2902 }
2903
2904 if (key) {
2905 SET_NODE(opline->op2, key);
2906 } else {
2907 SET_UNUSED(opline->op2);
2908 }
2909
2910 opline->result_type = IS_VAR;
2911 opline->result.var = get_temporary_variable(CG(active_op_array));
2912 GET_NODE(result, opline->result);
2913 }
2914
2915
2916 static int zend_add_try_element(zend_uint try_op TSRMLS_DC)
2917 {
2918 int try_catch_offset = CG(active_op_array)->last_try_catch++;
2919
2920 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);
2921 CG(active_op_array)->try_catch_array[try_catch_offset].try_op = try_op;
2922 CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = 0;
2923 CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = 0;
2924 CG(active_op_array)->try_catch_array[try_catch_offset].finally_end = 0;
2925 return try_catch_offset;
2926 }
2927
2928
2929 static void zend_add_catch_element(int offset, zend_uint catch_op TSRMLS_DC)
2930 {
2931 CG(active_op_array)->try_catch_array[offset].catch_op = catch_op;
2932 }
2933
2934
2935 void zend_do_first_catch(znode *open_parentheses TSRMLS_DC)
2936 {
2937 open_parentheses->u.op.opline_num = get_next_op_number(CG(active_op_array));
2938 }
2939
2940
2941 void zend_initialize_try_catch_element(znode *catch_token TSRMLS_DC)
2942 {
2943 int jmp_op_number = get_next_op_number(CG(active_op_array));
2944 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2945 zend_llist jmp_list;
2946 zend_llist *jmp_list_ptr;
2947
2948 opline->opcode = ZEND_JMP;
2949 SET_UNUSED(opline->op1);
2950 SET_UNUSED(opline->op2);
2951
2952
2953 zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
2954 zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
2955 zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
2956 zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
2957
2958 catch_token->EA = get_next_op_number(CG(active_op_array));
2959 }
2960
2961
2962 void zend_do_mark_last_catch(const znode *first_catch, const znode *last_additional_catch TSRMLS_DC)
2963 {
2964 CG(active_op_array)->last--;
2965 zend_do_if_end(TSRMLS_C);
2966 if (last_additional_catch->u.op.opline_num == -1) {
2967 CG(active_op_array)->opcodes[first_catch->u.op.opline_num].result.num = 1;
2968 CG(active_op_array)->opcodes[first_catch->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
2969 } else {
2970 CG(active_op_array)->opcodes[last_additional_catch->u.op.opline_num].result.num = 1;
2971 CG(active_op_array)->opcodes[last_additional_catch->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
2972 }
2973 DEC_BPC(CG(active_op_array));
2974 }
2975
2976
2977 void zend_do_try(znode *try_token TSRMLS_DC)
2978 {
2979 try_token->u.op.opline_num = zend_add_try_element(get_next_op_number(CG(active_op_array)) TSRMLS_CC);
2980 INC_BPC(CG(active_op_array));
2981 }
2982
2983
2984 void zend_do_finally(znode *finally_token TSRMLS_DC)
2985 {
2986 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2987
2988 finally_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
2989
2990 opline->opcode = ZEND_FAST_CALL;
2991 SET_UNUSED(opline->op1);
2992 opline->op1.opline_num = finally_token->u.op.opline_num + 1;
2993 SET_UNUSED(opline->op2);
2994
2995
2996
2997 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2998 opline->opcode = ZEND_JMP;
2999 SET_UNUSED(opline->op1);
3000 SET_UNUSED(opline->op2);
3001
3002 CG(context).in_finally++;
3003 }
3004
3005
3006 void zend_do_begin_catch(znode *catch_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC)
3007 {
3008 long catch_op_number;
3009 zend_op *opline;
3010 znode catch_class;
3011
3012 if (class_name->op_type == IS_CONST &&
3013 ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
3014 zend_resolve_class_name(class_name TSRMLS_CC);
3015 catch_class = *class_name;
3016 } else {
3017 zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
3018 }
3019
3020 catch_op_number = get_next_op_number(CG(active_op_array));
3021 if (first_catch) {
3022 first_catch->u.op.opline_num = catch_op_number;
3023 }
3024
3025 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3026 opline->opcode = ZEND_CATCH;
3027 opline->op1_type = IS_CONST;
3028 opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), &catch_class.u.constant TSRMLS_CC);
3029 opline->op2_type = IS_CV;
3030 opline->op2.var = lookup_cv(CG(active_op_array), Z_STRVAL(catch_var->u.constant), Z_STRLEN(catch_var->u.constant), 0 TSRMLS_CC);
3031 Z_STRVAL(catch_var->u.constant) = (char*)CG(active_op_array)->vars[opline->op2.var].name;
3032 opline->result.num = 0;
3033
3034 catch_token->u.op.opline_num = catch_op_number;
3035 }
3036
3037
3038 void zend_do_end_catch(znode *catch_token TSRMLS_DC)
3039 {
3040 int jmp_op_number = get_next_op_number(CG(active_op_array));
3041 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3042 zend_llist *jmp_list_ptr;
3043
3044 opline->opcode = ZEND_JMP;
3045 SET_UNUSED(opline->op1);
3046 SET_UNUSED(opline->op2);
3047
3048
3049 zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
3050 zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
3051
3052 CG(active_op_array)->opcodes[catch_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
3053 }
3054
3055
3056 void zend_do_bind_catch(znode *try_token, znode *catch_token TSRMLS_DC) {
3057 if (catch_token->op_type != IS_UNUSED) {
3058 zend_add_catch_element(try_token->u.op.opline_num, catch_token->EA TSRMLS_CC);
3059 }
3060 }
3061
3062
3063 void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_token TSRMLS_DC)
3064 {
3065 if (catch_token->op_type == IS_UNUSED && finally_token->op_type == IS_UNUSED) {
3066 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
3067 }
3068 if (finally_token->op_type != IS_UNUSED) {
3069 zend_op *opline;
3070
3071 CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_op = finally_token->u.op.opline_num + 1;
3072 CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_end = get_next_op_number(CG(active_op_array));
3073 CG(active_op_array)->has_finally_block = 1;
3074
3075 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3076 opline->opcode = ZEND_FAST_RET;
3077 SET_UNUSED(opline->op1);
3078 SET_UNUSED(opline->op2);
3079
3080 CG(active_op_array)->opcodes[finally_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
3081
3082 CG(context).in_finally--;
3083 }
3084 }
3085
3086
3087 void zend_do_throw(const znode *expr TSRMLS_DC)
3088 {
3089 zend_op *opline;
3090
3091 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3092 opline->opcode = ZEND_THROW;
3093 SET_NODE(opline->op1, expr);
3094 SET_UNUSED(opline->op2);
3095 }
3096
3097
3098 ZEND_API void function_add_ref(zend_function *function)
3099 {
3100 if (function->type == ZEND_USER_FUNCTION) {
3101 zend_op_array *op_array = &function->op_array;
3102
3103 (*op_array->refcount)++;
3104 if (op_array->static_variables) {
3105 HashTable *static_variables = op_array->static_variables;
3106 zval *tmp_zval;
3107
3108 ALLOC_HASHTABLE(op_array->static_variables);
3109 zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
3110 zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
3111 }
3112 op_array->run_time_cache = NULL;
3113 }
3114 }
3115
3116
3117 static void do_inherit_parent_constructor(zend_class_entry *ce)
3118 {
3119 zend_function *function, *new_function;
3120
3121 if (!ce->parent) {
3122 return;
3123 }
3124
3125
3126 ce->create_object = ce->parent->create_object;
3127
3128
3129 if (!ce->get_iterator) {
3130 ce->get_iterator = ce->parent->get_iterator;
3131 }
3132 if (!ce->iterator_funcs.funcs) {
3133 ce->iterator_funcs.funcs = ce->parent->iterator_funcs.funcs;
3134 }
3135 if (!ce->__get) {
3136 ce->__get = ce->parent->__get;
3137 }
3138 if (!ce->__set) {
3139 ce->__set = ce->parent->__set;
3140 }
3141 if (!ce->__unset) {
3142 ce->__unset = ce->parent->__unset;
3143 }
3144 if (!ce->__isset) {
3145 ce->__isset = ce->parent->__isset;
3146 }
3147 if (!ce->__call) {
3148 ce->__call = ce->parent->__call;
3149 }
3150 if (!ce->__callstatic) {
3151 ce->__callstatic = ce->parent->__callstatic;
3152 }
3153 if (!ce->__tostring) {
3154 ce->__tostring = ce->parent->__tostring;
3155 }
3156 if (!ce->clone) {
3157 ce->clone = ce->parent->clone;
3158 }
3159 if(!ce->serialize) {
3160 ce->serialize = ce->parent->serialize;
3161 }
3162 if(!ce->unserialize) {
3163 ce->unserialize = ce->parent->unserialize;
3164 }
3165 if (!ce->destructor) {
3166 ce->destructor = ce->parent->destructor;
3167 }
3168 if (!ce->__debugInfo) {
3169 ce->__debugInfo = ce->parent->__debugInfo;
3170 }
3171 if (ce->constructor) {
3172 if (ce->parent->constructor && ce->parent->constructor->common.fn_flags & ZEND_ACC_FINAL) {
3173 zend_error(E_ERROR, "Cannot override final %s::%s() with %s::%s()",
3174 ce->parent->name, ce->parent->constructor->common.function_name,
3175 ce->name, ce->constructor->common.function_name
3176 );
3177 }
3178 return;
3179 }
3180
3181 if (zend_hash_find(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), (void **)&function)==SUCCESS) {
3182
3183 zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), (void**)&new_function);
3184 function_add_ref(new_function);
3185 } else {
3186
3187 char *lc_class_name;
3188 char *lc_parent_class_name;
3189
3190 lc_class_name = zend_str_tolower_dup(ce->name, ce->name_length);
3191 if (!zend_hash_exists(&ce->function_table, lc_class_name, ce->name_length+1)) {
3192 lc_parent_class_name = zend_str_tolower_dup(ce->parent->name, ce->parent->name_length);
3193 if (!zend_hash_exists(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1) &&
3194 zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
3195 if (function->common.fn_flags & ZEND_ACC_CTOR) {
3196
3197 zend_hash_update(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1, function, sizeof(zend_function), (void**)&new_function);
3198 function_add_ref(new_function);
3199 }
3200 }
3201 efree(lc_parent_class_name);
3202 }
3203 efree(lc_class_name);
3204 }
3205 ce->constructor = ce->parent->constructor;
3206 }
3207
3208
3209 char *zend_visibility_string(zend_uint fn_flags)
3210 {
3211 if (fn_flags & ZEND_ACC_PRIVATE) {
3212 return "private";
3213 }
3214 if (fn_flags & ZEND_ACC_PROTECTED) {
3215 return "protected";
3216 }
3217 if (fn_flags & ZEND_ACC_PUBLIC) {
3218 return "public";
3219 }
3220 return "";
3221 }
3222
3223
3224 static void do_inherit_method(zend_function *function)
3225 {
3226
3227
3228
3229
3230 function_add_ref(function);
3231 }
3232
3233
3234 static zend_bool zend_do_perform_implementation_check(const zend_function *fe, const zend_function *proto TSRMLS_DC)
3235 {
3236 zend_uint i, num_args;
3237
3238
3239
3240
3241
3242 if (!proto || (!proto->common.arg_info && proto->common.type != ZEND_USER_FUNCTION)) {
3243 return 1;
3244 }
3245
3246
3247
3248
3249 if ((fe->common.fn_flags & ZEND_ACC_CTOR)
3250 && ((proto->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
3251 && (proto->common.fn_flags & ZEND_ACC_ABSTRACT) == 0)) {
3252 return 1;
3253 }
3254
3255
3256 if ((fe->common.fn_flags & ZEND_ACC_PRIVATE) && (proto->common.fn_flags & ZEND_ACC_PRIVATE)) {
3257 return 1;
3258 }
3259
3260
3261 if (proto->common.required_num_args < fe->common.required_num_args
3262 || proto->common.num_args > fe->common.num_args) {
3263 return 0;
3264 }
3265
3266
3267 if ((proto->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
3268 && !(fe->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
3269 return 0;
3270 }
3271
3272 if ((proto->common.fn_flags & ZEND_ACC_VARIADIC)
3273 && !(fe->common.fn_flags & ZEND_ACC_VARIADIC)) {
3274 return 0;
3275 }
3276
3277
3278
3279
3280
3281 num_args = proto->common.num_args;
3282 if ((proto->common.fn_flags & ZEND_ACC_VARIADIC)
3283 && fe->common.num_args > proto->common.num_args) {
3284 num_args = fe->common.num_args;
3285 }
3286
3287 for (i = 0; i < num_args; i++) {
3288 zend_arg_info *fe_arg_info = &fe->common.arg_info[i];
3289
3290 zend_arg_info *proto_arg_info;
3291 if (i < proto->common.num_args) {
3292 proto_arg_info = &proto->common.arg_info[i];
3293 } else {
3294 proto_arg_info = &proto->common.arg_info[proto->common.num_args-1];
3295 }
3296
3297 if (ZEND_LOG_XOR(fe_arg_info->class_name, proto_arg_info->class_name)) {
3298
3299 return 0;
3300 }
3301
3302 if (fe_arg_info->class_name) {
3303 const char *fe_class_name, *proto_class_name;
3304 zend_uint fe_class_name_len, proto_class_name_len;
3305
3306 if (!strcasecmp(fe_arg_info->class_name, "parent") && proto->common.scope) {
3307 fe_class_name = proto->common.scope->name;
3308 fe_class_name_len = proto->common.scope->name_length;
3309 } else if (!strcasecmp(fe_arg_info->class_name, "self") && fe->common.scope) {
3310 fe_class_name = fe->common.scope->name;
3311 fe_class_name_len = fe->common.scope->name_length;
3312 } else {
3313 fe_class_name = fe_arg_info->class_name;
3314 fe_class_name_len = fe_arg_info->class_name_len;
3315 }
3316
3317 if (!strcasecmp(proto_arg_info->class_name, "parent") && proto->common.scope && proto->common.scope->parent) {
3318 proto_class_name = proto->common.scope->parent->name;
3319 proto_class_name_len = proto->common.scope->parent->name_length;
3320 } else if (!strcasecmp(proto_arg_info->class_name, "self") && proto->common.scope) {
3321 proto_class_name = proto->common.scope->name;
3322 proto_class_name_len = proto->common.scope->name_length;
3323 } else {
3324 proto_class_name = proto_arg_info->class_name;
3325 proto_class_name_len = proto_arg_info->class_name_len;
3326 }
3327
3328 if (strcasecmp(fe_class_name, proto_class_name)!=0) {
3329 const char *colon;
3330
3331 if (fe->common.type != ZEND_USER_FUNCTION) {
3332 return 0;
3333 } else if (strchr(proto_class_name, '\\') != NULL ||
3334 (colon = zend_memrchr(fe_class_name, '\\', fe_class_name_len)) == NULL ||
3335 strcasecmp(colon+1, proto_class_name) != 0) {
3336 zend_class_entry **fe_ce, **proto_ce;
3337 int found, found2;
3338
3339 found = zend_lookup_class(fe_class_name, fe_class_name_len, &fe_ce TSRMLS_CC);
3340 found2 = zend_lookup_class(proto_class_name, proto_class_name_len, &proto_ce TSRMLS_CC);
3341
3342
3343 if (found != SUCCESS || found2 != SUCCESS ||
3344 (*fe_ce)->type == ZEND_INTERNAL_CLASS ||
3345 (*proto_ce)->type == ZEND_INTERNAL_CLASS ||
3346 *fe_ce != *proto_ce) {
3347 return 0;
3348 }
3349 }
3350 }
3351 }
3352 if (fe_arg_info->type_hint != proto_arg_info->type_hint) {
3353
3354 return 0;
3355 }
3356
3357
3358 if (fe_arg_info->pass_by_reference != proto_arg_info->pass_by_reference) {
3359 return 0;
3360 }
3361 }
3362
3363 return 1;
3364 }
3365
3366
3367 #define REALLOC_BUF_IF_EXCEED(buf, offset, length, size) \
3368 if (UNEXPECTED(offset - buf + size >= length)) { \
3369 length += size + 1; \
3370 buf = erealloc(buf, length); \
3371 }
3372
3373 static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC)
3374 {
3375 char *offset, *buf;
3376 zend_uint length = 1024;
3377
3378 offset = buf = (char *)emalloc(length * sizeof(char));
3379 if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
3380 *(offset++) = '&';
3381 *(offset++) = ' ';
3382 }
3383
3384 if (fptr->common.scope) {
3385 memcpy(offset, fptr->common.scope->name, fptr->common.scope->name_length);
3386 offset += fptr->common.scope->name_length;
3387 *(offset++) = ':';
3388 *(offset++) = ':';
3389 }
3390
3391 {
3392 size_t name_len = strlen(fptr->common.function_name);
3393 REALLOC_BUF_IF_EXCEED(buf, offset, length, name_len);
3394 memcpy(offset, fptr->common.function_name, name_len);
3395 offset += name_len;
3396 }
3397
3398 *(offset++) = '(';
3399 if (fptr->common.arg_info) {
3400 zend_uint i, required;
3401 zend_arg_info *arg_info = fptr->common.arg_info;
3402
3403 required = fptr->common.required_num_args;
3404 for (i = 0; i < fptr->common.num_args;) {
3405 if (arg_info->class_name) {
3406 const char *class_name;
3407 zend_uint class_name_len;
3408 if (!strcasecmp(arg_info->class_name, "self") && fptr->common.scope ) {
3409 class_name = fptr->common.scope->name;
3410 class_name_len = fptr->common.scope->name_length;
3411 } else if (!strcasecmp(arg_info->class_name, "parent") && fptr->common.scope->parent) {
3412 class_name = fptr->common.scope->parent->name;
3413 class_name_len = fptr->common.scope->parent->name_length;
3414 } else {
3415 class_name = arg_info->class_name;
3416 class_name_len = arg_info->class_name_len;
3417 }
3418 REALLOC_BUF_IF_EXCEED(buf, offset, length, class_name_len);
3419 memcpy(offset, class_name, class_name_len);
3420 offset += class_name_len;
3421 *(offset++) = ' ';
3422 } else if (arg_info->type_hint) {
3423 zend_uint type_name_len;
3424 char *type_name = zend_get_type_by_const(arg_info->type_hint);
3425 type_name_len = strlen(type_name);
3426 REALLOC_BUF_IF_EXCEED(buf, offset, length, type_name_len);
3427 memcpy(offset, type_name, type_name_len);
3428 offset += type_name_len;
3429 *(offset++) = ' ';
3430 }
3431
3432 if (arg_info->pass_by_reference) {
3433 *(offset++) = '&';
3434 }
3435
3436 if (arg_info->is_variadic) {
3437 *(offset++) = '.';
3438 *(offset++) = '.';
3439 *(offset++) = '.';
3440 }
3441
3442 *(offset++) = '$';
3443
3444 if (arg_info->name) {
3445 REALLOC_BUF_IF_EXCEED(buf, offset, length, arg_info->name_len);
3446 memcpy(offset, arg_info->name, arg_info->name_len);
3447 offset += arg_info->name_len;
3448 } else {
3449 zend_uint idx = i;
3450 memcpy(offset, "param", 5);
3451 offset += 5;
3452 do {
3453 *(offset++) = (char) (idx % 10) + '0';
3454 idx /= 10;
3455 } while (idx > 0);
3456 }
3457 if (i >= required && !arg_info->is_variadic) {
3458 *(offset++) = ' ';
3459 *(offset++) = '=';
3460 *(offset++) = ' ';
3461 if (fptr->type == ZEND_USER_FUNCTION) {
3462 zend_op *precv = NULL;
3463 {
3464 zend_uint idx = i;
3465 zend_op *op = ((zend_op_array *)fptr)->opcodes;
3466 zend_op *end = op + ((zend_op_array *)fptr)->last;
3467
3468 ++idx;
3469 while (op < end) {
3470 if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
3471 && op->op1.num == (long)idx)
3472 {
3473 precv = op;
3474 }
3475 ++op;
3476 }
3477 }
3478 if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
3479 zval *zv, zv_copy;
3480 int use_copy;
3481 zv = precv->op2.zv;
3482 if ((Z_TYPE_P(zv) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
3483 REALLOC_BUF_IF_EXCEED(buf, offset, length, Z_STRLEN_P(zv));
3484 memcpy(offset, Z_STRVAL_P(zv), Z_STRLEN_P(zv));
3485 offset += Z_STRLEN_P(zv);
3486 } else if (Z_TYPE_P(zv) == IS_BOOL) {
3487 if (Z_LVAL_P(zv)) {
3488 memcpy(offset, "true", 4);
3489 offset += 4;
3490 } else {
3491 memcpy(offset, "false", 5);
3492 offset += 5;
3493 }
3494 } else if (Z_TYPE_P(zv) == IS_NULL) {
3495 memcpy(offset, "NULL", 4);
3496 offset += 4;
3497 } else if (Z_TYPE_P(zv) == IS_STRING) {
3498 *(offset++) = '\'';
3499 REALLOC_BUF_IF_EXCEED(buf, offset, length, MIN(Z_STRLEN_P(zv), 10));
3500 memcpy(offset, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 10));
3501 offset += MIN(Z_STRLEN_P(zv), 10);
3502 if (Z_STRLEN_P(zv) > 10) {
3503 *(offset++) = '.';
3504 *(offset++) = '.';
3505 *(offset++) = '.';
3506 }
3507 *(offset++) = '\'';
3508 } else if (Z_TYPE_P(zv) == IS_ARRAY) {
3509 memcpy(offset, "Array", 5);
3510 offset += 5;
3511 } else if ((Z_TYPE_P(zv) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT_AST) {
3512 memcpy(offset, "<expression>", 12);
3513 offset += 12;
3514 } else {
3515 zend_make_printable_zval(zv, &zv_copy, &use_copy);
3516 REALLOC_BUF_IF_EXCEED(buf, offset, length, Z_STRLEN(zv_copy));
3517 memcpy(offset, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
3518 offset += Z_STRLEN(zv_copy);
3519 if (use_copy) {
3520 zval_dtor(&zv_copy);
3521 }
3522 }
3523 }
3524 } else {
3525 memcpy(offset, "NULL", 4);
3526 offset += 4;
3527 }
3528 }
3529
3530 if (++i < fptr->common.num_args) {
3531 *(offset++) = ',';
3532 *(offset++) = ' ';
3533 }
3534 arg_info++;
3535 REALLOC_BUF_IF_EXCEED(buf, offset, length, 32);
3536 }
3537 }
3538 *(offset++) = ')';
3539 *offset = '\0';
3540
3541 return buf;
3542 }
3543
3544
3545 static void do_inheritance_check_on_method(zend_function *child, zend_function *parent TSRMLS_DC)
3546 {
3547 zend_uint child_flags;
3548 zend_uint parent_flags = parent->common.fn_flags;
3549
3550 if ((parent->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
3551 && parent->common.fn_flags & ZEND_ACC_ABSTRACT
3552 && parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
3553 && child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
3554 zend_error_noreturn(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)",
3555 parent->common.scope->name,
3556 child->common.function_name,
3557 child->common.prototype ? child->common.prototype->common.scope->name : child->common.scope->name);
3558 }
3559
3560 if (parent_flags & ZEND_ACC_FINAL) {
3561 zend_error_noreturn(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name);
3562 }
3563
3564 child_flags = child->common.fn_flags;
3565
3566
3567 if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) {
3568 if (child->common.fn_flags & ZEND_ACC_STATIC) {
3569 zend_error_noreturn(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));
3570 } else {
3571 zend_error_noreturn(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));
3572 }
3573 }
3574
3575
3576 if ((child_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_ABSTRACT)) {
3577 zend_error_noreturn(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));
3578 }
3579
3580 if (parent_flags & ZEND_ACC_CHANGED) {
3581 child->common.fn_flags |= ZEND_ACC_CHANGED;
3582 } else {
3583
3584
3585 if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) {
3586 zend_error_noreturn(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");
3587 } else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
3588 && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
3589 child->common.fn_flags |= ZEND_ACC_CHANGED;
3590 }
3591 }
3592
3593 if (parent_flags & ZEND_ACC_PRIVATE) {
3594 child->common.prototype = NULL;
3595 } else if (parent_flags & ZEND_ACC_ABSTRACT) {
3596 child->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
3597 child->common.prototype = parent;
3598 } else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) {
3599
3600 child->common.prototype = parent->common.prototype ? parent->common.prototype : parent;
3601 }
3602
3603 if (child->common.prototype && (child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) {
3604 if (!zend_do_perform_implementation_check(child, child->common.prototype TSRMLS_CC)) {
3605 zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s::%s() must be compatible with %s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_get_function_declaration(child->common.prototype TSRMLS_CC));
3606 }
3607 } else if (EG(error_reporting) & E_STRICT || EG(user_error_handler)) {
3608 if (!zend_do_perform_implementation_check(child, parent TSRMLS_CC)) {
3609 char *method_prototype = zend_get_function_declaration(parent TSRMLS_CC);
3610 zend_error(E_STRICT, "Declaration of %s::%s() should be compatible with %s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, method_prototype);
3611 efree(method_prototype);
3612 }
3613 }
3614 }
3615
3616
3617 static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, const zend_hash_key *hash_key, zend_class_entry *child_ce)
3618 {
3619 zend_uint parent_flags = parent->common.fn_flags;
3620 zend_function *child;
3621 TSRMLS_FETCH();
3622
3623 if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
3624 if (parent_flags & (ZEND_ACC_ABSTRACT)) {
3625 child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
3626 }
3627 return 1;
3628 }
3629
3630 do_inheritance_check_on_method(child, parent TSRMLS_CC);
3631
3632 return 0;
3633 }
3634
3635
3636 static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_property_info *parent_info, const zend_hash_key *hash_key, zend_class_entry *ce)
3637 {
3638 zend_property_info *child_info;
3639 zend_class_entry *parent_ce = ce->parent;
3640
3641 if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
3642 if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
3643 child_info->flags |= ZEND_ACC_CHANGED;
3644 } else {
3645 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);
3646 if(ce->type & ZEND_INTERNAL_CLASS) {
3647 zend_duplicate_property_info_internal(child_info);
3648 } else {
3649 zend_duplicate_property_info(child_info);
3650 }
3651 child_info->flags &= ~ZEND_ACC_PRIVATE;
3652 child_info->flags |= ZEND_ACC_SHADOW;
3653 }
3654 return 0;
3655 }
3656
3657 if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
3658 if ((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC)) {
3659 zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s",
3660 (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->arKey,
3661 (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey);
3662
3663 }
3664
3665 if(parent_info->flags & ZEND_ACC_CHANGED) {
3666 child_info->flags |= ZEND_ACC_CHANGED;
3667 }
3668
3669 if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
3670 zend_error_noreturn(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");
3671 } else if ((child_info->flags & ZEND_ACC_STATIC) == 0) {
3672 zval_ptr_dtor(&(ce->default_properties_table[parent_info->offset]));
3673 ce->default_properties_table[parent_info->offset] = ce->default_properties_table[child_info->offset];
3674 ce->default_properties_table[child_info->offset] = NULL;
3675 child_info->offset = parent_info->offset;
3676 }
3677 return 0;
3678 } else {
3679 return 1;
3680 }
3681 }
3682
3683
3684 static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC)
3685 {
3686 if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce TSRMLS_CC) == FAILURE) {
3687 zend_error(E_CORE_ERROR, "Class %s could not implement interface %s", ce->name, iface->name);
3688 }
3689 if (ce == iface) {
3690 zend_error(E_ERROR, "Interface %s cannot implement itself", ce->name);
3691 }
3692 }
3693
3694
3695 ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC)
3696 {
3697
3698 zend_uint i, ce_num, if_num = iface->num_interfaces;
3699 zend_class_entry *entry;
3700
3701 if (if_num==0) {
3702 return;
3703 }
3704 ce_num = ce->num_interfaces;
3705
3706 if (ce->type == ZEND_INTERNAL_CLASS) {
3707 ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
3708 } else {
3709 ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
3710 }
3711
3712
3713 while (if_num--) {
3714 entry = iface->interfaces[if_num];
3715 for (i = 0; i < ce_num; i++) {
3716 if (ce->interfaces[i] == entry) {
3717 break;
3718 }
3719 }
3720 if (i == ce_num) {
3721 ce->interfaces[ce->num_interfaces++] = entry;
3722 }
3723 }
3724
3725
3726 while (ce_num < ce->num_interfaces) {
3727 do_implement_interface(ce, ce->interfaces[ce_num++] TSRMLS_CC);
3728 }
3729 }
3730
3731
3732 #ifdef ZTS
3733 static void zval_internal_ctor(zval **p)
3734 {
3735 zval *orig_ptr = *p;
3736
3737 ALLOC_ZVAL(*p);
3738 MAKE_COPY_ZVAL(&orig_ptr, *p);
3739 }
3740
3741
3742 # define zval_property_ctor(parent_ce, ce) \
3743 ((void (*)(void *)) (((parent_ce)->type != (ce)->type) ? zval_internal_ctor : zval_add_ref))
3744 #else
3745 # define zval_property_ctor(parent_ce, ce) \
3746 ((void (*)(void *)) zval_add_ref)
3747 #endif
3748
3749 ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC)
3750 {
3751 zend_property_info *property_info;
3752
3753 if ((ce->ce_flags & ZEND_ACC_INTERFACE)
3754 && !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
3755 zend_error_noreturn(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
3756 }
3757 if (parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
3758 zend_error_noreturn(E_COMPILE_ERROR, "Class %s may not inherit from final class (%s)", ce->name, parent_ce->name);
3759 }
3760
3761 ce->parent = parent_ce;
3762
3763 if (!ce->serialize) {
3764 ce->serialize = parent_ce->serialize;
3765 }
3766 if (!ce->unserialize) {
3767 ce->unserialize = parent_ce->unserialize;
3768 }
3769
3770
3771 zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);
3772
3773
3774 if (parent_ce->default_properties_count) {
3775 int i = ce->default_properties_count + parent_ce->default_properties_count;
3776
3777 ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
3778 if (ce->default_properties_count) {
3779 while (i-- > parent_ce->default_properties_count) {
3780 ce->default_properties_table[i] = ce->default_properties_table[i - parent_ce->default_properties_count];
3781 }
3782 }
3783 for (i = 0; i < parent_ce->default_properties_count; i++) {
3784 ce->default_properties_table[i] = parent_ce->default_properties_table[i];
3785 if (ce->default_properties_table[i]) {
3786 #ifdef ZTS
3787 if (parent_ce->type != ce->type) {
3788 zval *p;
3789
3790 ALLOC_ZVAL(p);
3791 MAKE_COPY_ZVAL(&ce->default_properties_table[i], p);
3792 ce->default_properties_table[i] = p;
3793 } else {
3794 Z_ADDREF_P(ce->default_properties_table[i]);
3795 }
3796 #else
3797 Z_ADDREF_P(ce->default_properties_table[i]);
3798 #endif
3799 }
3800 }
3801 ce->default_properties_count += parent_ce->default_properties_count;
3802 }
3803
3804 if (parent_ce->type != ce->type) {
3805
3806 zend_update_class_constants(parent_ce TSRMLS_CC);
3807 if (parent_ce->default_static_members_count) {
3808 int i = ce->default_static_members_count + parent_ce->default_static_members_count;
3809
3810 ce->default_static_members_table = erealloc(ce->default_static_members_table, sizeof(void*) * i);
3811 if (ce->default_static_members_count) {
3812 while (i-- > parent_ce->default_static_members_count) {
3813 ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
3814 }
3815 }
3816 for (i = 0; i < parent_ce->default_static_members_count; i++) {
3817 SEPARATE_ZVAL_TO_MAKE_IS_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
3818 ce->default_static_members_table[i] = CE_STATIC_MEMBERS(parent_ce)[i];
3819 Z_ADDREF_P(ce->default_static_members_table[i]);
3820 }
3821 ce->default_static_members_count += parent_ce->default_static_members_count;
3822 ce->static_members_table = ce->default_static_members_table;
3823 }
3824 } else {
3825 if (parent_ce->default_static_members_count) {
3826 int i = ce->default_static_members_count + parent_ce->default_static_members_count;
3827
3828 ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
3829 if (ce->default_static_members_count) {
3830 while (i-- > parent_ce->default_static_members_count) {
3831 ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
3832 }
3833 }
3834 for (i = 0; i < parent_ce->default_static_members_count; i++) {
3835 SEPARATE_ZVAL_TO_MAKE_IS_REF(&parent_ce->default_static_members_table[i]);
3836 ce->default_static_members_table[i] = parent_ce->default_static_members_table[i];
3837 Z_ADDREF_P(ce->default_static_members_table[i]);
3838 }
3839 ce->default_static_members_count += parent_ce->default_static_members_count;
3840 if (ce->type == ZEND_USER_CLASS) {
3841 ce->static_members_table = ce->default_static_members_table;
3842 }
3843 }
3844 }
3845
3846 for (zend_hash_internal_pointer_reset(&ce->properties_info);
3847 zend_hash_get_current_data(&ce->properties_info, (void *) &property_info) == SUCCESS;
3848 zend_hash_move_forward(&ce->properties_info)) {
3849 if (property_info->ce == ce) {
3850 if (property_info->flags & ZEND_ACC_STATIC) {
3851 property_info->offset += parent_ce->default_static_members_count;
3852 } else {
3853 property_info->offset += parent_ce->default_properties_count;
3854 }
3855 }
3856 }
3857
3858 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);
3859
3860 zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);
3861 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);
3862 do_inherit_parent_constructor(ce);
3863
3864 if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
3865 ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
3866 } else if (!(ce->ce_flags & (ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
3867
3868 zend_verify_abstract_class(ce TSRMLS_CC);
3869 }
3870 ce->ce_flags |= parent_ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS;
3871 }
3872
3873
3874 static zend_bool do_inherit_constant_check(HashTable *child_constants_table, const zval **parent_constant, const zend_hash_key *hash_key, const zend_class_entry *iface)
3875 {
3876 zval **old_constant;
3877
3878 if (zend_hash_quick_find(child_constants_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**)&old_constant) == SUCCESS) {
3879 if (*old_constant != *parent_constant) {
3880 zend_error_noreturn(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", hash_key->arKey, iface->name);
3881 }
3882 return 0;
3883 }
3884 return 1;
3885 }
3886
3887
3888 static int do_interface_constant_check(zval **val TSRMLS_DC, int num_args, va_list args, const zend_hash_key *key)
3889 {
3890 zend_class_entry **iface = va_arg(args, zend_class_entry**);
3891
3892 do_inherit_constant_check(&(*iface)->constants_table, (const zval **) val, key, *iface);
3893
3894 return ZEND_HASH_APPLY_KEEP;
3895 }
3896
3897
3898 ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC)
3899 {
3900 zend_uint i, ignore = 0;
3901 zend_uint current_iface_num = ce->num_interfaces;
3902 zend_uint parent_iface_num = ce->parent ? ce->parent->num_interfaces : 0;
3903
3904 for (i = 0; i < ce->num_interfaces; i++) {
3905 if (ce->interfaces[i] == NULL) {
3906 memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i));
3907 i--;
3908 } else if (ce->interfaces[i] == iface) {
3909 if (i < parent_iface_num) {
3910 ignore = 1;
3911 } else {
3912 zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ce->name, iface->name);
3913 }
3914 }
3915 }
3916 if (ignore) {
3917
3918 zend_hash_apply_with_arguments(&ce->constants_table TSRMLS_CC, (apply_func_args_t) do_interface_constant_check, 1, &iface);
3919 } else {
3920 if (ce->num_interfaces >= current_iface_num) {
3921 if (ce->type == ZEND_INTERNAL_CLASS) {
3922 ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
3923 } else {
3924 ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
3925 }
3926 }
3927 ce->interfaces[ce->num_interfaces++] = iface;
3928
3929 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);
3930 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);
3931
3932 do_implement_interface(ce, iface TSRMLS_CC);
3933 zend_do_inherit_interfaces(ce, iface TSRMLS_CC);
3934 }
3935 }
3936
3937
3938 ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC)
3939 {
3940 zend_uint i, ignore = 0;
3941 zend_uint current_trait_num = ce->num_traits;
3942 zend_uint parent_trait_num = ce->parent ? ce->parent->num_traits : 0;
3943
3944 for (i = 0; i < ce->num_traits; i++) {
3945 if (ce->traits[i] == NULL) {
3946 memmove(ce->traits + i, ce->traits + i + 1, sizeof(zend_class_entry*) * (--ce->num_traits - i));
3947 i--;
3948 } else if (ce->traits[i] == trait) {
3949 if (i < parent_trait_num) {
3950 ignore = 1;
3951 }
3952 }
3953 }
3954 if (!ignore) {
3955 if (ce->num_traits >= current_trait_num) {
3956 if (ce->type == ZEND_INTERNAL_CLASS) {
3957 ce->traits = (zend_class_entry **) realloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
3958 } else {
3959 ce->traits = (zend_class_entry **) erealloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
3960 }
3961 }
3962 ce->traits[ce->num_traits++] = trait;
3963 }
3964 }
3965
3966
3967 static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_function *other_fn TSRMLS_DC)
3968 {
3969 zend_uint fn_flags = fn->common.scope->ce_flags;
3970 zend_uint other_flags = other_fn->common.scope->ce_flags;
3971
3972 return zend_do_perform_implementation_check(fn, other_fn TSRMLS_CC)
3973 && ((other_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) || zend_do_perform_implementation_check(other_fn, fn TSRMLS_CC))
3974 && ((fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC)) ==
3975 (other_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC)));
3976 }
3977
3978
3979 static void zend_add_magic_methods(zend_class_entry* ce, const char* mname, uint mname_len, zend_function* fe TSRMLS_DC)
3980 {
3981 if (!strncmp(mname, ZEND_CLONE_FUNC_NAME, mname_len)) {
3982 ce->clone = fe; fe->common.fn_flags |= ZEND_ACC_CLONE;
3983 } else if (!strncmp(mname, ZEND_CONSTRUCTOR_FUNC_NAME, mname_len)) {
3984 if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
3985 zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name);
3986 }
3987 ce->constructor = fe; fe->common.fn_flags |= ZEND_ACC_CTOR;
3988 } else if (!strncmp(mname, ZEND_DESTRUCTOR_FUNC_NAME, mname_len)) {
3989 ce->destructor = fe; fe->common.fn_flags |= ZEND_ACC_DTOR;
3990 } else if (!strncmp(mname, ZEND_GET_FUNC_NAME, mname_len)) {
3991 ce->__get = fe;
3992 } else if (!strncmp(mname, ZEND_SET_FUNC_NAME, mname_len)) {
3993 ce->__set = fe;
3994 } else if (!strncmp(mname, ZEND_CALL_FUNC_NAME, mname_len)) {
3995 ce->__call = fe;
3996 } else if (!strncmp(mname, ZEND_UNSET_FUNC_NAME, mname_len)) {
3997 ce->__unset = fe;
3998 } else if (!strncmp(mname, ZEND_ISSET_FUNC_NAME, mname_len)) {
3999 ce->__isset = fe;
4000 } else if (!strncmp(mname, ZEND_CALLSTATIC_FUNC_NAME, mname_len)) {
4001 ce->__callstatic = fe;
4002 } else if (!strncmp(mname, ZEND_TOSTRING_FUNC_NAME, mname_len)) {
4003 ce->__tostring = fe;
4004 } else if (!strncmp(mname, ZEND_DEBUGINFO_FUNC_NAME, mname_len)) {
4005 ce->__debugInfo = fe;
4006 } else if (ce->name_length + 1 == mname_len) {
4007 char *lowercase_name = emalloc(ce->name_length + 1);
4008 zend_str_tolower_copy(lowercase_name, ce->name, ce->name_length);
4009 lowercase_name = (char*)zend_new_interned_string(lowercase_name, ce->name_length + 1, 1 TSRMLS_CC);
4010 if (!memcmp(mname, lowercase_name, mname_len)) {
4011 if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
4012 zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name);
4013 }
4014 ce->constructor = fe;
4015 fe->common.fn_flags |= ZEND_ACC_CTOR;
4016 }
4017 str_efree(lowercase_name);
4018 }
4019 }
4020
4021
4022 static void zend_add_trait_method(zend_class_entry *ce, const char *name, const char *arKey, uint nKeyLength, zend_function *fn, HashTable **overriden TSRMLS_DC)
4023 {
4024 zend_function *existing_fn = NULL;
4025 ulong h = zend_hash_func(arKey, nKeyLength);
4026
4027 if (zend_hash_quick_find(&ce->function_table, arKey, nKeyLength, h, (void**) &existing_fn) == SUCCESS) {
4028 if (existing_fn->common.scope == ce) {
4029
4030
4031 if (*overriden) {
4032 if (zend_hash_quick_find(*overriden, arKey, nKeyLength, h, (void**) &existing_fn) == SUCCESS) {
4033 if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4034
4035 if (!zend_traits_method_compatibility_check(fn, existing_fn TSRMLS_CC)) {
4036 zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
4037 zend_get_function_declaration(fn TSRMLS_CC),
4038 zend_get_function_declaration(existing_fn TSRMLS_CC));
4039 }
4040 } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4041
4042 if (!zend_traits_method_compatibility_check(existing_fn, fn TSRMLS_CC)) {
4043 zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
4044 zend_get_function_declaration(fn TSRMLS_CC),
4045 zend_get_function_declaration(existing_fn TSRMLS_CC));
4046 }
4047 return;
4048 }
4049 }
4050 } else {
4051 ALLOC_HASHTABLE(*overriden);
4052 zend_hash_init_ex(*overriden, 2, NULL, NULL, 0, 0);
4053 }
4054 zend_hash_quick_update(*overriden, arKey, nKeyLength, h, fn, sizeof(zend_function), (void**)&fn);
4055 return;
4056 } else if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT &&
4057 (existing_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0) {
4058
4059 if (!zend_traits_method_compatibility_check(fn, existing_fn TSRMLS_CC)) {
4060 zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
4061 zend_get_function_declaration(fn TSRMLS_CC),
4062 zend_get_function_declaration(existing_fn TSRMLS_CC));
4063 }
4064 } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4065
4066 if (!zend_traits_method_compatibility_check(existing_fn, fn TSRMLS_CC)) {
4067 zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
4068 zend_get_function_declaration(fn TSRMLS_CC),
4069 zend_get_function_declaration(existing_fn TSRMLS_CC));
4070 }
4071 return;
4072 } else if ((existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
4073
4074 #if 1
4075 zend_error_noreturn(E_COMPILE_ERROR, "Trait method %s has not been applied, because there are collisions with other trait methods on %s",
4076 name, ce->name);
4077 #else
4078 zend_error_noreturn(E_COMPILE_ERROR, "Trait method %s::%s has not been applied as %s::%s, because of collision with %s::%s",
4079 fn->common.scope->name, fn->common.function_name,
4080 ce->name, name,
4081 existing_fn->common.scope->name, existing_fn->common.function_name);
4082 #endif
4083 } else {
4084
4085
4086 do_inheritance_check_on_method(fn, existing_fn TSRMLS_CC);
4087 fn->common.prototype = NULL;
4088 }
4089 }
4090
4091 function_add_ref(fn);
4092 zend_hash_quick_update(&ce->function_table, arKey, nKeyLength, h, fn, sizeof(zend_function), (void**)&fn);
4093 zend_add_magic_methods(ce, arKey, nKeyLength, fn TSRMLS_CC);
4094 }
4095
4096
4097 static int zend_fixup_trait_method(zend_function *fn, zend_class_entry *ce TSRMLS_DC)
4098 {
4099 if ((fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
4100
4101 fn->common.scope = ce;
4102
4103 if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4104 ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
4105 }
4106 if (fn->type == ZEND_USER_FUNCTION && fn->op_array.static_variables) {
4107 ce->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
4108 }
4109 }
4110 return ZEND_HASH_APPLY_KEEP;
4111 }
4112
4113
4114 static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
4115 {
4116 zend_class_entry *ce;
4117 HashTable **overriden;
4118 zend_trait_alias *alias, **alias_ptr;
4119 HashTable *exclude_table;
4120 char *lcname;
4121 unsigned int fnname_len;
4122 zend_function fn_copy;
4123 void *dummy;
4124
4125 ce = va_arg(args, zend_class_entry*);
4126 overriden = va_arg(args, HashTable**);
4127 exclude_table = va_arg(args, HashTable*);
4128
4129 fnname_len = hash_key->nKeyLength - 1;
4130
4131
4132 if (ce->trait_aliases) {
4133 alias_ptr = ce->trait_aliases;
4134 alias = *alias_ptr;
4135 while (alias) {
4136
4137 if (alias->alias != NULL
4138 && (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce)
4139 && alias->trait_method->mname_len == fnname_len
4140 && (zend_binary_strcasecmp(alias->trait_method->method_name, alias->trait_method->mname_len, hash_key->arKey, fnname_len) == 0)) {
4141 fn_copy = *fn;
4142
4143
4144 if (alias->modifiers) {
4145 fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK));
4146 }
4147
4148 lcname = zend_str_tolower_dup(alias->alias, alias->alias_len);
4149 zend_add_trait_method(ce, alias->alias, lcname, alias->alias_len+1, &fn_copy, overriden TSRMLS_CC);
4150 efree(lcname);
4151
4152
4153 if (!alias->trait_method->ce) {
4154 alias->trait_method->ce = fn->common.scope;
4155 }
4156 }
4157 alias_ptr++;
4158 alias = *alias_ptr;
4159 }
4160 }
4161
4162 lcname = (char *) hash_key->arKey;
4163
4164 if (exclude_table == NULL || zend_hash_find(exclude_table, lcname, fnname_len, &dummy) == FAILURE) {
4165
4166 fn_copy = *fn;
4167
4168
4169 if (ce->trait_aliases) {
4170 alias_ptr = ce->trait_aliases;
4171 alias = *alias_ptr;
4172 while (alias) {
4173
4174 if (alias->alias == NULL && alias->modifiers != 0
4175 && (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce)
4176 && (alias->trait_method->mname_len == fnname_len)
4177 && (zend_binary_strcasecmp(alias->trait_method->method_name, alias->trait_method->mname_len, lcname, fnname_len) == 0)) {
4178
4179 fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK));
4180
4181
4182 if (!alias->trait_method->ce) {
4183 alias->trait_method->ce = fn->common.scope;
4184 }
4185 }
4186 alias_ptr++;
4187 alias = *alias_ptr;
4188 }
4189 }
4190
4191 zend_add_trait_method(ce, fn->common.function_name, lcname, fnname_len+1, &fn_copy, overriden TSRMLS_CC);
4192 }
4193
4194 return ZEND_HASH_APPLY_KEEP;
4195 }
4196
4197
4198 static void zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC)
4199 {
4200 zend_uint i;
4201
4202 if ((trait->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT) {
4203 zend_error_noreturn(E_COMPILE_ERROR, "Class %s is not a trait, Only traits may be used in 'as' and 'insteadof' statements", trait->name);
4204 }
4205
4206 for (i = 0; i < ce->num_traits; i++) {
4207 if (ce->traits[i] == trait) {
4208 return;
4209 }
4210 }
4211 zend_error_noreturn(E_COMPILE_ERROR, "Required Trait %s wasn't added to %s", trait->name, ce->name);
4212 }
4213
4214
4215 static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC)
4216 {
4217 size_t i, j = 0;
4218 zend_trait_precedence **precedences;
4219 zend_trait_precedence *cur_precedence;
4220 zend_trait_method_reference *cur_method_ref;
4221 char *lcname;
4222 zend_bool method_exists;
4223
4224
4225 if (ce->trait_precedences) {
4226 i = 0;
4227 precedences = ce->trait_precedences;
4228 ce->trait_precedences = NULL;
4229 while ((cur_precedence = precedences[i])) {
4230
4231 if (cur_precedence->exclude_from_classes) {
4232 cur_method_ref = cur_precedence->trait_method;
4233 if (!(cur_precedence->trait_method->ce = zend_fetch_class(cur_method_ref->class_name, cur_method_ref->cname_len,
4234 ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
4235 zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", cur_method_ref->class_name);
4236 }
4237 zend_check_trait_usage(ce, cur_precedence->trait_method->ce TSRMLS_CC);
4238
4239
4240 lcname = zend_str_tolower_dup(cur_method_ref->method_name,
4241 cur_method_ref->mname_len);
4242 method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
4243 lcname,
4244 cur_method_ref->mname_len + 1);
4245 efree(lcname);
4246 if (!method_exists) {
4247 zend_error_noreturn(E_COMPILE_ERROR,
4248 "A precedence rule was defined for %s::%s but this method does not exist",
4249 cur_method_ref->ce->name,
4250 cur_method_ref->method_name);
4251 }
4252
4253
4254
4255
4256
4257
4258
4259 j = 0;
4260 while (cur_precedence->exclude_from_classes[j]) {
4261 char* class_name = (char*)cur_precedence->exclude_from_classes[j];
4262 zend_uint name_length = strlen(class_name);
4263
4264 if (!(cur_precedence->exclude_from_classes[j] = zend_fetch_class(class_name, name_length, ZEND_FETCH_CLASS_TRAIT |ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
4265 zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", class_name);
4266 }
4267 zend_check_trait_usage(ce, cur_precedence->exclude_from_classes[j] TSRMLS_CC);
4268
4269
4270
4271 if (cur_precedence->trait_method->ce == cur_precedence->exclude_from_classes[j]) {
4272 zend_error(E_COMPILE_ERROR,
4273 "Inconsistent insteadof definition. "
4274 "The method %s is to be used from %s, but %s is also on the exclude list",
4275 cur_method_ref->method_name,
4276 cur_precedence->trait_method->ce->name,
4277 cur_precedence->trait_method->ce->name);
4278 }
4279
4280 efree(class_name);
4281 j++;
4282 }
4283 }
4284 i++;
4285 }
4286 ce->trait_precedences = precedences;
4287 }
4288
4289 if (ce->trait_aliases) {
4290 i = 0;
4291 while (ce->trait_aliases[i]) {
4292
4293 if (ce->trait_aliases[i]->trait_method->class_name) {
4294 cur_method_ref = ce->trait_aliases[i]->trait_method;
4295 if (!(cur_method_ref->ce = zend_fetch_class(cur_method_ref->class_name, cur_method_ref->cname_len, ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
4296 zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", cur_method_ref->class_name);
4297 }
4298 zend_check_trait_usage(ce, cur_method_ref->ce TSRMLS_CC);
4299
4300
4301 lcname = zend_str_tolower_dup(cur_method_ref->method_name,
4302 cur_method_ref->mname_len);
4303 method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
4304 lcname, cur_method_ref->mname_len + 1);
4305 efree(lcname);
4306
4307 if (!method_exists) {
4308 zend_error_noreturn(E_COMPILE_ERROR, "An alias was defined for %s::%s but this method does not exist", cur_method_ref->ce->name, cur_method_ref->method_name);
4309 }
4310 }
4311 i++;
4312 }
4313 }
4314 }
4315
4316
4317 static void zend_traits_compile_exclude_table(HashTable* exclude_table, zend_trait_precedence **precedences, zend_class_entry *trait)
4318 {
4319 size_t i = 0, j;
4320
4321 if (!precedences) {
4322 return;
4323 }
4324 while (precedences[i]) {
4325 if (precedences[i]->exclude_from_classes) {
4326 j = 0;
4327 while (precedences[i]->exclude_from_classes[j]) {
4328 if (precedences[i]->exclude_from_classes[j] == trait) {
4329 zend_uint lcname_len = precedences[i]->trait_method->mname_len;
4330 char *lcname = zend_str_tolower_dup(precedences[i]->trait_method->method_name, lcname_len);
4331
4332 if (zend_hash_add(exclude_table, lcname, lcname_len, NULL, 0, NULL) == FAILURE) {
4333 efree(lcname);
4334 zend_error_noreturn(E_COMPILE_ERROR, "Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times", precedences[i]->trait_method->method_name, trait->name);
4335 }
4336 efree(lcname);
4337 }
4338 ++j;
4339 }
4340 }
4341 ++i;
4342 }
4343 }
4344
4345
4346 static void zend_do_traits_method_binding(zend_class_entry *ce TSRMLS_DC)
4347 {
4348 zend_uint i;
4349 HashTable *overriden = NULL;
4350
4351 for (i = 0; i < ce->num_traits; i++) {
4352 if (ce->trait_precedences) {
4353 HashTable exclude_table;
4354 zend_trait_precedence **precedences;
4355
4356
4357 zend_hash_init_ex(&exclude_table, 2, NULL, NULL, 0, 0);
4358
4359 precedences = ce->trait_precedences;
4360 ce->trait_precedences = NULL;
4361 zend_traits_compile_exclude_table(&exclude_table, precedences, ce->traits[i]);
4362
4363
4364 zend_hash_apply_with_arguments(&ce->traits[i]->function_table TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, ce, &overriden, &exclude_table);
4365
4366 zend_hash_destroy(&exclude_table);
4367 ce->trait_precedences = precedences;
4368 } else {
4369 zend_hash_apply_with_arguments(&ce->traits[i]->function_table TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, ce, &overriden, NULL);
4370 }
4371 }
4372
4373 zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t)zend_fixup_trait_method, ce TSRMLS_CC);
4374
4375 if (ce->trait_precedences) {
4376 i = 0;
4377 while (ce->trait_precedences[i]) {
4378 if (ce->trait_precedences[i]->exclude_from_classes) {
4379 efree(ce->trait_precedences[i]->exclude_from_classes);
4380 ce->trait_precedences[i]->exclude_from_classes = NULL;
4381 }
4382 i++;
4383 }
4384 }
4385
4386 if (overriden) {
4387 zend_hash_destroy(overriden);
4388 FREE_HASHTABLE(overriden);
4389 }
4390 }
4391
4392
4393 static zend_class_entry* find_first_definition(zend_class_entry *ce, size_t current_trait, const char* prop_name, int prop_name_length, ulong prop_hash, zend_class_entry *coliding_ce)
4394 {
4395 size_t i;
4396
4397 if (coliding_ce == ce) {
4398 for (i = 0; i < current_trait; i++) {
4399 if (zend_hash_quick_exists(&ce->traits[i]->properties_info, prop_name, prop_name_length+1, prop_hash)) {
4400 return ce->traits[i];
4401 }
4402 }
4403 }
4404
4405 return coliding_ce;
4406 }
4407
4408
4409 static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC)
4410 {
4411 size_t i;
4412 zend_property_info *property_info;
4413 zend_property_info *coliding_prop;
4414 zval compare_result;
4415 const char* prop_name;
4416 int prop_name_length;
4417 ulong prop_hash;
4418 const char* class_name_unused;
4419 zend_bool not_compatible;
4420 zval* prop_value;
4421 char* doc_comment;
4422 zend_uint flags;
4423
4424
4425
4426
4427
4428
4429 for (i = 0; i < ce->num_traits; i++) {
4430 for (zend_hash_internal_pointer_reset(&ce->traits[i]->properties_info);
4431 zend_hash_get_current_data(&ce->traits[i]->properties_info, (void *) &property_info) == SUCCESS;
4432 zend_hash_move_forward(&ce->traits[i]->properties_info)) {
4433
4434
4435
4436 flags = property_info->flags;
4437 if ((flags & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) {
4438 prop_hash = property_info->h;
4439 prop_name = property_info->name;
4440 prop_name_length = property_info->name_length;
4441 } else {
4442
4443 zend_unmangle_property_name_ex(property_info->name, property_info->name_length,
4444 &class_name_unused, &prop_name, &prop_name_length);
4445 prop_hash = zend_get_hash_value(prop_name, prop_name_length + 1);
4446 }
4447
4448
4449 if (zend_hash_quick_find(&ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop) == SUCCESS) {
4450 if (coliding_prop->flags & ZEND_ACC_SHADOW) {
4451 zend_hash_quick_del(&ce->properties_info, prop_name, prop_name_length+1, prop_hash);
4452 flags |= ZEND_ACC_CHANGED;
4453 } else {
4454 if ((coliding_prop->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))
4455 == (flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
4456
4457 if (flags & ZEND_ACC_STATIC) {
4458 not_compatible = (FAILURE == compare_function(&compare_result,
4459 ce->default_static_members_table[coliding_prop->offset],
4460 ce->traits[i]->default_static_members_table[property_info->offset] TSRMLS_CC))
4461 || (Z_LVAL(compare_result) != 0);
4462 } else {
4463 not_compatible = (FAILURE == compare_function(&compare_result,
4464 ce->default_properties_table[coliding_prop->offset],
4465 ce->traits[i]->default_properties_table[property_info->offset] TSRMLS_CC))
4466 || (Z_LVAL(compare_result) != 0);
4467 }
4468 } else {
4469
4470 not_compatible = 1;
4471 }
4472
4473 if (not_compatible) {
4474 zend_error_noreturn(E_COMPILE_ERROR,
4475 "%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
4476 find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
4477 property_info->ce->name,
4478 prop_name,
4479 ce->name);
4480 } else {
4481 zend_error(E_STRICT,
4482 "%s and %s define the same property ($%s) in the composition of %s. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed",
4483 find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
4484 property_info->ce->name,
4485 prop_name,
4486 ce->name);
4487 continue;
4488 }
4489 }
4490 }
4491
4492
4493 if (flags & ZEND_ACC_STATIC) {
4494 prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
4495 } else {
4496 prop_value = ce->traits[i]->default_properties_table[property_info->offset];
4497 }
4498 Z_ADDREF_P(prop_value);
4499
4500 doc_comment = property_info->doc_comment ? estrndup(property_info->doc_comment, property_info->doc_comment_len) : NULL;
4501 zend_declare_property_ex(ce, prop_name, prop_name_length,
4502 prop_value, flags,
4503 doc_comment, property_info->doc_comment_len TSRMLS_CC);
4504 }
4505 }
4506 }
4507
4508
4509 static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce TSRMLS_DC)
4510 {
4511 int i = 0;
4512 zend_trait_alias* cur_alias;
4513 char* lc_method_name;
4514
4515 if (ce->trait_aliases) {
4516 while (ce->trait_aliases[i]) {
4517 cur_alias = ce->trait_aliases[i];
4518
4519
4520 if (!cur_alias->trait_method->ce) {
4521 if (cur_alias->alias) {
4522
4523 zend_error_noreturn(E_COMPILE_ERROR,
4524 "An alias (%s) was defined for method %s(), but this method does not exist",
4525 cur_alias->alias,
4526 cur_alias->trait_method->method_name);
4527 } else {
4528
4529
4530
4531
4532
4533
4534
4535
4536 lc_method_name = zend_str_tolower_dup(cur_alias->trait_method->method_name,
4537 cur_alias->trait_method->mname_len);
4538 if (zend_hash_exists(&ce->function_table,
4539 lc_method_name,
4540 cur_alias->trait_method->mname_len+1)) {
4541 efree(lc_method_name);
4542 zend_error_noreturn(E_COMPILE_ERROR,
4543 "The modifiers for the trait alias %s() need to be changed in the same statment in which the alias is defined. Error",
4544 cur_alias->trait_method->method_name);
4545 } else {
4546 efree(lc_method_name);
4547 zend_error_noreturn(E_COMPILE_ERROR,
4548 "The modifiers of the trait method %s() are changed, but this method does not exist. Error",
4549 cur_alias->trait_method->method_name);
4550
4551 }
4552 }
4553 }
4554 i++;
4555 }
4556 }
4557 }
4558
4559
4560 ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC)
4561 {
4562
4563 if (ce->num_traits <= 0) {
4564 return;
4565 }
4566
4567
4568 zend_traits_init_trait_structures(ce TSRMLS_CC);
4569
4570
4571 zend_do_traits_method_binding(ce TSRMLS_CC);
4572
4573
4574 zend_do_check_for_inconsistent_traits_aliasing(ce TSRMLS_CC);
4575
4576
4577 zend_do_traits_property_binding(ce TSRMLS_CC);
4578
4579
4580 zend_verify_abstract_class(ce TSRMLS_CC);
4581
4582
4583 if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
4584 ce->ce_flags -= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
4585 }
4586 }
4587
4588
4589 ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time)
4590 {
4591 zend_function *function;
4592 zval *op1, *op2;
4593
4594 if (compile_time) {
4595 op1 = &CONSTANT_EX(op_array, opline->op1.constant);
4596 op2 = &CONSTANT_EX(op_array, opline->op2.constant);
4597 } else {
4598 op1 = opline->op1.zv;
4599 op2 = opline->op2.zv;
4600 }
4601
4602 zend_hash_quick_find(function_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void *) &function);
4603 if (zend_hash_quick_add(function_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), function, sizeof(zend_function), NULL)==FAILURE) {
4604 int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
4605 zend_function *old_function;
4606
4607 if (zend_hash_quick_find(function_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), (void *) &old_function)==SUCCESS
4608 && old_function->type == ZEND_USER_FUNCTION
4609 && old_function->op_array.last > 0) {
4610 zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
4611 function->common.function_name,
4612 old_function->op_array.filename,
4613 old_function->op_array.opcodes[0].lineno);
4614 } else {
4615 zend_error(error_level, "Cannot redeclare %s()", function->common.function_name);
4616 }
4617 return FAILURE;
4618 } else {
4619 (*function->op_array.refcount)++;
4620 function->op_array.static_variables = NULL;
4621 return SUCCESS;
4622 }
4623 }
4624
4625
4626 void zend_prepare_reference(znode *result, znode *class_name, znode *method_name TSRMLS_DC)
4627 {
4628 zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference));
4629 method_ref->ce = NULL;
4630
4631
4632
4633 if (class_name) {
4634 zend_resolve_class_name(class_name TSRMLS_CC);
4635 method_ref->class_name = Z_STRVAL(class_name->u.constant);
4636 method_ref->cname_len = Z_STRLEN(class_name->u.constant);
4637 } else {
4638 method_ref->class_name = NULL;
4639 method_ref->cname_len = 0;
4640 }
4641
4642 method_ref->method_name = Z_STRVAL(method_name->u.constant);
4643 method_ref->mname_len = Z_STRLEN(method_name->u.constant);
4644
4645 result->u.op.ptr = method_ref;
4646 result->op_type = IS_TMP_VAR;
4647 }
4648
4649
4650 void zend_add_trait_alias(znode *method_reference, znode *modifiers, znode *alias TSRMLS_DC)
4651 {
4652 zend_class_entry *ce = CG(active_class_entry);
4653 zend_trait_alias *trait_alias;
4654
4655 if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_STATIC) {
4656 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as method modifier");
4657 return;
4658 } else if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_ABSTRACT) {
4659 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier");
4660 return;
4661 } else if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_FINAL) {
4662 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as method modifier");
4663 return;
4664 }
4665
4666 trait_alias = emalloc(sizeof(zend_trait_alias));
4667 trait_alias->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
4668 trait_alias->modifiers = Z_LVAL(modifiers->u.constant);
4669 if (alias) {
4670 trait_alias->alias = Z_STRVAL(alias->u.constant);
4671 trait_alias->alias_len = Z_STRLEN(alias->u.constant);
4672 } else {
4673 trait_alias->alias = NULL;
4674 }
4675 zend_add_to_list(&ce->trait_aliases, trait_alias TSRMLS_CC);
4676 }
4677
4678
4679 void zend_add_trait_precedence(znode *method_reference, znode *trait_list TSRMLS_DC)
4680 {
4681 zend_class_entry *ce = CG(active_class_entry);
4682 zend_trait_precedence *trait_precedence = emalloc(sizeof(zend_trait_precedence));
4683
4684 trait_precedence->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
4685 trait_precedence->exclude_from_classes = (zend_class_entry**) trait_list->u.op.ptr;
4686
4687 zend_add_to_list(&ce->trait_precedences, trait_precedence TSRMLS_CC);
4688 }
4689
4690
4691 ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC)
4692 {
4693 zend_class_entry *ce, **pce;
4694 zval *op1, *op2;
4695
4696 if (compile_time) {
4697 op1 = &CONSTANT_EX(op_array, opline->op1.constant);
4698 op2 = &CONSTANT_EX(op_array, opline->op2.constant);
4699 } else {
4700 op1 = opline->op1.zv;
4701 op2 = opline->op2.zv;
4702 }
4703 if (zend_hash_quick_find(class_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void **) &pce)==FAILURE) {
4704 zend_error_noreturn(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", Z_STRVAL_P(op1));
4705 return NULL;
4706 } else {
4707 ce = *pce;
4708 }
4709 ce->refcount++;
4710 if (zend_hash_quick_add(class_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
4711 ce->refcount--;
4712 if (!compile_time) {
4713
4714
4715
4716
4717
4718 zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
4719 }
4720 return NULL;
4721 } else {
4722 if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
4723 zend_verify_abstract_class(ce TSRMLS_CC);
4724 }
4725 return ce;
4726 }
4727 }
4728
4729
4730 ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC)
4731 {
4732 zend_class_entry *ce, **pce;
4733 int found_ce;
4734 zval *op1, *op2;
4735
4736 if (compile_time) {
4737 op1 = &CONSTANT_EX(op_array, opline->op1.constant);
4738 op2 = &CONSTANT_EX(op_array, opline->op2.constant);
4739 } else {
4740 op1 = opline->op1.zv;
4741 op2 = opline->op2.zv;
4742 }
4743
4744 found_ce = zend_hash_quick_find(class_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void **) &pce);
4745
4746 if (found_ce == FAILURE) {
4747 if (!compile_time) {
4748
4749
4750
4751
4752
4753 zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare class %s", Z_STRVAL_P(op2));
4754 }
4755 return NULL;
4756 } else {
4757 ce = *pce;
4758 }
4759
4760 if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
4761 zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name, parent_ce->name);
4762 } else if ((parent_ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
4763 zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend from trait %s", ce->name, parent_ce->name);
4764 }
4765
4766 zend_do_inheritance(ce, parent_ce TSRMLS_CC);
4767
4768 ce->refcount++;
4769
4770
4771 if (zend_hash_quick_add(class_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
4772 zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
4773 }
4774 return ce;
4775 }
4776
4777
4778 void zend_do_early_binding(TSRMLS_D)
4779 {
4780 zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
4781 HashTable *table;
4782
4783 while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) {
4784 opline--;
4785 }
4786
4787 switch (opline->opcode) {
4788 case ZEND_DECLARE_FUNCTION:
4789 if (do_bind_function(CG(active_op_array), opline, CG(function_table), 1) == FAILURE) {
4790 return;
4791 }
4792 table = CG(function_table);
4793 break;
4794 case ZEND_DECLARE_CLASS:
4795 if (do_bind_class(CG(active_op_array), opline, CG(class_table), 1 TSRMLS_CC) == NULL) {
4796 return;
4797 }
4798 table = CG(class_table);
4799 break;
4800 case ZEND_DECLARE_INHERITED_CLASS:
4801 {
4802 zend_op *fetch_class_opline = opline-1;
4803 zval *parent_name;
4804 zend_class_entry **pce;
4805
4806 parent_name = &CONSTANT(fetch_class_opline->op2.constant);
4807 if ((zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) ||
4808 ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
4809 ((*pce)->type == ZEND_INTERNAL_CLASS))) {
4810 if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
4811 zend_uint *opline_num = &CG(active_op_array)->early_binding;
4812
4813 while (*opline_num != -1) {
4814 opline_num = &CG(active_op_array)->opcodes[*opline_num].result.opline_num;
4815 }
4816 *opline_num = opline - CG(active_op_array)->opcodes;
4817 opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
4818 opline->result_type = IS_UNUSED;
4819 opline->result.opline_num = -1;
4820 }
4821 return;
4822 }
4823 if (do_bind_inherited_class(CG(active_op_array), opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
4824 return;
4825 }
4826
4827 zend_del_literal(CG(active_op_array), fetch_class_opline->op2.constant);
4828 MAKE_NOP(fetch_class_opline);
4829
4830 table = CG(class_table);
4831 break;
4832 }
4833 case ZEND_VERIFY_ABSTRACT_CLASS:
4834 case ZEND_ADD_INTERFACE:
4835 case ZEND_ADD_TRAIT:
4836 case ZEND_BIND_TRAITS:
4837
4838
4839 return;
4840 default:
4841 zend_error_noreturn(E_COMPILE_ERROR, "Invalid binding type");
4842 return;
4843 }
4844
4845 zend_hash_quick_del(table, Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)), Z_HASH_P(&CONSTANT(opline->op1.constant)));
4846 zend_del_literal(CG(active_op_array), opline->op1.constant);
4847 zend_del_literal(CG(active_op_array), opline->op2.constant);
4848 MAKE_NOP(opline);
4849 }
4850
4851
4852 ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS_DC)
4853 {
4854 if (op_array->early_binding != -1) {
4855 zend_bool orig_in_compilation = CG(in_compilation);
4856 zend_uint opline_num = op_array->early_binding;
4857 zend_class_entry **pce;
4858
4859 CG(in_compilation) = 1;
4860 while (opline_num != -1) {
4861 if (zend_lookup_class(Z_STRVAL_P(op_array->opcodes[opline_num-1].op2.zv), Z_STRLEN_P(op_array->opcodes[opline_num-1].op2.zv), &pce TSRMLS_CC) == SUCCESS) {
4862 do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), *pce, 0 TSRMLS_CC);
4863 }
4864 opline_num = op_array->opcodes[opline_num].result.opline_num;
4865 }
4866 CG(in_compilation) = orig_in_compilation;
4867 }
4868 }
4869
4870
4871 void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC)
4872 {
4873 int next_op_number = get_next_op_number(CG(active_op_array));
4874 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4875
4876 opline->opcode = ZEND_JMPNZ_EX;
4877 if (expr1->op_type == IS_TMP_VAR) {
4878 SET_NODE(opline->result, expr1);
4879 } else {
4880 opline->result.var = get_temporary_variable(CG(active_op_array));
4881 opline->result_type = IS_TMP_VAR;
4882 }
4883 SET_NODE(opline->op1, expr1);
4884 SET_UNUSED(opline->op2);
4885
4886 op_token->u.op.opline_num = next_op_number;
4887
4888 GET_NODE(expr1, opline->result);
4889 }
4890
4891
4892 void zend_do_boolean_or_end(znode *result, const znode *expr1, const znode *expr2, znode *op_token TSRMLS_DC)
4893 {
4894 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4895
4896 *result = *expr1;
4897 opline->opcode = ZEND_BOOL;
4898 SET_NODE(opline->result, result);
4899 SET_NODE(opline->op1, expr2);
4900 SET_UNUSED(opline->op2);
4901
4902 CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
4903 }
4904
4905
4906 void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC)
4907 {
4908 int next_op_number = get_next_op_number(CG(active_op_array));
4909 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4910
4911 opline->opcode = ZEND_JMPZ_EX;
4912 if (expr1->op_type == IS_TMP_VAR) {
4913 SET_NODE(opline->result, expr1);
4914 } else {
4915 opline->result.var = get_temporary_variable(CG(active_op_array));
4916 opline->result_type = IS_TMP_VAR;
4917 }
4918 SET_NODE(opline->op1, expr1);
4919 SET_UNUSED(opline->op2);
4920
4921 op_token->u.op.opline_num = next_op_number;
4922
4923 GET_NODE(expr1, opline->result);
4924 }
4925
4926
4927 void zend_do_boolean_and_end(znode *result, const znode *expr1, const znode *expr2, const znode *op_token TSRMLS_DC)
4928 {
4929 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4930
4931 *result = *expr1;
4932 opline->opcode = ZEND_BOOL;
4933 SET_NODE(opline->result, result);
4934 SET_NODE(opline->op1, expr2);
4935 SET_UNUSED(opline->op2);
4936
4937 CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
4938 }
4939
4940
4941 void zend_do_do_while_begin(TSRMLS_D)
4942 {
4943 do_begin_loop(TSRMLS_C);
4944 INC_BPC(CG(active_op_array));
4945 }
4946
4947
4948 void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket, const znode *expr TSRMLS_DC)
4949 {
4950 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4951
4952 opline->opcode = ZEND_JMPNZ;
4953 SET_NODE(opline->op1, expr);
4954 opline->op2.opline_num = do_token->u.op.opline_num;
4955 SET_UNUSED(opline->op2);
4956
4957 do_end_loop(expr_open_bracket->u.op.opline_num, 0 TSRMLS_CC);
4958
4959 DEC_BPC(CG(active_op_array));
4960 }
4961
4962
4963 void zend_do_brk_cont(zend_uchar op, const znode *expr TSRMLS_DC)
4964 {
4965 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4966
4967 opline->opcode = op;
4968 opline->op1.opline_num = CG(context).current_brk_cont;
4969 SET_UNUSED(opline->op1);
4970 if (expr) {
4971 if (expr->op_type != IS_CONST) {
4972 zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand is no longer supported", op == ZEND_BRK ? "break" : "continue");
4973 } else if (Z_TYPE(expr->u.constant) != IS_LONG || Z_LVAL(expr->u.constant) < 1) {
4974 zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers", op == ZEND_BRK ? "break" : "continue");
4975 }
4976 SET_NODE(opline->op2, expr);
4977 } else {
4978 LITERAL_LONG(opline->op2, 1);
4979 opline->op2_type = IS_CONST;
4980 }
4981 }
4982
4983
4984 void zend_do_switch_cond(const znode *cond TSRMLS_DC)
4985 {
4986 zend_switch_entry switch_entry;
4987
4988 switch_entry.cond = *cond;
4989 switch_entry.default_case = -1;
4990 switch_entry.control_var = -1;
4991 zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
4992
4993 do_begin_loop(TSRMLS_C);
4994
4995 INC_BPC(CG(active_op_array));
4996 }
4997
4998
4999 void zend_do_switch_end(const znode *case_list TSRMLS_DC)
5000 {
5001 zend_op *opline;
5002 zend_switch_entry *switch_entry_ptr;
5003
5004 zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
5005
5006
5007 if (switch_entry_ptr->default_case != -1) {
5008 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5009 opline->opcode = ZEND_JMP;
5010 SET_UNUSED(opline->op1);
5011 SET_UNUSED(opline->op2);
5012 opline->op1.opline_num = switch_entry_ptr->default_case;
5013 }
5014
5015 if (case_list->op_type != IS_UNUSED) {
5016 int next_op_number = get_next_op_number(CG(active_op_array));
5017
5018 CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
5019 }
5020
5021
5022 CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
5023 CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
5024
5025 if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
5026
5027 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5028 opline->opcode = (switch_entry_ptr->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
5029 SET_NODE(opline->op1, &switch_entry_ptr->cond);
5030 SET_UNUSED(opline->op2);
5031 }
5032 if (switch_entry_ptr->cond.op_type == IS_CONST) {
5033 zval_dtor(&switch_entry_ptr->cond.u.constant);
5034 }
5035
5036 zend_stack_del_top(&CG(switch_cond_stack));
5037
5038 DEC_BPC(CG(active_op_array));
5039 }
5040
5041
5042 void zend_do_case_before_statement(const znode *case_list, znode *case_token, const znode *case_expr TSRMLS_DC)
5043 {
5044 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5045 int next_op_number;
5046 zend_switch_entry *switch_entry_ptr;
5047 znode result;
5048
5049 zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
5050
5051 if (switch_entry_ptr->control_var == -1) {
5052 switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array));
5053 }
5054 opline->opcode = ZEND_CASE;
5055 opline->result.var = switch_entry_ptr->control_var;
5056 opline->result_type = IS_TMP_VAR;
5057 SET_NODE(opline->op1, &switch_entry_ptr->cond);
5058 SET_NODE(opline->op2, case_expr);
5059 if (opline->op1_type == IS_CONST) {
5060 zval_copy_ctor(&CONSTANT(opline->op1.constant));
5061 }
5062 GET_NODE(&result, opline->result);
5063
5064 next_op_number = get_next_op_number(CG(active_op_array));
5065 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5066 opline->opcode = ZEND_JMPZ;
5067 SET_NODE(opline->op1, &result);
5068 SET_UNUSED(opline->op2);
5069 case_token->u.op.opline_num = next_op_number;
5070
5071 if (case_list->op_type==IS_UNUSED) {
5072 return;
5073 }
5074 next_op_number = get_next_op_number(CG(active_op_array));
5075 CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
5076 }
5077
5078
5079 void zend_do_case_after_statement(znode *result, const znode *case_token TSRMLS_DC)
5080 {
5081 int next_op_number = get_next_op_number(CG(active_op_array));
5082 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5083
5084 opline->opcode = ZEND_JMP;
5085 SET_UNUSED(opline->op1);
5086 SET_UNUSED(opline->op2);
5087 result->u.op.opline_num = next_op_number;
5088
5089 switch (CG(active_op_array)->opcodes[case_token->u.op.opline_num].opcode) {
5090 case ZEND_JMP:
5091 CG(active_op_array)->opcodes[case_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
5092 break;
5093 case ZEND_JMPZ:
5094 CG(active_op_array)->opcodes[case_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
5095 break;
5096 }
5097 }
5098
5099
5100 void zend_do_default_before_statement(const znode *case_list, znode *default_token TSRMLS_DC)
5101 {
5102 int next_op_number = get_next_op_number(CG(active_op_array));
5103 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5104 zend_switch_entry *switch_entry_ptr;
5105
5106 zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
5107
5108 opline->opcode = ZEND_JMP;
5109 SET_UNUSED(opline->op1);
5110 SET_UNUSED(opline->op2);
5111 default_token->u.op.opline_num = next_op_number;
5112
5113 next_op_number = get_next_op_number(CG(active_op_array));
5114 switch_entry_ptr->default_case = next_op_number;
5115
5116 if (case_list->op_type==IS_UNUSED) {
5117 return;
5118 }
5119 CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
5120 }
5121
5122
5123 void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC)
5124 {
5125 zend_op *opline;
5126 int doing_inheritance = 0;
5127 zend_class_entry *new_class_entry;
5128 char *lcname;
5129 int error = 0;
5130 zval **ns_name, key;
5131
5132 if (CG(active_class_entry)) {
5133 zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
5134 return;
5135 }
5136
5137 lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
5138
5139 if (!(strcmp(lcname, "self") && strcmp(lcname, "parent"))) {
5140 efree(lcname);
5141 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", Z_STRVAL(class_name->u.constant));
5142 }
5143
5144
5145 if (CG(current_import) &&
5146 zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
5147 error = 1;
5148 }
5149
5150 if (CG(current_namespace)) {
5151
5152 znode tmp;
5153
5154 tmp.op_type = IS_CONST;
5155 tmp.u.constant = *CG(current_namespace);
5156 zval_copy_ctor(&tmp.u.constant);
5157 zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
5158 *class_name = tmp;
5159 efree(lcname);
5160 lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
5161 }
5162
5163 if (error) {
5164 char *tmp = zend_str_tolower_dup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
5165
5166 if (Z_STRLEN_PP(ns_name) != Z_STRLEN(class_name->u.constant) ||
5167 memcmp(tmp, lcname, Z_STRLEN(class_name->u.constant))) {
5168 zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s because the name is already in use", Z_STRVAL(class_name->u.constant));
5169 }
5170 efree(tmp);
5171 }
5172
5173 new_class_entry = emalloc(sizeof(zend_class_entry));
5174 new_class_entry->type = ZEND_USER_CLASS;
5175 new_class_entry->name = zend_new_interned_string(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant) + 1, 1 TSRMLS_CC);
5176 new_class_entry->name_length = Z_STRLEN(class_name->u.constant);
5177
5178 zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
5179 new_class_entry->info.user.filename = zend_get_compiled_filename(TSRMLS_C);
5180 new_class_entry->info.user.line_start = class_token->u.op.opline_num;
5181 new_class_entry->ce_flags |= class_token->EA;
5182
5183 if (parent_class_name && parent_class_name->op_type != IS_UNUSED) {
5184 switch (parent_class_name->EA) {
5185 case ZEND_FETCH_CLASS_SELF:
5186 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'self' as class name as it is reserved");
5187 break;
5188 case ZEND_FETCH_CLASS_PARENT:
5189 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved");
5190 break;
5191 case ZEND_FETCH_CLASS_STATIC:
5192 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as class name as it is reserved");
5193 break;
5194 default:
5195 break;
5196 }
5197 doing_inheritance = 1;
5198 }
5199
5200 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5201 opline->op1_type = IS_CONST;
5202 build_runtime_defined_function_key(&key, lcname, new_class_entry->name_length TSRMLS_CC);
5203 opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
5204 Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
5205
5206 opline->op2_type = IS_CONST;
5207
5208 if (doing_inheritance) {
5209
5210 if ((new_class_entry->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
5211 zend_error_noreturn(E_COMPILE_ERROR, "A trait (%s) cannot extend a class. Traits can only be composed from other traits with the 'use' keyword. Error", new_class_entry->name);
5212 }
5213
5214 opline->extended_value = parent_class_name->u.op.var;
5215 opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
5216 } else {
5217 opline->opcode = ZEND_DECLARE_CLASS;
5218 }
5219
5220 LITERAL_STRINGL(opline->op2, lcname, new_class_entry->name_length, 0);
5221 CALCULATE_LITERAL_HASH(opline->op2.constant);
5222
5223 zend_hash_quick_update(CG(class_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &new_class_entry, sizeof(zend_class_entry *), NULL);
5224 CG(active_class_entry) = new_class_entry;
5225
5226 opline->result.var = get_temporary_variable(CG(active_op_array));
5227 opline->result_type = IS_VAR;
5228 GET_NODE(&CG(implementing_class), opline->result);
5229
5230 if (CG(doc_comment)) {
5231 CG(active_class_entry)->info.user.doc_comment = CG(doc_comment);
5232 CG(active_class_entry)->info.user.doc_comment_len = CG(doc_comment_len);
5233 CG(doc_comment) = NULL;
5234 CG(doc_comment_len) = 0;
5235 }
5236 }
5237
5238
5239 static void do_verify_abstract_class(TSRMLS_D)
5240 {
5241 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5242
5243 opline->opcode = ZEND_VERIFY_ABSTRACT_CLASS;
5244 SET_NODE(opline->op1, &CG(implementing_class));
5245 SET_UNUSED(opline->op2);
5246 }
5247
5248
5249 void zend_do_end_class_declaration(const znode *class_token, const znode *parent_token TSRMLS_DC)
5250 {
5251 zend_class_entry *ce = CG(active_class_entry);
5252
5253 if (ce->constructor) {
5254 ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
5255 if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
5256 zend_error_noreturn(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static", ce->name, ce->constructor->common.function_name);
5257 }
5258 }
5259 if (ce->destructor) {
5260 ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
5261 if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
5262 zend_error_noreturn(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static", ce->name, ce->destructor->common.function_name);
5263 }
5264 }
5265 if (ce->clone) {
5266 ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
5267 if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
5268 zend_error_noreturn(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static", ce->name, ce->clone->common.function_name);
5269 }
5270 }
5271
5272 ce->info.user.line_end = zend_get_compiled_lineno(TSRMLS_C);
5273
5274
5275
5276
5277 if (ce->num_traits > 0) {
5278 zend_op *opline;
5279
5280 ce->traits = NULL;
5281 ce->num_traits = 0;
5282 ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS;
5283
5284
5285 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5286 opline->opcode = ZEND_BIND_TRAITS;
5287 SET_NODE(opline->op1, &CG(implementing_class));
5288 }
5289
5290 if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
5291 && (parent_token || (ce->num_interfaces > 0))) {
5292 zend_verify_abstract_class(ce TSRMLS_CC);
5293 if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) {
5294 do_verify_abstract_class(TSRMLS_C);
5295 }
5296 }
5297
5298
5299
5300
5301 if (ce->num_interfaces > 0) {
5302 ce->interfaces = NULL;
5303 ce->num_interfaces = 0;
5304 ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
5305 }
5306
5307 CG(active_class_entry) = NULL;
5308 }
5309
5310
5311 void zend_do_implements_interface(znode *interface_name TSRMLS_DC)
5312 {
5313 zend_op *opline;
5314
5315
5316 if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
5317 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as interface on '%s' since it is a Trait",
5318 Z_STRVAL(interface_name->u.constant),
5319 CG(active_class_entry)->name);
5320 }
5321
5322 switch (zend_get_class_fetch_type(Z_STRVAL(interface_name->u.constant), Z_STRLEN(interface_name->u.constant))) {
5323 case ZEND_FETCH_CLASS_SELF:
5324 case ZEND_FETCH_CLASS_PARENT:
5325 case ZEND_FETCH_CLASS_STATIC:
5326 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as interface name as it is reserved", Z_STRVAL(interface_name->u.constant));
5327 break;
5328 default:
5329 break;
5330 }
5331
5332 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5333 opline->opcode = ZEND_ADD_INTERFACE;
5334 SET_NODE(opline->op1, &CG(implementing_class));
5335 zend_resolve_class_name(interface_name TSRMLS_CC);
5336 opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;
5337 opline->op2_type = IS_CONST;
5338 opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &interface_name->u.constant TSRMLS_CC);
5339 CG(active_class_entry)->num_interfaces++;
5340 }
5341
5342
5343 void zend_do_use_trait(znode *trait_name TSRMLS_DC)
5344 {
5345 zend_op *opline;
5346
5347 if ((CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
5348 zend_error_noreturn(E_COMPILE_ERROR,
5349 "Cannot use traits inside of interfaces. %s is used in %s",
5350 Z_STRVAL(trait_name->u.constant), CG(active_class_entry)->name);
5351 }
5352
5353
5354 switch (zend_get_class_fetch_type(Z_STRVAL(trait_name->u.constant), Z_STRLEN(trait_name->u.constant))) {
5355 case ZEND_FETCH_CLASS_SELF:
5356 case ZEND_FETCH_CLASS_PARENT:
5357 case ZEND_FETCH_CLASS_STATIC:
5358 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as trait name as it is reserved", Z_STRVAL(trait_name->u.constant));
5359 break;
5360 default:
5361 break;
5362 }
5363
5364 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5365 opline->opcode = ZEND_ADD_TRAIT;
5366 SET_NODE(opline->op1, &CG(implementing_class));
5367 zend_resolve_class_name(trait_name TSRMLS_CC);
5368 opline->extended_value = ZEND_FETCH_CLASS_TRAIT;
5369 opline->op2_type = IS_CONST;
5370 opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &trait_name->u.constant TSRMLS_CC);
5371 CG(active_class_entry)->num_traits++;
5372 }
5373
5374
5375 ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, const char *src1, int src1_length, const char *src2, int src2_length, int internal)
5376 {
5377 char *prop_name;
5378 int prop_name_length;
5379
5380 prop_name_length = 1 + src1_length + 1 + src2_length;
5381 prop_name = pemalloc(prop_name_length + 1, internal);
5382 prop_name[0] = '\0';
5383 memcpy(prop_name + 1, src1, src1_length+1);
5384 memcpy(prop_name + 1 + src1_length + 1, src2, src2_length+1);
5385
5386 *dest = prop_name;
5387 *dest_length = prop_name_length;
5388 }
5389
5390
5391 static int zend_strnlen(const char* s, int maxlen)
5392 {
5393 int len = 0;
5394 while (*s++ && maxlen--) len++;
5395 return len;
5396 }
5397
5398
5399 ZEND_API int zend_unmangle_property_name_ex(const char *mangled_property, int len, const char **class_name, const char **prop_name, int *prop_len)
5400 {
5401 int class_name_len;
5402
5403 *class_name = NULL;
5404
5405 if (mangled_property[0]!=0) {
5406 *prop_name = mangled_property;
5407 if (prop_len) {
5408 *prop_len = len;
5409 }
5410 return SUCCESS;
5411 }
5412 if (len < 3 || mangled_property[1]==0) {
5413 zend_error(E_NOTICE, "Illegal member variable name");
5414 *prop_name = mangled_property;
5415 if (prop_len) {
5416 *prop_len = len;
5417 }
5418 return FAILURE;
5419 }
5420
5421 class_name_len = zend_strnlen(mangled_property + 1, --len - 1) + 1;
5422 if (class_name_len >= len || mangled_property[class_name_len]!=0) {
5423 zend_error(E_NOTICE, "Corrupt member variable name");
5424 *prop_name = mangled_property;
5425 if (prop_len) {
5426 *prop_len = len + 1;
5427 }
5428 return FAILURE;
5429 }
5430 *class_name = mangled_property + 1;
5431 *prop_name = (*class_name) + class_name_len;
5432 if (prop_len) {
5433 *prop_len = len - class_name_len;
5434 }
5435 return SUCCESS;
5436 }
5437
5438
5439 void zend_do_declare_property(const znode *var_name, const znode *value, zend_uint access_type TSRMLS_DC)
5440 {
5441 zval *property;
5442 zend_property_info *existing_property_info;
5443 char *comment = NULL;
5444 int comment_len = 0;
5445
5446 if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
5447 zend_error_noreturn(E_COMPILE_ERROR, "Interfaces may not include member variables");
5448 }
5449
5450 if (access_type & ZEND_ACC_ABSTRACT) {
5451 zend_error_noreturn(E_COMPILE_ERROR, "Properties cannot be declared abstract");
5452 }
5453
5454 if (access_type & ZEND_ACC_FINAL) {
5455 zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, the final modifier is allowed only for methods and classes",
5456 CG(active_class_entry)->name, Z_STRVAL(var_name->u.constant));
5457 }
5458
5459 if (zend_hash_find(&CG(active_class_entry)->properties_info, Z_STRVAL(var_name->u.constant), Z_STRLEN(var_name->u.constant)+1, (void **) &existing_property_info)==SUCCESS) {
5460 zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, Z_STRVAL(var_name->u.constant));
5461 }
5462 ALLOC_ZVAL(property);
5463
5464 if (value) {
5465 *property = value->u.constant;
5466 } else {
5467 INIT_PZVAL(property);
5468 Z_TYPE_P(property) = IS_NULL;
5469 }
5470
5471 if (CG(doc_comment)) {
5472 comment = CG(doc_comment);
5473 comment_len = CG(doc_comment_len);
5474 CG(doc_comment) = NULL;
5475 CG(doc_comment_len) = 0;
5476 }
5477
5478 zend_declare_property_ex(CG(active_class_entry), zend_new_interned_string(Z_STRVAL(var_name->u.constant), Z_STRLEN(var_name->u.constant) + 1, 0 TSRMLS_CC), Z_STRLEN(var_name->u.constant), property, access_type, comment, comment_len TSRMLS_CC);
5479 efree(Z_STRVAL(var_name->u.constant));
5480 }
5481
5482
5483 void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_DC)
5484 {
5485 zval *property;
5486 const char *cname = NULL;
5487 zend_ulong hash;
5488
5489 if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
5490 zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants");
5491 return;
5492 }
5493
5494 ALLOC_ZVAL(property);
5495 *property = value->u.constant;
5496
5497 cname = zend_new_interned_string(Z_STRVAL(var_name->u.constant), Z_STRLEN(var_name->u.constant)+1, 0 TSRMLS_CC);
5498 hash = str_hash(cname, Z_STRLEN(var_name->u.constant));
5499 if (zend_hash_quick_add(&CG(active_class_entry)->constants_table, cname, Z_STRLEN(var_name->u.constant)+1, hash, &property, sizeof(zval *), NULL) == FAILURE) {
5500 FREE_ZVAL(property);
5501 zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name, Z_STRVAL(var_name->u.constant));
5502 }
5503 FREE_PNODE(var_name);
5504
5505 if (CG(doc_comment)) {
5506 efree(CG(doc_comment));
5507 CG(doc_comment) = NULL;
5508 CG(doc_comment_len) = 0;
5509 }
5510 }
5511
5512
5513 void zend_do_fetch_property(znode *result, znode *object, const znode *property TSRMLS_DC)
5514 {
5515 zend_op opline;
5516 zend_llist *fetch_list_ptr;
5517
5518 zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
5519
5520 if (object->op_type == IS_CV) {
5521 if (object->u.op.var == CG(active_op_array)->this_var) {
5522 object->op_type = IS_UNUSED;
5523 }
5524 } else if (fetch_list_ptr->count == 1) {
5525 zend_llist_element *le = fetch_list_ptr->head;
5526 zend_op *opline_ptr = (zend_op *) le->data;
5527
5528 if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
5529 zend_del_literal(CG(active_op_array), opline_ptr->op1.constant);
5530 SET_UNUSED(opline_ptr->op1);
5531 SET_NODE(opline_ptr->op2, property);
5532
5533 switch (opline_ptr->opcode) {
5534 case ZEND_FETCH_W:
5535 opline_ptr->opcode = ZEND_FETCH_OBJ_W;
5536 break;
5537 case ZEND_FETCH_R:
5538 opline_ptr->opcode = ZEND_FETCH_OBJ_R;
5539 break;
5540 case ZEND_FETCH_RW:
5541 opline_ptr->opcode = ZEND_FETCH_OBJ_RW;
5542 break;
5543 case ZEND_FETCH_IS:
5544 opline_ptr->opcode = ZEND_FETCH_OBJ_IS;
5545 break;
5546 case ZEND_FETCH_UNSET:
5547 opline_ptr->opcode = ZEND_FETCH_OBJ_UNSET;
5548 break;
5549 case ZEND_FETCH_FUNC_ARG:
5550 opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG;
5551 break;
5552 }
5553 if (opline_ptr->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline_ptr->op2.constant)) == IS_STRING) {
5554 CALCULATE_LITERAL_HASH(opline_ptr->op2.constant);
5555 GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op2.constant);
5556 }
5557 GET_NODE(result, opline_ptr->result);
5558 return;
5559 }
5560 }
5561
5562 if (zend_is_function_or_method_call(object)) {
5563 init_op(&opline TSRMLS_CC);
5564 opline.opcode = ZEND_SEPARATE;
5565 SET_NODE(opline.op1, object);
5566 SET_UNUSED(opline.op2);
5567 opline.result_type = IS_VAR;
5568 opline.result.var = opline.op1.var;
5569 zend_llist_add_element(fetch_list_ptr, &opline);
5570 }
5571
5572 init_op(&opline TSRMLS_CC);
5573 opline.opcode = ZEND_FETCH_OBJ_W;
5574 opline.result_type = IS_VAR;
5575 opline.result.var = get_temporary_variable(CG(active_op_array));
5576 SET_NODE(opline.op1, object);
5577 SET_NODE(opline.op2, property);
5578 if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
5579 CALCULATE_LITERAL_HASH(opline.op2.constant);
5580 GET_POLYMORPHIC_CACHE_SLOT(opline.op2.constant);
5581 }
5582 GET_NODE(result, opline.result);
5583
5584 zend_llist_add_element(fetch_list_ptr, &opline);
5585 }
5586
5587
5588 void zend_do_halt_compiler_register(TSRMLS_D)
5589 {
5590 char *name, *cfilename;
5591 char haltoff[] = "__COMPILER_HALT_OFFSET__";
5592 int len, clen;
5593
5594 if (CG(has_bracketed_namespaces) && CG(in_namespace)) {
5595 zend_error_noreturn(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope");
5596 }
5597
5598 cfilename = zend_get_compiled_filename(TSRMLS_C);
5599 clen = strlen(cfilename);
5600 zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, cfilename, clen, 0);
5601 zend_register_long_constant(name, len+1, zend_get_scanned_file_offset(TSRMLS_C), CONST_CS, 0 TSRMLS_CC);
5602 pefree(name, 0);
5603
5604 if (CG(in_namespace)) {
5605 zend_do_end_namespace(TSRMLS_C);
5606 }
5607 }
5608
5609
5610 void zend_do_push_object(const znode *object TSRMLS_DC)
5611 {
5612 zend_stack_push(&CG(object_stack), object, sizeof(znode));
5613 }
5614
5615
5616 void zend_do_pop_object(znode *object TSRMLS_DC)
5617 {
5618 if (object) {
5619 znode *tmp;
5620
5621 zend_stack_top(&CG(object_stack), (void **) &tmp);
5622 *object = *tmp;
5623 }
5624 zend_stack_del_top(&CG(object_stack));
5625 }
5626
5627
5628 void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC)
5629 {
5630 zend_op *opline;
5631
5632 new_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
5633 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5634 opline->opcode = ZEND_NEW;
5635 opline->extended_value = CG(context).nested_calls;
5636 opline->result_type = IS_VAR;
5637 opline->result.var = get_temporary_variable(CG(active_op_array));
5638 SET_NODE(opline->op1, class_type);
5639 SET_UNUSED(opline->op2);
5640
5641 zend_push_function_call_entry(NULL TSRMLS_CC);
5642 if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
5643 CG(active_op_array)->nested_calls = CG(context).nested_calls;
5644 }
5645 }
5646
5647
5648 void zend_do_end_new_object(znode *result, const znode *new_token TSRMLS_DC)
5649 {
5650 znode ctor_result;
5651
5652 zend_do_end_function_call(NULL, &ctor_result, 1, 0 TSRMLS_CC);
5653 zend_do_free(&ctor_result TSRMLS_CC);
5654
5655 CG(active_op_array)->opcodes[new_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
5656 GET_NODE(result, CG(active_op_array)->opcodes[new_token->u.op.opline_num].result);
5657 }
5658
5659
5660 static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal_constants_substitution TSRMLS_DC)
5661 {
5662 zend_constant *c = NULL;
5663
5664 if (Z_STRVAL_P(const_name)[0] == '\\') {
5665 if (zend_hash_find(EG(zend_constants), Z_STRVAL_P(const_name)+1, Z_STRLEN_P(const_name), (void **) &c) == FAILURE) {
5666 char *lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name)+1, Z_STRLEN_P(const_name)-1);
5667
5668 if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name), (void **) &c)==SUCCESS) {
5669 if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
5670 efree(lookup_name);
5671 return c;
5672 }
5673 }
5674 efree(lookup_name);
5675 return NULL;
5676 }
5677 } else if (zend_hash_find(EG(zend_constants), Z_STRVAL_P(const_name), Z_STRLEN_P(const_name)+1, (void **) &c) == FAILURE) {
5678 char *lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name), Z_STRLEN_P(const_name));
5679
5680 if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name)+1, (void **) &c)==SUCCESS) {
5681 if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
5682 efree(lookup_name);
5683 return c;
5684 }
5685 }
5686 efree(lookup_name);
5687 return NULL;
5688 }
5689 if (c->flags & CONST_CT_SUBST) {
5690 return c;
5691 }
5692 if (all_internal_constants_substitution &&
5693 (c->flags & CONST_PERSISTENT) &&
5694 !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
5695 !IS_CONSTANT_TYPE(Z_TYPE(c->value))) {
5696 return c;
5697 }
5698 return NULL;
5699 }
5700
5701
5702 static int zend_constant_ct_subst(znode *result, zval *const_name, int all_internal_constants_substitution TSRMLS_DC)
5703 {
5704 zend_constant *c = zend_get_ct_const(const_name, all_internal_constants_substitution TSRMLS_CC);
5705
5706 if (c) {
5707 zval_dtor(const_name);
5708 result->op_type = IS_CONST;
5709 result->u.constant = c->value;
5710 zval_copy_ctor(&result->u.constant);
5711 INIT_PZVAL(&result->u.constant);
5712 return 1;
5713 }
5714 return 0;
5715 }
5716
5717
5718 void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC)
5719 {
5720 znode tmp;
5721 zend_op *opline;
5722 int type;
5723 char *compound;
5724 ulong fetch_type = 0;
5725
5726 if (constant_container) {
5727 switch (mode) {
5728 case ZEND_CT:
5729
5730 type = zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant));
5731
5732 if (ZEND_FETCH_CLASS_STATIC == type) {
5733 zend_error(E_ERROR, "\"static::\" is not allowed in compile-time constants");
5734 } else if (ZEND_FETCH_CLASS_DEFAULT == type) {
5735 zend_resolve_class_name(constant_container TSRMLS_CC);
5736 }
5737 zend_do_build_full_name(NULL, constant_container, constant_name, 1 TSRMLS_CC);
5738 *result = *constant_container;
5739 result->u.constant.type = IS_CONSTANT | fetch_type;
5740 break;
5741 case ZEND_RT:
5742 if (constant_container->op_type == IS_CONST &&
5743 ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant))) {
5744 zend_resolve_class_name(constant_container TSRMLS_CC);
5745 } else {
5746 zend_do_fetch_class(&tmp, constant_container TSRMLS_CC);
5747 constant_container = &tmp;
5748 }
5749 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5750 opline->opcode = ZEND_FETCH_CONSTANT;
5751 opline->result_type = IS_TMP_VAR;
5752 opline->result.var = get_temporary_variable(CG(active_op_array));
5753 if (constant_container->op_type == IS_CONST) {
5754 opline->op1_type = IS_CONST;
5755 opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), &constant_container->u.constant TSRMLS_CC);
5756 } else {
5757 SET_NODE(opline->op1, constant_container);
5758 }
5759 SET_NODE(opline->op2, constant_name);
5760 CALCULATE_LITERAL_HASH(opline->op2.constant);
5761 if (opline->op1_type == IS_CONST) {
5762 GET_CACHE_SLOT(opline->op2.constant);
5763 } else {
5764 GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
5765 }
5766 GET_NODE(result, opline->result);
5767 break;
5768 }
5769 return;
5770 }
5771
5772
5773 switch (mode) {
5774 case ZEND_CT:
5775 compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
5776
5777
5778 if (zend_constant_ct_subst(result, &constant_name->u.constant, 0 TSRMLS_CC)) {
5779 break;
5780 }
5781
5782 zend_resolve_const_name(constant_name, &check_namespace TSRMLS_CC);
5783
5784 if(!compound) {
5785 fetch_type |= IS_CONSTANT_UNQUALIFIED;
5786 }
5787
5788 *result = *constant_name;
5789 result->u.constant.type = IS_CONSTANT | fetch_type;
5790 break;
5791 case ZEND_RT:
5792 compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
5793
5794 zend_resolve_const_name(constant_name, &check_namespace TSRMLS_CC);
5795
5796 if(zend_constant_ct_subst(result, &constant_name->u.constant, 1 TSRMLS_CC)) {
5797 break;
5798 }
5799
5800 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5801 opline->opcode = ZEND_FETCH_CONSTANT;
5802 opline->result_type = IS_TMP_VAR;
5803 opline->result.var = get_temporary_variable(CG(active_op_array));
5804 GET_NODE(result, opline->result);
5805 SET_UNUSED(opline->op1);
5806 opline->op2_type = IS_CONST;
5807 if (compound) {
5808
5809 opline->extended_value = 0;
5810 opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC);
5811 } else {
5812 opline->extended_value = IS_CONSTANT_UNQUALIFIED;
5813 if (check_namespace && CG(current_namespace)) {
5814 opline->extended_value |= IS_CONSTANT_IN_NAMESPACE;
5815 opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 1 TSRMLS_CC);
5816 } else {
5817 opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC);
5818 }
5819 }
5820 GET_CACHE_SLOT(opline->op2.constant);
5821 break;
5822 }
5823 }
5824
5825
5826 void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC)
5827 {
5828 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5829
5830 switch (cmd->op_type) {
5831 case IS_CONST:
5832 case IS_TMP_VAR:
5833 opline->opcode = ZEND_SEND_VAL;
5834 break;
5835 default:
5836 opline->opcode = ZEND_SEND_VAR;
5837 break;
5838 }
5839 SET_NODE(opline->op1, cmd);
5840 opline->op2.opline_num = 1;
5841 opline->extended_value = ZEND_DO_FCALL;
5842 SET_UNUSED(opline->op2);
5843
5844
5845 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5846 opline->opcode = ZEND_DO_FCALL;
5847 opline->result.var = get_temporary_variable(CG(active_op_array));
5848 opline->result_type = IS_VAR;
5849 LITERAL_STRINGL(opline->op1, estrndup("shell_exec", sizeof("shell_exec")-1), sizeof("shell_exec")-1, 0);
5850 CALCULATE_LITERAL_HASH(opline->op1.constant);
5851 opline->op1_type = IS_CONST;
5852 GET_CACHE_SLOT(opline->op1.constant);
5853 opline->extended_value = 1;
5854 SET_UNUSED(opline->op2);
5855 opline->op2.num = CG(context).nested_calls;
5856 GET_NODE(result, opline->result);
5857
5858 if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
5859 CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
5860 }
5861 if (CG(context).used_stack + 2 > CG(active_op_array)->used_stack) {
5862 CG(active_op_array)->used_stack = CG(context).used_stack + 2;
5863 }
5864 }
5865
5866
5867 void zend_do_init_array(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC)
5868 {
5869 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5870
5871 opline->opcode = ZEND_INIT_ARRAY;
5872 opline->result.var = get_temporary_variable(CG(active_op_array));
5873 opline->result_type = IS_TMP_VAR;
5874 GET_NODE(result, opline->result);
5875 if (expr) {
5876 SET_NODE(opline->op1, expr);
5877 if (offset) {
5878 SET_NODE(opline->op2, offset);
5879 if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) {
5880 ulong index;
5881 int numeric = 0;
5882
5883 ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline->op2.constant)), Z_STRLEN(CONSTANT(opline->op2.constant))+1, index, numeric = 1);
5884 if (numeric) {
5885 zval_dtor(&CONSTANT(opline->op2.constant));
5886 ZVAL_LONG(&CONSTANT(opline->op2.constant), index);
5887 } else {
5888 CALCULATE_LITERAL_HASH(opline->op2.constant);
5889 }
5890 }
5891 } else {
5892 SET_UNUSED(opline->op2);
5893 }
5894 } else {
5895 SET_UNUSED(opline->op1);
5896 SET_UNUSED(opline->op2);
5897 }
5898 opline->extended_value = is_ref;
5899 }
5900
5901
5902 void zend_do_add_array_element(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC)
5903 {
5904 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
5905
5906 opline->opcode = ZEND_ADD_ARRAY_ELEMENT;
5907 SET_NODE(opline->result, result);
5908 SET_NODE(opline->op1, expr);
5909 if (offset) {
5910 SET_NODE(opline->op2, offset);
5911 if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) {
5912 ulong index;
5913 int numeric = 0;
5914
5915 ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline->op2.constant)), Z_STRLEN(CONSTANT(opline->op2.constant))+1, index, numeric = 1);
5916 if (numeric) {
5917 zval_dtor(&CONSTANT(opline->op2.constant));
5918 ZVAL_LONG(&CONSTANT(opline->op2.constant), index);
5919 } else {
5920 CALCULATE_LITERAL_HASH(opline->op2.constant);
5921 }
5922 }
5923 } else {
5924 SET_UNUSED(opline->op2);
5925 }
5926 opline->extended_value = is_ref;
5927 }
5928
5929
5930 void zend_do_add_static_array_element(zval *result, zval *offset, const zval *expr)
5931 {
5932 if (offset) {
5933 switch (Z_TYPE_P(offset)) {
5934 case IS_STRING:
5935 zend_symtable_update(Z_ARRVAL_P(result), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, &expr, sizeof(zval *), NULL);
5936 zval_dtor(offset);
5937 break;
5938 case IS_NULL:
5939 zend_symtable_update(Z_ARRVAL_P(result), "", 1, &expr, sizeof(zval *), NULL);
5940 break;
5941 case IS_LONG:
5942 case IS_BOOL:
5943 zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(offset), &expr, sizeof(zval *), NULL);
5944 break;
5945 case IS_DOUBLE:
5946 zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), &expr, sizeof(zval *), NULL);
5947 break;
5948 case IS_ARRAY:
5949 zend_error(E_ERROR, "Illegal offset type");
5950 break;
5951 }
5952 } else {
5953 zend_hash_next_index_insert(Z_ARRVAL_P(result), &expr, sizeof(zval *), NULL);
5954 }
5955 }
5956
5957
5958 void zend_do_add_list_element(const znode *element TSRMLS_DC)
5959 {
5960 list_llist_element lle;
5961
5962 if (element) {
5963 zend_check_writable_variable(element);
5964
5965 lle.var = *element;
5966 zend_llist_copy(&lle.dimensions, &CG(dimension_llist));
5967 zend_llist_prepend_element(&CG(list_llist), &lle);
5968 }
5969 (*((int *)CG(dimension_llist).tail->data))++;
5970 }
5971
5972
5973 void zend_do_new_list_begin(TSRMLS_D)
5974 {
5975 int current_dimension = 0;
5976 zend_llist_add_element(&CG(dimension_llist), ¤t_dimension);
5977 }
5978
5979
5980 void zend_do_new_list_end(TSRMLS_D)
5981 {
5982 zend_llist_remove_tail(&CG(dimension_llist));
5983 (*((int *)CG(dimension_llist).tail->data))++;
5984 }
5985
5986
5987 void zend_do_list_init(TSRMLS_D)
5988 {
5989 zend_stack_push(&CG(list_stack), &CG(list_llist), sizeof(zend_llist));
5990 zend_stack_push(&CG(list_stack), &CG(dimension_llist), sizeof(zend_llist));
5991 zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
5992 zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
5993 zend_do_new_list_begin(TSRMLS_C);
5994 }
5995
5996
5997 void zend_do_list_end(znode *result, znode *expr TSRMLS_DC)
5998 {
5999 zend_llist_element *le;
6000 zend_llist_element *dimension;
6001 zend_op *opline;
6002 znode last_container;
6003
6004 le = CG(list_llist).head;
6005 while (le) {
6006 zend_llist *tmp_dimension_llist = &((list_llist_element *)le->data)->dimensions;
6007 dimension = tmp_dimension_llist->head;
6008 while (dimension) {
6009 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6010 if (dimension == tmp_dimension_llist->head) {
6011 last_container = *expr;
6012 switch (expr->op_type) {
6013 case IS_VAR:
6014 case IS_CV:
6015 opline->opcode = ZEND_FETCH_DIM_R;
6016 break;
6017 case IS_TMP_VAR:
6018 opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
6019 break;
6020 case IS_CONST:
6021 zval_copy_ctor(&expr->u.constant);
6022 opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
6023 break;
6024 }
6025 opline->extended_value |= ZEND_FETCH_ADD_LOCK;
6026 } else {
6027 opline->opcode = ZEND_FETCH_DIM_R;
6028 }
6029 opline->result_type = IS_VAR;
6030 opline->result.var = get_temporary_variable(CG(active_op_array));
6031 SET_NODE(opline->op1, &last_container);
6032 opline->op2_type = IS_CONST;
6033 LITERAL_LONG(opline->op2, *((int *) dimension->data));
6034 GET_NODE(&last_container, opline->result);
6035 dimension = dimension->next;
6036 }
6037 ((list_llist_element *) le->data)->value = last_container;
6038 zend_llist_destroy(&((list_llist_element *) le->data)->dimensions);
6039 zend_do_assign(result, &((list_llist_element *) le->data)->var, &((list_llist_element *) le->data)->value TSRMLS_CC);
6040 zend_do_free(result TSRMLS_CC);
6041 le = le->next;
6042 }
6043 zend_llist_destroy(&CG(dimension_llist));
6044 zend_llist_destroy(&CG(list_llist));
6045 *result = *expr;
6046 {
6047 zend_llist *p;
6048
6049
6050 zend_stack_top(&CG(list_stack), (void **) &p);
6051 CG(dimension_llist) = *p;
6052 zend_stack_del_top(&CG(list_stack));
6053 zend_stack_top(&CG(list_stack), (void **) &p);
6054 CG(list_llist) = *p;
6055 zend_stack_del_top(&CG(list_stack));
6056 }
6057 }
6058
6059
6060 void zend_init_list(void *result, void *item TSRMLS_DC)
6061 {
6062 void** list = emalloc(sizeof(void*) * 2);
6063
6064 list[0] = item;
6065 list[1] = NULL;
6066
6067 *(void**)result = list;
6068 }
6069
6070
6071 void zend_add_to_list(void *result, void *item TSRMLS_DC)
6072 {
6073 void** list = *(void**)result;
6074 size_t n = 0;
6075
6076 if (list) {
6077 while (list[n]) {
6078 n++;
6079 }
6080 }
6081
6082 list = erealloc(list, sizeof(void*) * (n+2));
6083
6084 list[n] = item;
6085 list[n+1] = NULL;
6086
6087 *(void**)result = list;
6088 }
6089
6090
6091 void zend_do_fetch_static_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC)
6092 {
6093 zval *tmp;
6094 zend_op *opline;
6095 znode lval;
6096 znode result;
6097
6098 ALLOC_ZVAL(tmp);
6099
6100 if (static_assignment) {
6101 *tmp = static_assignment->u.constant;
6102 } else {
6103 INIT_ZVAL(*tmp);
6104 }
6105 if (!CG(active_op_array)->static_variables) {
6106 if (CG(active_op_array)->scope) {
6107 CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
6108 }
6109 ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
6110 zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
6111 }
6112 zend_hash_update(CG(active_op_array)->static_variables, Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant)+1, &tmp, sizeof(zval *), NULL);
6113
6114 if (varname->op_type == IS_CONST) {
6115 if (Z_TYPE(varname->u.constant) != IS_STRING) {
6116 convert_to_string(&varname->u.constant);
6117 }
6118 }
6119
6120 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6121 opline->opcode = (fetch_type == ZEND_FETCH_LEXICAL) ? ZEND_FETCH_R : ZEND_FETCH_W;
6122 opline->result_type = IS_VAR;
6123 opline->result.var = get_temporary_variable(CG(active_op_array));
6124 SET_NODE(opline->op1, varname);
6125 if (opline->op1_type == IS_CONST) {
6126 CALCULATE_LITERAL_HASH(opline->op1.constant);
6127 }
6128 SET_UNUSED(opline->op2);
6129 opline->extended_value = ZEND_FETCH_STATIC;
6130 GET_NODE(&result, opline->result);
6131
6132 if (varname->op_type == IS_CONST) {
6133 zval_copy_ctor(&varname->u.constant);
6134 }
6135 fetch_simple_variable(&lval, varname, 0 TSRMLS_CC);
6136
6137 if (fetch_type == ZEND_FETCH_LEXICAL) {
6138 znode dummy;
6139
6140 zend_do_begin_variable_parse(TSRMLS_C);
6141 zend_do_assign(&dummy, &lval, &result TSRMLS_CC);
6142 zend_do_free(&dummy TSRMLS_CC);
6143 } else {
6144 zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
6145 }
6146 CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result_type |= EXT_TYPE_UNUSED;
6147 }
6148
6149
6150 void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC)
6151 {
6152 znode value;
6153
6154 if (Z_STRLEN(varname->u.constant) == sizeof("this") - 1 &&
6155 memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1) == 0) {
6156 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
6157 return;
6158 }
6159
6160 value.op_type = IS_CONST;
6161 ZVAL_NULL(&value.u.constant);
6162 Z_TYPE(value.u.constant) |= is_ref ? IS_LEXICAL_REF : IS_LEXICAL_VAR;
6163 Z_SET_REFCOUNT_P(&value.u.constant, 1);
6164 Z_UNSET_ISREF_P(&value.u.constant);
6165
6166 zend_do_fetch_static_variable(varname, &value, is_ref ? ZEND_FETCH_STATIC : ZEND_FETCH_LEXICAL TSRMLS_CC);
6167 }
6168
6169
6170 void zend_do_fetch_global_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC)
6171 {
6172 zend_op *opline;
6173 znode lval;
6174 znode result;
6175
6176 if (varname->op_type == IS_CONST) {
6177 if (Z_TYPE(varname->u.constant) != IS_STRING) {
6178 convert_to_string(&varname->u.constant);
6179 }
6180 }
6181
6182 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6183 opline->opcode = ZEND_FETCH_W;
6184 opline->result_type = IS_VAR;
6185 opline->result.var = get_temporary_variable(CG(active_op_array));
6186 SET_NODE(opline->op1, varname);
6187 if (opline->op1_type == IS_CONST) {
6188 CALCULATE_LITERAL_HASH(opline->op1.constant);
6189 }
6190 SET_UNUSED(opline->op2);
6191 opline->extended_value = fetch_type;
6192 GET_NODE(&result, opline->result);
6193
6194 if (varname->op_type == IS_CONST) {
6195 zval_copy_ctor(&varname->u.constant);
6196 }
6197 fetch_simple_variable(&lval, varname, 0 TSRMLS_CC);
6198
6199 zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
6200 CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result_type |= EXT_TYPE_UNUSED;
6201 }
6202
6203
6204 void zend_do_cast(znode *result, const znode *expr, int type TSRMLS_DC)
6205 {
6206 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6207
6208 opline->opcode = ZEND_CAST;
6209 opline->result_type = IS_TMP_VAR;
6210 opline->result.var = get_temporary_variable(CG(active_op_array));
6211 SET_NODE(opline->op1, expr);
6212 SET_UNUSED(opline->op2);
6213 opline->extended_value = type;
6214 GET_NODE(result, opline->result);
6215 }
6216
6217
6218 void zend_do_include_or_eval(int type, znode *result, const znode *op1 TSRMLS_DC)
6219 {
6220 zend_do_extended_fcall_begin(TSRMLS_C);
6221 {
6222 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6223
6224 opline->opcode = ZEND_INCLUDE_OR_EVAL;
6225 opline->result_type = IS_VAR;
6226 opline->result.var = get_temporary_variable(CG(active_op_array));
6227 SET_NODE(opline->op1, op1);
6228 SET_UNUSED(opline->op2);
6229 opline->extended_value = type;
6230 GET_NODE(result, opline->result);
6231 }
6232 zend_do_extended_fcall_end(TSRMLS_C);
6233 }
6234
6235
6236 void zend_do_indirect_references(znode *result, const znode *num_references, znode *variable TSRMLS_DC)
6237 {
6238 int i;
6239
6240 zend_do_end_variable_parse(variable, BP_VAR_R, 0 TSRMLS_CC);
6241 for (i=1; i<Z_LVAL(num_references->u.constant); i++) {
6242 fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
6243 *variable = *result;
6244 }
6245 zend_do_begin_variable_parse(TSRMLS_C);
6246 fetch_simple_variable(result, variable, 1 TSRMLS_CC);
6247
6248 if (CG(active_op_array)->scope && CG(active_op_array)->this_var == -1) {
6249 CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1, THIS_HASHVAL TSRMLS_CC);
6250 }
6251 }
6252
6253
6254 void zend_do_unset(const znode *variable TSRMLS_DC)
6255 {
6256 zend_op *last_op;
6257
6258 zend_check_writable_variable(variable);
6259
6260 if (variable->op_type == IS_CV) {
6261 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6262 opline->opcode = ZEND_UNSET_VAR;
6263 SET_NODE(opline->op1, variable);
6264 SET_UNUSED(opline->op2);
6265 SET_UNUSED(opline->result);
6266 opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
6267 } else {
6268 last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
6269
6270 switch (last_op->opcode) {
6271 case ZEND_FETCH_UNSET:
6272 last_op->opcode = ZEND_UNSET_VAR;
6273 SET_UNUSED(last_op->result);
6274 break;
6275 case ZEND_FETCH_DIM_UNSET:
6276 last_op->opcode = ZEND_UNSET_DIM;
6277 SET_UNUSED(last_op->result);
6278 break;
6279 case ZEND_FETCH_OBJ_UNSET:
6280 last_op->opcode = ZEND_UNSET_OBJ;
6281 SET_UNUSED(last_op->result);
6282 break;
6283
6284 }
6285 }
6286 }
6287
6288
6289 void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC)
6290 {
6291 zend_op *last_op;
6292
6293 zend_do_end_variable_parse(variable, BP_VAR_IS, 0 TSRMLS_CC);
6294
6295 if (zend_is_function_or_method_call(variable)) {
6296 if (type == ZEND_ISEMPTY) {
6297
6298 zend_do_unary_op(ZEND_BOOL_NOT, result, variable TSRMLS_CC);
6299 } else {
6300 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use isset() on the result of a function call (you can use \"null !== func()\" instead)");
6301 }
6302
6303 return;
6304 }
6305
6306 if (variable->op_type == IS_CV) {
6307 last_op = get_next_op(CG(active_op_array) TSRMLS_CC);
6308 last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
6309 SET_NODE(last_op->op1, variable);
6310 SET_UNUSED(last_op->op2);
6311 last_op->result.var = get_temporary_variable(CG(active_op_array));
6312 last_op->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
6313 } else {
6314 last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
6315
6316 switch (last_op->opcode) {
6317 case ZEND_FETCH_IS:
6318 last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
6319 break;
6320 case ZEND_FETCH_DIM_IS:
6321 last_op->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
6322 break;
6323 case ZEND_FETCH_OBJ_IS:
6324 last_op->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
6325 break;
6326 }
6327 }
6328 last_op->result_type = IS_TMP_VAR;
6329 last_op->extended_value |= type;
6330
6331 GET_NODE(result, last_op->result);
6332 }
6333
6334
6335 void zend_do_instanceof(znode *result, const znode *expr, const znode *class_znode, int type TSRMLS_DC)
6336 {
6337 int last_op_number = get_next_op_number(CG(active_op_array));
6338 zend_op *opline;
6339
6340 if (last_op_number > 0) {
6341 opline = &CG(active_op_array)->opcodes[last_op_number-1];
6342 if (opline->opcode == ZEND_FETCH_CLASS) {
6343 opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
6344 }
6345 }
6346
6347 if (expr->op_type == IS_CONST) {
6348 zend_error_noreturn(E_COMPILE_ERROR, "instanceof expects an object instance, constant given");
6349 }
6350
6351 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6352 opline->opcode = ZEND_INSTANCEOF;
6353 opline->result_type = IS_TMP_VAR;
6354 opline->result.var = get_temporary_variable(CG(active_op_array));
6355 SET_NODE(opline->op1, expr);
6356
6357 SET_NODE(opline->op2, class_znode);
6358
6359 GET_NODE(result, opline->result);
6360 }
6361
6362
6363 void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, znode *as_token, int variable TSRMLS_DC)
6364 {
6365 zend_op *opline;
6366 zend_bool is_variable;
6367 zend_op dummy_opline;
6368
6369 if (variable) {
6370 if (zend_is_function_or_method_call(array)) {
6371 is_variable = 0;
6372 } else {
6373 is_variable = 1;
6374 }
6375
6376 open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
6377 zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
6378
6379 if (zend_is_function_or_method_call(array)) {
6380 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6381 opline->opcode = ZEND_SEPARATE;
6382 SET_NODE(opline->op1, array);
6383 SET_UNUSED(opline->op2);
6384 opline->result_type = IS_VAR;
6385 opline->result.var = opline->op1.var;
6386 }
6387 } else {
6388 is_variable = 0;
6389 open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
6390 }
6391
6392
6393 foreach_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
6394
6395 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6396
6397
6398 opline->opcode = ZEND_FE_RESET;
6399 opline->result_type = IS_VAR;
6400 opline->result.var = get_temporary_variable(CG(active_op_array));
6401 SET_NODE(opline->op1, array);
6402 SET_UNUSED(opline->op2);
6403 opline->extended_value = is_variable ? ZEND_FE_RESET_VARIABLE : 0;
6404
6405 COPY_NODE(dummy_opline.result, opline->result);
6406 zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
6407
6408
6409 as_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
6410
6411 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6412 opline->opcode = ZEND_FE_FETCH;
6413 opline->result_type = IS_VAR;
6414 opline->result.var = get_temporary_variable(CG(active_op_array));
6415 COPY_NODE(opline->op1, dummy_opline.result);
6416 opline->extended_value = 0;
6417 SET_UNUSED(opline->op2);
6418
6419 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6420 opline->opcode = ZEND_OP_DATA;
6421 SET_UNUSED(opline->op1);
6422 SET_UNUSED(opline->op2);
6423 SET_UNUSED(opline->result);
6424 }
6425
6426
6427 void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token, const znode *as_token, znode *value, znode *key TSRMLS_DC)
6428 {
6429 zend_op *opline;
6430 znode dummy, value_node;
6431 zend_bool assign_by_ref=0;
6432
6433 opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num];
6434 if (key->op_type != IS_UNUSED) {
6435 znode *tmp;
6436
6437
6438 tmp = key;
6439 key = value;
6440 value = tmp;
6441
6442
6443 opline->extended_value |= ZEND_FE_FETCH_WITH_KEY;
6444 }
6445
6446 if ((key->op_type != IS_UNUSED)) {
6447 if (key->EA & ZEND_PARSED_REFERENCE_VARIABLE) {
6448 zend_error_noreturn(E_COMPILE_ERROR, "Key element cannot be a reference");
6449 }
6450 if (key->EA & ZEND_PARSED_LIST_EXPR) {
6451 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use list as key element");
6452 }
6453 }
6454
6455 if (value->EA & ZEND_PARSED_REFERENCE_VARIABLE) {
6456 assign_by_ref = 1;
6457
6458
6459 opline->extended_value |= ZEND_FE_FETCH_BYREF;
6460 CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE;
6461 } else {
6462 zend_op *fetch = &CG(active_op_array)->opcodes[foreach_token->u.op.opline_num];
6463 zend_op *end = &CG(active_op_array)->opcodes[open_brackets_token->u.op.opline_num];
6464
6465
6466 fetch->extended_value = 0;
6467 while (fetch != end) {
6468 --fetch;
6469 if (fetch->opcode == ZEND_FETCH_DIM_W && fetch->op2_type == IS_UNUSED) {
6470 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
6471 }
6472 if (fetch->opcode == ZEND_SEPARATE) {
6473 MAKE_NOP(fetch);
6474 } else {
6475 fetch->opcode -= 3;
6476 }
6477 }
6478 }
6479
6480 GET_NODE(&value_node, opline->result);
6481
6482 if (value->EA & ZEND_PARSED_LIST_EXPR) {
6483 if (!CG(list_llist).head) {
6484 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
6485 }
6486 zend_do_list_end(&dummy, &value_node TSRMLS_CC);
6487 zend_do_free(&dummy TSRMLS_CC);
6488 } else {
6489 if (assign_by_ref) {
6490 zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
6491
6492 zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
6493 } else {
6494 zend_do_assign(&dummy, value, &value_node TSRMLS_CC);
6495 zend_do_free(&dummy TSRMLS_CC);
6496 }
6497 }
6498
6499 if (key->op_type != IS_UNUSED) {
6500 znode key_node;
6501
6502 opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num+1];
6503 opline->result_type = IS_TMP_VAR;
6504 opline->result.opline_num = get_temporary_variable(CG(active_op_array));
6505 GET_NODE(&key_node, opline->result);
6506
6507 zend_do_assign(&dummy, key, &key_node TSRMLS_CC);
6508 zend_do_free(&dummy TSRMLS_CC);
6509 }
6510
6511 do_begin_loop(TSRMLS_C);
6512 INC_BPC(CG(active_op_array));
6513 }
6514
6515
6516 void zend_do_foreach_end(const znode *foreach_token, const znode *as_token TSRMLS_DC)
6517 {
6518 zend_op *container_ptr;
6519 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6520
6521 opline->opcode = ZEND_JMP;
6522 opline->op1.opline_num = as_token->u.op.opline_num;
6523 SET_UNUSED(opline->op1);
6524 SET_UNUSED(opline->op2);
6525
6526 CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
6527 CG(active_op_array)->opcodes[as_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
6528
6529 do_end_loop(as_token->u.op.opline_num, 1 TSRMLS_CC);
6530
6531 zend_stack_top(&CG(foreach_copy_stack), (void **) &container_ptr);
6532 generate_free_foreach_copy(container_ptr TSRMLS_CC);
6533 zend_stack_del_top(&CG(foreach_copy_stack));
6534
6535 DEC_BPC(CG(active_op_array));
6536 }
6537
6538
6539 void zend_do_declare_begin(TSRMLS_D)
6540 {
6541 zend_stack_push(&CG(declare_stack), &CG(declarables), sizeof(zend_declarables));
6542 }
6543
6544
6545 void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC)
6546 {
6547 if (!zend_binary_strcasecmp(Z_STRVAL(var->u.constant), Z_STRLEN(var->u.constant), "ticks", sizeof("ticks")-1)) {
6548 convert_to_long(&val->u.constant);
6549 CG(declarables).ticks = val->u.constant;
6550 } else if (!zend_binary_strcasecmp(Z_STRVAL(var->u.constant), Z_STRLEN(var->u.constant), "encoding", sizeof("encoding")-1)) {
6551 if ((Z_TYPE(val->u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
6552 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use constants as encoding");
6553 }
6554
6555
6556
6557
6558
6559
6560
6561 {
6562 int num = CG(active_op_array)->last;
6563
6564 while (num > 0 &&
6565 (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
6566 CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
6567 --num;
6568 }
6569
6570 if (num > 0) {
6571 zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be the very first statement in the script");
6572 }
6573 }
6574
6575 if (CG(multibyte)) {
6576 const zend_encoding *new_encoding, *old_encoding;
6577 zend_encoding_filter old_input_filter;
6578
6579 CG(encoding_declared) = 1;
6580
6581 convert_to_string(&val->u.constant);
6582 new_encoding = zend_multibyte_fetch_encoding(Z_STRVAL(val->u.constant) TSRMLS_CC);
6583 if (!new_encoding) {
6584 zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", Z_STRVAL(val->u.constant));
6585 } else {
6586 old_input_filter = LANG_SCNG(input_filter);
6587 old_encoding = LANG_SCNG(script_encoding);
6588 zend_multibyte_set_filter(new_encoding TSRMLS_CC);
6589
6590
6591 if (old_input_filter != LANG_SCNG(input_filter) ||
6592 (old_input_filter && new_encoding != old_encoding)) {
6593 zend_multibyte_yyinput_again(old_input_filter, old_encoding TSRMLS_CC);
6594 }
6595 }
6596 } else {
6597 zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because Zend multibyte feature is turned off by settings");
6598 }
6599 zval_dtor(&val->u.constant);
6600 } else {
6601 zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", Z_STRVAL(var->u.constant));
6602 zval_dtor(&val->u.constant);
6603 }
6604 zval_dtor(&var->u.constant);
6605 }
6606
6607
6608 void zend_do_declare_end(const znode *declare_token TSRMLS_DC)
6609 {
6610 zend_declarables *declarables;
6611
6612 zend_stack_top(&CG(declare_stack), (void **) &declarables);
6613
6614 if ((get_next_op_number(CG(active_op_array)) - declare_token->u.op.opline_num) - ((Z_LVAL(CG(declarables).ticks))?1:0)) {
6615 CG(declarables) = *declarables;
6616 }
6617 }
6618
6619
6620 void zend_do_exit(znode *result, const znode *message TSRMLS_DC)
6621 {
6622 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6623
6624 opline->opcode = ZEND_EXIT;
6625 SET_NODE(opline->op1, message);
6626 SET_UNUSED(opline->op2);
6627
6628 result->op_type = IS_CONST;
6629 Z_TYPE(result->u.constant) = IS_BOOL;
6630 Z_LVAL(result->u.constant) = 1;
6631 }
6632
6633
6634 void zend_do_begin_silence(znode *strudel_token TSRMLS_DC)
6635 {
6636 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6637
6638 opline->opcode = ZEND_BEGIN_SILENCE;
6639 opline->result_type = IS_TMP_VAR;
6640 opline->result.var = get_temporary_variable(CG(active_op_array));
6641 SET_UNUSED(opline->op1);
6642 SET_UNUSED(opline->op2);
6643 GET_NODE(strudel_token, opline->result);
6644 }
6645
6646
6647 void zend_do_end_silence(const znode *strudel_token TSRMLS_DC)
6648 {
6649 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6650
6651 opline->opcode = ZEND_END_SILENCE;
6652 SET_NODE(opline->op1, strudel_token);
6653 SET_UNUSED(opline->op2);
6654 }
6655
6656
6657 void zend_do_jmp_set(const znode *value, znode *jmp_token, znode *colon_token TSRMLS_DC)
6658 {
6659 int op_number = get_next_op_number(CG(active_op_array));
6660 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6661
6662 if (value->op_type == IS_VAR || value->op_type == IS_CV) {
6663 opline->opcode = ZEND_JMP_SET_VAR;
6664 opline->result_type = IS_VAR;
6665 } else {
6666 opline->opcode = ZEND_JMP_SET;
6667 opline->result_type = IS_TMP_VAR;
6668 }
6669 opline->result.var = get_temporary_variable(CG(active_op_array));
6670 SET_NODE(opline->op1, value);
6671 SET_UNUSED(opline->op2);
6672
6673 GET_NODE(colon_token, opline->result);
6674
6675 jmp_token->u.op.opline_num = op_number;
6676
6677 INC_BPC(CG(active_op_array));
6678 }
6679
6680
6681 void zend_do_jmp_set_else(znode *result, const znode *false_value, const znode *jmp_token, const znode *colon_token TSRMLS_DC)
6682 {
6683 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6684
6685 SET_NODE(opline->result, colon_token);
6686 if (colon_token->op_type == IS_TMP_VAR) {
6687 if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
6688 CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].opcode = ZEND_JMP_SET_VAR;
6689 CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].result_type = IS_VAR;
6690 opline->opcode = ZEND_QM_ASSIGN_VAR;
6691 opline->result_type = IS_VAR;
6692 } else {
6693 opline->opcode = ZEND_QM_ASSIGN;
6694 }
6695 } else {
6696 opline->opcode = ZEND_QM_ASSIGN_VAR;
6697 }
6698 opline->extended_value = 0;
6699 SET_NODE(opline->op1, false_value);
6700 SET_UNUSED(opline->op2);
6701
6702 GET_NODE(result, opline->result);
6703
6704 CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
6705
6706 DEC_BPC(CG(active_op_array));
6707 }
6708
6709
6710 void zend_do_begin_qm_op(const znode *cond, znode *qm_token TSRMLS_DC)
6711 {
6712 int jmpz_op_number = get_next_op_number(CG(active_op_array));
6713 zend_op *opline;
6714
6715 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6716
6717 opline->opcode = ZEND_JMPZ;
6718 SET_NODE(opline->op1, cond);
6719 SET_UNUSED(opline->op2);
6720 opline->op2.opline_num = jmpz_op_number;
6721 GET_NODE(qm_token, opline->op2);
6722
6723 INC_BPC(CG(active_op_array));
6724 }
6725
6726
6727 void zend_do_qm_true(const znode *true_value, znode *qm_token, znode *colon_token TSRMLS_DC)
6728 {
6729 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6730
6731 CG(active_op_array)->opcodes[qm_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array))+1;
6732
6733 if (true_value->op_type == IS_VAR || true_value->op_type == IS_CV) {
6734 opline->opcode = ZEND_QM_ASSIGN_VAR;
6735 opline->result_type = IS_VAR;
6736 } else {
6737 opline->opcode = ZEND_QM_ASSIGN;
6738 opline->result_type = IS_TMP_VAR;
6739 }
6740 opline->result.var = get_temporary_variable(CG(active_op_array));
6741 SET_NODE(opline->op1, true_value);
6742 SET_UNUSED(opline->op2);
6743
6744 GET_NODE(qm_token, opline->result);
6745 colon_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
6746
6747 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6748 opline->opcode = ZEND_JMP;
6749 SET_UNUSED(opline->op1);
6750 SET_UNUSED(opline->op2);
6751 }
6752
6753
6754 void zend_do_qm_false(znode *result, const znode *false_value, const znode *qm_token, const znode *colon_token TSRMLS_DC)
6755 {
6756 zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6757
6758 SET_NODE(opline->result, qm_token);
6759 if (qm_token->op_type == IS_TMP_VAR) {
6760 if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
6761 CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].opcode = ZEND_QM_ASSIGN_VAR;
6762 CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].result_type = IS_VAR;
6763 opline->opcode = ZEND_QM_ASSIGN_VAR;
6764 opline->result_type = IS_VAR;
6765 } else {
6766 opline->opcode = ZEND_QM_ASSIGN;
6767 }
6768 } else {
6769 opline->opcode = ZEND_QM_ASSIGN_VAR;
6770 }
6771 SET_NODE(opline->op1, false_value);
6772 SET_UNUSED(opline->op2);
6773
6774 CG(active_op_array)->opcodes[colon_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
6775
6776 GET_NODE(result, opline->result);
6777
6778 DEC_BPC(CG(active_op_array));
6779 }
6780
6781
6782 void zend_do_extended_info(TSRMLS_D)
6783 {
6784 zend_op *opline;
6785
6786 if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
6787 return;
6788 }
6789
6790 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6791
6792 opline->opcode = ZEND_EXT_STMT;
6793 SET_UNUSED(opline->op1);
6794 SET_UNUSED(opline->op2);
6795 }
6796
6797
6798 void zend_do_extended_fcall_begin(TSRMLS_D)
6799 {
6800 zend_op *opline;
6801
6802 if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
6803 return;
6804 }
6805
6806 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6807
6808 opline->opcode = ZEND_EXT_FCALL_BEGIN;
6809 SET_UNUSED(opline->op1);
6810 SET_UNUSED(opline->op2);
6811 }
6812
6813
6814 void zend_do_extended_fcall_end(TSRMLS_D)
6815 {
6816 zend_op *opline;
6817
6818 if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
6819 return;
6820 }
6821
6822 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6823
6824 opline->opcode = ZEND_EXT_FCALL_END;
6825 SET_UNUSED(opline->op1);
6826 SET_UNUSED(opline->op2);
6827 }
6828
6829
6830 void zend_do_ticks(TSRMLS_D)
6831 {
6832 zend_op *opline;
6833
6834
6835 if (CG(active_op_array)->last && CG(active_op_array)->opcodes[CG(active_op_array)->last - 1].opcode == ZEND_TICKS) {
6836 return;
6837 }
6838
6839 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
6840
6841 opline->opcode = ZEND_TICKS;
6842 SET_UNUSED(opline->op1);
6843 SET_UNUSED(opline->op2);
6844 opline->extended_value = Z_LVAL(CG(declarables).ticks);
6845 }
6846
6847
6848 zend_bool zend_is_auto_global_quick(const char *name, uint name_len, ulong hash TSRMLS_DC)
6849 {
6850 zend_auto_global *auto_global;
6851
6852 if (zend_hash_quick_find(CG(auto_globals), name, name_len+1, hash, (void **) &auto_global)==SUCCESS) {
6853 if (auto_global->armed) {
6854 auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
6855 }
6856 return 1;
6857 }
6858 return 0;
6859 }
6860
6861
6862 zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC)
6863 {
6864 return zend_is_auto_global_quick(name, name_len, zend_hash_func(name, name_len+1) TSRMLS_CC);
6865 }
6866
6867
6868 int zend_register_auto_global(const char *name, uint name_len, zend_bool jit, zend_auto_global_callback auto_global_callback TSRMLS_DC)
6869 {
6870 zend_auto_global auto_global;
6871
6872 auto_global.name = zend_new_interned_string((char*)name, name_len + 1, 0 TSRMLS_CC);
6873 auto_global.name_len = name_len;
6874 auto_global.auto_global_callback = auto_global_callback;
6875 auto_global.jit = jit;
6876
6877 return zend_hash_add(CG(auto_globals), name, name_len+1, &auto_global, sizeof(zend_auto_global), NULL);
6878 }
6879
6880
6881 static int zend_auto_global_init(zend_auto_global *auto_global TSRMLS_DC)
6882 {
6883 if (auto_global->jit) {
6884 auto_global->armed = 1;
6885 } else if (auto_global->auto_global_callback) {
6886 auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
6887 } else {
6888 auto_global->armed = 0;
6889 }
6890 return 0;
6891 }
6892
6893
6894 ZEND_API void zend_activate_auto_globals(TSRMLS_D)
6895 {
6896 zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_init TSRMLS_CC);
6897 }
6898
6899
6900 int zendlex(znode *zendlval TSRMLS_DC)
6901 {
6902 int retval;
6903
6904 if (CG(increment_lineno)) {
6905 CG(zend_lineno)++;
6906 CG(increment_lineno) = 0;
6907 }
6908
6909 again:
6910 Z_TYPE(zendlval->u.constant) = IS_LONG;
6911 retval = lex_scan(&zendlval->u.constant TSRMLS_CC);
6912 switch (retval) {
6913 case T_COMMENT:
6914 case T_DOC_COMMENT:
6915 case T_OPEN_TAG:
6916 case T_WHITESPACE:
6917 goto again;
6918
6919 case T_CLOSE_TAG:
6920 if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1] != '>') {
6921 CG(increment_lineno) = 1;
6922 }
6923 if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
6924 goto again;
6925 }
6926 retval = ';';
6927 break;
6928 case T_OPEN_TAG_WITH_ECHO:
6929 retval = T_ECHO;
6930 break;
6931 }
6932
6933 INIT_PZVAL(&zendlval->u.constant);
6934 zendlval->op_type = IS_CONST;
6935 return retval;
6936 }
6937
6938
6939 ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers TSRMLS_DC)
6940 {
6941 zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
6942 dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR);
6943
6944 ce->refcount = 1;
6945 ce->ce_flags = 0;
6946
6947 ce->default_properties_table = NULL;
6948 ce->default_static_members_table = NULL;
6949 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);
6950 zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
6951 zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
6952
6953 if (ce->type == ZEND_INTERNAL_CLASS) {
6954 #ifdef ZTS
6955 int n = zend_hash_num_elements(CG(class_table));
6956
6957 if (CG(static_members_table) && n >= CG(last_static_member)) {
6958
6959 CG(last_static_member) = n+1;
6960 CG(static_members_table) = realloc(CG(static_members_table), (n+1)*sizeof(zval**));
6961 CG(static_members_table)[n] = NULL;
6962 }
6963 ce->static_members_table = (zval**)(zend_intptr_t)n;
6964 #else
6965 ce->static_members_table = NULL;
6966 #endif
6967 } else {
6968 ce->static_members_table = ce->default_static_members_table;
6969 ce->info.user.doc_comment = NULL;
6970 ce->info.user.doc_comment_len = 0;
6971 }
6972
6973 ce->default_properties_count = 0;
6974 ce->default_static_members_count = 0;
6975
6976 if (nullify_handlers) {
6977 ce->constructor = NULL;
6978 ce->destructor = NULL;
6979 ce->clone = NULL;
6980 ce->__get = NULL;
6981 ce->__set = NULL;
6982 ce->__unset = NULL;
6983 ce->__isset = NULL;
6984 ce->__call = NULL;
6985 ce->__callstatic = NULL;
6986 ce->__tostring = NULL;
6987 ce->create_object = NULL;
6988 ce->get_iterator = NULL;
6989 ce->iterator_funcs.funcs = NULL;
6990 ce->interface_gets_implemented = NULL;
6991 ce->get_static_method = NULL;
6992 ce->parent = NULL;
6993 ce->num_interfaces = 0;
6994 ce->interfaces = NULL;
6995 ce->num_traits = 0;
6996 ce->traits = NULL;
6997 ce->trait_aliases = NULL;
6998 ce->trait_precedences = NULL;
6999 ce->serialize = NULL;
7000 ce->unserialize = NULL;
7001 ce->serialize_func = NULL;
7002 ce->unserialize_func = NULL;
7003 ce->__debugInfo = NULL;
7004 if (ce->type == ZEND_INTERNAL_CLASS) {
7005 ce->info.internal.module = NULL;
7006 ce->info.internal.builtin_functions = NULL;
7007 }
7008 }
7009 }
7010
7011
7012 int zend_get_class_fetch_type(const char *class_name, uint class_name_len)
7013 {
7014 if ((class_name_len == sizeof("self")-1) &&
7015 !strncasecmp(class_name, "self", sizeof("self")-1)) {
7016 return ZEND_FETCH_CLASS_SELF;
7017 } else if ((class_name_len == sizeof("parent")-1) &&
7018 !strncasecmp(class_name, "parent", sizeof("parent")-1)) {
7019 return ZEND_FETCH_CLASS_PARENT;
7020 } else if ((class_name_len == sizeof("static")-1) &&
7021 !strncasecmp(class_name, "static", sizeof("static")-1)) {
7022 return ZEND_FETCH_CLASS_STATIC;
7023 } else {
7024 return ZEND_FETCH_CLASS_DEFAULT;
7025 }
7026 }
7027
7028
7029 ZEND_API const char* zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var, int* name_len)
7030 {
7031 if (name_len) {
7032 *name_len = op_array->vars[var].name_len;
7033 }
7034 return op_array->vars[var].name;
7035 }
7036
7037
7038 void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC)
7039 {
7040 if (prefix) {
7041 *result = *prefix;
7042 if (Z_TYPE(result->u.constant) == IS_STRING &&
7043 Z_STRLEN(result->u.constant) == 0) {
7044
7045 if (CG(current_namespace)) {
7046 znode tmp;
7047
7048 zval_dtor(&result->u.constant);
7049 tmp.op_type = IS_CONST;
7050 tmp.u.constant = *CG(current_namespace);
7051 zval_copy_ctor(&tmp.u.constant);
7052 zend_do_build_namespace_name(result, NULL, &tmp TSRMLS_CC);
7053 }
7054 }
7055 } else {
7056 result->op_type = IS_CONST;
7057 Z_TYPE(result->u.constant) = IS_STRING;
7058 Z_STRVAL(result->u.constant) = NULL;
7059 Z_STRLEN(result->u.constant) = 0;
7060 }
7061
7062 zend_do_build_full_name(NULL, result, name, 0 TSRMLS_CC);
7063 }
7064
7065
7066 void zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC)
7067 {
7068 char *lcname;
7069
7070
7071 if (!CG(has_bracketed_namespaces)) {
7072 if (CG(current_namespace)) {
7073
7074 if (with_bracket) {
7075 zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations with unbracketed namespace declarations");
7076 }
7077 }
7078 } else {
7079
7080 if (!with_bracket) {
7081 zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations with unbracketed namespace declarations");
7082 } else if (CG(current_namespace) || CG(in_namespace)) {
7083 zend_error_noreturn(E_COMPILE_ERROR, "Namespace declarations cannot be nested");
7084 }
7085 }
7086
7087 if (((!with_bracket && !CG(current_namespace)) || (with_bracket && !CG(has_bracketed_namespaces))) && CG(active_op_array)->last > 0) {
7088
7089 int num = CG(active_op_array)->last;
7090 while (num > 0 &&
7091 (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
7092 CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
7093 --num;
7094 }
7095 if (num > 0) {
7096 zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be the very first statement in the script");
7097 }
7098 }
7099
7100 CG(in_namespace) = 1;
7101 if (with_bracket) {
7102 CG(has_bracketed_namespaces) = 1;
7103 }
7104
7105 if (name) {
7106 lcname = zend_str_tolower_dup(Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant));
7107 if (((Z_STRLEN(name->u.constant) == sizeof("self")-1) &&
7108 !memcmp(lcname, "self", sizeof("self")-1)) ||
7109 ((Z_STRLEN(name->u.constant) == sizeof("parent")-1) &&
7110 !memcmp(lcname, "parent", sizeof("parent")-1))) {
7111 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", Z_STRVAL(name->u.constant));
7112 }
7113 efree(lcname);
7114
7115 if (CG(current_namespace)) {
7116 zval_dtor(CG(current_namespace));
7117 } else {
7118 ALLOC_ZVAL(CG(current_namespace));
7119 }
7120 *CG(current_namespace) = name->u.constant;
7121 } else {
7122 if (CG(current_namespace)) {
7123 zval_dtor(CG(current_namespace));
7124 FREE_ZVAL(CG(current_namespace));
7125 CG(current_namespace) = NULL;
7126 }
7127 }
7128
7129 if (CG(current_import)) {
7130 zend_hash_destroy(CG(current_import));
7131 efree(CG(current_import));
7132 CG(current_import) = NULL;
7133 }
7134
7135 if (CG(current_import_function)) {
7136 zend_hash_destroy(CG(current_import_function));
7137 efree(CG(current_import_function));
7138 CG(current_import_function) = NULL;
7139 }
7140
7141 if (CG(current_import_const)) {
7142 zend_hash_destroy(CG(current_import_const));
7143 efree(CG(current_import_const));
7144 CG(current_import_const) = NULL;
7145 }
7146
7147 if (CG(doc_comment)) {
7148 efree(CG(doc_comment));
7149 CG(doc_comment) = NULL;
7150 CG(doc_comment_len) = 0;
7151 }
7152 }
7153
7154
7155 void zend_do_use(znode *ns_name, znode *new_name TSRMLS_DC)
7156 {
7157 char *lcname;
7158 zval *name, *ns, tmp;
7159 zend_bool warn = 0;
7160 zend_class_entry **pce;
7161
7162 if (!CG(current_import)) {
7163 CG(current_import) = emalloc(sizeof(HashTable));
7164 zend_hash_init(CG(current_import), 0, NULL, ZVAL_PTR_DTOR, 0);
7165 }
7166
7167 MAKE_STD_ZVAL(ns);
7168 ZVAL_ZVAL(ns, &ns_name->u.constant, 0, 0);
7169 if (new_name) {
7170 name = &new_name->u.constant;
7171 } else {
7172 const char *p;
7173
7174
7175
7176 name = &tmp;
7177 p = zend_memrchr(Z_STRVAL_P(ns), '\\', Z_STRLEN_P(ns));
7178 if (p) {
7179 ZVAL_STRING(name, p+1, 1);
7180 } else {
7181 ZVAL_ZVAL(name, ns, 1, 0);
7182 warn = !CG(current_namespace);
7183 }
7184 }
7185
7186 lcname = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
7187
7188 if (((Z_STRLEN_P(name) == sizeof("self")-1) &&
7189 !memcmp(lcname, "self", sizeof("self")-1)) ||
7190 ((Z_STRLEN_P(name) == sizeof("parent")-1) &&
7191 !memcmp(lcname, "parent", sizeof("parent")-1))) {
7192 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' is a special class name", Z_STRVAL_P(ns), Z_STRVAL_P(name), Z_STRVAL_P(name));
7193 }
7194
7195 if (CG(current_namespace)) {
7196
7197 char *c_ns_name = emalloc(Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) + 1);
7198
7199 zend_str_tolower_copy(c_ns_name, Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
7200 c_ns_name[Z_STRLEN_P(CG(current_namespace))] = '\\';
7201 memcpy(c_ns_name+Z_STRLEN_P(CG(current_namespace))+1, lcname, Z_STRLEN_P(name)+1);
7202 if (zend_hash_exists(CG(class_table), c_ns_name, Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name)+1)) {
7203 char *tmp2 = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
7204
7205 if (Z_STRLEN_P(ns) != Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) ||
7206 memcmp(tmp2, c_ns_name, Z_STRLEN_P(ns))) {
7207 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7208 }
7209 efree(tmp2);
7210 }
7211 efree(c_ns_name);
7212 } else if (zend_hash_find(CG(class_table), lcname, Z_STRLEN_P(name)+1, (void**)&pce) == SUCCESS &&
7213 (*pce)->type == ZEND_USER_CLASS &&
7214 (*pce)->info.user.filename == CG(compiled_filename)) {
7215 char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
7216
7217 if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
7218 memcmp(c_tmp, lcname, Z_STRLEN_P(ns))) {
7219 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7220 }
7221 efree(c_tmp);
7222 }
7223
7224 if (zend_hash_add(CG(current_import), lcname, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
7225 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7226 }
7227 if (warn) {
7228 if (!strcmp(Z_STRVAL_P(name), "strict")) {
7229 zend_error_noreturn(E_COMPILE_ERROR, "You seem to be trying to use a different language...");
7230 }
7231 zend_error(E_WARNING, "The use statement with non-compound name '%s' has no effect", Z_STRVAL_P(name));
7232 }
7233 efree(lcname);
7234 zval_dtor(name);
7235 }
7236
7237
7238 void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_function, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC)
7239 {
7240 char *lookup_name;
7241 zval *name, *ns, tmp;
7242 zend_bool warn = 0;
7243
7244 MAKE_STD_ZVAL(ns);
7245 ZVAL_ZVAL(ns, &ns_name->u.constant, 0, 0);
7246 if (new_name) {
7247 name = &new_name->u.constant;
7248 } else {
7249 const char *p;
7250
7251
7252
7253 name = &tmp;
7254 p = zend_memrchr(Z_STRVAL_P(ns), '\\', Z_STRLEN_P(ns));
7255 if (p) {
7256 ZVAL_STRING(name, p+1, 1);
7257 } else {
7258 ZVAL_ZVAL(name, ns, 1, 0);
7259 warn = !CG(current_namespace);
7260 }
7261 }
7262
7263 if (case_sensitive) {
7264 lookup_name = estrndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
7265 } else {
7266 lookup_name = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
7267 }
7268
7269 if (CG(current_namespace)) {
7270
7271 char *c_ns_name = emalloc(Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) + 1);
7272
7273 zend_str_tolower_copy(c_ns_name, Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
7274 c_ns_name[Z_STRLEN_P(CG(current_namespace))] = '\\';
7275 memcpy(c_ns_name+Z_STRLEN_P(CG(current_namespace))+1, lookup_name, Z_STRLEN_P(name)+1);
7276 if (zend_hash_exists(lookup_table, c_ns_name, Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name)+1)) {
7277 char *tmp2 = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
7278
7279 if (Z_STRLEN_P(ns) != Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) ||
7280 memcmp(tmp2, c_ns_name, Z_STRLEN_P(ns))) {
7281 zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", is_function ? "function" : "const", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7282 }
7283 efree(tmp2);
7284 }
7285 efree(c_ns_name);
7286 } else if (is_function) {
7287 zend_function *function;
7288
7289 if (zend_hash_find(lookup_table, lookup_name, Z_STRLEN_P(name)+1, (void **) &function) == SUCCESS && function->type == ZEND_USER_FUNCTION && strcmp(function->op_array.filename, CG(compiled_filename)) == 0) {
7290 char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
7291
7292 if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
7293 memcmp(c_tmp, lookup_name, Z_STRLEN_P(ns))) {
7294 zend_error(E_COMPILE_ERROR, "Cannot use function %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7295 }
7296 efree(c_tmp);
7297 }
7298 } else {
7299 const char *filename;
7300
7301 if (zend_hash_find(lookup_table, lookup_name, Z_STRLEN_P(name)+1, (void **) &filename) == SUCCESS && strcmp(filename, CG(compiled_filename)) == 0) {
7302 char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
7303
7304 if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
7305 memcmp(c_tmp, lookup_name, Z_STRLEN_P(ns))) {
7306 zend_error(E_COMPILE_ERROR, "Cannot use const %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7307 }
7308 efree(c_tmp);
7309 }
7310 }
7311
7312 if (zend_hash_add(current_import_sub, lookup_name, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
7313 zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", is_function ? "function" : "const", Z_STRVAL_P(ns), Z_STRVAL_P(name));
7314 }
7315 if (warn) {
7316 zend_error(E_WARNING, "The use %s statement with non-compound name '%s' has no effect", is_function ? "function" : "const", Z_STRVAL_P(name));
7317 }
7318 efree(lookup_name);
7319 zval_dtor(name);
7320 }
7321
7322
7323 void zend_do_use_function(znode *ns_name, znode *new_name TSRMLS_DC)
7324 {
7325 if (!CG(current_import_function)) {
7326 CG(current_import_function) = emalloc(sizeof(HashTable));
7327 zend_hash_init(CG(current_import_function), 0, NULL, ZVAL_PTR_DTOR, 0);
7328 }
7329
7330 zend_do_use_non_class(ns_name, new_name, 1, 0, CG(current_import_function), CG(function_table) TSRMLS_CC);
7331 }
7332
7333
7334 void zend_do_use_const(znode *ns_name, znode *new_name TSRMLS_DC)
7335 {
7336 if (!CG(current_import_const)) {
7337 CG(current_import_const) = emalloc(sizeof(HashTable));
7338 zend_hash_init(CG(current_import_const), 0, NULL, ZVAL_PTR_DTOR, 0);
7339 }
7340
7341 zend_do_use_non_class(ns_name, new_name, 0, 1, CG(current_import_const), &CG(const_filenames) TSRMLS_CC);
7342 }
7343
7344
7345 void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC)
7346 {
7347 zend_op *opline;
7348 zval **ns_name;
7349
7350 if (zend_get_ct_const(&name->u.constant, 0 TSRMLS_CC)) {
7351 zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", Z_STRVAL(name->u.constant));
7352 }
7353
7354 if (CG(current_namespace)) {
7355
7356 znode tmp;
7357
7358 tmp.op_type = IS_CONST;
7359 tmp.u.constant = *CG(current_namespace);
7360 Z_STRVAL(tmp.u.constant) = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), Z_STRLEN(tmp.u.constant));
7361 zend_do_build_namespace_name(&tmp, &tmp, name TSRMLS_CC);
7362 *name = tmp;
7363 }
7364
7365
7366 if (CG(current_import_const) &&
7367 zend_hash_find(CG(current_import_const), Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
7368
7369 char *tmp = estrndup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
7370
7371 if (Z_STRLEN_PP(ns_name) != Z_STRLEN(name->u.constant) ||
7372 memcmp(tmp, Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant))) {
7373 zend_error(E_COMPILE_ERROR, "Cannot declare const %s because the name is already in use", Z_STRVAL(name->u.constant));
7374 }
7375 efree(tmp);
7376 }
7377
7378 opline = get_next_op(CG(active_op_array) TSRMLS_CC);
7379 opline->opcode = ZEND_DECLARE_CONST;
7380 SET_UNUSED(opline->result);
7381 SET_NODE(opline->op1, name);
7382 SET_NODE(opline->op2, value);
7383
7384 zend_hash_add(&CG(const_filenames), Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1, CG(compiled_filename), strlen(CG(compiled_filename))+1, NULL);
7385 }
7386
7387
7388 void zend_verify_namespace(TSRMLS_D)
7389 {
7390 if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
7391 zend_error_noreturn(E_COMPILE_ERROR, "No code may exist outside of namespace {}");
7392 }
7393 }
7394
7395
7396 void zend_do_end_namespace(TSRMLS_D)
7397 {
7398 CG(in_namespace) = 0;
7399 if (CG(current_namespace)) {
7400 zval_dtor(CG(current_namespace));
7401 FREE_ZVAL(CG(current_namespace));
7402 CG(current_namespace) = NULL;
7403 }
7404 if (CG(current_import)) {
7405 zend_hash_destroy(CG(current_import));
7406 efree(CG(current_import));
7407 CG(current_import) = NULL;
7408 }
7409 if (CG(current_import_function)) {
7410 zend_hash_destroy(CG(current_import_function));
7411 efree(CG(current_import_function));
7412 CG(current_import_function) = NULL;
7413 }
7414 if (CG(current_import_const)) {
7415 zend_hash_destroy(CG(current_import_const));
7416 efree(CG(current_import_const));
7417 CG(current_import_const) = NULL;
7418 }
7419 }
7420
7421
7422 void zend_do_end_compilation(TSRMLS_D)
7423 {
7424 CG(has_bracketed_namespaces) = 0;
7425 zend_do_end_namespace(TSRMLS_C);
7426 }
7427
7428
7429 void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC)
7430 {
7431 if (ast->kind == ZEND_CONST) {
7432 result->u.constant = *ast->u.val;
7433 efree(ast);
7434 } else if (zend_ast_is_ct_constant(ast)) {
7435 zend_ast_evaluate(&result->u.constant, ast, NULL TSRMLS_CC);
7436 zend_ast_destroy(ast);
7437 } else {
7438 Z_TYPE(result->u.constant) = IS_CONSTANT_AST;
7439 Z_AST(result->u.constant) = ast;
7440 }
7441 }
7442
7443
7444
7445
7446 ZEND_API size_t zend_dirname(char *path, size_t len)
7447 {
7448 register char *end = path + len - 1;
7449 unsigned int len_adjust = 0;
7450
7451 #ifdef PHP_WIN32
7452
7453
7454
7455 if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
7456
7457 path += 2;
7458 len_adjust += 2;
7459 if (2 == len) {
7460
7461
7462
7463
7464 return len;
7465 }
7466 }
7467 #elif defined(NETWARE)
7468
7469
7470
7471
7472
7473
7474 char *colonpos = NULL;
7475 colonpos = strchr(path, ':');
7476 if (colonpos != NULL) {
7477 len_adjust = ((colonpos - path) + 1);
7478 path += len_adjust;
7479 if (len_adjust == len) {
7480 return len;
7481 }
7482 }
7483 #endif
7484
7485 if (len == 0) {
7486
7487 return 0;
7488 }
7489
7490
7491 while (end >= path && IS_SLASH_P(end)) {
7492 end--;
7493 }
7494 if (end < path) {
7495
7496 path[0] = DEFAULT_SLASH;
7497 path[1] = '\0';
7498 return 1 + len_adjust;
7499 }
7500
7501
7502 while (end >= path && !IS_SLASH_P(end)) {
7503 end--;
7504 }
7505 if (end < path) {
7506
7507 #ifdef NETWARE
7508 if (len_adjust == 0) {
7509 path[0] = '.';
7510 path[1] = '\0';
7511 return 1;
7512 } else {
7513 path[0] = '\0';
7514 return len_adjust;
7515 }
7516 #else
7517 path[0] = '.';
7518 path[1] = '\0';
7519 return 1 + len_adjust;
7520 #endif
7521 }
7522
7523
7524 while (end >= path && IS_SLASH_P(end)) {
7525 end--;
7526 }
7527 if (end < path) {
7528 path[0] = DEFAULT_SLASH;
7529 path[1] = '\0';
7530 return 1 + len_adjust;
7531 }
7532 *(end+1) = '\0';
7533
7534 return (size_t)(end + 1 - path) + len_adjust;
7535 }
7536
7537
7538
7539
7540
7541
7542
7543
7544