1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2007 Zend Technologies Ltd. (http://www.zend.com) |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 2.00 of the Zend license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.zend.com/license/2_00.txt. |
11 : | If you did not receive a copy of the Zend license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@zend.com so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Andi Gutmans <andi@zend.com> |
16 : | Zeev Suraski <zeev@zend.com> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: zend_execute_API.c,v 1.331.2.20.2.17 2007/03/15 16:44:12 tony2001 Exp $ */
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 1125 : {
100 1125 : 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 224 : {
112 224 : 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 219 : {
124 219 : INIT_ZVAL(EG(uninitialized_zval));
125 : /* trick to make uninitialized_zval never be modified, passed by ref, etc. */
126 219 : EG(uninitialized_zval).refcount++;
127 219 : INIT_ZVAL(EG(error_zval));
128 219 : EG(uninitialized_zval_ptr)=&EG(uninitialized_zval);
129 219 : EG(error_zval_ptr)=&EG(error_zval);
130 219 : 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 219 : EG(return_value_ptr_ptr) = NULL;
136 :
137 219 : EG(symtable_cache_ptr) = EG(symtable_cache)-1;
138 219 : EG(symtable_cache_limit)=EG(symtable_cache)+SYMTABLE_CACHE_SIZE-1;
139 219 : EG(no_extensions)=0;
140 :
141 219 : EG(function_table) = CG(function_table);
142 219 : EG(class_table) = CG(class_table);
143 :
144 219 : EG(in_execution) = 0;
145 219 : EG(in_autoload) = NULL;
146 219 : EG(autoload_func) = NULL;
147 :
148 219 : zend_ptr_stack_init(&EG(argument_stack));
149 219 : zend_ptr_stack_push(&EG(argument_stack), (void *) NULL);
150 :
151 219 : zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0);
152 : {
153 : zval *globals;
154 :
155 219 : ALLOC_ZVAL(globals);
156 219 : globals->refcount=1;
157 219 : globals->is_ref=1;
158 219 : Z_TYPE_P(globals) = IS_ARRAY;
159 219 : Z_ARRVAL_P(globals) = &EG(symbol_table);
160 219 : zend_hash_update(&EG(symbol_table), "GLOBALS", sizeof("GLOBALS"), &globals, sizeof(zval *), NULL);
161 : }
162 219 : EG(active_symbol_table) = &EG(symbol_table);
163 :
164 219 : zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator TSRMLS_CC);
165 219 : EG(opline_ptr) = NULL;
166 :
167 219 : zend_hash_init(&EG(included_files), 5, NULL, NULL, 0);
168 :
169 219 : EG(ticks_count) = 0;
170 :
171 219 : EG(user_error_handler) = NULL;
172 :
173 219 : EG(current_execute_data) = NULL;
174 :
175 219 : zend_stack_init(&EG(user_error_handlers_error_reporting));
176 219 : zend_ptr_stack_init(&EG(user_error_handlers));
177 219 : zend_ptr_stack_init(&EG(user_exception_handlers));
178 :
179 219 : zend_objects_store_init(&EG(objects_store), 1024);
180 :
181 219 : EG(full_tables_cleanup) = 0;
182 : #ifdef ZEND_WIN32
183 : EG(timed_out) = 0;
184 : #endif
185 :
186 219 : EG(exception) = NULL;
187 :
188 219 : EG(scope) = NULL;
189 :
190 219 : EG(This) = NULL;
191 :
192 219 : EG(active_op_array) = NULL;
193 :
194 219 : EG(active) = 1;
195 219 : }
196 :
197 : static int zval_call_destructor(zval **zv TSRMLS_DC)
198 3878 : {
199 3878 : if (Z_TYPE_PP(zv) == IS_OBJECT && (*zv)->refcount == 1) {
200 44 : return ZEND_HASH_APPLY_REMOVE;
201 : } else {
202 3834 : return ZEND_HASH_APPLY_KEEP;
203 : }
204 : }
205 :
206 219 : void shutdown_destructors(TSRMLS_D) {
207 219 : zend_try {
208 : int symbols;
209 : do {
210 248 : symbols = zend_hash_num_elements(&EG(symbol_table));
211 248 : zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor TSRMLS_CC);
212 248 : } while (symbols != zend_hash_num_elements(&EG(symbol_table)));
213 219 : 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 219 : } zend_end_try();
218 219 : }
219 :
220 : void shutdown_executor(TSRMLS_D)
221 219 : {
222 219 : 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 219 : zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator TSRMLS_CC);
239 219 : zend_hash_graceful_reverse_destroy(&EG(symbol_table));
240 219 : } zend_end_try();
241 :
242 219 : 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 219 : if (EG(user_error_handler)) {
247 0 : zeh = EG(user_error_handler);
248 0 : EG(user_error_handler) = NULL;
249 0 : zval_dtor(zeh);
250 0 : FREE_ZVAL(zeh);
251 : }
252 :
253 219 : if (EG(user_exception_handler)) {
254 0 : zeh = EG(user_exception_handler);
255 0 : EG(user_exception_handler) = NULL;
256 0 : zval_dtor(zeh);
257 0 : FREE_ZVAL(zeh);
258 : }
259 :
260 219 : zend_stack_destroy(&EG(user_error_handlers_error_reporting));
261 219 : zend_stack_init(&EG(user_error_handlers_error_reporting));
262 219 : zend_ptr_stack_clean(&EG(user_error_handlers), ZVAL_DESTRUCTOR, 1);
263 219 : zend_ptr_stack_clean(&EG(user_exception_handlers), ZVAL_DESTRUCTOR, 1);
264 219 : } zend_end_try();
265 :
266 219 : 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 219 : 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 219 : zend_hash_reverse_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data TSRMLS_CC);
280 : }
281 219 : zend_hash_apply(EG(class_table), (apply_func_t) zend_cleanup_class_data TSRMLS_CC);
282 :
283 219 : zend_ptr_stack_destroy(&EG(argument_stack));
284 :
285 : /* Destroy all op arrays */
286 219 : 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 219 : zend_hash_reverse_apply(EG(function_table), (apply_func_t) clean_non_persistent_function TSRMLS_CC);
291 219 : zend_hash_reverse_apply(EG(class_table), (apply_func_t) clean_non_persistent_class TSRMLS_CC);
292 : }
293 :
294 684 : while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
295 246 : zend_hash_destroy(*EG(symtable_cache_ptr));
296 246 : FREE_HASHTABLE(*EG(symtable_cache_ptr));
297 246 : EG(symtable_cache_ptr)--;
298 : }
299 219 : zend_objects_store_free_object_storage(&EG(objects_store) TSRMLS_CC);
300 219 : } zend_end_try();
301 :
302 219 : zend_try {
303 219 : clean_non_persistent_constants(TSRMLS_C);
304 219 : } zend_end_try();
305 :
306 219 : zend_try {
307 : #if 0&&ZEND_DEBUG
308 : signal(SIGSEGV, original_sigsegv_handler);
309 : #endif
310 :
311 219 : zend_hash_destroy(&EG(included_files));
312 :
313 219 : zend_ptr_stack_destroy(&EG(arg_types_stack));
314 219 : zend_stack_destroy(&EG(user_error_handlers_error_reporting));
315 219 : zend_ptr_stack_destroy(&EG(user_error_handlers));
316 219 : zend_ptr_stack_destroy(&EG(user_exception_handlers));
317 219 : zend_objects_store_destroy(&EG(objects_store));
318 219 : if (EG(in_autoload)) {
319 0 : zend_hash_destroy(EG(in_autoload));
320 0 : FREE_HASHTABLE(EG(in_autoload));
321 : }
322 219 : } zend_end_try();
323 219 : EG(active) = 0;
324 219 : }
325 :
326 :
327 : /* return class name and "::" or "". */
328 : ZEND_API char *get_active_class_name(char **space TSRMLS_DC)
329 6782 : {
330 6782 : if (!zend_is_executing(TSRMLS_C)) {
331 0 : if (space) {
332 0 : *space = "";
333 : }
334 0 : return "";
335 : }
336 6782 : switch (EG(function_state_ptr)->function->type) {
337 : case ZEND_USER_FUNCTION:
338 : case ZEND_INTERNAL_FUNCTION:
339 : {
340 6782 : zend_class_entry *ce = EG(function_state_ptr)->function->common.scope;
341 :
342 6782 : if (space) {
343 6782 : *space = ce ? "::" : "";
344 : }
345 6782 : 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 6782 : {
358 6782 : if (!zend_is_executing(TSRMLS_C)) {
359 0 : return NULL;
360 : }
361 6782 : switch (EG(function_state_ptr)->function->type) {
362 : case ZEND_USER_FUNCTION: {
363 0 : char *function_name = ((zend_op_array *) EG(function_state_ptr)->function)->function_name;
364 :
365 0 : if (function_name) {
366 0 : return function_name;
367 : } else {
368 0 : return "main";
369 : }
370 : }
371 : break;
372 : case ZEND_INTERNAL_FUNCTION:
373 6782 : 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 7792 : {
383 7792 : if (EG(active_op_array)) {
384 7792 : return EG(active_op_array)->filename;
385 : } else {
386 0 : return "[no active file]";
387 : }
388 : }
389 :
390 :
391 : ZEND_API uint zend_get_executed_lineno(TSRMLS_D)
392 7676 : {
393 7676 : if (EG(opline_ptr)) {
394 7676 : return active_opline->lineno;
395 : } else {
396 0 : return 0;
397 : }
398 : }
399 :
400 :
401 : ZEND_API zend_bool zend_is_executing(TSRMLS_D)
402 21777 : {
403 21777 : return EG(in_execution);
404 : }
405 :
406 :
407 : ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC)
408 662495 : {
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 662495 : (*zval_ptr)->refcount--;
413 662495 : if ((*zval_ptr)->refcount==0) {
414 201852 : zval_dtor(*zval_ptr);
415 201852 : safe_free_zval_ptr_rel(*zval_ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC);
416 460643 : } else if ((*zval_ptr)->refcount == 1) {
417 179799 : if ((*zval_ptr)->type == IS_OBJECT) {
418 : TSRMLS_FETCH();
419 :
420 955 : if (EG(ze1_compatibility_mode)) {
421 0 : return;
422 : }
423 : }
424 179799 : (*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 87389 : {
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 87389 : (*zval_ptr)->refcount--;
435 87389 : if ((*zval_ptr)->refcount==0) {
436 42930 : zval_internal_dtor(*zval_ptr);
437 42930 : free(*zval_ptr);
438 44459 : } else if ((*zval_ptr)->refcount == 1) {
439 5039 : (*zval_ptr)->is_ref = 0;
440 : }
441 87389 : }
442 :
443 :
444 : ZEND_API int zend_is_true(zval *op)
445 0 : {
446 0 : return i_zend_is_true(op);
447 : }
448 :
449 : #include "../TSRM/tsrm_strtok_r.h"
450 :
451 : ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC)
452 1857 : {
453 1857 : zval *p = *pp;
454 1857 : zend_bool inline_change = (zend_bool) (unsigned long) arg;
455 : zval const_value;
456 :
457 1857 : if (Z_TYPE_P(p) == IS_CONSTANT) {
458 : int refcount;
459 : zend_uchar is_ref;
460 :
461 0 : SEPARATE_ZVAL_IF_NOT_REF(pp);
462 0 : p = *pp;
463 :
464 0 : refcount = p->refcount;
465 0 : is_ref = p->is_ref;
466 :
467 0 : if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope TSRMLS_CC)) {
468 0 : zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
469 : p->value.str.val,
470 : p->value.str.val);
471 0 : p->type = IS_STRING;
472 0 : if (!inline_change) {
473 0 : zval_copy_ctor(p);
474 : }
475 : } else {
476 0 : if (inline_change) {
477 0 : STR_FREE(p->value.str.val);
478 : }
479 0 : *p = const_value;
480 : }
481 :
482 0 : p->refcount = refcount;
483 0 : p->is_ref = is_ref;
484 1857 : } else if (Z_TYPE_P(p) == IS_CONSTANT_ARRAY) {
485 : zval **element, *new_val;
486 : char *str_index;
487 : uint str_index_len;
488 : ulong num_index;
489 :
490 1 : SEPARATE_ZVAL_IF_NOT_REF(pp);
491 1 : p = *pp;
492 1 : Z_TYPE_P(p) = IS_ARRAY;
493 :
494 : /* First go over the array and see if there are any constant indices */
495 1 : zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
496 2 : while (zend_hash_get_current_data(Z_ARRVAL_P(p), (void **) &element)==SUCCESS) {
497 0 : if (!(Z_TYPE_PP(element) & IS_CONSTANT_INDEX)) {
498 0 : zend_hash_move_forward(Z_ARRVAL_P(p));
499 0 : continue;
500 : }
501 0 : Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
502 0 : if (zend_hash_get_current_key_ex(Z_ARRVAL_P(p), &str_index, &str_index_len, &num_index, 0, NULL)!=HASH_KEY_IS_STRING) {
503 0 : zend_hash_move_forward(Z_ARRVAL_P(p));
504 0 : continue;
505 : }
506 0 : if (!zend_get_constant_ex(str_index, str_index_len-1, &const_value, scope TSRMLS_CC)) {
507 0 : zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
508 0 : zend_hash_move_forward(Z_ARRVAL_P(p));
509 0 : continue;
510 : }
511 :
512 0 : if (const_value.type == IS_STRING && const_value.value.str.len == (int)str_index_len-1 &&
513 : !strncmp(const_value.value.str.val, str_index, str_index_len)) {
514 : /* constant value is the same as its name */
515 0 : zval_dtor(&const_value);
516 0 : zend_hash_move_forward(p->value.ht);
517 0 : continue;
518 : }
519 :
520 0 : ALLOC_ZVAL(new_val);
521 0 : *new_val = **element;
522 0 : zval_copy_ctor(new_val);
523 0 : new_val->refcount = 1;
524 0 : new_val->is_ref = 0;
525 :
526 : /* preserve this bit for inheritance */
527 0 : Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
528 0 : zval_ptr_dtor(element);
529 0 : *element = new_val;
530 :
531 0 : switch (Z_TYPE(const_value)) {
532 : case IS_STRING:
533 0 : zend_symtable_update_current_key(Z_ARRVAL_P(p), const_value.value.str.val, const_value.value.str.len+1);
534 0 : break;
535 : case IS_BOOL:
536 : case IS_LONG:
537 0 : zend_hash_update_current_key(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, Z_LVAL(const_value));
538 0 : break;
539 : case IS_DOUBLE:
540 0 : zend_hash_update_current_key(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL, 0, (long)Z_DVAL(const_value));
541 0 : break;
542 : case IS_NULL:
543 0 : zend_hash_update_current_key(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, "", 1, 0);
544 : break;
545 : }
546 0 : zend_hash_move_forward(Z_ARRVAL_P(p));
547 0 : zval_dtor(&const_value);
548 : }
549 1 : zend_hash_apply_with_argument(Z_ARRVAL_P(p), (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
550 1 : zend_hash_internal_pointer_reset(Z_ARRVAL_P(p));
551 : }
552 1857 : return 0;
553 : }
554 :
555 : ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
556 1857 : {
557 1857 : return zval_update_constant_ex(pp, arg, NULL TSRMLS_CC);
558 : }
559 :
560 : int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC)
561 9 : {
562 : zval ***params_array;
563 : zend_uint i;
564 : int ex_retval;
565 9 : zval *local_retval_ptr = NULL;
566 :
567 9 : if (param_count) {
568 9 : params_array = (zval ***) emalloc(sizeof(zval **)*param_count);
569 18 : for (i=0; i<param_count; i++) {
570 9 : params_array[i] = ¶ms[i];
571 : }
572 : } else {
573 0 : params_array = NULL;
574 : }
575 9 : ex_retval = call_user_function_ex(function_table, object_pp, function_name, &local_retval_ptr, param_count, params_array, 1, NULL TSRMLS_CC);
576 9 : if (local_retval_ptr) {
577 9 : COPY_PZVAL_TO_ZVAL(*retval_ptr, local_retval_ptr);
578 : } else {
579 0 : INIT_ZVAL(*retval_ptr);
580 : }
581 9 : if (params_array) {
582 9 : efree(params_array);
583 : }
584 9 : return ex_retval;
585 : }
586 :
587 :
588 : 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)
589 274 : {
590 : zend_fcall_info fci;
591 :
592 274 : fci.size = sizeof(fci);
593 274 : fci.function_table = function_table;
594 274 : fci.object_pp = object_pp;
595 274 : fci.function_name = function_name;
596 274 : fci.retval_ptr_ptr = retval_ptr_ptr;
597 274 : fci.param_count = param_count;
598 274 : fci.params = params;
599 274 : fci.no_separation = (zend_bool) no_separation;
600 274 : fci.symbol_table = symbol_table;
601 :
602 274 : return zend_call_function(&fci, NULL TSRMLS_CC);
603 : }
604 :
605 :
606 : int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC)
607 1222 : {
608 : zend_uint i;
609 : zval **original_return_value;
610 : HashTable *calling_symbol_table;
611 : zend_function_state *original_function_state_ptr;
612 : zend_op_array *original_op_array;
613 : zend_op **original_opline_ptr;
614 : zend_class_entry *current_scope;
615 1222 : zend_class_entry *calling_scope = NULL;
616 1222 : zend_class_entry *check_scope_or_static = NULL;
617 : zval *current_this;
618 : zend_execute_data execute_data;
619 : zval *method_name;
620 : zval *params_array;
621 1222 : int call_via_handler = 0;
622 : char *fname, *colon;
623 : int fname_len;
624 :
625 1222 : if (!EG(active)) {
626 0 : return FAILURE; /* executor is already inactive */
627 : }
628 :
629 1222 : if (EG(exception)) {
630 0 : return FAILURE; /* we would result in an instable executor otherwise */
631 : }
632 :
633 1222 : switch (fci->size) {
634 : case sizeof(zend_fcall_info):
635 1222 : break; /* nothing to do currently */
636 : default:
637 0 : zend_error(E_ERROR, "Corrupted fcall_info provided to zend_call_function()");
638 : break;
639 : }
640 :
641 : /* Initialize execute_data */
642 1222 : if (EG(current_execute_data)) {
643 1205 : execute_data = *EG(current_execute_data);
644 1205 : EX(op_array) = NULL;
645 1205 : EX(opline) = NULL;
646 1205 : EX(object) = NULL;
647 : } else {
648 : /* This only happens when we're called outside any execute()'s
649 : * It shouldn't be strictly necessary to NULL execute_data out,
650 : * but it may make bugs easier to spot
651 : */
652 17 : memset(&execute_data, 0, sizeof(zend_execute_data));
653 : }
654 :
655 : /* we may return SUCCESS, and yet retval may be uninitialized,
656 : * if there was an exception...
657 : */
658 1222 : *fci->retval_ptr_ptr = NULL;
659 :
660 1498 : if (!fci_cache || !fci_cache->initialized) {
661 276 : if (Z_TYPE_P(fci->function_name)==IS_ARRAY) { /* assume array($obj, $name) couple */
662 : zval **tmp_object_ptr, **tmp_real_function_name;
663 :
664 9 : if (zend_hash_index_find(Z_ARRVAL_P(fci->function_name), 0, (void **) &tmp_object_ptr)==FAILURE) {
665 0 : return FAILURE;
666 : }
667 9 : if (zend_hash_index_find(Z_ARRVAL_P(fci->function_name), 1, (void **) &tmp_real_function_name)==FAILURE) {
668 0 : return FAILURE;
669 : }
670 9 : fci->function_name = *tmp_real_function_name;
671 9 : SEPARATE_ZVAL_IF_NOT_REF(tmp_object_ptr);
672 9 : fci->object_pp = tmp_object_ptr;
673 9 : (*fci->object_pp)->is_ref = 1;
674 : }
675 :
676 276 : if (fci->object_pp && !*fci->object_pp) {
677 0 : fci->object_pp = NULL;
678 : }
679 :
680 276 : if (fci->object_pp) {
681 : /* TBI!! new object handlers */
682 9 : if (Z_TYPE_PP(fci->object_pp) == IS_OBJECT) {
683 9 : if (!IS_ZEND_STD_OBJECT(**fci->object_pp)) {
684 0 : zend_error(E_WARNING, "Cannot use call_user_function on objects without a class entry");
685 0 : return FAILURE;
686 : }
687 :
688 9 : calling_scope = Z_OBJCE_PP(fci->object_pp);
689 9 : fci->function_table = &calling_scope->function_table;
690 9 : EX(object) = *fci->object_pp;
691 0 : } else if (Z_TYPE_PP(fci->object_pp) == IS_STRING) {
692 : zend_class_entry **ce;
693 0 : int found = FAILURE;
694 :
695 0 : if (EG(active_op_array) && strcmp(Z_STRVAL_PP(fci->object_pp), "self") == 0) {
696 0 : if (!EG(active_op_array)->scope) {
697 0 : zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
698 : }
699 0 : ce = &(EG(active_op_array)->scope);
700 0 : found = (*ce != NULL?SUCCESS:FAILURE);
701 0 : fci->object_pp = EG(This)?&EG(This):NULL;
702 0 : EX(object) = EG(This);
703 0 : } else if (strcmp(Z_STRVAL_PP(fci->object_pp), "parent") == 0 && EG(active_op_array)) {
704 :
705 0 : if (!EG(active_op_array)->scope) {
706 0 : zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
707 : }
708 0 : if (!EG(active_op_array)->scope->parent) {
709 0 : zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
710 : }
711 0 : ce = &(EG(active_op_array)->scope->parent);
712 0 : found = (*ce != NULL?SUCCESS:FAILURE);
713 0 : fci->object_pp = EG(This)?&EG(This):NULL;
714 0 : EX(object) = EG(This);
715 : } else {
716 : zend_class_entry *scope;
717 0 : scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
718 :
719 0 : found = zend_lookup_class(Z_STRVAL_PP(fci->object_pp), Z_STRLEN_PP(fci->object_pp), &ce TSRMLS_CC);
720 0 : if (found == FAILURE) {
721 0 : zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL_PP(fci->object_pp));
722 : }
723 0 : if (scope && EG(This) &&
724 : instanceof_function(Z_OBJCE_P(EG(This)), scope TSRMLS_CC) &&
725 : instanceof_function(scope, *ce TSRMLS_CC)) {
726 0 : fci->object_pp = &EG(This);
727 0 : EX(object) = EG(This);
728 : } else {
729 0 : fci->object_pp = NULL;
730 : }
731 : }
732 0 : if (found == FAILURE)
733 0 : return FAILURE;
734 :
735 0 : fci->function_table = &(*ce)->function_table;
736 0 : calling_scope = *ce;
737 : } else {
738 0 : zend_error(E_NOTICE, "Non-callable array passed to zend_call_function()");
739 0 : return FAILURE;
740 : }
741 :
742 9 : if (fci->function_table == NULL) {
743 0 : return FAILURE;
744 : }
745 : }
746 :
747 276 : if (fci->function_name->type!=IS_STRING) {
748 0 : return FAILURE;
749 : }
750 :
751 276 : fname = Z_STRVAL_P(fci->function_name);
752 276 : fname_len = Z_STRLEN_P(fci->function_name);
753 276 : if ((colon = strstr(fname, "::")) != NULL) {
754 0 : int clen = colon - fname;
755 0 : int mlen = fname_len - clen - 2;
756 0 : zend_class_entry **pce, *ce_child = NULL;
757 0 : if (zend_lookup_class(fname, clen, &pce TSRMLS_CC) == SUCCESS) {
758 0 : ce_child = *pce;
759 : } else {
760 0 : char *lcname = zend_str_tolower_dup(fname, clen);
761 : /* caution: lcname is not '\0' terminated */
762 0 : if (calling_scope) {
763 0 : if (clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0) {
764 0 : ce_child = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
765 0 : } else if (clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) {
766 0 : ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL;
767 : }
768 : }
769 0 : efree(lcname);
770 : }
771 0 : if (!ce_child) {
772 0 : zend_error(E_ERROR, "Cannot call method %s() or method does not exist", fname);
773 0 : return FAILURE;
774 : }
775 0 : check_scope_or_static = calling_scope;
776 0 : fci->function_table = &ce_child->function_table;
777 0 : calling_scope = ce_child;
778 0 : fname = fname + clen + 2;
779 0 : fname_len = mlen;
780 : }
781 :
782 276 : if (fci->object_pp) {
783 9 : if (Z_OBJ_HT_PP(fci->object_pp)->get_method == NULL) {
784 0 : zend_error(E_ERROR, "Object does not support method calls");
785 : }
786 9 : EX(function_state).function =
787 : Z_OBJ_HT_PP(fci->object_pp)->get_method(fci->object_pp, fname, fname_len TSRMLS_CC);
788 9 : if (EX(function_state).function && calling_scope != EX(function_state).function->common.scope) {
789 0 : char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
790 0 : if (zend_hash_find(&calling_scope->function_table, function_name_lc, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
791 0 : efree(function_name_lc);
792 0 : zend_error(E_ERROR, "Cannot call method %s::%s() or method does not exist", calling_scope->name, fname);
793 : }
794 0 : efree(function_name_lc);
795 : }
796 267 : } else if (calling_scope) {
797 0 : char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
798 :
799 0 : EX(function_state).function =
800 : zend_std_get_static_method(calling_scope, function_name_lc, fname_len TSRMLS_CC);
801 0 : efree(function_name_lc);
802 0 : if (check_scope_or_static && EX(function_state).function
803 : && !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)
804 : && !instanceof_function(check_scope_or_static, calling_scope TSRMLS_CC)) {
805 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);
806 0 : return FAILURE;
807 : }
808 : } else {
809 267 : char *function_name_lc = zend_str_tolower_dup(fname, fname_len);
810 :
811 267 : if (zend_hash_find(fci->function_table, function_name_lc, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
812 0 : EX(function_state).function = NULL;
813 : }
814 267 : efree(function_name_lc);
815 : }
816 :
817 276 : if (EX(function_state).function == NULL) {
818 : /* try calling __call */
819 0 : if (calling_scope && calling_scope->__call) {
820 0 : EX(function_state).function = calling_scope->__call;
821 : /* prepare params */
822 0 : ALLOC_INIT_ZVAL(method_name);
823 0 : ZVAL_STRINGL(method_name, Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name), 0);
824 :
825 0 : ALLOC_INIT_ZVAL(params_array);
826 0 : array_init(params_array);
827 0 : call_via_handler = 1;
828 : } else {
829 0 : return FAILURE;
830 : }
831 : }
832 276 : if (fci_cache &&
833 : (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION ||
834 : ((zend_internal_function*)EX(function_state).function)->handler != zend_std_call_user_call)) {
835 2 : fci_cache->function_handler = EX(function_state).function;
836 2 : fci_cache->object_pp = fci->object_pp;
837 2 : fci_cache->calling_scope = calling_scope;
838 2 : fci_cache->initialized = 1;
839 : }
840 : } else {
841 946 : EX(function_state).function = fci_cache->function_handler;
842 946 : calling_scope = fci_cache->calling_scope;
843 946 : fci->object_pp = fci_cache->object_pp;
844 946 : EX(object) = fci->object_pp ? *fci->object_pp : NULL;
845 : }
846 :
847 1222 : if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
848 0 : if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
849 0 : 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);
850 : }
851 0 : if (EX(function_state).function->common.fn_flags & ZEND_ACC_DEPRECATED) {
852 0 : zend_error(E_STRICT, "Function %s%s%s() is deprecated",
853 : EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name : "",
854 : EX(function_state).function->common.scope ? "::" : "",
855 : EX(function_state).function->common.function_name);
856 : }
857 : }
858 :
859 2878 : for (i=0; i<fci->param_count; i++) {
860 : zval *param;
861 :
862 1656 : if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i+1)
863 : && !PZVAL_IS_REF(*fci->params[i])) {
864 0 : if ((*fci->params[i])->refcount>1) {
865 : zval *new_zval;
866 :
867 0 : if (fci->no_separation) {
868 0 : if(i) {
869 : /* hack to clean up the stack */
870 0 : zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (long) i, NULL);
871 0 : zend_ptr_stack_clear_multiple(TSRMLS_C);
872 : }
873 :
874 0 : if (call_via_handler) {
875 0 : zval_ptr_dtor(&method_name);
876 0 : zval_ptr_dtor(¶ms_array);
877 : }
878 0 : return FAILURE;
879 : }
880 0 : ALLOC_ZVAL(new_zval);
881 0 : *new_zval = **fci->params[i];
882 0 : zval_copy_ctor(new_zval);
883 0 : new_zval->refcount = 1;
884 0 : (*fci->params[i])->refcount--;
885 0 : *fci->params[i] = new_zval;
886 : }
887 0 : (*fci->params[i])->refcount++;
888 0 : (*fci->params[i])->is_ref = 1;
889 0 : param = *fci->params[i];
890 1656 : } else if (*fci->params[i] != &EG(uninitialized_zval)) {
891 1656 : (*fci->params[i])->refcount++;
892 1656 : param = *fci->params[i];
893 : } else {
894 0 : ALLOC_ZVAL(param);
895 0 : *param = **(fci->params[i]);
896 0 : INIT_PZVAL(param);
897 : }
898 1656 : if (call_via_handler) {
899 0 : add_next_index_zval(params_array, param);
900 : } else {
901 1656 : zend_ptr_stack_push(&EG(argument_stack), param);
902 : }
903 : }
904 :
905 1222 : if (call_via_handler) {
906 0 : zend_ptr_stack_push(&EG(argument_stack), method_name);
907 0 : zend_ptr_stack_push(&EG(argument_stack), params_array);
908 0 : fci->param_count = 2;
909 : }
910 :
911 1222 : zend_ptr_stack_2_push(&EG(argument_stack), (void *) (long) fci->param_count, NULL);
912 :
913 1222 : original_function_state_ptr = EG(function_state_ptr);
914 1222 : EG(function_state_ptr) = &EX(function_state);
915 :
916 1222 : current_scope = EG(scope);
917 1222 : EG(scope) = calling_scope;
918 :
919 1222 : current_this = EG(This);
920 :
921 1222 : if (fci->object_pp) {
922 150 : if ((EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
923 0 : EG(This) = NULL;
924 : } else {
925 150 : EG(This) = *fci->object_pp;
926 :
927 150 : if (!PZVAL_IS_REF(EG(This))) {
928 141 : EG(This)->refcount++; /* For $this pointer */
929 : } else {
930 : zval *this_ptr;
931 :
932 9 : ALLOC_ZVAL(this_ptr);
933 9 : *this_ptr = *EG(This);
934 9 : INIT_PZVAL(this_ptr);
935 9 : zval_copy_ctor(this_ptr);
936 9 : EG(This) = this_ptr;
937 : }
938 : }
939 : } else {
940 1072 : EG(This) = NULL;
941 1072 : if (calling_scope && !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
942 : int severity;
943 0 : if (EX(function_state).function->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
944 0 : severity = E_STRICT;
945 : } else {
946 0 : severity = E_ERROR;
947 : }
948 0 : zend_error(severity, "Non-static method %s::%s() cannot be called statically", calling_scope->name, EX(function_state).function->common.function_name);
949 : }
950 : }
951 :
952 1222 : EX(prev_execute_data) = EG(current_execute_data);
953 1222 : EG(current_execute_data) = &execute_data;
954 :
955 1222 : if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
956 770 : calling_symbol_table = EG(active_symbol_table);
957 770 : EG(scope) = EX(function_state).function->common.scope;
958 770 : if (fci->symbol_table) {
959 0 : EG(active_symbol_table) = fci->symbol_table;
960 : } else {
961 770 : ALLOC_HASHTABLE(EG(active_symbol_table));
962 770 : zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
963 : }
964 :
965 770 : original_return_value = EG(return_value_ptr_ptr);
966 770 : original_op_array = EG(active_op_array);
967 770 : EG(return_value_ptr_ptr) = fci->retval_ptr_ptr;
968 770 : EG(active_op_array) = (zend_op_array *) EX(function_state).function;
969 770 : original_opline_ptr = EG(opline_ptr);
970 770 : zend_execute(EG(active_op_array) TSRMLS_CC);
971 770 : if (!fci->symbol_table) {
972 770 : zend_hash_destroy(EG(active_symbol_table));
973 770 : FREE_HASHTABLE(EG(active_symbol_table));
974 : }
975 770 : EG(active_symbol_table) = calling_symbol_table;
976 770 : EG(active_op_array) = original_op_array;
977 770 : EG(return_value_ptr_ptr)=original_return_value;
978 770 : EG(opline_ptr) = original_opline_ptr;
979 : } else {
980 452 : ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr);
981 452 : if (EX(function_state).function->common.scope) {
982 138 : EG(scope) = EX(function_state).function->common.scope;
983 : }
984 452 : ((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);
985 452 : INIT_PZVAL(*fci->retval_ptr_ptr);
986 : }
987 1222 : zend_ptr_stack_clear_multiple(TSRMLS_C);
988 1222 : if (call_via_handler) {
989 0 : zval_ptr_dtor(&method_name);
990 0 : zval_ptr_dtor(¶ms_array);
991 : }
992 1222 : EG(function_state_ptr) = original_function_state_ptr;
993 :
994 1222 : if (EG(This)) {
995 150 : zval_ptr_dtor(&EG(This));
996 : }
997 1222 : EG(scope) = current_scope;
998 1222 : EG(This) = current_this;
999 1222 : EG(current_execute_data) = EX(prev_execute_data);
1000 :
1001 1222 : if (EG(exception)) {
1002 0 : zend_throw_exception_internal(NULL TSRMLS_CC);
1003 : }
1004 1222 : return SUCCESS;
1005 : }
1006 :
1007 :
1008 : ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC)
1009 395 : {
1010 : zval **args[1];
1011 : zval autoload_function;
1012 : zval *class_name_ptr;
1013 395 : zval *retval_ptr = NULL;
1014 : int retval;
1015 : char *lc_name;
1016 : zval *exception;
1017 395 : char dummy = 1;
1018 : zend_fcall_info fcall_info;
1019 : zend_fcall_info_cache fcall_cache;
1020 :
1021 395 : if (name == NULL || !name_length) {
1022 0 : return FAILURE;
1023 : }
1024 :
1025 395 : lc_name = do_alloca(name_length + 1);
1026 395 : zend_str_tolower_copy(lc_name, name, name_length);
1027 :
1028 395 : if (zend_hash_find(EG(class_table), lc_name, name_length+1, (void **) ce) == SUCCESS) {
1029 : free_alloca(lc_name);
1030 395 : return SUCCESS;
1031 : }
1032 :
1033 : /* The compiler is not-reentrant. Make sure we __autoload() only during run-time
1034 : * (doesn't impact fuctionality of __autoload()
1035 : */
1036 0 : if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
1037 : free_alloca(lc_name);
1038 0 : return FAILURE;
1039 : }
1040 :
1041 0 : if (EG(in_autoload) == NULL) {
1042 0 : ALLOC_HASHTABLE(EG(in_autoload));
1043 0 : zend_hash_init(EG(in_autoload), 0, NULL, NULL, 0);
1044 : }
1045 :
1046 0 : if (zend_hash_add(EG(in_autoload), lc_name, name_length+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
1047 : free_alloca(lc_name);
1048 0 : return FAILURE;
1049 : }
1050 :
1051 0 : ZVAL_STRINGL(&autoload_function, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1, 0);
1052 :
1053 0 : ALLOC_ZVAL(class_name_ptr);
1054 0 : INIT_PZVAL(class_name_ptr);
1055 0 : ZVAL_STRINGL(class_name_ptr, name, name_length, 1);
1056 :
1057 0 : args[0] = &class_name_ptr;
1058 :
1059 0 : fcall_info.size = sizeof(fcall_info);
1060 0 : fcall_info.function_table = EG(function_table);
1061 0 : fcall_info.function_name = &autoload_function;
1062 0 : fcall_info.symbol_table = NULL;
1063 0 : fcall_info.retval_ptr_ptr = &retval_ptr;
1064 0 : fcall_info.param_count = 1;
1065 0 : fcall_info.params = args;
1066 0 : fcall_info.object_pp = NULL;
1067 0 : fcall_info.no_separation = 1;
1068 :
1069 0 : fcall_cache.initialized = EG(autoload_func) ? 1 : 0;
1070 0 : fcall_cache.function_handler = EG(autoload_func);
1071 0 : fcall_cache.calling_scope = NULL;
1072 0 : fcall_cache.object_pp = NULL;
1073 :
1074 0 : exception = EG(exception);
1075 0 : EG(exception) = NULL;
1076 0 : retval = zend_call_function(&fcall_info, &fcall_cache TSRMLS_CC);
1077 0 : EG(autoload_func) = fcall_cache.function_handler;
1078 :
1079 0 : zval_ptr_dtor(&class_name_ptr);
1080 :
1081 0 : zend_hash_del(EG(in_autoload), lc_name, name_length+1);
1082 :
1083 0 : if (retval == FAILURE) {
1084 0 : EG(exception) = exception;
1085 : free_alloca(lc_name);
1086 0 : return FAILURE;
1087 : }
1088 :
1089 0 : if (EG(exception) && exception) {
1090 : free_alloca(lc_name);
1091 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);
1092 0 : return FAILURE;
1093 : }
1094 0 : if (!EG(exception)) {
1095 0 : EG(exception) = exception;
1096 : }
1097 0 : if (retval_ptr) {
1098 0 : zval_ptr_dtor(&retval_ptr);
1099 : }
1100 :
1101 0 : retval = zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce);
1102 : free_alloca(lc_name);
1103 0 : return retval;
1104 : }
1105 :
1106 : ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC)
1107 26 : {
1108 26 : return zend_lookup_class_ex(name, name_length, 1, ce TSRMLS_CC);
1109 : }
1110 :
1111 : ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
1112 0 : {
1113 : zval pv;
1114 : zend_op_array *new_op_array;
1115 0 : zend_op_array *original_active_op_array = EG(active_op_array);
1116 0 : zend_function_state *original_function_state_ptr = EG(function_state_ptr);
1117 : zend_uchar original_handle_op_arrays;
1118 : int retval;
1119 :
1120 0 : if (retval_ptr) {
1121 0 : int l = strlen(str);
1122 0 : Z_STRLEN(pv) = l+sizeof("return ;")-1;
1123 0 : Z_STRVAL(pv) = emalloc(Z_STRLEN(pv) + 1);
1124 0 : memcpy(Z_STRVAL(pv), "return ", sizeof("return ")-1);
1125 0 : memcpy(Z_STRVAL(pv) + sizeof("return ")-1, str, l);
1126 0 : Z_STRVAL(pv)[Z_STRLEN(pv)-2] = ' ';
1127 0 : Z_STRVAL(pv)[Z_STRLEN(pv)-1] = ';';
1128 0 : Z_STRVAL(pv)[Z_STRLEN(pv)] = '\0';
1129 : } else {
1130 0 : pv.value.str.len = strlen(str);
1131 0 : pv.value.str.val = estrndup(str, pv.value.str.len);
1132 : }
1133 0 : pv.type = IS_STRING;
1134 :
1135 : /*printf("Evaluating '%s'\n", pv.value.str.val);*/
1136 :
1137 0 : original_handle_op_arrays = CG(handle_op_arrays);
1138 0 : CG(handle_op_arrays) = 0;
1139 0 : new_op_array = zend_compile_string(&pv, string_name TSRMLS_CC);
1140 0 : CG(handle_op_arrays) = original_handle_op_arrays;
1141 :
1142 0 : if (new_op_array) {
1143 0 : zval *local_retval_ptr=NULL;
1144 0 : zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
1145 0 : zend_op **original_opline_ptr = EG(opline_ptr);
1146 :
1147 0 : EG(return_value_ptr_ptr) = &local_retval_ptr;
1148 0 : EG(active_op_array) = new_op_array;
1149 0 : EG(no_extensions)=1;
1150 :
1151 0 : zend_execute(new_op_array TSRMLS_CC);
1152 :
1153 0 : if (local_retval_ptr) {
1154 0 : if (retval_ptr) {
1155 0 : COPY_PZVAL_TO_ZVAL(*retval_ptr, local_retval_ptr);
1156 : } else {
1157 0 : zval_ptr_dtor(&local_retval_ptr);
1158 : }
1159 : } else {
1160 0 : if (retval_ptr) {
1161 0 : INIT_ZVAL(*retval_ptr);
1162 : }
1163 : }
1164 :
1165 0 : EG(no_extensions)=0;
1166 0 : EG(opline_ptr) = original_opline_ptr;
1167 0 : EG(active_op_array) = original_active_op_array;
1168 0 : EG(function_state_ptr) = original_function_state_ptr;
1169 0 : destroy_op_array(new_op_array TSRMLS_CC);
1170 0 : efree(new_op_array);
1171 0 : EG(return_value_ptr_ptr) = original_return_value_ptr_ptr;
1172 0 : retval = SUCCESS;
1173 : } else {
1174 0 : retval = FAILURE;
1175 : }
1176 0 : zval_dtor(&pv);
1177 0 : return retval;
1178 : }
1179 :
1180 :
1181 : ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC)
1182 0 : {
1183 : int result;
1184 :
1185 0 : result = zend_eval_string(str, retval_ptr, string_name TSRMLS_CC);
1186 0 : if (handle_exceptions && EG(exception)) {
1187 0 : zend_exception_error(EG(exception) TSRMLS_CC);
1188 0 : result = FAILURE;
1189 : }
1190 0 : return result;
1191 : }
1192 :
1193 :
1194 : void execute_new_code(TSRMLS_D)
1195 0 : {
1196 : zend_op *opline, *end;
1197 : zend_op *ret_opline;
1198 0 : zval *local_retval=NULL;
1199 :
1200 0 : if (!(CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE)
1201 : || CG(active_op_array)->backpatch_count>0
1202 : || CG(active_op_array)->function_name
1203 : || CG(active_op_array)->type!=ZEND_USER_FUNCTION) {
1204 0 : return;
1205 : }
1206 :
1207 0 : ret_opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1208 0 : ret_opline->opcode = ZEND_RETURN;
1209 0 : ret_opline->op1.op_type = IS_CONST;
1210 0 : INIT_ZVAL(ret_opline->op1.u.constant);
1211 0 : SET_UNUSED(ret_opline->op2);
1212 :
1213 0 : zend_do_handle_exception(TSRMLS_C);
1214 :
1215 0 : if (!CG(active_op_array)->start_op) {
1216 0 : CG(active_op_array)->start_op = CG(active_op_array)->opcodes;
1217 : }
1218 :
1219 0 : opline=CG(active_op_array)->start_op;
1220 0 : end=CG(active_op_array)->opcodes+CG(active_op_array)->last;
1221 :
1222 0 : while (opline<end) {
1223 0 : if (opline->op1.op_type==IS_CONST) {
1224 0 : opline->op1.u.constant.is_ref = 1;
1225 0 : opline->op1.u.constant.refcount = 2; /* Make sure is_ref won't be reset */
1226 : }
1227 0 : if (opline->op2.op_type==IS_CONST) {
1228 0 : opline->op2.u.constant.is_ref = 1;
1229 0 : opline->op2.u.constant.refcount = 2;
1230 : }
1231 0 : switch (opline->opcode) {
1232 : case ZEND_JMP:
1233 0 : opline->op1.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op1.u.opline_num];
1234 0 : break;
1235 : case ZEND_JMPZ:
1236 : case ZEND_JMPNZ:
1237 : case ZEND_JMPZ_EX:
1238 : case ZEND_JMPNZ_EX:
1239 0 : opline->op2.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.u.opline_num];
1240 : break;
1241 : }
1242 0 : ZEND_VM_SET_OPCODE_HANDLER(opline);
1243 0 : opline++;
1244 : }
1245 :
1246 0 : EG(return_value_ptr_ptr) = &local_retval;
1247 0 : EG(active_op_array) = CG(active_op_array);
1248 0 : zend_execute(CG(active_op_array) TSRMLS_CC);
1249 0 : if (local_retval) {
1250 0 : zval_ptr_dtor(&local_retval);
1251 : }
1252 :
1253 0 : if (EG(exception)) {
1254 0 : zend_exception_error(EG(exception) TSRMLS_CC);
1255 : }
1256 :
1257 0 : CG(active_op_array)->last -= 2; /* get rid of that ZEND_RETURN and ZEND_HANDLE_EXCEPTION */
1258 0 : CG(active_op_array)->start_op = CG(active_op_array)->opcodes+CG(active_op_array)->last;
1259 : }
1260 :
1261 :
1262 : ZEND_API void zend_timeout(int dummy)
1263 0 : {
1264 : TSRMLS_FETCH();
1265 :
1266 0 : if (zend_on_timeout) {
1267 0 : zend_on_timeout(EG(timeout_seconds) TSRMLS_CC);
1268 : }
1269 :
1270 0 : zend_error(E_ERROR, "Maximum execution time of %d second%s exceeded",
1271 : EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s");
1272 0 : }
1273 :
1274 : #ifdef ZEND_WIN32
1275 : static LRESULT CALLBACK zend_timeout_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1276 : {
1277 : switch (message) {
1278 : case WM_DESTROY:
1279 : PostQuitMessage(0);
1280 : break;
1281 : case WM_REGISTER_ZEND_TIMEOUT:
1282 : /* wParam is the thread id pointer, lParam is the timeout amount in seconds */
1283 : if (lParam==0) {
1284 : KillTimer(timeout_window, wParam);
1285 : } else {
1286 : #ifdef ZTS
1287 : void ***tsrm_ls;
1288 : #endif
1289 : SetTimer(timeout_window, wParam, lParam*1000, NULL);
1290 : #ifdef ZTS
1291 : tsrm_ls = ts_resource_ex(0, &wParam);
1292 : if (!tsrm_ls) {
1293 : /* shouldn't normally happen */
1294 : break;
1295 : }
1296 : #endif
1297 : EG(timed_out) = 0;
1298 : }
1299 : break;
1300 : case WM_UNREGISTER_ZEND_TIMEOUT:
1301 : /* wParam is the thread id pointer */
1302 : KillTimer(timeout_window, wParam);
1303 : break;
1304 : case WM_TIMER: {
1305 : #ifdef ZTS
1306 : void ***tsrm_ls;
1307 :
1308 : tsrm_ls = ts_resource_ex(0, &wParam);
1309 : if (!tsrm_ls) {
1310 : /* Thread died before receiving its timeout? */
1311 : break;
1312 : }
1313 : #endif
1314 : KillTimer(timeout_window, wParam);
1315 : EG(timed_out) = 1;
1316 : }
1317 : break;
1318 : default:
1319 : return DefWindowProc(hWnd, message, wParam, lParam);
1320 : }
1321 : return 0;
1322 : }
1323 :
1324 :
1325 :
1326 : static unsigned __stdcall timeout_thread_proc(void *pArgs)
1327 : {
1328 : MSG message;
1329 :
1330 : wc.style=0;
1331 : wc.lpfnWndProc = zend_timeout_WndProc;
1332 : wc.cbClsExtra=0;
1333 : wc.cbWndExtra=0;
1334 : wc.hInstance=NULL;
1335 : wc.hIcon=NULL;
1336 : wc.hCursor=NULL;
1337 : wc.hbrBackground=(HBRUSH)(COLOR_BACKGROUND + 5);
1338 : wc.lpszMenuName=NULL;
1339 : wc.lpszClassName = "Zend Timeout Window";
1340 : if (!RegisterClass(&wc)) {
1341 : return -1;
1342 : }
1343 : timeout_window = CreateWindow(wc.lpszClassName, wc.lpszClassName, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
1344 : SetEvent(timeout_thread_event);
1345 : while (GetMessage(&message, NULL, 0, 0)) {
1346 : SendMessage(timeout_window, message.message, message.wParam, message.lParam);
1347 : if (message.message == WM_QUIT) {
1348 : break;
1349 : }
1350 : }
1351 : DestroyWindow(timeout_window);
1352 : UnregisterClass(wc.lpszClassName, NULL);
1353 : SetEvent(timeout_thread_handle);
1354 : return 0;
1355 : }
1356 :
1357 :
1358 : void zend_init_timeout_thread()
1359 : {
1360 : timeout_thread_event = CreateEvent(NULL, FALSE, FALSE, NULL);
1361 : timeout_thread_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
1362 : _beginthreadex(NULL, 0, timeout_thread_proc, NULL, 0, &timeout_thread_id);
1363 : WaitForSingleObject(timeout_thread_event, INFINITE);
1364 : }
1365 :
1366 :
1367 : void zend_shutdown_timeout_thread()
1368 : {
1369 : if (!timeout_thread_initialized) {
1370 : return;
1371 : }
1372 : PostThreadMessage(timeout_thread_id, WM_QUIT, 0, 0);
1373 :
1374 : /* Wait for thread termination */
1375 : WaitForSingleObject(timeout_thread_handle, 5000);
1376 : CloseHandle(timeout_thread_handle);
1377 : timeout_thread_initialized = 0;
1378 : }
1379 :
1380 : #endif
1381 :
1382 : /* This one doesn't exists on QNX */
1383 : #ifndef SIGPROF
1384 : #define SIGPROF 27
1385 : #endif
1386 :
1387 : void zend_set_timeout(long seconds)
1388 225 : {
1389 : TSRMLS_FETCH();
1390 :
1391 225 : EG(timeout_seconds) = seconds;
1392 225 : if(!seconds) {
1393 5 : return;
1394 : }
1395 : #ifdef ZEND_WIN32
1396 : if (timeout_thread_initialized==0 && InterlockedIncrement(&timeout_thread_initialized)==1) {
1397 : /* We start up this process-wide thread here and not in zend_startup(), because if Zend
1398 : * is initialized inside a DllMain(), you're not supposed to start threads from it.
1399 : */
1400 : zend_init_timeout_thread();
1401 : }
1402 : PostThreadMessage(timeout_thread_id, WM_REGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) seconds);
1403 : #else
1404 : # ifdef HAVE_SETITIMER
1405 : {
1406 : struct itimerval t_r; /* timeout requested */
1407 : sigset_t sigset;
1408 :
1409 220 : t_r.it_value.tv_sec = seconds;
1410 220 : t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;
1411 :
1412 : # ifdef __CYGWIN__
1413 : setitimer(ITIMER_REAL, &t_r, NULL);
1414 : signal(SIGALRM, zend_timeout);
1415 : sigemptyset(&sigset);
1416 : sigaddset(&sigset, SIGALRM);
1417 : # else
1418 220 : setitimer(ITIMER_PROF, &t_r, NULL);
1419 220 : signal(SIGPROF, zend_timeout);
1420 220 : sigemptyset(&sigset);
1421 220 : sigaddset(&sigset, SIGPROF);
1422 : # endif
1423 220 : sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1424 : }
1425 : # endif
1426 : #endif
1427 : }
1428 :
1429 :
1430 : void zend_unset_timeout(TSRMLS_D)
1431 225 : {
1432 : #ifdef ZEND_WIN32
1433 : if(timeout_thread_initialized) {
1434 : PostThreadMessage(timeout_thread_id, WM_UNREGISTER_ZEND_TIMEOUT, (WPARAM) GetCurrentThreadId(), (LPARAM) 0);
1435 : }
1436 : #else
1437 : # ifdef HAVE_SETITIMER
1438 : {
1439 : struct itimerval no_timeout;
1440 :
1441 225 : 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;
1442 :
1443 : #ifdef __CYGWIN__
1444 : setitimer(ITIMER_REAL, &no_timeout, NULL);
1445 : #else
1446 225 : setitimer(ITIMER_PROF, &no_timeout, NULL);
1447 : #endif
1448 : }
1449 : # endif
1450 : #endif
1451 225 : }
1452 :
1453 :
1454 : zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC)
1455 619 : {
1456 : zend_class_entry **pce;
1457 619 : int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0;
1458 :
1459 619 : fetch_type = fetch_type & ~ZEND_FETCH_CLASS_NO_AUTOLOAD;
1460 619 : check_fetch_type:
1461 619 : switch (fetch_type) {
1462 : case ZEND_FETCH_CLASS_SELF:
1463 0 : if (!EG(scope)) {
1464 0 : zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
1465 : }
1466 0 : return EG(scope);
1467 : case ZEND_FETCH_CLASS_PARENT:
1468 250 : if (!EG(scope)) {
1469 0 : zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
1470 : }
1471 250 : if (!EG(scope)->parent) {
1472 0 : zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
1473 : }
1474 250 : return EG(scope)->parent;
1475 : case ZEND_FETCH_CLASS_AUTO: {
1476 121 : fetch_type = zend_get_class_fetch_type(class_name, class_name_len);
1477 121 : if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) {
1478 0 : goto check_fetch_type;
1479 : }
1480 : }
1481 : break;
1482 : }
1483 :
1484 369 : if (zend_lookup_class_ex(class_name, class_name_len, use_autoload, &pce TSRMLS_CC)==FAILURE) {
1485 0 : if (use_autoload) {
1486 0 : if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
1487 0 : zend_error(E_ERROR, "Interface '%s' not found", class_name);
1488 : } else {
1489 0 : zend_error(E_ERROR, "Class '%s' not found", class_name);
1490 : }
1491 : }
1492 0 : return NULL;
1493 : }
1494 369 : return *pce;
1495 : }
1496 :
1497 :
1498 :
1499 : #define MAX_ABSTRACT_INFO_CNT 3
1500 : #define MAX_ABSTRACT_INFO_FMT "%s%s%s%s"
1501 : #define DISPLAY_ABSTRACT_FN(idx) \
1502 : ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \
1503 : ai.afn[idx] ? "::" : "", \
1504 : ai.afn[idx] ? ai.afn[idx]->common.function_name : "", \
1505 : ai.afn[idx] && ai.afn[idx+1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "")
1506 :
1507 : typedef struct _zend_abstract_info {
1508 : zend_function *afn[MAX_ABSTRACT_INFO_CNT+1];
1509 : int cnt;
1510 : } zend_abstract_info;
1511 :
1512 :
1513 : static int zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai TSRMLS_DC)
1514 0 : {
1515 0 : if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
1516 0 : if (ai->cnt < MAX_ABSTRACT_INFO_CNT) {
1517 0 : ai->afn[ai->cnt] = fn;
1518 : }
1519 0 : ai->cnt++;
1520 : }
1521 0 : return 0;
1522 : }
1523 :
1524 :
1525 : void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC)
1526 9690 : {
1527 : zend_abstract_info ai;
1528 :
1529 9690 : if ((ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) && !(ce->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
1530 0 : memset(&ai, 0, sizeof(ai));
1531 :
1532 0 : zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC);
1533 :
1534 0 : if (ai.cnt) {
1535 0 : 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 ")",
1536 : ce->name, ai.cnt,
1537 : ai.cnt > 1 ? "s" : "",
1538 : DISPLAY_ABSTRACT_FN(0),
1539 : DISPLAY_ABSTRACT_FN(1),
1540 : DISPLAY_ABSTRACT_FN(2)
1541 : );
1542 : }
1543 : }
1544 9690 : }
1545 :
1546 : ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC)
1547 0 : {
1548 : zend_execute_data *ex;
1549 : int i;
1550 :
1551 0 : for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
1552 0 : if (ex->op_array && ex->symbol_table == symbol_table) {
1553 0 : for (i = 0; i < ex->op_array->last_var; i++) {
1554 0 : ex->CVs[i] = NULL;
1555 : }
1556 : }
1557 : }
1558 0 : }
1559 :
1560 : ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC)
1561 2 : {
1562 : zend_execute_data *ex;
1563 2 : ulong hash_value = zend_inline_hash_func(name, name_len+1);
1564 :
1565 2 : if (zend_hash_quick_exists(&EG(symbol_table), name, name_len+1, hash_value)) {
1566 0 : for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
1567 0 : if (ex->op_array && ex->symbol_table == &EG(symbol_table)) {
1568 : int i;
1569 0 : for (i = 0; i < ex->op_array->last_var; i++) {
1570 0 : if (ex->op_array->vars[i].hash_value == hash_value &&
1571 : ex->op_array->vars[i].name_len == name_len &&
1572 : !memcmp(ex->op_array->vars[i].name, name, name_len)) {
1573 0 : ex->CVs[i] = NULL;
1574 0 : break;
1575 : }
1576 : }
1577 : }
1578 : }
1579 0 : return zend_hash_del(&EG(symbol_table), name, name_len+1);
1580 : }
1581 2 : return FAILURE;
1582 : }
1583 :
1584 : /*
1585 : * Local variables:
1586 : * tab-width: 4
1587 : * c-basic-offset: 4
1588 : * indent-tabs-mode: t
1589 : * End:
1590 : */
|