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