1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2018 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$ */
21
22 #include "zend.h"
23 #include "zend_extensions.h"
24 #include "zend_modules.h"
25 #include "zend_constants.h"
26 #include "zend_list.h"
27 #include "zend_API.h"
28 #include "zend_exceptions.h"
29 #include "zend_builtin_functions.h"
30 #include "zend_ini.h"
31 #include "zend_vm.h"
32 #include "zend_dtrace.h"
33 #include "zend_virtual_cwd.h"
34 #include "zend_smart_str.h"
35 #include "zend_smart_string.h"
36
37 #ifdef ZTS
38 ZEND_API int compiler_globals_id;
39 ZEND_API int executor_globals_id;
40 static HashTable *global_function_table = NULL;
41 static HashTable *global_class_table = NULL;
42 static HashTable *global_constants_table = NULL;
43 static HashTable *global_auto_globals_table = NULL;
44 static HashTable *global_persistent_list = NULL;
45 ZEND_TSRMLS_CACHE_DEFINE()
46 # define GLOBAL_FUNCTION_TABLE global_function_table
47 # define GLOBAL_CLASS_TABLE global_class_table
48 # define GLOBAL_CONSTANTS_TABLE global_constants_table
49 # define GLOBAL_AUTO_GLOBALS_TABLE global_auto_globals_table
50 #else
51 # define GLOBAL_FUNCTION_TABLE CG(function_table)
52 # define GLOBAL_CLASS_TABLE CG(class_table)
53 # define GLOBAL_AUTO_GLOBALS_TABLE CG(auto_globals)
54 # define GLOBAL_CONSTANTS_TABLE EG(zend_constants)
55 #endif
56
57 ZEND_API zend_utility_values zend_uv;
58 ZEND_API zend_bool zend_dtrace_enabled;
59
60 /* version information */
61 static char *zend_version_info;
62 static uint32_t zend_version_info_length;
63 #define ZEND_CORE_VERSION_INFO "Zend Engine v" ZEND_VERSION ", Copyright (c) 1998-2018 Zend Technologies\n"
64 #define PRINT_ZVAL_INDENT 4
65
66 /* true multithread-shared globals */
67 ZEND_API zend_class_entry *zend_standard_class_def = NULL;
68 ZEND_API size_t (*zend_printf)(const char *format, ...);
69 ZEND_API zend_write_func_t zend_write;
70 ZEND_API FILE *(*zend_fopen)(const char *filename, zend_string **opened_path);
71 ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle);
72 ZEND_API void (*zend_ticks_function)(int ticks);
73 ZEND_API void (*zend_interrupt_function)(zend_execute_data *execute_data);
74 ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint32_t error_lineno, const char *format, va_list args);
75 void (*zend_printf_to_smart_string)(smart_string *buf, const char *format, va_list ap);
76 void (*zend_printf_to_smart_str)(smart_str *buf, const char *format, va_list ap);
77 ZEND_API char *(*zend_getenv)(char *name, size_t name_len);
78 ZEND_API zend_string *(*zend_resolve_path)(const char *filename, int filename_len);
79
80 void (*zend_on_timeout)(int seconds);
81
82 static void (*zend_message_dispatcher_p)(zend_long message, const void *data);
83 static zval *(*zend_get_configuration_directive_p)(zend_string *name);
84
ZEND_INI_MH(OnUpdateErrorReporting)85 static ZEND_INI_MH(OnUpdateErrorReporting) /* {{{ */
86 {
87 if (!new_value) {
88 EG(error_reporting) = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED;
89 } else {
90 EG(error_reporting) = atoi(ZSTR_VAL(new_value));
91 }
92 return SUCCESS;
93 }
94 /* }}} */
95
ZEND_INI_MH(OnUpdateGCEnabled)96 static ZEND_INI_MH(OnUpdateGCEnabled) /* {{{ */
97 {
98 OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
99
100 if (GC_G(gc_enabled)) {
101 gc_init();
102 }
103
104 return SUCCESS;
105 }
106 /* }}} */
107
ZEND_INI_MH(OnUpdateScriptEncoding)108 static ZEND_INI_MH(OnUpdateScriptEncoding) /* {{{ */
109 {
110 if (!CG(multibyte)) {
111 return FAILURE;
112 }
113 if (!zend_multibyte_get_functions()) {
114 return SUCCESS;
115 }
116 return zend_multibyte_set_script_encoding_by_string(new_value ? ZSTR_VAL(new_value) : NULL, new_value ? ZSTR_LEN(new_value) : 0);
117 }
118 /* }}} */
119
ZEND_INI_MH(OnUpdateAssertions)120 static ZEND_INI_MH(OnUpdateAssertions) /* {{{ */
121 {
122 zend_long *p, val;
123 #ifndef ZTS
124 char *base = (char *) mh_arg2;
125 #else
126 char *base;
127
128 base = (char *) ts_resource(*((int *) mh_arg2));
129 #endif
130
131 p = (zend_long *) (base+(size_t) mh_arg1);
132
133 val = zend_atol(ZSTR_VAL(new_value), (int)ZSTR_LEN(new_value));
134
135 if (stage != ZEND_INI_STAGE_STARTUP &&
136 stage != ZEND_INI_STAGE_SHUTDOWN &&
137 *p != val &&
138 (*p < 0 || val < 0)) {
139 zend_error(E_WARNING, "zend.assertions may be completely enabled or disabled only in php.ini");
140 return FAILURE;
141 }
142
143 *p = val;
144 return SUCCESS;
145 }
146 /* }}} */
147
148 ZEND_INI_BEGIN()
149 ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
150 STD_ZEND_INI_ENTRY("zend.assertions", "1", ZEND_INI_ALL, OnUpdateAssertions, assertions, zend_executor_globals, executor_globals)
151 STD_ZEND_INI_BOOLEAN("zend.enable_gc", "1", ZEND_INI_ALL, OnUpdateGCEnabled, gc_enabled, zend_gc_globals, gc_globals)
152 STD_ZEND_INI_BOOLEAN("zend.multibyte", "0", ZEND_INI_PERDIR, OnUpdateBool, multibyte, zend_compiler_globals, compiler_globals)
153 ZEND_INI_ENTRY("zend.script_encoding", NULL, ZEND_INI_ALL, OnUpdateScriptEncoding)
154 STD_ZEND_INI_BOOLEAN("zend.detect_unicode", "1", ZEND_INI_ALL, OnUpdateBool, detect_unicode, zend_compiler_globals, compiler_globals)
155 #ifdef ZEND_SIGNALS
156 STD_ZEND_INI_BOOLEAN("zend.signal_check", "0", ZEND_INI_SYSTEM, OnUpdateBool, check, zend_signal_globals_t, zend_signal_globals)
157 #endif
ZEND_INI_END()158 ZEND_INI_END()
159
160 ZEND_API size_t zend_vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap) /* {{{ */
161 {
162 smart_string buf = {0};
163
164 /* since there are places where (v)spprintf called without checking for null,
165 a bit of defensive coding here */
166 if (!pbuf) {
167 return 0;
168 }
169
170 zend_printf_to_smart_string(&buf, format, ap);
171
172 if (max_len && buf.len > max_len) {
173 buf.len = max_len;
174 }
175
176 smart_string_0(&buf);
177
178 if (buf.c) {
179 *pbuf = buf.c;
180 return buf.len;
181 } else {
182 *pbuf = estrndup("", 0);
183 return 0;
184 }
185 }
186 /* }}} */
187
zend_spprintf(char ** message,size_t max_len,const char * format,...)188 ZEND_API size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) /* {{{ */
189 {
190 va_list arg;
191 size_t len;
192
193 va_start(arg, format);
194 len = zend_vspprintf(message, max_len, format, arg);
195 va_end(arg);
196 return len;
197 }
198 /* }}} */
199
zend_vstrpprintf(size_t max_len,const char * format,va_list ap)200 ZEND_API zend_string *zend_vstrpprintf(size_t max_len, const char *format, va_list ap) /* {{{ */
201 {
202 smart_str buf = {0};
203
204 zend_printf_to_smart_str(&buf, format, ap);
205
206 if (!buf.s) {
207 return ZSTR_EMPTY_ALLOC();
208 }
209
210 if (max_len && ZSTR_LEN(buf.s) > max_len) {
211 ZSTR_LEN(buf.s) = max_len;
212 }
213
214 smart_str_0(&buf);
215 return buf.s;
216 }
217 /* }}} */
218
zend_strpprintf(size_t max_len,const char * format,...)219 ZEND_API zend_string *zend_strpprintf(size_t max_len, const char *format, ...) /* {{{ */
220 {
221 va_list arg;
222 zend_string *str;
223
224 va_start(arg, format);
225 str = zend_vstrpprintf(max_len, format, arg);
226 va_end(arg);
227 return str;
228 }
229 /* }}} */
230
231 static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent);
232
print_hash(smart_str * buf,HashTable * ht,int indent,zend_bool is_object)233 static void print_hash(smart_str *buf, HashTable *ht, int indent, zend_bool is_object) /* {{{ */
234 {
235 zval *tmp;
236 zend_string *string_key;
237 zend_ulong num_key;
238 int i;
239
240 for (i = 0; i < indent; i++) {
241 smart_str_appendc(buf, ' ');
242 }
243 smart_str_appends(buf, "(\n");
244 indent += PRINT_ZVAL_INDENT;
245 ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, string_key, tmp) {
246 for (i = 0; i < indent; i++) {
247 smart_str_appendc(buf, ' ');
248 }
249 smart_str_appendc(buf, '[');
250 if (string_key) {
251 if (is_object) {
252 const char *prop_name, *class_name;
253 size_t prop_len;
254 int mangled = zend_unmangle_property_name_ex(string_key, &class_name, &prop_name, &prop_len);
255
256 smart_str_appendl(buf, prop_name, prop_len);
257 if (class_name && mangled == SUCCESS) {
258 if (class_name[0] == '*') {
259 smart_str_appends(buf, ":protected");
260 } else {
261 smart_str_appends(buf, ":");
262 smart_str_appends(buf, class_name);
263 smart_str_appends(buf, ":private");
264 }
265 }
266 } else {
267 smart_str_append(buf, string_key);
268 }
269 } else {
270 smart_str_append_long(buf, num_key);
271 }
272 smart_str_appends(buf, "] => ");
273 zend_print_zval_r_to_buf(buf, tmp, indent+PRINT_ZVAL_INDENT);
274 smart_str_appends(buf, "\n");
275 } ZEND_HASH_FOREACH_END();
276 indent -= PRINT_ZVAL_INDENT;
277 for (i = 0; i < indent; i++) {
278 smart_str_appendc(buf, ' ');
279 }
280 smart_str_appends(buf, ")\n");
281 }
282 /* }}} */
283
print_flat_hash(HashTable * ht)284 static void print_flat_hash(HashTable *ht) /* {{{ */
285 {
286 zval *tmp;
287 zend_string *string_key;
288 zend_ulong num_key;
289 int i = 0;
290
291 ZEND_HASH_FOREACH_KEY_VAL_IND(ht, num_key, string_key, tmp) {
292 if (i++ > 0) {
293 ZEND_PUTS(",");
294 }
295 ZEND_PUTS("[");
296 if (string_key) {
297 ZEND_WRITE(ZSTR_VAL(string_key), ZSTR_LEN(string_key));
298 } else {
299 zend_printf(ZEND_ULONG_FMT, num_key);
300 }
301 ZEND_PUTS("] => ");
302 zend_print_flat_zval_r(tmp);
303 } ZEND_HASH_FOREACH_END();
304 }
305 /* }}} */
306
zend_make_printable_zval(zval * expr,zval * expr_copy)307 ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy) /* {{{ */
308 {
309 if (Z_TYPE_P(expr) == IS_STRING) {
310 return 0;
311 } else {
312 ZVAL_STR(expr_copy, _zval_get_string_func(expr));
313 return 1;
314 }
315 }
316 /* }}} */
317
zend_print_zval(zval * expr,int indent)318 ZEND_API size_t zend_print_zval(zval *expr, int indent) /* {{{ */
319 {
320 zend_string *str = zval_get_string(expr);
321 size_t len = ZSTR_LEN(str);
322
323 if (len != 0) {
324 zend_write(ZSTR_VAL(str), len);
325 }
326
327 zend_string_release(str);
328 return len;
329 }
330 /* }}} */
331
zend_print_flat_zval_r(zval * expr)332 ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */
333 {
334 switch (Z_TYPE_P(expr)) {
335 case IS_ARRAY:
336 ZEND_PUTS("Array (");
337 if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) &&
338 ++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) {
339 ZEND_PUTS(" *RECURSION*");
340 Z_ARRVAL_P(expr)->u.v.nApplyCount--;
341 return;
342 }
343 print_flat_hash(Z_ARRVAL_P(expr));
344 ZEND_PUTS(")");
345 if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) {
346 Z_ARRVAL_P(expr)->u.v.nApplyCount--;
347 }
348 break;
349 case IS_OBJECT:
350 {
351 HashTable *properties = NULL;
352 zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr));
353 zend_printf("%s Object (", ZSTR_VAL(class_name));
354 zend_string_release(class_name);
355
356 if (Z_OBJ_APPLY_COUNT_P(expr) > 0) {
357 ZEND_PUTS(" *RECURSION*");
358 return;
359 }
360
361 if (Z_OBJ_HANDLER_P(expr, get_properties)) {
362 properties = Z_OBJPROP_P(expr);
363 }
364 if (properties) {
365 Z_OBJ_INC_APPLY_COUNT_P(expr);
366 print_flat_hash(properties);
367 Z_OBJ_DEC_APPLY_COUNT_P(expr);
368 }
369 ZEND_PUTS(")");
370 break;
371 }
372 case IS_REFERENCE:
373 zend_print_flat_zval_r(Z_REFVAL_P(expr));
374 break;
375 default:
376 zend_print_variable(expr);
377 break;
378 }
379 }
380 /* }}} */
381
zend_print_zval_r_to_buf(smart_str * buf,zval * expr,int indent)382 static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /* {{{ */
383 {
384 switch (Z_TYPE_P(expr)) {
385 case IS_ARRAY:
386 smart_str_appends(buf, "Array\n");
387 if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr)) &&
388 ++Z_ARRVAL_P(expr)->u.v.nApplyCount>1) {
389 smart_str_appends(buf, " *RECURSION*");
390 Z_ARRVAL_P(expr)->u.v.nApplyCount--;
391 return;
392 }
393 print_hash(buf, Z_ARRVAL_P(expr), indent, 0);
394 if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(expr))) {
395 Z_ARRVAL_P(expr)->u.v.nApplyCount--;
396 }
397 break;
398 case IS_OBJECT:
399 {
400 HashTable *properties;
401 int is_temp;
402
403 zend_string *class_name = Z_OBJ_HANDLER_P(expr, get_class_name)(Z_OBJ_P(expr));
404 smart_str_appends(buf, ZSTR_VAL(class_name));
405 zend_string_release(class_name);
406
407 smart_str_appends(buf, " Object\n");
408 if (Z_OBJ_APPLY_COUNT_P(expr) > 0) {
409 smart_str_appends(buf, " *RECURSION*");
410 return;
411 }
412 if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) {
413 break;
414 }
415
416 Z_OBJ_INC_APPLY_COUNT_P(expr);
417 print_hash(buf, properties, indent, 1);
418 Z_OBJ_DEC_APPLY_COUNT_P(expr);
419
420 if (is_temp) {
421 zend_hash_destroy(properties);
422 FREE_HASHTABLE(properties);
423 }
424 break;
425 }
426 case IS_LONG:
427 smart_str_append_long(buf, Z_LVAL_P(expr));
428 break;
429 case IS_REFERENCE:
430 zend_print_zval_r_to_buf(buf, Z_REFVAL_P(expr), indent);
431 break;
432 default:
433 {
434 zend_string *str = zval_get_string(expr);
435 smart_str_append(buf, str);
436 zend_string_release(str);
437 }
438 break;
439 }
440 }
441 /* }}} */
442
zend_print_zval_r_to_str(zval * expr,int indent)443 ZEND_API zend_string *zend_print_zval_r_to_str(zval *expr, int indent) /* {{{ */
444 {
445 smart_str buf = {0};
446 zend_print_zval_r_to_buf(&buf, expr, indent);
447 smart_str_0(&buf);
448 return buf.s;
449 }
450 /* }}} */
451
zend_print_zval_r(zval * expr,int indent)452 ZEND_API void zend_print_zval_r(zval *expr, int indent) /* {{{ */
453 {
454 zend_string *str = zend_print_zval_r_to_str(expr, indent);
455 zend_write(ZSTR_VAL(str), ZSTR_LEN(str));
456 zend_string_release(str);
457 }
458 /* }}} */
459
zend_fopen_wrapper(const char * filename,zend_string ** opened_path)460 static FILE *zend_fopen_wrapper(const char *filename, zend_string **opened_path) /* {{{ */
461 {
462 if (opened_path) {
463 *opened_path = zend_string_init(filename, strlen(filename), 0);
464 }
465 return fopen(filename, "rb");
466 }
467 /* }}} */
468
469 #ifdef ZTS
470 static zend_bool short_tags_default = 1;
471 static uint32_t compiler_options_default = ZEND_COMPILE_DEFAULT;
472 #else
473 # define short_tags_default 1
474 # define compiler_options_default ZEND_COMPILE_DEFAULT
475 #endif
476
zend_set_default_compile_time_values(void)477 static void zend_set_default_compile_time_values(void) /* {{{ */
478 {
479 /* default compile-time values */
480 CG(short_tags) = short_tags_default;
481 CG(compiler_options) = compiler_options_default;
482 }
483 /* }}} */
484
485 #ifdef ZEND_WIN32
zend_get_windows_version_info(OSVERSIONINFOEX * osvi)486 static void zend_get_windows_version_info(OSVERSIONINFOEX *osvi) /* {{{ */
487 {
488 ZeroMemory(osvi, sizeof(OSVERSIONINFOEX));
489 osvi->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
490 if(!GetVersionEx((OSVERSIONINFO *) osvi)) {
491 ZEND_ASSERT(0); /* Should not happen as sizeof is used. */
492 }
493 }
494 /* }}} */
495 #endif
496
zend_init_exception_op(void)497 static void zend_init_exception_op(void) /* {{{ */
498 {
499 memset(EG(exception_op), 0, sizeof(EG(exception_op)));
500 EG(exception_op)[0].opcode = ZEND_HANDLE_EXCEPTION;
501 EG(exception_op)[0].op1_type = IS_UNUSED;
502 EG(exception_op)[0].op2_type = IS_UNUSED;
503 EG(exception_op)[0].result_type = IS_UNUSED;
504 ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op));
505 EG(exception_op)[1].opcode = ZEND_HANDLE_EXCEPTION;
506 EG(exception_op)[1].op1_type = IS_UNUSED;
507 EG(exception_op)[1].op2_type = IS_UNUSED;
508 EG(exception_op)[1].result_type = IS_UNUSED;
509 ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)+1);
510 EG(exception_op)[2].opcode = ZEND_HANDLE_EXCEPTION;
511 EG(exception_op)[2].op1_type = IS_UNUSED;
512 EG(exception_op)[2].op2_type = IS_UNUSED;
513 EG(exception_op)[2].result_type = IS_UNUSED;
514 ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)+2);
515 }
516 /* }}} */
517
zend_init_call_trampoline_op(void)518 static void zend_init_call_trampoline_op(void) /* {{{ */
519 {
520 memset(&EG(call_trampoline_op), 0, sizeof(EG(call_trampoline_op)));
521 EG(call_trampoline_op).opcode = ZEND_CALL_TRAMPOLINE;
522 EG(call_trampoline_op).op1_type = IS_UNUSED;
523 EG(call_trampoline_op).op2_type = IS_UNUSED;
524 EG(call_trampoline_op).result_type = IS_UNUSED;
525 ZEND_VM_SET_OPCODE_HANDLER(&EG(call_trampoline_op));
526 }
527 /* }}} */
528
auto_global_dtor(zval * zv)529 static void auto_global_dtor(zval *zv) /* {{{ */
530 {
531 free(Z_PTR_P(zv));
532 }
533 /* }}} */
534
535 #ifdef ZTS
function_copy_ctor(zval * zv)536 static void function_copy_ctor(zval *zv) /* {{{ */
537 {
538 zend_function *old_func = Z_FUNC_P(zv);
539 Z_FUNC_P(zv) = pemalloc(sizeof(zend_internal_function), 1);
540 memcpy(Z_FUNC_P(zv), old_func, sizeof(zend_internal_function));
541 function_add_ref(Z_FUNC_P(zv));
542 }
543 /* }}} */
544
auto_global_copy_ctor(zval * zv)545 static void auto_global_copy_ctor(zval *zv) /* {{{ */
546 {
547 zend_auto_global *old_ag = (zend_auto_global *) Z_PTR_P(zv);
548 zend_auto_global *new_ag = pemalloc(sizeof(zend_auto_global), 1);
549
550 new_ag->name = old_ag->name;
551 new_ag->auto_global_callback = old_ag->auto_global_callback;
552 new_ag->jit = old_ag->jit;
553
554 Z_PTR_P(zv) = new_ag;
555 }
556 /* }}} */
557
compiler_globals_ctor(zend_compiler_globals * compiler_globals)558 static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{{ */
559 {
560 compiler_globals->compiled_filename = NULL;
561
562 compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable));
563 zend_hash_init_ex(compiler_globals->function_table, 1024, NULL, ZEND_FUNCTION_DTOR, 1, 0);
564 zend_hash_copy(compiler_globals->function_table, global_function_table, function_copy_ctor);
565
566 compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable));
567 zend_hash_init_ex(compiler_globals->class_table, 64, NULL, ZEND_CLASS_DTOR, 1, 0);
568 zend_hash_copy(compiler_globals->class_table, global_class_table, zend_class_add_ref);
569
570 zend_set_default_compile_time_values();
571
572 compiler_globals->auto_globals = (HashTable *) malloc(sizeof(HashTable));
573 zend_hash_init_ex(compiler_globals->auto_globals, 8, NULL, auto_global_dtor, 1, 0);
574 zend_hash_copy(compiler_globals->auto_globals, global_auto_globals_table, auto_global_copy_ctor);
575
576 compiler_globals->last_static_member = zend_hash_num_elements(compiler_globals->class_table);
577 if (compiler_globals->last_static_member) {
578 compiler_globals->static_members_table = calloc(compiler_globals->last_static_member, sizeof(zval*));
579 } else {
580 compiler_globals->static_members_table = NULL;
581 }
582 compiler_globals->script_encoding_list = NULL;
583 }
584 /* }}} */
585
compiler_globals_dtor(zend_compiler_globals * compiler_globals)586 static void compiler_globals_dtor(zend_compiler_globals *compiler_globals) /* {{{ */
587 {
588 if (compiler_globals->function_table != GLOBAL_FUNCTION_TABLE) {
589 zend_hash_destroy(compiler_globals->function_table);
590 free(compiler_globals->function_table);
591 }
592 if (compiler_globals->class_table != GLOBAL_CLASS_TABLE) {
593 zend_hash_destroy(compiler_globals->class_table);
594 free(compiler_globals->class_table);
595 }
596 if (compiler_globals->auto_globals != GLOBAL_AUTO_GLOBALS_TABLE) {
597 zend_hash_destroy(compiler_globals->auto_globals);
598 free(compiler_globals->auto_globals);
599 }
600 if (compiler_globals->static_members_table) {
601 free(compiler_globals->static_members_table);
602 }
603 if (compiler_globals->script_encoding_list) {
604 pefree((char*)compiler_globals->script_encoding_list, 1);
605 }
606 compiler_globals->last_static_member = 0;
607 }
608 /* }}} */
609
executor_globals_ctor(zend_executor_globals * executor_globals)610 static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{{ */
611 {
612 ZEND_TSRMLS_CACHE_UPDATE();
613
614 zend_startup_constants();
615 zend_copy_constants(executor_globals->zend_constants, GLOBAL_CONSTANTS_TABLE);
616 zend_init_rsrc_plist();
617 zend_init_exception_op();
618 zend_init_call_trampoline_op();
619 memset(&executor_globals->trampoline, 0, sizeof(zend_op_array));
620 executor_globals->lambda_count = 0;
621 ZVAL_UNDEF(&executor_globals->user_error_handler);
622 ZVAL_UNDEF(&executor_globals->user_exception_handler);
623 executor_globals->in_autoload = NULL;
624 executor_globals->current_execute_data = NULL;
625 executor_globals->current_module = NULL;
626 executor_globals->exit_status = 0;
627 #if XPFPA_HAVE_CW
628 executor_globals->saved_fpu_cw = 0;
629 #endif
630 executor_globals->saved_fpu_cw_ptr = NULL;
631 executor_globals->active = 0;
632 executor_globals->bailout = NULL;
633 executor_globals->error_handling = EH_NORMAL;
634 executor_globals->exception_class = NULL;
635 executor_globals->exception = NULL;
636 executor_globals->objects_store.object_buckets = NULL;
637 #ifdef ZEND_WIN32
638 zend_get_windows_version_info(&executor_globals->windows_version_info);
639 #endif
640 executor_globals->flags = EG_FLAGS_INITIAL;
641 }
642 /* }}} */
643
executor_globals_dtor(zend_executor_globals * executor_globals)644 static void executor_globals_dtor(zend_executor_globals *executor_globals) /* {{{ */
645 {
646 zend_ini_dtor(executor_globals->ini_directives);
647
648 if (&executor_globals->persistent_list != global_persistent_list) {
649 zend_destroy_rsrc_list(&executor_globals->persistent_list);
650 }
651 if (executor_globals->zend_constants != GLOBAL_CONSTANTS_TABLE) {
652 zend_hash_destroy(executor_globals->zend_constants);
653 free(executor_globals->zend_constants);
654 }
655 }
656 /* }}} */
657
zend_new_thread_end_handler(THREAD_T thread_id)658 static void zend_new_thread_end_handler(THREAD_T thread_id) /* {{{ */
659 {
660 if (zend_copy_ini_directives() == SUCCESS) {
661 zend_ini_refresh_caches(ZEND_INI_STAGE_STARTUP);
662 }
663 }
664 /* }}} */
665 #endif
666
667 #if defined(__FreeBSD__) || defined(__DragonFly__)
668 /* FreeBSD and DragonFly floating point precision fix */
669 #include <floatingpoint.h>
670 #endif
671
ini_scanner_globals_ctor(zend_ini_scanner_globals * scanner_globals_p)672 static void ini_scanner_globals_ctor(zend_ini_scanner_globals *scanner_globals_p) /* {{{ */
673 {
674 memset(scanner_globals_p, 0, sizeof(*scanner_globals_p));
675 }
676 /* }}} */
677
php_scanner_globals_ctor(zend_php_scanner_globals * scanner_globals_p)678 static void php_scanner_globals_ctor(zend_php_scanner_globals *scanner_globals_p) /* {{{ */
679 {
680 memset(scanner_globals_p, 0, sizeof(*scanner_globals_p));
681 }
682 /* }}} */
683
684 void zend_init_opcodes_handlers(void);
685
module_destructor_zval(zval * zv)686 static void module_destructor_zval(zval *zv) /* {{{ */
687 {
688 zend_module_entry *module = (zend_module_entry*)Z_PTR_P(zv);
689
690 module_destructor(module);
691 free(module);
692 }
693 /* }}} */
694
php_auto_globals_create_globals(zend_string * name)695 static zend_bool php_auto_globals_create_globals(zend_string *name) /* {{{ */
696 {
697 zval globals;
698
699 ZVAL_ARR(&globals, &EG(symbol_table));
700 Z_TYPE_INFO_P(&globals) = IS_ARRAY;
701 ZVAL_NEW_REF(&globals, &globals);
702 zend_hash_update(&EG(symbol_table), name, &globals);
703 return 0;
704 }
705 /* }}} */
706
zend_startup(zend_utility_functions * utility_functions,char ** extensions)707 int zend_startup(zend_utility_functions *utility_functions, char **extensions) /* {{{ */
708 {
709 #ifdef ZTS
710 zend_compiler_globals *compiler_globals;
711 zend_executor_globals *executor_globals;
712 extern ZEND_API ts_rsrc_id ini_scanner_globals_id;
713 extern ZEND_API ts_rsrc_id language_scanner_globals_id;
714 ZEND_TSRMLS_CACHE_UPDATE();
715 #else
716 extern zend_ini_scanner_globals ini_scanner_globals;
717 extern zend_php_scanner_globals language_scanner_globals;
718 #endif
719
720 #ifdef ZEND_WIN32
721 php_win32_cp_set_by_id(65001);
722 #endif
723
724 start_memory_manager();
725
726 virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would just slow it down for CGI */
727
728 #if defined(__FreeBSD__) || defined(__DragonFly__)
729 /* FreeBSD and DragonFly floating point precision fix */
730 fpsetmask(0);
731 #endif
732
733 zend_startup_strtod();
734 zend_startup_extensions_mechanism();
735
736 /* Set up utility functions and values */
737 zend_error_cb = utility_functions->error_function;
738 zend_printf = utility_functions->printf_function;
739 zend_write = (zend_write_func_t) utility_functions->write_function;
740 zend_fopen = utility_functions->fopen_function;
741 if (!zend_fopen) {
742 zend_fopen = zend_fopen_wrapper;
743 }
744 zend_stream_open_function = utility_functions->stream_open_function;
745 zend_message_dispatcher_p = utility_functions->message_handler;
746 zend_get_configuration_directive_p = utility_functions->get_configuration_directive;
747 zend_ticks_function = utility_functions->ticks_function;
748 zend_on_timeout = utility_functions->on_timeout;
749 zend_printf_to_smart_string = utility_functions->printf_to_smart_string_function;
750 zend_printf_to_smart_str = utility_functions->printf_to_smart_str_function;
751 zend_getenv = utility_functions->getenv_function;
752 zend_resolve_path = utility_functions->resolve_path_function;
753
754 zend_interrupt_function = NULL;
755
756 #if HAVE_DTRACE
757 /* build with dtrace support */
758 {
759 char *tmp = getenv("USE_ZEND_DTRACE");
760
761 if (tmp && zend_atoi(tmp, 0)) {
762 zend_dtrace_enabled = 1;
763 zend_compile_file = dtrace_compile_file;
764 zend_execute_ex = dtrace_execute_ex;
765 zend_execute_internal = dtrace_execute_internal;
766 } else {
767 zend_compile_file = compile_file;
768 zend_execute_ex = execute_ex;
769 zend_execute_internal = NULL;
770 }
771 }
772 #else
773 zend_compile_file = compile_file;
774 zend_execute_ex = execute_ex;
775 zend_execute_internal = NULL;
776 #endif /* HAVE_DTRACE */
777 zend_compile_string = compile_string;
778 zend_throw_exception_hook = NULL;
779
780 /* Set up the default garbage collection implementation. */
781 gc_collect_cycles = zend_gc_collect_cycles;
782
783 zend_init_opcodes_handlers();
784
785 /* set up version */
786 zend_version_info = strdup(ZEND_CORE_VERSION_INFO);
787 zend_version_info_length = sizeof(ZEND_CORE_VERSION_INFO) - 1;
788
789 GLOBAL_FUNCTION_TABLE = (HashTable *) malloc(sizeof(HashTable));
790 GLOBAL_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable));
791 GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable));
792 GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable));
793
794 zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 1024, NULL, ZEND_FUNCTION_DTOR, 1, 0);
795 zend_hash_init_ex(GLOBAL_CLASS_TABLE, 64, NULL, ZEND_CLASS_DTOR, 1, 0);
796 zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, auto_global_dtor, 1, 0);
797 zend_hash_init_ex(GLOBAL_CONSTANTS_TABLE, 128, NULL, ZEND_CONSTANT_DTOR, 1, 0);
798
799 zend_hash_init_ex(&module_registry, 32, NULL, module_destructor_zval, 1, 0);
800 zend_init_rsrc_list_dtors();
801
802 #ifdef ZTS
803 ts_allocate_id(&compiler_globals_id, sizeof(zend_compiler_globals), (ts_allocate_ctor) compiler_globals_ctor, (ts_allocate_dtor) compiler_globals_dtor);
804 ts_allocate_id(&executor_globals_id, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor);
805 ts_allocate_id(&language_scanner_globals_id, sizeof(zend_php_scanner_globals), (ts_allocate_ctor) php_scanner_globals_ctor, NULL);
806 ts_allocate_id(&ini_scanner_globals_id, sizeof(zend_ini_scanner_globals), (ts_allocate_ctor) ini_scanner_globals_ctor, NULL);
807 compiler_globals = ts_resource(compiler_globals_id);
808 executor_globals = ts_resource(executor_globals_id);
809
810 compiler_globals_dtor(compiler_globals);
811 compiler_globals->in_compilation = 0;
812 compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable));
813 compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable));
814
815 *compiler_globals->function_table = *GLOBAL_FUNCTION_TABLE;
816 *compiler_globals->class_table = *GLOBAL_CLASS_TABLE;
817 compiler_globals->auto_globals = GLOBAL_AUTO_GLOBALS_TABLE;
818
819 zend_hash_destroy(executor_globals->zend_constants);
820 *executor_globals->zend_constants = *GLOBAL_CONSTANTS_TABLE;
821 #else
822 ini_scanner_globals_ctor(&ini_scanner_globals);
823 php_scanner_globals_ctor(&language_scanner_globals);
824 zend_set_default_compile_time_values();
825 #ifdef ZEND_WIN32
826 zend_get_windows_version_info(&EG(windows_version_info));
827 #endif
828 #endif
829 EG(error_reporting) = E_ALL & ~E_NOTICE;
830
831 zend_interned_strings_init();
832 zend_startup_builtin_functions();
833 zend_register_standard_constants();
834 zend_register_auto_global(zend_string_init("GLOBALS", sizeof("GLOBALS") - 1, 1), 1, php_auto_globals_create_globals);
835
836 #ifndef ZTS
837 zend_init_rsrc_plist();
838 zend_init_exception_op();
839 zend_init_call_trampoline_op();
840 #endif
841
842 zend_ini_startup();
843
844 #ifdef ZEND_WIN32
845 /* Uses INI settings, so needs to be run after it. */
846 php_win32_cp_setup();
847 #endif
848
849 #ifdef ZTS
850 tsrm_set_new_thread_end_handler(zend_new_thread_end_handler);
851 tsrm_set_shutdown_handler(zend_interned_strings_dtor);
852 #endif
853
854 return SUCCESS;
855 }
856 /* }}} */
857
zend_register_standard_ini_entries(void)858 void zend_register_standard_ini_entries(void) /* {{{ */
859 {
860 int module_number = 0;
861
862 REGISTER_INI_ENTRIES();
863 }
864 /* }}} */
865
866 /* Unlink the global (r/o) copies of the class, function and constant tables,
867 * and use a fresh r/w copy for the startup thread
868 */
zend_post_startup(void)869 void zend_post_startup(void) /* {{{ */
870 {
871 #ifdef ZTS
872 zend_encoding **script_encoding_list;
873
874 zend_compiler_globals *compiler_globals = ts_resource(compiler_globals_id);
875 zend_executor_globals *executor_globals = ts_resource(executor_globals_id);
876
877 *GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table;
878 *GLOBAL_CLASS_TABLE = *compiler_globals->class_table;
879 *GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants;
880
881 short_tags_default = CG(short_tags);
882 compiler_options_default = CG(compiler_options);
883
884 zend_destroy_rsrc_list(&EG(persistent_list));
885 free(compiler_globals->function_table);
886 free(compiler_globals->class_table);
887 if ((script_encoding_list = (zend_encoding **)compiler_globals->script_encoding_list)) {
888 compiler_globals_ctor(compiler_globals);
889 compiler_globals->script_encoding_list = (const zend_encoding **)script_encoding_list;
890 } else {
891 compiler_globals_ctor(compiler_globals);
892 }
893 free(EG(zend_constants));
894
895 executor_globals_ctor(executor_globals);
896 global_persistent_list = &EG(persistent_list);
897 zend_copy_ini_directives();
898 #endif
899 }
900 /* }}} */
901
zend_shutdown(void)902 void zend_shutdown(void) /* {{{ */
903 {
904 zend_destroy_rsrc_list(&EG(persistent_list));
905 zend_destroy_modules();
906
907 virtual_cwd_deactivate();
908 virtual_cwd_shutdown();
909
910 zend_hash_destroy(GLOBAL_FUNCTION_TABLE);
911 zend_hash_destroy(GLOBAL_CLASS_TABLE);
912
913 zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE);
914 free(GLOBAL_AUTO_GLOBALS_TABLE);
915
916 zend_shutdown_extensions();
917 free(zend_version_info);
918
919 free(GLOBAL_FUNCTION_TABLE);
920 free(GLOBAL_CLASS_TABLE);
921
922 zend_hash_destroy(GLOBAL_CONSTANTS_TABLE);
923 free(GLOBAL_CONSTANTS_TABLE);
924 zend_shutdown_strtod();
925
926 #ifdef ZTS
927 GLOBAL_FUNCTION_TABLE = NULL;
928 GLOBAL_CLASS_TABLE = NULL;
929 GLOBAL_AUTO_GLOBALS_TABLE = NULL;
930 GLOBAL_CONSTANTS_TABLE = NULL;
931 #endif
932 zend_destroy_rsrc_list_dtors();
933 }
934 /* }}} */
935
zend_set_utility_values(zend_utility_values * utility_values)936 void zend_set_utility_values(zend_utility_values *utility_values) /* {{{ */
937 {
938 zend_uv = *utility_values;
939 zend_uv.import_use_extension_length = (uint32_t)strlen(zend_uv.import_use_extension);
940 }
941 /* }}} */
942
943 /* this should be compatible with the standard zenderror */
zenderror(const char * error)944 ZEND_COLD void zenderror(const char *error) /* {{{ */
945 {
946 CG(parse_error) = 0;
947
948 if (EG(exception)) {
949 /* An exception was thrown in the lexer, don't throw another in the parser. */
950 return;
951 }
952
953 zend_throw_exception(zend_ce_parse_error, error, 0);
954 }
955 /* }}} */
956
BEGIN_EXTERN_C()957 BEGIN_EXTERN_C()
958 ZEND_API ZEND_COLD void _zend_bailout(const char *filename, uint32_t lineno) /* {{{ */
959 {
960
961 if (!EG(bailout)) {
962 zend_output_debug_string(1, "%s(%d) : Bailed out without a bailout address!", filename, lineno);
963 exit(-1);
964 }
965 CG(unclean_shutdown) = 1;
966 CG(active_class_entry) = NULL;
967 CG(in_compilation) = 0;
968 EG(current_execute_data) = NULL;
969 LONGJMP(*EG(bailout), FAILURE);
970 }
971 /* }}} */
END_EXTERN_C()972 END_EXTERN_C()
973
974 ZEND_API void zend_append_version_info(const zend_extension *extension) /* {{{ */
975 {
976 char *new_info;
977 uint32_t new_info_length;
978
979 new_info_length = (uint32_t)(sizeof(" with v, , by \n")
980 + strlen(extension->name)
981 + strlen(extension->version)
982 + strlen(extension->copyright)
983 + strlen(extension->author));
984
985 new_info = (char *) malloc(new_info_length + 1);
986
987 snprintf(new_info, new_info_length, " with %s v%s, %s, by %s\n", extension->name, extension->version, extension->copyright, extension->author);
988
989 zend_version_info = (char *) realloc(zend_version_info, zend_version_info_length+new_info_length + 1);
990 strncat(zend_version_info, new_info, new_info_length);
991 zend_version_info_length += new_info_length;
992 free(new_info);
993 }
994 /* }}} */
995
get_zend_version(void)996 ZEND_API char *get_zend_version(void) /* {{{ */
997 {
998 return zend_version_info;
999 }
1000 /* }}} */
1001
zend_activate(void)1002 ZEND_API void zend_activate(void) /* {{{ */
1003 {
1004 #ifdef ZTS
1005 virtual_cwd_activate();
1006 #endif
1007 gc_reset();
1008 init_compiler();
1009 init_executor();
1010 startup_scanner();
1011 }
1012 /* }}} */
1013
zend_call_destructors(void)1014 void zend_call_destructors(void) /* {{{ */
1015 {
1016 zend_try {
1017 shutdown_destructors();
1018 } zend_end_try();
1019 }
1020 /* }}} */
1021
zend_deactivate(void)1022 ZEND_API void zend_deactivate(void) /* {{{ */
1023 {
1024 /* we're no longer executing anything */
1025 EG(current_execute_data) = NULL;
1026
1027 zend_try {
1028 shutdown_scanner();
1029 } zend_end_try();
1030
1031 /* shutdown_executor() takes care of its own bailout handling */
1032 shutdown_executor();
1033
1034 zend_try {
1035 zend_ini_deactivate();
1036 } zend_end_try();
1037
1038 zend_try {
1039 shutdown_compiler();
1040 } zend_end_try();
1041
1042 zend_destroy_rsrc_list(&EG(regular_list));
1043
1044 #if GC_BENCH
1045 fprintf(stderr, "GC Statistics\n");
1046 fprintf(stderr, "-------------\n");
1047 fprintf(stderr, "Runs: %d\n", GC_G(gc_runs));
1048 fprintf(stderr, "Collected: %d\n", GC_G(collected));
1049 fprintf(stderr, "Root buffer length: %d\n", GC_G(root_buf_length));
1050 fprintf(stderr, "Root buffer peak: %d\n\n", GC_G(root_buf_peak));
1051 fprintf(stderr, " Possible Remove from Marked\n");
1052 fprintf(stderr, " Root Buffered buffer grey\n");
1053 fprintf(stderr, " -------- -------- ----------- ------\n");
1054 fprintf(stderr, "ZVAL %8d %8d %9d %8d\n", GC_G(zval_possible_root), GC_G(zval_buffered), GC_G(zval_remove_from_buffer), GC_G(zval_marked_grey));
1055 #endif
1056 }
1057 /* }}} */
1058
BEGIN_EXTERN_C()1059 BEGIN_EXTERN_C()
1060 ZEND_API void zend_message_dispatcher(zend_long message, const void *data) /* {{{ */
1061 {
1062 if (zend_message_dispatcher_p) {
1063 zend_message_dispatcher_p(message, data);
1064 }
1065 }
1066 /* }}} */
END_EXTERN_C()1067 END_EXTERN_C()
1068
1069 ZEND_API zval *zend_get_configuration_directive(zend_string *name) /* {{{ */
1070 {
1071 if (zend_get_configuration_directive_p) {
1072 return zend_get_configuration_directive_p(name);
1073 } else {
1074 return NULL;
1075 }
1076 }
1077 /* }}} */
1078
1079 #define SAVE_STACK(stack) do { \
1080 if (CG(stack).top) { \
1081 memcpy(&stack, &CG(stack), sizeof(zend_stack)); \
1082 CG(stack).top = CG(stack).max = 0; \
1083 CG(stack).elements = NULL; \
1084 } else { \
1085 stack.top = 0; \
1086 } \
1087 } while (0)
1088
1089 #define RESTORE_STACK(stack) do { \
1090 if (stack.top) { \
1091 zend_stack_destroy(&CG(stack)); \
1092 memcpy(&CG(stack), &stack, sizeof(zend_stack)); \
1093 } \
1094 } while (0)
1095
1096 #if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
zend_error(int type,const char * format,...)1097 ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) /* {{{ */
1098 #else
1099 static ZEND_COLD void zend_error_va_list(int type, const char *format, va_list args)
1100 #endif
1101 {
1102 #if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
1103 va_list args;
1104 #endif
1105 va_list usr_copy;
1106 zval params[5];
1107 zval retval;
1108 const char *error_filename;
1109 uint32_t error_lineno = 0;
1110 zval orig_user_error_handler;
1111 zend_bool in_compilation;
1112 zend_class_entry *saved_class_entry;
1113 zend_stack loop_var_stack;
1114 zend_stack delayed_oplines_stack;
1115 zend_array *symbol_table;
1116 zend_class_entry *orig_fake_scope;
1117
1118 /* Report about uncaught exception in case of fatal errors */
1119 if (EG(exception)) {
1120 zend_execute_data *ex;
1121 const zend_op *opline;
1122
1123 switch (type) {
1124 case E_CORE_ERROR:
1125 case E_ERROR:
1126 case E_RECOVERABLE_ERROR:
1127 case E_PARSE:
1128 case E_COMPILE_ERROR:
1129 case E_USER_ERROR:
1130 ex = EG(current_execute_data);
1131 opline = NULL;
1132 while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
1133 ex = ex->prev_execute_data;
1134 }
1135 if (ex && ex->opline->opcode == ZEND_HANDLE_EXCEPTION &&
1136 EG(opline_before_exception)) {
1137 opline = EG(opline_before_exception);
1138 }
1139 zend_exception_error(EG(exception), E_WARNING);
1140 EG(exception) = NULL;
1141 if (opline) {
1142 ex->opline = opline;
1143 }
1144 break;
1145 default:
1146 break;
1147 }
1148 }
1149
1150 /* Obtain relevant filename and lineno */
1151 switch (type) {
1152 case E_CORE_ERROR:
1153 case E_CORE_WARNING:
1154 error_filename = NULL;
1155 error_lineno = 0;
1156 break;
1157 case E_PARSE:
1158 case E_COMPILE_ERROR:
1159 case E_COMPILE_WARNING:
1160 case E_ERROR:
1161 case E_NOTICE:
1162 case E_STRICT:
1163 case E_DEPRECATED:
1164 case E_WARNING:
1165 case E_USER_ERROR:
1166 case E_USER_WARNING:
1167 case E_USER_NOTICE:
1168 case E_USER_DEPRECATED:
1169 case E_RECOVERABLE_ERROR:
1170 if (zend_is_compiling()) {
1171 error_filename = ZSTR_VAL(zend_get_compiled_filename());
1172 error_lineno = zend_get_compiled_lineno();
1173 } else if (zend_is_executing()) {
1174 error_filename = zend_get_executed_filename();
1175 if (error_filename[0] == '[') { /* [no active file] */
1176 error_filename = NULL;
1177 error_lineno = 0;
1178 } else {
1179 error_lineno = zend_get_executed_lineno();
1180 }
1181 } else {
1182 error_filename = NULL;
1183 error_lineno = 0;
1184 }
1185 break;
1186 default:
1187 error_filename = NULL;
1188 error_lineno = 0;
1189 break;
1190 }
1191 if (!error_filename) {
1192 error_filename = "Unknown";
1193 }
1194
1195 #ifdef HAVE_DTRACE
1196 if (DTRACE_ERROR_ENABLED()) {
1197 char *dtrace_error_buffer;
1198 #if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
1199 va_start(args, format);
1200 #endif
1201 zend_vspprintf(&dtrace_error_buffer, 0, format, args);
1202 DTRACE_ERROR(dtrace_error_buffer, (char *)error_filename, error_lineno);
1203 efree(dtrace_error_buffer);
1204 #if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
1205 va_end(args);
1206 #endif
1207 }
1208 #endif /* HAVE_DTRACE */
1209
1210 #if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
1211 va_start(args, format);
1212 #endif
1213
1214 /* if we don't have a user defined error handler */
1215 if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF
1216 || !(EG(user_error_handler_error_reporting) & type)
1217 || EG(error_handling) != EH_NORMAL) {
1218 zend_error_cb(type, error_filename, error_lineno, format, args);
1219 } else switch (type) {
1220 case E_ERROR:
1221 case E_PARSE:
1222 case E_CORE_ERROR:
1223 case E_CORE_WARNING:
1224 case E_COMPILE_ERROR:
1225 case E_COMPILE_WARNING:
1226 /* The error may not be safe to handle in user-space */
1227 zend_error_cb(type, error_filename, error_lineno, format, args);
1228 break;
1229 default:
1230 /* Handle the error in user space */
1231 va_copy(usr_copy, args);
1232 ZVAL_STR(¶ms[1], zend_vstrpprintf(0, format, usr_copy));
1233 va_end(usr_copy);
1234
1235 ZVAL_LONG(¶ms[0], type);
1236
1237 if (error_filename) {
1238 ZVAL_STRING(¶ms[2], error_filename);
1239 } else {
1240 ZVAL_NULL(¶ms[2]);
1241 }
1242
1243 ZVAL_LONG(¶ms[3], error_lineno);
1244
1245 symbol_table = zend_rebuild_symbol_table();
1246
1247 /* during shutdown the symbol table table can be still null */
1248 if (!symbol_table) {
1249 ZVAL_NULL(¶ms[4]);
1250 } else {
1251 ZVAL_ARR(¶ms[4], zend_array_dup(symbol_table));
1252 }
1253
1254 ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler));
1255 ZVAL_UNDEF(&EG(user_error_handler));
1256
1257 /* User error handler may include() additinal PHP files.
1258 * If an error was generated during comilation PHP will compile
1259 * such scripts recursivly, but some CG() variables may be
1260 * inconsistent. */
1261
1262 in_compilation = CG(in_compilation);
1263 if (in_compilation) {
1264 saved_class_entry = CG(active_class_entry);
1265 CG(active_class_entry) = NULL;
1266 SAVE_STACK(loop_var_stack);
1267 SAVE_STACK(delayed_oplines_stack);
1268 CG(in_compilation) = 0;
1269 }
1270
1271 orig_fake_scope = EG(fake_scope);
1272 EG(fake_scope) = NULL;
1273
1274 if (call_user_function_ex(CG(function_table), NULL, &orig_user_error_handler, &retval, 5, params, 1, NULL) == SUCCESS) {
1275 if (Z_TYPE(retval) != IS_UNDEF) {
1276 if (Z_TYPE(retval) == IS_FALSE) {
1277 zend_error_cb(type, error_filename, error_lineno, format, args);
1278 }
1279 zval_ptr_dtor(&retval);
1280 }
1281 } else if (!EG(exception)) {
1282 /* The user error handler failed, use built-in error handler */
1283 zend_error_cb(type, error_filename, error_lineno, format, args);
1284 }
1285
1286 EG(fake_scope) = orig_fake_scope;
1287
1288 if (in_compilation) {
1289 CG(active_class_entry) = saved_class_entry;
1290 RESTORE_STACK(loop_var_stack);
1291 RESTORE_STACK(delayed_oplines_stack);
1292 CG(in_compilation) = 1;
1293 }
1294
1295 zval_ptr_dtor(¶ms[4]);
1296 zval_ptr_dtor(¶ms[3]);
1297 zval_ptr_dtor(¶ms[2]);
1298 zval_ptr_dtor(¶ms[1]);
1299 zval_ptr_dtor(¶ms[0]);
1300
1301 if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF) {
1302 ZVAL_COPY_VALUE(&EG(user_error_handler), &orig_user_error_handler);
1303 } else {
1304 zval_ptr_dtor(&orig_user_error_handler);
1305 }
1306 break;
1307 }
1308
1309 #if !defined(HAVE_NORETURN) || defined(HAVE_NORETURN_ALIAS)
1310 va_end(args);
1311 #endif
1312
1313 if (type == E_PARSE) {
1314 /* eval() errors do not affect exit_status */
1315 if (!(EG(current_execute_data) &&
1316 EG(current_execute_data)->func &&
1317 ZEND_USER_CODE(EG(current_execute_data)->func->type) &&
1318 EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL &&
1319 EG(current_execute_data)->opline->extended_value == ZEND_EVAL)) {
1320 EG(exit_status) = 255;
1321 }
1322 }
1323 }
1324 /* }}} */
1325
1326 #ifdef HAVE_NORETURN
1327 # ifdef HAVE_NORETURN_ALIAS
1328 ZEND_COLD void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((alias("zend_error"),noreturn));
1329 # else
zend_error(int type,const char * format,...)1330 ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) /* {{{ */
1331 {
1332 va_list va;
1333
1334 va_start(va, format);
1335 zend_error_va_list(type, format, va);
1336 va_end(va);
1337 }
1338
zend_error_noreturn(int type,const char * format,...)1339 ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ...)
1340 {
1341 va_list va;
1342
1343 va_start(va, format);
1344 zend_error_va_list(type, format, va);
1345 va_end(va);
1346 }
1347 /* }}} */
1348 # endif
1349 #endif
1350
zend_throw_error(zend_class_entry * exception_ce,const char * format,...)1351 ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format, ...) /* {{{ */
1352 {
1353 va_list va;
1354 char *message = NULL;
1355
1356 if (exception_ce) {
1357 if (!instanceof_function(exception_ce, zend_ce_error)) {
1358 zend_error(E_NOTICE, "Error exceptions must be derived from Error");
1359 exception_ce = zend_ce_error;
1360 }
1361 } else {
1362 exception_ce = zend_ce_error;
1363 }
1364
1365 va_start(va, format);
1366 zend_vspprintf(&message, 0, format, va);
1367
1368 //TODO: we can't convert compile-time errors to exceptions yet???
1369 if (EG(current_execute_data) && !CG(in_compilation)) {
1370 zend_throw_exception(exception_ce, message, 0);
1371 } else {
1372 zend_error(E_ERROR, "%s", message);
1373 }
1374
1375 efree(message);
1376 va_end(va);
1377 }
1378 /* }}} */
1379
zend_type_error(const char * format,...)1380 ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) /* {{{ */
1381 {
1382 va_list va;
1383 char *message = NULL;
1384
1385 va_start(va, format);
1386 zend_vspprintf(&message, 0, format, va);
1387 zend_throw_exception(zend_ce_type_error, message, 0);
1388 efree(message);
1389 va_end(va);
1390 } /* }}} */
1391
zend_internal_type_error(zend_bool throw_exception,const char * format,...)1392 ZEND_API ZEND_COLD void zend_internal_type_error(zend_bool throw_exception, const char *format, ...) /* {{{ */
1393 {
1394 va_list va;
1395 char *message = NULL;
1396
1397 va_start(va, format);
1398 zend_vspprintf(&message, 0, format, va);
1399 if (throw_exception) {
1400 zend_throw_exception(zend_ce_type_error, message, 0);
1401 } else {
1402 zend_error(E_WARNING, "%s", message);
1403 }
1404 efree(message);
1405
1406 va_end(va);
1407 } /* }}} */
1408
zend_internal_argument_count_error(zend_bool throw_exception,const char * format,...)1409 ZEND_API ZEND_COLD void zend_internal_argument_count_error(zend_bool throw_exception, const char *format, ...) /* {{{ */
1410 {
1411 va_list va;
1412 char *message = NULL;
1413
1414 va_start(va, format);
1415 zend_vspprintf(&message, 0, format, va);
1416 if (throw_exception) {
1417 zend_throw_exception(zend_ce_argument_count_error, message, 0);
1418 } else {
1419 zend_error(E_WARNING, "%s", message);
1420 }
1421 efree(message);
1422
1423 va_end(va);
1424 } /* }}} */
1425
zend_output_debug_string(zend_bool trigger_break,const char * format,...)1426 ZEND_API ZEND_COLD void zend_output_debug_string(zend_bool trigger_break, const char *format, ...) /* {{{ */
1427 {
1428 #if ZEND_DEBUG
1429 va_list args;
1430
1431 va_start(args, format);
1432 # ifdef ZEND_WIN32
1433 {
1434 char output_buf[1024];
1435
1436 vsnprintf(output_buf, 1024, format, args);
1437 OutputDebugString(output_buf);
1438 OutputDebugString("\n");
1439 if (trigger_break && IsDebuggerPresent()) {
1440 DebugBreak();
1441 }
1442 }
1443 # else
1444 vfprintf(stderr, format, args);
1445 fprintf(stderr, "\n");
1446 # endif
1447 va_end(args);
1448 #endif
1449 }
1450 /* }}} */
1451
zend_try_exception_handler()1452 ZEND_API void zend_try_exception_handler() /* {{{ */
1453 {
1454 if (EG(exception)) {
1455 if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
1456 zval orig_user_exception_handler;
1457 zval params[1], retval2;
1458 zend_object *old_exception;
1459 old_exception = EG(exception);
1460 EG(exception) = NULL;
1461 ZVAL_OBJ(¶ms[0], old_exception);
1462 ZVAL_COPY_VALUE(&orig_user_exception_handler, &EG(user_exception_handler));
1463
1464 if (call_user_function_ex(CG(function_table), NULL, &orig_user_exception_handler, &retval2, 1, params, 1, NULL) == SUCCESS) {
1465 zval_ptr_dtor(&retval2);
1466 if (EG(exception)) {
1467 OBJ_RELEASE(EG(exception));
1468 EG(exception) = NULL;
1469 }
1470 OBJ_RELEASE(old_exception);
1471 } else {
1472 EG(exception) = old_exception;
1473 }
1474 }
1475 }
1476 } /* }}} */
1477
zend_execute_scripts(int type,zval * retval,int file_count,...)1478 ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...) /* {{{ */
1479 {
1480 va_list files;
1481 int i;
1482 zend_file_handle *file_handle;
1483 zend_op_array *op_array;
1484
1485 va_start(files, file_count);
1486 for (i = 0; i < file_count; i++) {
1487 file_handle = va_arg(files, zend_file_handle *);
1488 if (!file_handle) {
1489 continue;
1490 }
1491
1492 op_array = zend_compile_file(file_handle, type);
1493 if (file_handle->opened_path) {
1494 zend_hash_add_empty_element(&EG(included_files), file_handle->opened_path);
1495 }
1496 zend_destroy_file_handle(file_handle);
1497 if (op_array) {
1498 zend_execute(op_array, retval);
1499 zend_exception_restore();
1500 zend_try_exception_handler();
1501 if (EG(exception)) {
1502 zend_exception_error(EG(exception), E_ERROR);
1503 }
1504 destroy_op_array(op_array);
1505 efree_size(op_array, sizeof(zend_op_array));
1506 } else if (type==ZEND_REQUIRE) {
1507 va_end(files);
1508 return FAILURE;
1509 }
1510 }
1511 va_end(files);
1512
1513 return SUCCESS;
1514 }
1515 /* }}} */
1516
1517 #define COMPILED_STRING_DESCRIPTION_FORMAT "%s(%d) : %s"
1518
zend_make_compiled_string_description(const char * name)1519 ZEND_API char *zend_make_compiled_string_description(const char *name) /* {{{ */
1520 {
1521 const char *cur_filename;
1522 int cur_lineno;
1523 char *compiled_string_description;
1524
1525 if (zend_is_compiling()) {
1526 cur_filename = ZSTR_VAL(zend_get_compiled_filename());
1527 cur_lineno = zend_get_compiled_lineno();
1528 } else if (zend_is_executing()) {
1529 cur_filename = zend_get_executed_filename();
1530 cur_lineno = zend_get_executed_lineno();
1531 } else {
1532 cur_filename = "Unknown";
1533 cur_lineno = 0;
1534 }
1535
1536 zend_spprintf(&compiled_string_description, 0, COMPILED_STRING_DESCRIPTION_FORMAT, cur_filename, cur_lineno, name);
1537 return compiled_string_description;
1538 }
1539 /* }}} */
1540
free_estring(char ** str_p)1541 void free_estring(char **str_p) /* {{{ */
1542 {
1543 efree(*str_p);
1544 }
1545 /* }}} */
1546
1547 /*
1548 * Local variables:
1549 * tab-width: 4
1550 * c-basic-offset: 4
1551 * indent-tabs-mode: t
1552 * End:
1553 * vim600: sw=4 ts=4 fdm=marker
1554 * vim<600: sw=4 ts=4
1555 */
1556