1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 2.00 of the Zend license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.zend.com/license/2_00.txt. |
11 : | If you did not receive a copy of the Zend license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@zend.com so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Andi Gutmans <andi@zend.com> |
16 : | Zeev Suraski <zeev@zend.com> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: zend_execute_API.c 290231 2009-11-05 09:33:19Z dmitry $ */
21 :
22 : #include <stdio.h>
23 : #include <signal.h>
24 :
25 : #include "zend.h"
26 : #include "zend_compile.h"
27 : #include "zend_execute.h"
28 : #include "zend_API.h"
29 : #include "zend_ptr_stack.h"
30 : #include "zend_constants.h"
31 : #include "zend_extensions.h"
32 : #include "zend_exceptions.h"
33 : #include "zend_closures.h"
34 : #include "zend_vm.h"
35 : #include "zend_float.h"
36 : #ifdef HAVE_SYS_TIME_H
37 : #include <sys/time.h>
38 : #endif
39 :
40 : ZEND_API void (*zend_execute)(zend_op_array *op_array TSRMLS_DC);
41 : ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
42 :
43 : /* true globals */
44 : ZEND_API const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 };
45 : ZEND_API const zend_fcall_info_cache empty_fcall_info_cache = { 0, NULL, NULL, NULL, NULL };
46 :
47 : #ifdef ZEND_WIN32
48 : #include <process.h>
49 : static WNDCLASS wc;
50 : static HWND timeout_window;
51 : static HANDLE timeout_thread_event;
52 : static HANDLE timeout_thread_handle;
53 : static DWORD timeout_thread_id;
54 : static int timeout_thread_initialized=0;
55 : #endif
56 :
57 : #if 0&&ZEND_DEBUG
58 : static void (*original_sigsegv_handler)(int);
59 : static void zend_handle_sigsegv(int dummy) /* {{{ */
60 : {
61 : fflush(stdout);
62 : fflush(stderr);
63 : if (original_sigsegv_handler == zend_handle_sigsegv) {
64 : signal(SIGSEGV, original_sigsegv_handler);
65 : } else {
66 : signal(SIGSEGV, SIG_DFL);
67 : }
68 : {
69 : TSRMLS_FETCH();
70 :
71 : fprintf(stderr, "SIGSEGV caught on opcode %d on opline %d of %s() at %s:%d\n\n",
72 : active_opline->opcode,
73 : active_opline-EG(active_op_array)->opcodes,
74 : get_active_function_name(TSRMLS_C),
75 : zend_get_executed_filename(TSRMLS_C),
76 : zend_get_executed_lineno(TSRMLS_C));
77 : }
78 : if (original_sigsegv_handler!=zend_handle_sigsegv) {
79 : original_sigsegv_handler(dummy);
80 : }
81 : }
82 : /* }}} */
83 : #endif
84 :
85 : static void zend_extension_activator(zend_extension *extension TSRMLS_DC) /* {{{ */
86 0 : {
87 0 : if (extension->activate) {
88 0 : extension->activate();
89 : }
90 0 : }
91 : /* }}} */
92 :
93 : static void zend_extension_deactivator(zend_extension *extension TSRMLS_DC) /* {{{ */
94 0 : {
95 0 : if (extension->deactivate) {
96 0 : extension->deactivate();
97 : }
98 0 : }
99 : /* }}} */
100 :
101 : static int clean_non_persistent_function(zend_function *function TSRMLS_DC) /* {{{ */
102 33649 : {
103 33649 : return (function->type == ZEND_INTERNAL_FUNCTION) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
104 : }
105 : /* }}} */
106 :
107 : static int clean_non_persistent_function_full(zend_function *function TSRMLS_DC) /* {{{ */
108 0 : {
109 0 : return (function->type != ZEND_INTERNAL_FUNCTION);
110 : }
111 : /* }}} */
112 :
113 : static int clean_non_persistent_class(zend_class_entry **ce TSRMLS_DC) /* {{{ */
114 25259 : {
115 25259 : return ((*ce)->type == ZEND_INTERNAL_CLASS) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
116 : }
117 : /* }}} */
118 :
119 : static int clean_non_persistent_class_full(zend_class_entry **ce TSRMLS_DC) /* {{{ */
120 0 : {
121 0 : return ((*ce)->type != ZEND_INTERNAL_CLASS);
122 : }
123 : /* }}} */
124 :
125 : void init_executor(TSRMLS_D) /* {{{ */
126 17619 : {
127 17619 : zend_init_fpu(TSRMLS_C);
128 :
129 17619 : INIT_ZVAL(EG(uninitialized_zval));
130 : /* trick to make uninitialized_zval never be modified, passed by ref, etc. */
131 17619 : Z_ADDREF(EG(uninitialized_zval));
132 17619 : INIT_ZVAL(EG(error_zval));
133 17619 : EG(uninitialized_zval_ptr)=&EG(uninitialized_zval);
134 17619 : EG(error_zval_ptr)=&EG(error_zval);
135 17619 : zend_ptr_stack_init(&EG(arg_types_stack));
136 : /* destroys stack frame, therefore makes core dumps worthless */
137 : #if 0&&ZEND_DEBUG
138 : original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv);
139 : #endif
140 17619 : EG(return_value_ptr_ptr) = NULL;
141 :
142 17619 : EG(symtable_cache_ptr) = EG(symtable_cache) - 1;
143 17619 : EG(symtable_cache_limit) = EG(symtable_cache) + SYMTABLE_CACHE_SIZE - 1;
144 17619 : EG(no_extensions) = 0;
145 :
146 17619 : EG(function_table) = CG(function_table);
147 17619 : EG(class_table) = CG(class_table);
148 :
149 17619 : EG(in_execution) = 0;
150 17619 : EG(in_autoload) = NULL;
151 17619 : EG(autoload_func) = NULL;
152 17619 : EG(error_handling) = EH_NORMAL;
153 :
154 17619 : zend_vm_stack_init(TSRMLS_C);
155 17619 : zend_vm_stack_push((void *) NULL TSRMLS_CC);
156 :
157 17619 : zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0);
158 : {
159 : zval *globals;
160 :
161 17619 : ALLOC_ZVAL(globals);
162 17619 : Z_SET_REFCOUNT_P(globals, 1);
163 17619 : Z_SET_ISREF_P(globals);
164 17619 : Z_TYPE_P(globals) = IS_ARRAY;
165 17619 : Z_ARRVAL_P(globals) = &EG(symbol_table);
166 17619 : zend_hash_update(&EG(symbol_table), "GLOBALS", sizeof("GLOBALS"), &globals, sizeof(zval *), NULL);
167 : }
168 17619 : EG(active_symbol_table) = &EG(symbol_table);
169 :
170 17619 : zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator TSRMLS_CC);
171 17619 : EG(opline_ptr) = NULL;
172 :
173 17619 : zend_hash_init(&EG(included_files), 5, NULL, NULL, 0);
174 :
175 17619 : EG(ticks_count) = 0;
176 :
177 17619 : EG(user_error_handler) = NULL;
178 :
179 17619 : EG(current_execute_data) = NULL;
180 :
181 17619 : zend_stack_init(&EG(user_error_handlers_error_reporting));
182 17619 : zend_ptr_stack_init(&EG(user_error_handlers));
183 17619 : zend_ptr_stack_init(&EG(user_exception_handlers));
184 :
185 17619 : zend_objects_store_init(&EG(objects_store), 1024);
186 :
187 17619 : EG(full_tables_cleanup) = 0;
188 : #ifdef ZEND_WIN32
189 : EG(timed_out) = 0;
190 : #endif
191 :
192 17619 : EG(exception) = NULL;
193 17619 : EG(prev_exception) = NULL;
194 :
195 17619 : EG(scope) = NULL;
196 17619 : EG(called_scope) = NULL;
197 :
198 17619 : EG(This) = NULL;
199 :
200 17619 : EG(active_op_array) = NULL;
201 :
202 17619 : EG(active) = 1;
203 17619 : }
204 : /* }}} */
205 :
206 : static int zval_call_destructor(zval **zv TSRMLS_DC) /* {{{ */
207 428175 : {
208 428175 : if (Z_TYPE_PP(zv) == IS_OBJECT && Z_REFCOUNT_PP(zv) == 1) {
209 7149 : return ZEND_HASH_APPLY_REMOVE;
210 : } else {
211 421026 : return ZEND_HASH_APPLY_KEEP;
212 : }
213 : }
214 : /* }}} */
215 :
216 : void shutdown_destructors(TSRMLS_D) /* {{{ */
217 17651 : {
218 17651 : zend_try {
219 : int symbols;
220 : do {
221 21716 : symbols = zend_hash_num_elements(&EG(symbol_table));
222 21716 : zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor TSRMLS_CC);
223 21716 : } while (symbols != zend_hash_num_elements(&EG(symbol_table)));
224 17651 : zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC);
225 0 : } zend_catch {
226 : /* if we couldn't destruct cleanly, mark all objects as destructed anyway */
227 0 : zend_objects_store_mark_destructed(&EG(objects_store) TSRMLS_CC);
228 17651 : } zend_end_try();
229 17651 : }
230 : /* }}} */
231 :
232 : void shutdown_executor(TSRMLS_D) /* {{{ */
233 17651 : {
234 17651 : zend_try {
235 :
236 : /* Removed because this can not be safely done, e.g. in this situation:
237 : Object 1 creates object 2
238 : Object 3 holds reference to object 2.
239 : Now when 1 and 2 are destroyed, 3 can still access 2 in its destructor, with
240 : very problematic results */
241 : /* zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); */
242 :
243 : /* Moved after symbol table cleaners, because some of the cleaners can call
244 : destructors, which would use EG(symtable_cache_ptr) and thus leave leaks */
245 : /* while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
246 : zend_hash_destroy(*EG(symtable_cache_ptr));
247 : efree(*EG(symtable_cache_ptr));
248 : EG(symtable_cache_ptr)--;
249 : }
250 : */
251 17651 : zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator TSRMLS_CC);
252 17651 : zend_hash_graceful_reverse_destroy(&EG(symbol_table));
253 17651 : } zend_end_try();
254 :
255 17651 : zend_try {
256 : zval *zeh;
257 : /* remove error handlers before destroying classes and functions,
258 : * so that if handler used some class, crash would not happen */
259 17651 : if (EG(user_error_handler)) {
260 229 : zeh = EG(user_error_handler);
261 229 : EG(user_error_handler) = NULL;
262 229 : zval_dtor(zeh);
263 229 : FREE_ZVAL(zeh);
264 : }
265 :
266 17651 : if (EG(user_exception_handler)) {
267 10 : zeh = EG(user_exception_handler);
268 10 : EG(user_exception_handler) = NULL;
269 10 : zval_dtor(zeh);
270 10 : FREE_ZVAL(zeh);
271 : }
272 :
273 17651 : zend_stack_destroy(&EG(user_error_handlers_error_reporting));
274 17651 : zend_stack_init(&EG(user_error_handlers_error_reporting));
275 17651 : zend_ptr_stack_clean(&EG(user_error_handlers), ZVAL_DESTRUCTOR, 1);
276 17651 : zend_ptr_stack_clean(&EG(user_exception_handlers), ZVAL_DESTRUCTOR, 1);
277 17651 : } zend_end_try();
278 :
279 17651 : zend_try {
280 : /* Cleanup static data for functions and arrays.
281 : * We need a separate cleanup stage because of the following problem:
282 : * Suppose we destroy class X, which destroys the class's function table,
283 : * and in the function table we have function foo() that has static $bar.
284 : * Now if an object of class X is assigned to $bar, its destructor will be
285 : * called and will fail since X's function table is in mid-destruction.
286 : * So we want first of all to clean up all data and then move to tables destruction.
287 : * Note that only run-time accessed data need to be cleaned up, pre-defined data can
288 : * not contain objects and thus are not probelmatic */
289 17651 : if (EG(full_tables_cleanup)) {
290 0 : zend_hash_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC);
291 : } else {
292 17651 : zend_hash_reverse_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data TSRMLS_CC);
293 : }
294 17651 : zend_hash_apply(EG(class_table), (apply_func_t) zend_cleanup_class_data TSRMLS_CC);
295 :
296 17651 : zend_vm_stack_destroy(TSRMLS_C);
297 :
298 17651 : zend_objects_store_free_object_storage(&EG(objects_store) TSRMLS_CC);
299 :
300 : /* Destroy all op arrays */
301 17651 : if (EG(full_tables_cleanup)) {
302 0 : zend_hash_apply(EG(function_table), (apply_func_t) clean_non_persistent_function_full TSRMLS_CC);
303 0 : zend_hash_apply(EG(class_table), (apply_func_t) clean_non_persistent_class_full TSRMLS_CC);
304 : } else {
305 17651 : zend_hash_reverse_apply(EG(function_table), (apply_func_t) clean_non_persistent_function TSRMLS_CC);
306 17651 : zend_hash_reverse_apply(EG(class_table), (apply_func_t) clean_non_persistent_class TSRMLS_CC);
307 : }
308 :
309 35659 : while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
310 357 : zend_hash_destroy(*EG(symtable_cache_ptr));
311 357 : FREE_HASHTABLE(*EG(symtable_cache_ptr));
312 357 : EG(symtable_cache_ptr)--;
313 : }
314 17651 : } zend_end_try();
315 :
316 17651 : zend_try {
317 17651 : clean_non_persistent_constants(TSRMLS_C);
318 17651 : } zend_end_try();
319 :
320 17651 : zend_try {
321 : #if 0&&ZEND_DEBUG
322 : signal(SIGSEGV, original_sigsegv_handler);
323 : #endif
324 :
325 17651 : zend_hash_destroy(&EG(included_files));
326 :
327 17651 : zend_ptr_stack_destroy(&EG(arg_types_stack));
328 17651 : zend_stack_destroy(&EG(user_error_handlers_error_reporting));
329 17651 : zend_ptr_stack_destroy(&EG(user_error_handlers));
330 17651 : zend_ptr_stack_destroy(&EG(user_exception_handlers));
331 17651 : zend_objects_store_destroy(&EG(objects_store));
332 17651 : if (EG(in_autoload)) {
333 140 : zend_hash_destroy(EG(in_autoload));
334 140 : FREE_HASHTABLE(EG(in_autoload));
335 : }
336 17651 : } zend_end_try();
337 :
338 17651 : zend_shutdown_fpu(TSRMLS_C);
339 :
340 17651 : EG(active) = 0;
341 17651 : }
342 : /* }}} */
343 :
344 : /* return class name and "::" or "". */
345 : ZEND_API char *get_active_class_name(char **space TSRMLS_DC) /* {{{ */
346 2300545 : {
347 2300545 : if (!zend_is_executing(TSRMLS_C)) {
348 0 : if (space) {
349 0 : *space = "";
350 : }
351 0 : return "";
352 : }
353 2300545 : switch (EG(current_execute_data)->function_state.function->type) {
354 : case ZEND_USER_FUNCTION:
355 : case ZEND_INTERNAL_FUNCTION:
356 : {
357 2300545 : zend_class_entry *ce = EG(current_execute_data)->function_state.function->common.scope;
358 :
359 2300545 : if (space) {
360 2300545 : *space = ce ? "::" : "";
361 : }
362 2300545 : return ce ? ce->name : "";
363 : }
364 : default:
365 0 : if (space) {
366 0 : *space = "";
367 : }
368 0 : return "";
369 : }
370 : }
371 : /* }}} */
372 :
373 : ZEND_API char *get_active_function_name(TSRMLS_D) /* {{{ */
374 2302664 : {
375 2302664 : if (!zend_is_executing(TSRMLS_C)) {
376 7 : return NULL;
377 : }
378 2302657 : switch (EG(current_execute_data)->function_state.function->type) {
379 : case ZEND_USER_FUNCTION: {
380 121 : char *function_name = ((zend_op_array *) EG(current_execute_data)->function_state.function)->function_name;
381 :
382 121 : if (function_name) {
383 67 : return function_name;
384 : } else {
385 54 : return "main";
386 : }
387 : }
388 : break;
389 : case ZEND_INTERNAL_FUNCTION:
390 2302536 : return ((zend_internal_function *) EG(current_execute_data)->function_state.function)->function_name;
391 : break;
392 : default:
393 0 : return NULL;
394 : }
395 : }
396 : /* }}} */
397 :
398 : ZEND_API char *zend_get_executed_filename(TSRMLS_D) /* {{{ */
399 2427356 : {
400 2427356 : if (EG(active_op_array)) {
401 2427351 : return EG(active_op_array)->filename;
402 : } else {
403 5 : return "[no active file]";
404 : }
405 : }
406 : /* }}} */
407 :
408 : ZEND_API uint zend_get_executed_lineno(TSRMLS_D) /* {{{ */
409 2421165 : {
410 2421165 : if (EG(opline_ptr)) {
411 2421160 : return active_opline->lineno;
412 : } else {
413 5 : return 0;
414 : }
415 : }
416 : /* }}} */
417 :
418 : ZEND_API zend_bool zend_is_executing(TSRMLS_D) /* {{{ */
419 7078041 : {
420 7078041 : return EG(in_execution);
421 : }
422 : /* }}} */
423 :
424 : ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) /* {{{ */
425 66217750 : {
426 : #if DEBUG_ZEND>=2
427 : printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, Z_REFCOUNT_PP(zval_ptr), Z_REFCOUNT_PP(zval_ptr) - 1);
428 : #endif
429 66217750 : Z_DELREF_PP(zval_ptr);
430 66217750 : if (Z_REFCOUNT_PP(zval_ptr) == 0) {
431 : TSRMLS_FETCH();
432 :
433 29415461 : if (*zval_ptr != &EG(uninitialized_zval)) {
434 29415461 : GC_REMOVE_ZVAL_FROM_BUFFER(*zval_ptr);
435 29415461 : zval_dtor(*zval_ptr);
436 29415460 : efree_rel(*zval_ptr);
437 : }
438 : } else {
439 : TSRMLS_FETCH();
440 :
441 36802289 : if (Z_REFCOUNT_PP(zval_ptr) == 1) {
442 24537963 : Z_UNSET_ISREF_PP(zval_ptr);
443 : }
444 :
445 36802289 : GC_ZVAL_CHECK_POSSIBLE_ROOT(*zval_ptr);
446 : }
447 66217749 : }
448 : /* }}} */
449 :
450 : ZEND_API void _zval_internal_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) /* {{{ */
451 11800092 : {
452 : #if DEBUG_ZEND>=2
453 : printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, Z_REFCOUNT_PP(zval_ptr), Z_REFCOUNT_PP(zval_ptr) - 1);
454 : #endif
455 11800092 : Z_DELREF_PP(zval_ptr);
456 11800092 : if (Z_REFCOUNT_PP(zval_ptr) == 0) {
457 7807930 : zval_internal_dtor(*zval_ptr);
458 7807930 : free(*zval_ptr);
459 3992162 : } else if (Z_REFCOUNT_PP(zval_ptr) == 1) {
460 865521 : Z_UNSET_ISREF_PP(zval_ptr);
461 : }
462 11800092 : }
463 : /* }}} */
464 :
465 : ZEND_API int zend_is_true(zval *op) /* {{{ */
466 12676 : {
467 12676 : return i_zend_is_true(op);
468 : }
469 : /* }}} */
470 :
471 : #include "../TSRM/tsrm_strtok_r.h"
472 :
473 : #define IS_VISITED_CONSTANT IS_CONSTANT_INDEX
474 : #define IS_CONSTANT_VISITED(p) (Z_TYPE_P(p) & IS_VISITED_CONSTANT)
475 : #define Z_REAL_TYPE_P(p) (Z_TYPE_P(p) & ~IS_VISITED_CONSTANT)
476 : #define MARK_CONSTANT_VISITED(p) Z_TYPE_P(p) |= IS_VISITED_CONSTANT
477 :
478 : static void zval_deep_copy(zval **p)
479 29 : {
480 : zval *value;
481 :
482 29 : ALLOC_ZVAL(value);
483 29 : *value = **p;
484 29 : Z_TYPE_P(value) &= ~IS_CONSTANT_INDEX;
485 29 : zval_copy_ctor(value);
486 29 : Z_TYPE_P(value) = Z_TYPE_PP(p);
487 29 : INIT_PZVAL(value);
488 29 : *p = value;
489 29 : }
490 :
491 : ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC) /* {{{ */
492 141362 : {
493 141362 : zval *p = *pp;
494 141362 : zend_bool inline_change = (zend_bool) (zend_uintptr_t) arg;
495 : zval const_value;
496 : char *colon;
497 :
498 141362 : if (IS_CONSTANT_VISITED(p)) {
499 1 : zend_error(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p));
500 141361 : } else if ((Z_TYPE_P(p) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
501 : int refcount;
502 : zend_uchar is_ref;
503 :
504 268 : SEPARATE_ZVAL_IF_NOT_REF(pp);
505 268 : p = *pp;
506 :
507 268 : MARK_CONSTANT_VISITED(p);
508 :
509 268 : refcount = Z_REFCOUNT_P(p);
510 268 : is_ref = Z_ISREF_P(p);
511 :
512 268 : if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope, Z_REAL_TYPE_P(p) TSRMLS_CC)) {
513 13 : char *actual = Z_STRVAL_P(p);
514 :
515 13 : if ((colon = zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) {
516 0 : zend_error(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
517 0 : Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1);
518 0 : if (inline_change) {
519 0 : colon = estrndup(colon, Z_STRLEN_P(p));
520 0 : efree(Z_STRVAL_P(p));
521 0 : Z_STRVAL_P(p) = colon;
522 : } else {
523 0 : Z_STRVAL_P(p) = colon + 1;
524 : }
525 : } else {
526 13 : char *save = actual, *slash;
527 13 : int actual_len = Z_STRLEN_P(p);
528 13 : if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) && (slash = (char *)zend_memrchr(actual, '\\', actual_len))) {
529 2 : actual = slash + 1;
530 2 : actual_len -= (actual - Z_STRVAL_P(p));
531 2 : if (inline_change) {
532 1 : actual = estrndup(actual, actual_len);
533 1 : Z_STRVAL_P(p) = actual;
534 1 : Z_STRLEN_P(p) = actual_len;
535 : }
536 : }
537 13 : if (actual[0] == '\\') {
538 0 : if (inline_change) {
539 0 : memmove(Z_STRVAL_P(p), Z_STRVAL_P(p)+1, Z_STRLEN_P(p));
540 0 : --Z_STRLEN_P(p);
541 : } else {
542 0 : ++actual;
543 : }
544 0 : --actual_len;
545 : }
546 13 : if ((Z_TYPE_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
547 10 : int fix_save = 0;
548 10 : if (save[0] == '\\') {
549 0 : save++;
550 0 : fix_save = 1;
551 : }
552 10 : zend_error(E_ERROR, "Undefined constant '%s'", save);
553 0 : if (fix_save) {
554 0 : save--;
555 : }
556 0 : if (inline_change) {
557 0 : efree(save);
558 : }
559 0 : save = NULL;
560 : }
561 3 : if (inline_change && save && save != actual) {
562 1 : efree(save);
563 : }
564 3 : zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
565 3 : p->type = IS_STRING;
566 3 : if (!inline_change) {
567 1 : Z_STRVAL_P(p) = actual;
568 1 : Z_STRLEN_P(p) = actual_len;
569 1 : zval_copy_ctor(p);
570 : }
571 : }
572 : } else {
573 247 : if (inline_change) {
574 91 : STR_FREE(Z_STRVAL_P(p));
575 : }
576 247 : *p = const_value;
577 : }
578 :
579 250 : Z_SET_REFCOUNT_P(p, refcount);
580 250 : Z_SET_ISREF_TO_P(p, is_ref);
581 141093 : } else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) {
582 : zval **element, *new_val;
583 : char *str_index;
584 : uint str_index_len;
585 : ulong num_index;
586 : int ret;
587 :
588 993 : SEPARATE_ZVAL_IF_NOT_REF(pp);
589 993 : p = *pp;
590 993 : Z_TYPE_P(p) = IS_ARRAY;
591 :
592 993 : if (!inline_change) {
593 : zval *tmp;
594 51 : HashTable *tmp_ht = NULL;
595 :
596 51 : ALLOC_HASHTABLE(tmp_ht);
597 51 : zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0);
598 51 : zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *));
599 51 : Z_ARRVAL_P(p) = tmp_ht;
600 : }
601 :
602 : /* First go over the array and see if there are any constant indices */
603 993 : zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
604 4574 : while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element) == SUCCESS) {
605 2594 : if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
606 2513 : zend_hash_move_forward(Z_ARRVAL_P(p));
607 2513 : continue;
608 : }
609 81 : Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
610 81 : if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL) != HASH_KEY_IS_STRING) {
611 0 : zend_hash_move_forward(Z_ARRVAL_P(p));
612 0 : continue;
613 : }
614 81 : if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) {
615 7 : char *actual, *save = str_index;
616 7 : if ((colon = zend_memrchr(str_index, ':', str_index_len - 3))) {
617 0 : zend_error(E_ERROR, "Undefined class constant '%s'", str_index);
618 0 : str_index_len -= ((colon - str_index) + 1);
619 0 : str_index = colon;
620 : } else {
621 7 : if (str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) {
622 2 : if ((actual = (char *)zend_memrchr(str_index, '\\', str_index_len - 3))) {
623 1 : actual++;
624 1 : str_index_len -= (actual - str_index);
625 1 : str_index = actual;
626 : }
627 : }
628 7 : if (str_index[0] == '\\') {
629 0 : ++str_index;
630 0 : --str_index_len;
631 : }
632 7 : if (save[0] == '\\') {
633 0 : ++save;
634 : }
635 7 : if ((str_index[str_index_len - 2] & IS_CONSTANT_UNQUALIFIED) == 0) {
636 5 : zend_error(E_ERROR, "Undefined constant '%s'", save);
637 : }
638 2 : zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
639 : }
640 2 : ZVAL_STRINGL(&const_value, str_index, str_index_len-3, 1);
641 : }
642 :
643 75 : if (Z_REFCOUNT_PP(element) > 1) {
644 3 : ALLOC_ZVAL(new_val);
645 3 : *new_val = **element;
646 3 : zval_copy_ctor(new_val);
647 3 : Z_SET_REFCOUNT_P(new_val, 1);
648 3 : Z_UNSET_ISREF_P(new_val);
649 :
650 : /* preserve this bit for inheritance */
651 3 : Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
652 3 : zval_ptr_dtor(element);
653 3 : *element = new_val;
654 : }
655 :
656 75 : switch (Z_TYPE(const_value)) {
657 : case IS_STRING:
658 27 : ret = zend_symtable_update_current_key(Z_ARRVAL_P(p), Z_STRVAL(const_value), Z_STRLEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
659 27 : break;
660 : case IS_BOOL:
661 : case IS_LONG:
662 48 : ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
663 48 : break;
664 : case IS_DOUBLE:
665 0 : ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, zend_dval_to_lval(Z_DVAL(const_value)), HASH_UPDATE_KEY_IF_BEFORE, NULL);
666 0 : break;
667 : case IS_NULL:
668 0 : ret = zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
669 0 : break;
670 : default:
671 0 : ret = SUCCESS;
672 : break;
673 : }
674 75 : if (ret == SUCCESS) {
675 71 : zend_hash_move_forward(Z_ARRVAL_P(p));
676 : }
677 75 : zval_dtor(&const_value);
678 : }
679 987 : zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
680 978 : zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
681 : }
682 141328 : return 0;
683 : }
684 : /* }}} */
685 :
686 : ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC) /* {{{ */
687 140988 : {
688 140988 : return zval_update_constant_ex(pp, arg, NULL TSRMLS_CC);
689 : }
690 : /* }}} */
691 :
692 : int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC) /* {{{ */
693 1008 : {
694 : zval ***params_array;
695 : zend_uint i;
696 : int ex_retval;
697 1008 : zval *local_retval_ptr = NULL;
698 :
699 1008 : if (param_count) {
700 896 : params_array = (zval ***) emalloc(sizeof(zval **)*param_count);
701 3516 : for (i=0; i<param_count; i++) {
702 2620 : params_array[i] = ¶ms[i];
703 : }
704 : } else {
705 112 : params_array = NULL;
706 : }
707 1008 : ex_retval = call_user_function_ex(function_table, object_pp, function_name, &local_retval_ptr, param_count, params_array, 1, NULL TSRMLS_CC);
708 992 : if (local_retval_ptr) {
709 978 : COPY_PZVAL_TO_ZVAL(*retval_ptr, local_retval_ptr);
710 : } else {
711 14 : INIT_ZVAL(*retval_ptr);
712 : }
713 992 : if (params_array) {
714 883 : efree(params_array);
715 : }
716 992 : return ex_retval;
717 : }
718 : /* }}} */
719 :
720 : int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC) /* {{{ */
721 10937 : {
722 : zend_fcall_info fci;
723 :
724 10937 : fci.size = sizeof(fci);
725 10937 : fci.function_table = function_table;
726 10937 : fci.object_ptr = object_pp ? *object_pp : NULL;
727 10937 : fci.function_name = function_name;
728 10937 : fci.retval_ptr_ptr = retval_ptr_ptr;
729 10937 : fci.param_count = param_count;
730 10937 : fci.params = params;
731 10937 : fci.no_separation = (zend_bool) no_separation;
732 10937 : fci.symbol_table = symbol_table;
733 :
734 10937 : return zend_call_function(&fci, NULL TSRMLS_CC);
735 : }
736 : /* }}} */
737 :
738 : int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC) /* {{{ */
739 377324 : {
740 : zend_uint i;
741 : zval **original_return_value;
742 : HashTable *calling_symbol_table;
743 : zend_op_array *original_op_array;
744 : zend_op **original_opline_ptr;
745 : zend_class_entry *current_scope;
746 : zend_class_entry *current_called_scope;
747 377324 : zend_class_entry *calling_scope = NULL;
748 377324 : zend_class_entry *called_scope = NULL;
749 : zval *current_this;
750 : zend_execute_data execute_data;
751 :
752 377324 : *fci->retval_ptr_ptr = NULL;
753 :
754 377324 : if (!EG(active)) {
755 2 : return FAILURE; /* executor is already inactive */
756 : }
757 :
758 377322 : if (EG(exception)) {
759 8 : return FAILURE; /* we would result in an instable executor otherwise */
760 : }
761 :
762 377314 : switch (fci->size) {
763 : case sizeof(zend_fcall_info):
764 377314 : break; /* nothing to do currently */
765 : default:
766 0 : zend_error(E_ERROR, "Corrupted fcall_info provided to zend_call_function()");
767 : break;
768 : }
769 :
770 : /* Initialize execute_data */
771 377314 : if (EG(current_execute_data)) {
772 376803 : execute_data = *EG(current_execute_data);
773 376803 : EX(op_array) = NULL;
774 376803 : EX(opline) = NULL;
775 376803 : EX(object) = NULL;
776 : } else {
777 : /* This only happens when we're called outside any execute()'s
778 : * It shouldn't be strictly necessary to NULL execute_data out,
779 : * but it may make bugs easier to spot
780 : */
781 511 : memset(&execute_data, 0, sizeof(zend_execute_data));
782 : }
783 :
784 377314 : if (!fci_cache || !fci_cache->initialized) {
785 : zend_fcall_info_cache fci_cache_local;
786 : char *callable_name;
787 226924 : char *error = NULL;
788 :
789 226924 : if (!fci_cache) {
790 11299 : fci_cache = &fci_cache_local;
791 : }
792 :
793 226924 : if (!zend_is_callable_ex(fci->function_name, fci->object_ptr, IS_CALLABLE_CHECK_SILENT, &callable_name, NULL, fci_cache, &error TSRMLS_CC)) {
794 213 : if (error) {
795 0 : zend_error(E_WARNING, "Invalid callback %s, %s", callable_name, error);
796 0 : efree(error);
797 : }
798 213 : if (callable_name) {
799 211 : efree(callable_name);
800 : }
801 213 : return FAILURE;
802 226711 : } else if (error) {
803 : /* Capitalize the first latter of the error message */
804 4 : if (error[0] >= 'a' && error[0] <= 'z') {
805 4 : error[0] += ('A' - 'a');
806 : }
807 4 : zend_error(E_STRICT, "%s", error);
808 4 : efree(error);
809 : }
810 226711 : efree(callable_name);
811 : }
812 :
813 377101 : EX(function_state).function = fci_cache->function_handler;
814 377101 : calling_scope = fci_cache->calling_scope;
815 377101 : called_scope = fci_cache->called_scope;
816 377101 : fci->object_ptr = fci_cache->object_ptr;
817 377101 : EX(object) = fci->object_ptr;
818 377101 : if (fci->object_ptr && Z_TYPE_P(fci->object_ptr) == IS_OBJECT &&
819 : (!EG(objects_store).object_buckets || !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(fci->object_ptr)].valid)) {
820 0 : return FAILURE;
821 : }
822 :
823 377101 : if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
824 1 : if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
825 1 : zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
826 : }
827 0 : if (EX(function_state).function->common.fn_flags & ZEND_ACC_DEPRECATED) {
828 0 : zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
829 : EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name : "",
830 : EX(function_state).function->common.scope ? "::" : "",
831 : EX(function_state).function->common.function_name);
832 : }
833 : }
834 :
835 377100 : ZEND_VM_STACK_GROW_IF_NEEDED(fci->param_count + 1);
836 :
837 836588 : for (i=0; i<fci->param_count; i++) {
838 : zval *param;
839 :
840 459495 : if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION
841 : && !ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)
842 : && PZVAL_IS_REF(*fci->params[i])) {
843 81 : SEPARATE_ZVAL(fci->params[i]);
844 : }
845 :
846 459711 : if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)
847 : && !PZVAL_IS_REF(*fci->params[i])) {
848 :
849 223 : if (Z_REFCOUNT_PP(fci->params[i]) > 1) {
850 : zval *new_zval;
851 :
852 18 : if (fci->no_separation) {
853 7 : if(i) {
854 : /* hack to clean up the stack */
855 0 : zend_vm_stack_push_nocheck((void *) (zend_uintptr_t)i TSRMLS_CC);
856 0 : zend_vm_stack_clear_multiple(TSRMLS_C);
857 : }
858 :
859 7 : zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
860 : i+1,
861 : EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name : "",
862 : EX(function_state).function->common.scope ? "::" : "",
863 : EX(function_state).function->common.function_name);
864 7 : return FAILURE;
865 : }
866 :
867 11 : ALLOC_ZVAL(new_zval);
868 11 : *new_zval = **fci->params[i];
869 11 : zval_copy_ctor(new_zval);
870 11 : Z_SET_REFCOUNT_P(new_zval, 1);
871 11 : Z_DELREF_PP(fci->params[i]);
872 11 : *fci->params[i] = new_zval;
873 : }
874 216 : Z_ADDREF_PP(fci->params[i]);
875 216 : Z_SET_ISREF_PP(fci->params[i]);
876 216 : param = *fci->params[i];
877 459272 : } else if (*fci->params[i] != &EG(uninitialized_zval)) {
878 459266 : Z_ADDREF_PP(fci->params[i]);
879 459266 : param = *fci->params[i];
880 : } else {
881 6 : ALLOC_ZVAL(param);
882 6 : *param = **(fci->params[i]);
883 6 : INIT_PZVAL(param);
884 : }
885 459488 : zend_vm_stack_push_nocheck(param TSRMLS_CC);
886 : }
887 :
888 377093 : EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C);
889 377093 : zend_vm_stack_push_nocheck((void*)(zend_uintptr_t)fci->param_count TSRMLS_CC);
890 :
891 377093 : current_scope = EG(scope);
892 377093 : EG(scope) = calling_scope;
893 :
894 377093 : current_this = EG(This);
895 :
896 377093 : current_called_scope = EG(called_scope);
897 377093 : if (called_scope) {
898 158124 : EG(called_scope) = called_scope;
899 218969 : } else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) {
900 217952 : EG(called_scope) = NULL;
901 : }
902 :
903 377093 : if (fci->object_ptr) {
904 157716 : if ((EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
905 42 : EG(This) = NULL;
906 : } else {
907 157674 : EG(This) = fci->object_ptr;
908 :
909 157674 : if (!PZVAL_IS_REF(EG(This))) {
910 133954 : Z_ADDREF_P(EG(This)); /* For $this pointer */
911 : } else {
912 : zval *this_ptr;
913 :
914 23720 : ALLOC_ZVAL(this_ptr);
915 23720 : *this_ptr = *EG(This);
916 23720 : INIT_PZVAL(this_ptr);
917 23720 : zval_copy_ctor(this_ptr);
918 23720 : EG(This) = this_ptr;
919 : }
920 : }
921 : } else {
922 219377 : EG(This) = NULL;
923 : }
924 :
925 377093 : EX(prev_execute_data) = EG(current_execute_data);
926 377093 : EG(current_execute_data) = &execute_data;
927 :
928 377093 : if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
929 341585 : calling_symbol_table = EG(active_symbol_table);
930 341585 : EG(scope) = EX(function_state).function->common.scope;
931 341585 : if (fci->symbol_table) {
932 0 : EG(active_symbol_table) = fci->symbol_table;
933 : } else {
934 341585 : EG(active_symbol_table) = NULL;
935 : }
936 :
937 341585 : original_return_value = EG(return_value_ptr_ptr);
938 341585 : original_op_array = EG(active_op_array);
939 341585 : EG(return_value_ptr_ptr) = fci->retval_ptr_ptr;
940 341585 : EG(active_op_array) = (zend_op_array *) EX(function_state).function;
941 341585 : original_opline_ptr = EG(opline_ptr);
942 341585 : zend_execute(EG(active_op_array) TSRMLS_CC);
943 341560 : if (!fci->symbol_table && EG(active_symbol_table)) {
944 166 : if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) {
945 0 : zend_hash_destroy(EG(active_symbol_table));
946 0 : FREE_HASHTABLE(EG(active_symbol_table));
947 : } else {
948 : /* clean before putting into the cache, since clean
949 : could call dtors, which could use cached hash */
950 166 : zend_hash_clean(EG(active_symbol_table));
951 166 : *(++EG(symtable_cache_ptr)) = EG(active_symbol_table);
952 : }
953 : }
954 341560 : EG(active_symbol_table) = calling_symbol_table;
955 341560 : EG(active_op_array) = original_op_array;
956 341560 : EG(return_value_ptr_ptr)=original_return_value;
957 341560 : EG(opline_ptr) = original_opline_ptr;
958 35508 : } else if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
959 35508 : int call_via_handler = (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
960 35508 : ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr);
961 35508 : if (EX(function_state).function->common.scope) {
962 34491 : EG(scope) = EX(function_state).function->common.scope;
963 : }
964 35508 : ((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
965 : /* We shouldn't fix bad extensions here,
966 : because it can break proper ones (Bug #34045)
967 : if (!EX(function_state).function->common.return_reference)
968 : {
969 : INIT_PZVAL(*fci->retval_ptr_ptr);
970 : }*/
971 35498 : if (EG(exception) && fci->retval_ptr_ptr) {
972 64 : zval_ptr_dtor(fci->retval_ptr_ptr);
973 64 : *fci->retval_ptr_ptr = NULL;
974 : }
975 :
976 35498 : if (call_via_handler) {
977 : /* We must re-initialize function again */
978 33 : fci_cache->initialized = 0;
979 : }
980 : } else { /* ZEND_OVERLOADED_FUNCTION */
981 0 : ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr);
982 :
983 : /* Not sure what should be done here if it's a static method */
984 0 : if (fci->object_ptr) {
985 0 : Z_OBJ_HT_P(fci->object_ptr)->call_method(EX(function_state).function->common.function_name, fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
986 : } else {
987 0 : zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
988 : }
989 :
990 0 : if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
991 0 : efree(EX(function_state).function->common.function_name);
992 : }
993 0 : efree(EX(function_state).function);
994 :
995 0 : if (EG(exception) && fci->retval_ptr_ptr) {
996 0 : zval_ptr_dtor(fci->retval_ptr_ptr);
997 0 : *fci->retval_ptr_ptr = NULL;
998 : }
999 : }
1000 377058 : zend_vm_stack_clear_multiple(TSRMLS_C);
1001 :
1002 377058 : if (EG(This)) {
1003 157656 : zval_ptr_dtor(&EG(This));
1004 : }
1005 377058 : EG(called_scope) = current_called_scope;
1006 377058 : EG(scope) = current_scope;
1007 377058 : EG(This) = current_this;
1008 377058 : EG(current_execute_data) = EX(prev_execute_data);
1009 :
1010 377058 : if (EG(exception)) {
1011 203 : zend_throw_exception_internal(NULL TSRMLS_CC);
1012 : }
1013 377057 : return SUCCESS;
1014 : }
1015 : /* }}} */
1016 :
1017 : ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC) /* {{{ */
1018 136245 : {
1019 : zval **args[1];
1020 : zval autoload_function;
1021 : zval *class_name_ptr;
1022 136245 : zval *retval_ptr = NULL;
1023 : int retval, lc_length;
1024 : char *lc_name;
1025 : char *lc_free;
1026 : zend_fcall_info fcall_info;
1027 : zend_fcall_info_cache fcall_cache;
1028 136245 : char dummy = 1;
1029 : ulong hash;
1030 : ALLOCA_FLAG(use_heap)
1031 :
1032 136245 : if (name == NULL || !name_length) {
1033 67 : return FAILURE;
1034 : }
1035 :
1036 136178 : lc_free = lc_name = do_alloca(name_length + 1, use_heap);
1037 136178 : zend_str_tolower_copy(lc_name, name, name_length);
1038 136178 : lc_length = name_length + 1;
1039 :
1040 136178 : if (lc_name[0] == '\\') {
1041 9 : lc_name += 1;
1042 9 : lc_length -= 1;
1043 : }
1044 :
1045 136178 : hash = zend_inline_hash_func(lc_name, lc_length);
1046 :
1047 136178 : if (zend_hash_quick_find(EG(class_table), lc_name, lc_length, hash, (void **) ce) == SUCCESS) {
1048 135641 : free_alloca(lc_free, use_heap);
1049 135641 : return SUCCESS;
1050 : }
1051 :
1052 : /* The compiler is not-reentrant. Make sure we __autoload() only during run-time
1053 : * (doesn't impact fuctionality of __autoload()
1054 : */
1055 537 : if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
1056 278 : free_alloca(lc_free, use_heap);
1057 278 : return FAILURE;
1058 : }
1059 :
1060 259 : if (EG(in_autoload) == NULL) {
1061 140 : ALLOC_HASHTABLE(EG(in_autoload));
1062 140 : zend_hash_init(EG(in_autoload), 0, NULL, NULL, 0);
1063 : }
1064 :
1065 259 : if (zend_hash_quick_add(EG(in_autoload), lc_name, lc_length, hash, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
1066 4 : free_alloca(lc_free, use_heap);
1067 4 : return FAILURE;
1068 : }
1069 :
1070 255 : ZVAL_STRINGL(&autoload_function, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1, 0);
1071 :
1072 255 : ALLOC_ZVAL(class_name_ptr);
1073 255 : INIT_PZVAL(class_name_ptr);
1074 255 : ZVAL_STRINGL(class_name_ptr, name, name_length, 1);
1075 :
1076 255 : args[0] = &class_name_ptr;
1077 :
1078 255 : fcall_info.size = sizeof(fcall_info);
1079 255 : fcall_info.function_table = EG(function_table);
1080 255 : fcall_info.function_name = &autoload_function;
1081 255 : fcall_info.symbol_table = NULL;
1082 255 : fcall_info.retval_ptr_ptr = &retval_ptr;
1083 255 : fcall_info.param_count = 1;
1084 255 : fcall_info.params = args;
1085 255 : fcall_info.object_ptr = NULL;
1086 255 : fcall_info.no_separation = 1;
1087 :
1088 255 : fcall_cache.initialized = EG(autoload_func) ? 1 : 0;
1089 255 : fcall_cache.function_handler = EG(autoload_func);
1090 255 : fcall_cache.calling_scope = NULL;
1091 255 : fcall_cache.called_scope = NULL;
1092 255 : fcall_cache.object_ptr = NULL;
1093 :
1094 255 : zend_exception_save(TSRMLS_C);
1095 255 : retval = zend_call_function(&fcall_info, &fcall_cache TSRMLS_CC);
1096 251 : zend_exception_restore(TSRMLS_C);
1097 :
1098 251 : EG(autoload_func) = fcall_cache.function_handler;
1099 :
1100 251 : zval_ptr_dtor(&class_name_ptr);
1101 :
1102 251 : zend_hash_quick_del(EG(in_autoload), lc_name, lc_length, hash);
1103 :
1104 251 : if (retval_ptr) {
1105 111 : zval_ptr_dtor(&retval_ptr);
1106 : }
1107 :
1108 251 : if (retval == FAILURE) {
1109 126 : free_alloca(lc_free, use_heap);
1110 126 : return FAILURE;
1111 : }
1112 :
1113 125 : retval = zend_hash_quick_find(EG(class_table), lc_name, lc_length, hash, (void **) ce);
1114 125 : free_alloca(lc_free, use_heap);
1115 125 : return retval;
1116 : }
1117 : /* }}} */
1118 :
1119 : ZEND_API int zend_lookup_class(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC) /* {{{ */
1120 3129 : {
1121 3129 : return zend_lookup_class_ex(name, name_length, 1, ce TSRMLS_CC);
1122 : }
1123 : /* }}} */
1124 :
1125 : ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *string_name TSRMLS_DC) /* {{{ */
1126 115 : {
1127 : zval pv;
1128 : zend_op_array *new_op_array;
1129 115 : zend_op_array *original_active_op_array = EG(active_op_array);
1130 : zend_uint original_compiler_options;
1131 : int retval;
1132 :
1133 115 : if (retval_ptr) {
1134 31 : Z_STRLEN(pv) = str_len + sizeof("return ;") - 1;
1135 31 : Z_STRVAL(pv) = emalloc(Z_STRLEN(pv) + 1);
1136 31 : memcpy(Z_STRVAL(pv), "return ", sizeof("return ") - 1);
1137 31 : memcpy(Z_STRVAL(pv) + sizeof("return ") - 1, str, str_len);
1138 31 : Z_STRVAL(pv)[Z_STRLEN(pv) - 1] = ';';
1139 31 : Z_STRVAL(pv)[Z_STRLEN(pv)] = '\0';
1140 : } else {
1141 84 : Z_STRLEN(pv) = str_len;
1142 84 : Z_STRVAL(pv) = str;
1143 : }
1144 115 : Z_TYPE(pv) = IS_STRING;
1145 :
1146 : /*printf("Evaluating '%s'\n", pv.value.str.val);*/
1147 :
1148 115 : original_compiler_options = CG(compiler_options);
1149 115 : CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL;
1150 115 : new_op_array = zend_compile_string(&pv, string_name TSRMLS_CC);
1151 115 : CG(compiler_options) = original_compiler_options;
1152 :
1153 115 : if (new_op_array) {
1154 108 : zval *local_retval_ptr=NULL;
1155 108 : zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
1156 108 : zend_op **original_opline_ptr = EG(opline_ptr);
1157 108 : int orig_interactive = CG(interactive);
1158 :
1159 108 : EG(return_value_ptr_ptr) = &local_retval_ptr;
1160 108 : EG(active_op_array) = new_op_array;
1161 108 : EG(no_extensions)=1;
1162 108 : if (!EG(active_symbol_table)) {
1163 3 : zend_rebuild_symbol_table(TSRMLS_C);
1164 : }
1165 108 : CG(interactive) = 0;
1166 :
1167 108 : zend_execute(new_op_array TSRMLS_CC);
1168 :
1169 108 : CG(interactive) = orig_interactive;
1170 108 : if (local_retval_ptr) {
1171 108 : if (retval_ptr) {
1172 26 : COPY_PZVAL_TO_ZVAL(*retval_ptr, local_retval_ptr);
1173 : } else {
1174 82 : zval_ptr_dtor(&local_retval_ptr);
1175 : }
1176 : } else {
1177 0 : if (retval_ptr) {
1178 0 : INIT_ZVAL(*retval_ptr);
1179 : }
1180 : }
1181 :
1182 108 : EG(no_extensions)=0;
1183 108 : EG(opline_ptr) = original_opline_ptr;
1184 108 : EG(active_op_array) = original_active_op_array;
1185 108 : destroy_op_array(new_op_array TSRMLS_CC);
1186 108 : efree(new_op_array);
1187 108 : EG(return_value_ptr_ptr) = original_return_value_ptr_ptr;
1188 108 : retval = SUCCESS;
1189 : } else {
1190 7 : retval = FAILURE;
1191 : }
1192 115 : if (retval_ptr) {
1193 31 : zval_dtor(&pv);
1194 : }
1195 115 : return retval;
1196 : }
1197 : /* }}} */
1198 :
1199 : ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC) /* {{{ */
1200 0 : {
1201 0 : return zend_eval_stringl(str, strlen(str), retval_ptr, string_name TSRMLS_CC);
1202 : }
1203 : /* }}} */
1204 :
1205 : ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC) /* {{{ */
1206 20 : {
1207 : int result;
1208 :
1209 20 : result = zend_eval_stringl(str, str_len, retval_ptr, string_name TSRMLS_CC);
1210 20 : if (handle_exceptions && EG(exception)) {
1211 0 : zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
1212 0 : result = FAILURE;
1213 : }
1214 20 : return result;
1215 : }
1216 : /* }}} */
1217 :
1218 : ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC) /* {{{ */
1219 20 : {
1220 20 : return zend_eval_stringl_ex(str, strlen(str), retval_ptr, string_name, handle_exceptions TSRMLS_CC);
1221 : }
1222 : /* }}} */
1223 :
1224 : void execute_new_code(TSRMLS_D) /* {{{ */
1225 0 : {
1226 : zend_op *opline, *end;
1227 : zend_op *ret_opline;
1228 : int orig_interactive;
1229 :
1230 0 : if (!(CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE)
1231 : || CG(active_op_array)->backpatch_count>0
1232 : || CG(active_op_array)->function_name
1233 : || CG(active_op_array)->type!=ZEND_USER_FUNCTION) {
1234 0 : return;
1235 : }
1236 :
1237 0 : ret_opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1238 0 : ret_opline->opcode = ZEND_RETURN;
1239 0 : ret_opline->op1.op_type = IS_CONST;
1240 0 : INIT_ZVAL(ret_opline->op1.u.constant);
1241 0 : SET_UNUSED(ret_opline->op2);
1242 :
1243 0 : if (!CG(active_op_array)->start_op) {
1244 0 : CG(active_op_array)->start_op = CG(active_op_array)->opcodes;
1245 : }
1246 :
1247 0 : opline=CG(active_op_array)->start_op;
1248 0 : end=CG(active_op_array)->opcodes+CG(active_op_array)->last;
1249 :
1250 0 : while (opline<end) {
1251 0 : if (opline->op1.op_type == IS_CONST) {
1252 0 : Z_SET_ISREF(opline->op1.u.constant);
1253 0 : Z_SET_REFCOUNT(opline->op1.u.constant, 2); /* Make sure is_ref won't be reset */
1254 : }
1255 0 : if (opline->op2.op_type == IS_CONST) {
1256 0 : Z_SET_ISREF(opline->op2.u.constant);
1257 0 : Z_SET_REFCOUNT(opline->op2.u.constant, 2);
1258 : }
1259 0 : switch (opline->opcode) {
1260 : case ZEND_GOTO:
1261 0 : if (Z_TYPE(opline->op2.u.constant) != IS_LONG) {
1262 0 : zend_resolve_goto_label(CG(active_op_array), opline, 1 TSRMLS_CC);
1263 : }
1264 : /* break omitted intentionally */
1265 : case ZEND_JMP:
1266 0 : opline->op1.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op1.u.opline_num];
1267 0 : break;
1268 : case ZEND_JMPZ:
1269 : case ZEND_JMPNZ:
1270 : case ZEND_JMPZ_EX:
1271 : case ZEND_JMPNZ_EX:
1272 : case ZEND_JMP_SET:
1273 0 : opline->op2.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.u.opline_num];
1274 : break;
1275 : }
1276 0 : ZEND_VM_SET_OPCODE_HANDLER(opline);
1277 0 : opline++;
1278 : }
1279 :
1280 0 : zend_release_labels(TSRMLS_C);
1281 :
1282 0 : EG(return_value_ptr_ptr) = NULL;
1283 0 : EG(active_op_array) = CG(active_op_array);
1284 0 : orig_interactive = CG(interactive);
1285 0 : CG(interactive) = 0;
1286 0 : zend_execute(CG(active_op_array) TSRMLS_CC);
1287 0 : CG(interactive) = orig_interactive;
1288 :
1289 0 : if (EG(exception)) {
1290 0 : zend_exception_error(EG(exception), E_ERROR TSRMLS_CC);
1291 : }
1292 :
1293 0 : CG(active_op_array)->last -= 1; /* get rid of that ZEND_RETURN */
1294 0 : CG(active_op_array)->start_op = CG(active_op_array)->opcodes+CG(active_op_array)->last;
1295 : }
1296 : /* }}} */
1297 :
1298 : ZEND_API void zend_timeout(int dummy) /* {{{ */
1299 3 : {
1300 : TSRMLS_FETCH();
1301 :
1302 3 : if (zend_on_timeout) {
1303 3 : zend_on_timeout(EG(timeout_seconds) TSRMLS_CC);
1304 : }
1305 :
1306 3 : zend_error(E_ERROR, "Maximum execution time of %d second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
1307 0 : }
1308 : /* }}} */
1309 :
1310 : #ifdef ZEND_WIN32
1311 : static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) /* {{{ */
1312 : {
1313 : switch (message) {
1314 : case WM_DESTROY:
1315 : PostQuitMessage(0);
1316 : break;
1317 : case WM_REGISTER_ZEND_TIMEOUT:
1318 : /* wParam is the thread id pointer, lParam is the timeout amount in seconds */
1319 : if (lParam == 0) {
1320 : KillTimer(timeout_window, wParam);
1321 : } else {
1322 : #ifdef ZTS
1323 : void ***tsrm_ls;
1324 : #endif
1325 : SetTimer(timeout_window, wParam, lParam*1000, NULL);
1326 : #ifdef ZTS
1327 : tsrm_ls = ts_resource_ex(0, &wParam);
1328 : if (!tsrm_ls) {
1329 : /* shouldn't normally happen */
1330 : break;
1331 : }
1332 : #endif
1333 : EG(timed_out) = 0;
1334 : }
1335 : break;
1336 : case WM_UNREGISTER_ZEND_TIMEOUT:
1337 : /* wParam is the thread id pointer */
1338 : KillTimer(timeout_window, wParam);
1339 : break;
1340 : case WM_TIMER: {
1341 : #ifdef ZTS
1342 : void ***tsrm_ls;
1343 :
1344 : tsrm_ls = ts_resource_ex(0, &wParam);
1345 : if (!tsrm_ls) {
1346 : /* Thread died before receiving its timeout? */
1347 : break;
1348 : }
1349 : #endif
1350 : KillTimer(timeout_window, wParam);
1351 : EG(timed_out) = 1;
1352 : }
1353 : break;
1354 : default:
1355 : return DefWindowProc(hWnd, message, wParam, lParam);
1356 : }
1357 : return 0;
1358 : }
1359 : /* }}} */
1360 :
1361 : static unsigned __stdcall timeout_thread_proc(void *pArgs) /* {{{ */
1362 : {
1363 : MSG message;
1364 :
1365 : wc.style=0;
1366 : wc.lpfnWndProc = zend_timeout_WndProc;
1367 : wc.cbClsExtra=0;
1368 : wc.cbWndExtra=0;
1369 : wc.hInstance=NULL;
1370 : wc.hIcon=NULL;
1371 : wc.hCursor=NULL;
1372 : wc.hbrBackground=(HBRUSH)(COLOR_BACKGROUND + 5);
1373 : wc.lpszMenuName=NULL;
1374 : wc.lpszClassName = "Zend Timeout Window";
1375 : if (!RegisterClass(&wc)) {
1376 : return -1;
1377 : }
1378 : timeout_window = CreateWindow(wc.lpszClassName, wc.lpszClassName, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
1379 : SetEvent(timeout_thread_event);
1380 : while (GetMessage(&message, NULL, 0, 0)) {
1381 : SendMessage(timeout_window, message.message, message.wParam, message.lParam);
1382 : if (message.message == WM_QUIT) {
1383 : break;
1384 : }
1385 : }
1386 : DestroyWindow(timeout_window);
1387 : UnregisterClass(wc.lpszClassName, NULL);
1388 : SetEvent(timeout_thread_handle);
1389 : return 0;
1390 : }
1391 : /* }}} */
1392 :
1393 : void zend_init_timeout_thread(void) /* {{{ */
1394 : {
1395 : timeout_thread_event = CreateEvent(NULL, FALSE, FALSE, NULL);
1396 : timeout_thread_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
1397 : _beginthreadex(NULL, 0, timeout_thread_proc, NULL, 0, &timeout_thread_id);
1398 : WaitForSingleObject(timeout_thread_event, INFINITE);
1399 : }
1400 : /* }}} */
1401 :
1402 : void zend_shutdown_timeout_thread(void) /* {{{ */
1403 : {
1404 : if (!timeout_thread_initialized) {
1405 : return;
1406 : }
1407 : PostThreadMessage(timeout_thread_id, WM_QUIT, 0, 0);
1408 :
1409 : /* Wait for thread termination */
1410 : WaitForSingleObject(timeout_thread_handle, 5000);
1411 : CloseHandle(timeout_thread_handle);
1412 : timeout_thread_initialized = 0;
1413 : }
1414 : /* }}} */
1415 :
1416 : #endif
1417 :
1418 : /* This one doesn't exists on QNX */
1419 : #ifndef SIGPROF
1420 : #define SIGPROF 27
1421 : #endif
1422 :
1423 : void zend_set_timeout(long seconds, int reset_signals) /* {{{ */
1424 17656 : {
1425 : TSRMLS_FETCH();
1426 :
1427 17656 : EG(timeout_seconds) = seconds;
1428 :
1429 : #ifdef ZEND_WIN32
1430 : if(!seconds) {
1431 : return;
1432 : }
1433 : if (timeout_thread_initialized == 0 && InterlockedIncrement(&timeout_thread_initialized) == 1) {
1434 : /* We start up this process-wide thread here and not in zend_startup(), because if Zend
1435 : * is initialized inside a DllMain(), you're not supposed to start threads from it.
1436 : */
1437 : zend_init_timeout_thread();
1438 : }
1439 : PostThreadMessage(timeout_thread_id, WM_REGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) seconds);
1440 : #else
1441 : # ifdef HAVE_SETITIMER
1442 : {
1443 : struct itimerval t_r; /* timeout requested */
1444 : sigset_t sigset;
1445 :
1446 17656 : if(seconds) {
1447 359 : t_r.it_value.tv_sec = seconds;
1448 359 : t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;
1449 :
1450 : # ifdef __CYGWIN__
1451 : setitimer(ITIMER_REAL, &t_r, NULL);
1452 : }
1453 : if(reset_signals) {
1454 : signal(SIGALRM, zend_timeout);
1455 : sigemptyset(&sigset);
1456 : sigaddset(&sigset, SIGALRM);
1457 : }
1458 : # else
1459 359 : setitimer(ITIMER_PROF, &t_r, NULL);
1460 : }
1461 17656 : if(reset_signals) {
1462 17622 : signal(SIGPROF, zend_timeout);
1463 17622 : sigemptyset(&sigset);
1464 17622 : sigaddset(&sigset, SIGPROF);
1465 : }
1466 : # endif
1467 17656 : if(reset_signals) {
1468 17622 : sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1469 : }
1470 : }
1471 : # endif
1472 : #endif
1473 17656 : }
1474 : /* }}} */
1475 :
1476 : void zend_unset_timeout(TSRMLS_D) /* {{{ */
1477 17685 : {
1478 : #ifdef ZEND_WIN32
1479 : if(timeout_thread_initialized) {
1480 : PostThreadMessage(timeout_thread_id, WM_UNREGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) 0);
1481 : }
1482 : #else
1483 : # ifdef HAVE_SETITIMER
1484 17685 : if (EG(timeout_seconds)) {
1485 : struct itimerval no_timeout;
1486 :
1487 353 : no_timeout.it_value.tv_sec = no_timeout.it_value.tv_usec = no_timeout.it_interval.tv_sec = no_timeout.it_interval.tv_usec = 0;
1488 :
1489 : #ifdef __CYGWIN__
1490 : setitimer(ITIMER_REAL, &no_timeout, NULL);
1491 : #else
1492 353 : setitimer(ITIMER_PROF, &no_timeout, NULL);
1493 : #endif
1494 : }
1495 : # endif
1496 : #endif
1497 17685 : }
1498 : /* }}} */
1499 :
1500 : zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len, int fetch_type TSRMLS_DC) /* {{{ */
1501 135192 : {
1502 : zend_class_entry **pce;
1503 135192 : int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0;
1504 135192 : int silent = (fetch_type & ZEND_FETCH_CLASS_SILENT) != 0;
1505 :
1506 135192 : fetch_type &= ZEND_FETCH_CLASS_MASK;
1507 :
1508 135198 : check_fetch_type:
1509 135198 : switch (fetch_type) {
1510 : case ZEND_FETCH_CLASS_SELF:
1511 1139 : if (!EG(scope)) {
1512 0 : zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
1513 : }
1514 1139 : return EG(scope);
1515 : case ZEND_FETCH_CLASS_PARENT:
1516 1150 : if (!EG(scope)) {
1517 0 : zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
1518 : }
1519 1150 : if (!EG(scope)->parent) {
1520 0 : zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
1521 : }
1522 1150 : return EG(scope)->parent;
1523 : case ZEND_FETCH_CLASS_STATIC:
1524 88 : if (!EG(called_scope)) {
1525 0 : zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
1526 : }
1527 88 : return EG(called_scope);
1528 : case ZEND_FETCH_CLASS_AUTO: {
1529 1431 : fetch_type = zend_get_class_fetch_type(class_name, class_name_len);
1530 1431 : if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) {
1531 6 : goto check_fetch_type;
1532 : }
1533 : }
1534 : break;
1535 : }
1536 :
1537 132815 : if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC) == FAILURE) {
1538 37 : if (use_autoload) {
1539 29 : if (!silent && !EG(exception)) {
1540 25 : if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
1541 2 : zend_error(E_ERROR, "Interface '%s' not found", class_name);
1542 : } else {
1543 23 : zend_error(E_ERROR, "Class '%s' not found", class_name);
1544 : }
1545 : }
1546 : }
1547 12 : return NULL;
1548 : }
1549 132775 : return *pce;
1550 : }
1551 : /* }}} */
1552 :
1553 : #define MAX_ABSTRACT_INFO_CNT 3
1554 : #define MAX_ABSTRACT_INFO_FMT "%s%s%s%s"
1555 : #define DISPLAY_ABSTRACT_FN(idx) \
1556 : ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \
1557 : ai.afn[idx] ? "::" : "", \
1558 : ai.afn[idx] ? ai.afn[idx]->common.function_name : "", \
1559 : ai.afn[idx] && ai.afn[idx + 1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "")
1560 :
1561 : typedef struct _zend_abstract_info {
1562 : zend_function *afn[MAX_ABSTRACT_INFO_CNT + 1];
1563 : int cnt;
1564 : int ctor;
1565 : } zend_abstract_info;
1566 :
1567 : static int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai TSRMLS_DC) /* {{{ */
1568 13 : {
1569 13 : if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
1570 12 : if (ai->cnt < MAX_ABSTRACT_INFO_CNT) {
1571 12 : ai->afn[ai->cnt] = fn;
1572 : }
1573 12 : if (fn->common.fn_flags & ZEND_ACC_CTOR) {
1574 1 : if (!ai->ctor) {
1575 1 : ai->cnt++;
1576 1 : ai->ctor = 1;
1577 : } else {
1578 0 : ai->afn[ai->cnt] = NULL;
1579 : }
1580 : } else {
1581 11 : ai->cnt++;
1582 : }
1583 : }
1584 13 : return 0;
1585 : }
1586 : /* }}} */
1587 :
1588 : void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) /* {{{ */
1589 1087532 : {
1590 : zend_abstract_info ai;
1591 :
1592 1087532 : if ((ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) && !(ce->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
1593 11 : memset(&ai, 0, sizeof(ai));
1594 :
1595 11 : zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC);
1596 :
1597 11 : if (ai.cnt) {
1598 11 : zend_error(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")",
1599 : ce->name, ai.cnt,
1600 : ai.cnt > 1 ? "s" : "",
1601 : DISPLAY_ABSTRACT_FN(0),
1602 : DISPLAY_ABSTRACT_FN(1),
1603 : DISPLAY_ABSTRACT_FN(2)
1604 : );
1605 : }
1606 : }
1607 1087521 : }
1608 : /* }}} */
1609 :
1610 : ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC) /* {{{ */
1611 1 : {
1612 : zend_execute_data *ex;
1613 : int i;
1614 :
1615 3 : for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
1616 2 : if (ex->op_array && ex->symbol_table == symbol_table) {
1617 1 : for (i = 0; i < ex->op_array->last_var; i++) {
1618 0 : ex->CVs[i] = NULL;
1619 : }
1620 : }
1621 : }
1622 1 : }
1623 : /* }}} */
1624 :
1625 : ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC) /* {{{ */
1626 707 : {
1627 : zend_execute_data *ex;
1628 707 : ulong hash_value = zend_inline_hash_func(name, name_len + 1);
1629 :
1630 707 : if (zend_hash_quick_exists(&EG(symbol_table), name, name_len + 1, hash_value)) {
1631 773 : for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
1632 387 : if (ex->op_array && ex->symbol_table == &EG(symbol_table)) {
1633 : int i;
1634 1878 : for (i = 0; i < ex->op_array->last_var; i++) {
1635 1528 : if (ex->op_array->vars[i].hash_value == hash_value &&
1636 : ex->op_array->vars[i].name_len == name_len &&
1637 : !memcmp(ex->op_array->vars[i].name, name, name_len)
1638 : ) {
1639 36 : ex->CVs[i] = NULL;
1640 36 : break;
1641 : }
1642 : }
1643 : }
1644 : }
1645 386 : return zend_hash_quick_del(&EG(symbol_table), name, name_len + 1, hash_value);
1646 : }
1647 321 : return FAILURE;
1648 : }
1649 : /* }}} */
1650 :
1651 : ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
1652 30269 : {
1653 : zend_uint i;
1654 : zend_execute_data *ex;
1655 :
1656 30269 : if (!EG(active_symbol_table)) {
1657 :
1658 : /* Search for last called user function */
1659 30269 : ex = EG(current_execute_data);
1660 60540 : while (ex && !ex->op_array) {
1661 2 : ex = ex->prev_execute_data;
1662 : }
1663 30269 : if (ex && ex->symbol_table) {
1664 0 : EG(active_symbol_table) = ex->symbol_table;
1665 0 : return;
1666 : }
1667 :
1668 30269 : if (ex && ex->op_array) {
1669 30200 : if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
1670 : /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
1671 29833 : EG(active_symbol_table) = *(EG(symtable_cache_ptr)--);
1672 : } else {
1673 367 : ALLOC_HASHTABLE(EG(active_symbol_table));
1674 367 : zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
1675 : /*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
1676 : }
1677 30200 : ex->symbol_table = EG(active_symbol_table);
1678 :
1679 30200 : if (ex->op_array->this_var != -1 &&
1680 : !ex->CVs[ex->op_array->this_var] &&
1681 : EG(This)) {
1682 0 : ex->CVs[ex->op_array->this_var] = (zval**)ex->CVs + ex->op_array->last_var + ex->op_array->this_var;
1683 0 : *ex->CVs[ex->op_array->this_var] = EG(This);
1684 : }
1685 1462845 : for (i = 0; i < ex->op_array->last_var; i++) {
1686 1432645 : if (ex->CVs[i]) {
1687 617773 : zend_hash_quick_update(EG(active_symbol_table),
1688 : ex->op_array->vars[i].name,
1689 : ex->op_array->vars[i].name_len + 1,
1690 : ex->op_array->vars[i].hash_value,
1691 : (void**)ex->CVs[i],
1692 : sizeof(zval*),
1693 : (void**)&ex->CVs[i]);
1694 : }
1695 : }
1696 : }
1697 : }
1698 : }
1699 : /* }}} */
1700 :
1701 : /*
1702 : * Local variables:
1703 : * tab-width: 4
1704 : * c-basic-offset: 4
1705 : * indent-tabs-mode: t
1706 : * End:
1707 : */
|