1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Andi Gutmans <andi@php.net> |
14 | Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
15 | Zeev Suraski <zeev@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* {{{ includes */
20
21 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
22
23 #include "php.h"
24 #include <stdio.h>
25 #include <fcntl.h>
26 #ifdef PHP_WIN32
27 #include "win32/time.h"
28 #include "win32/signal.h"
29 #include "win32/php_win32_globals.h"
30 #include "win32/winutil.h"
31 #include <process.h>
32 #endif
33 #ifdef HAVE_SYS_TIME_H
34 #include <sys/time.h>
35 #endif
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39
40 #include <signal.h>
41 #include <locale.h>
42 #include "zend.h"
43 #include "zend_types.h"
44 #include "zend_extensions.h"
45 #include "php_ini.h"
46 #include "php_globals.h"
47 #include "php_main.h"
48 #include "php_syslog.h"
49 #include "fopen_wrappers.h"
50 #include "ext/standard/php_standard.h"
51 #include "ext/date/php_date.h"
52 #include "ext/random/php_random_csprng.h"
53 #include "ext/random/php_random_zend_utils.h"
54 #include "php_variables.h"
55 #include "ext/standard/credits.h"
56 #ifdef PHP_WIN32
57 #include <io.h>
58 #include "win32/php_registry.h"
59 #include "ext/standard/flock_compat.h"
60 #endif
61 #include "php_syslog.h"
62 #include "Zend/zend_exceptions.h"
63
64 #if PHP_SIGCHILD
65 #include <sys/types.h>
66 #include <sys/wait.h>
67 #endif
68
69 #include "zend_compile.h"
70 #include "zend_execute.h"
71 #include "zend_highlight.h"
72 #include "zend_extensions.h"
73 #include "zend_ini.h"
74 #include "zend_dtrace.h"
75 #include "zend_observer.h"
76 #include "zend_system_id.h"
77
78 #include "php_content_types.h"
79 #include "php_ticks.h"
80 #include "php_streams.h"
81 #include "php_open_temporary_file.h"
82
83 #include "SAPI.h"
84 #include "rfc1867.h"
85
86 #include "main_arginfo.h"
87 /* }}} */
88
89 PHPAPI int (*php_register_internal_extensions_func)(void) = php_register_internal_extensions;
90
91 #ifndef ZTS
92 php_core_globals core_globals;
93 #else
94 PHPAPI int core_globals_id;
95 PHPAPI size_t core_globals_offset;
96 #endif
97
98 #define SAFE_FILENAME(f) ((f)?(f):"-")
99
php_version(void)100 PHPAPI const char *php_version(void)
101 {
102 return PHP_VERSION;
103 }
104
php_version_id(void)105 PHPAPI unsigned int php_version_id(void)
106 {
107 return PHP_VERSION_ID;
108 }
109
php_get_version(sapi_module_struct * sapi_module)110 PHPAPI char *php_get_version(sapi_module_struct *sapi_module)
111 {
112 char *version_info;
113 spprintf(&version_info, 0, "PHP %s (%s) (built: %s %s) (%s)\nCopyright (c) The PHP Group\n%s%s",
114 PHP_VERSION, sapi_module->name, __DATE__, __TIME__,
115 #ifdef ZTS
116 "ZTS"
117 #else
118 "NTS"
119 #endif
120 #ifdef PHP_BUILD_COMPILER
121 " " PHP_BUILD_COMPILER
122 #endif
123 #ifdef PHP_BUILD_ARCH
124 " " PHP_BUILD_ARCH
125 #endif
126 #if ZEND_DEBUG
127 " DEBUG"
128 #endif
129 #ifdef HAVE_GCOV
130 " GCOV"
131 #endif
132 ,
133 #ifdef PHP_BUILD_PROVIDER
134 "Built by " PHP_BUILD_PROVIDER "\n"
135 #else
136 ""
137 #endif
138 ,
139 get_zend_version()
140 );
141 return version_info;
142 }
143
php_print_version(sapi_module_struct * sapi_module)144 PHPAPI void php_print_version(sapi_module_struct *sapi_module)
145 {
146 char *version_info = php_get_version(sapi_module);
147 php_printf("%s", version_info);
148 efree(version_info);
149 }
150
151 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnSetFacility)152 static PHP_INI_MH(OnSetFacility)
153 {
154 const zend_string *facility = new_value;
155
156 #ifdef LOG_AUTH
157 if (zend_string_equals_literal(facility, "LOG_AUTH") || zend_string_equals_literal(facility, "auth")
158 || zend_string_equals_literal(facility, "security")) {
159 PG(syslog_facility) = LOG_AUTH;
160 return SUCCESS;
161 }
162 #endif
163 #ifdef LOG_AUTHPRIV
164 if (zend_string_equals_literal(facility, "LOG_AUTHPRIV") || zend_string_equals_literal(facility, "authpriv")) {
165 PG(syslog_facility) = LOG_AUTHPRIV;
166 return SUCCESS;
167 }
168 #endif
169 #ifdef LOG_CRON
170 if (zend_string_equals_literal(facility, "LOG_CRON") || zend_string_equals_literal(facility, "cron")) {
171 PG(syslog_facility) = LOG_CRON;
172 return SUCCESS;
173 }
174 #endif
175 #ifdef LOG_DAEMON
176 if (zend_string_equals_literal(facility, "LOG_DAEMON") || zend_string_equals_literal(facility, "daemon")) {
177 PG(syslog_facility) = LOG_DAEMON;
178 return SUCCESS;
179 }
180 #endif
181 #ifdef LOG_FTP
182 if (zend_string_equals_literal(facility, "LOG_FTP") || zend_string_equals_literal(facility, "ftp")) {
183 PG(syslog_facility) = LOG_FTP;
184 return SUCCESS;
185 }
186 #endif
187 #ifdef LOG_KERN
188 if (zend_string_equals_literal(facility, "LOG_KERN") || zend_string_equals_literal(facility, "kern")) {
189 PG(syslog_facility) = LOG_KERN;
190 return SUCCESS;
191 }
192 #endif
193 #ifdef LOG_LPR
194 if (zend_string_equals_literal(facility, "LOG_LPR") || zend_string_equals_literal(facility, "lpr")) {
195 PG(syslog_facility) = LOG_LPR;
196 return SUCCESS;
197 }
198 #endif
199 #ifdef LOG_MAIL
200 if (zend_string_equals_literal(facility, "LOG_MAIL") || zend_string_equals_literal(facility, "mail")) {
201 PG(syslog_facility) = LOG_MAIL;
202 return SUCCESS;
203 }
204 #endif
205 #ifdef LOG_INTERNAL_MARK
206 if (zend_string_equals_literal(facility, "LOG_INTERNAL_MARK") || zend_string_equals_literal(facility, "mark")) {
207 PG(syslog_facility) = LOG_INTERNAL_MARK;
208 return SUCCESS;
209 }
210 #endif
211 #ifdef LOG_NEWS
212 if (zend_string_equals_literal(facility, "LOG_NEWS") || zend_string_equals_literal(facility, "news")) {
213 PG(syslog_facility) = LOG_NEWS;
214 return SUCCESS;
215 }
216 #endif
217 #ifdef LOG_SYSLOG
218 if (zend_string_equals_literal(facility, "LOG_SYSLOG") || zend_string_equals_literal(facility, "syslog")) {
219 PG(syslog_facility) = LOG_SYSLOG;
220 return SUCCESS;
221 }
222 #endif
223 #ifdef LOG_USER
224 if (zend_string_equals(facility, ZSTR_KNOWN(ZEND_STR_USER)) || zend_string_equals_literal(facility, "LOG_USER")) {
225 PG(syslog_facility) = LOG_USER;
226 return SUCCESS;
227 }
228 #endif
229 #ifdef LOG_UUCP
230 if (zend_string_equals_literal(facility, "LOG_UUCP") || zend_string_equals_literal(facility, "uucp")) {
231 PG(syslog_facility) = LOG_UUCP;
232 return SUCCESS;
233 }
234 #endif
235 #ifdef LOG_LOCAL0
236 if (zend_string_equals_literal(facility, "LOG_LOCAL0") || zend_string_equals_literal(facility, "local0")) {
237 PG(syslog_facility) = LOG_LOCAL0;
238 return SUCCESS;
239 }
240 #endif
241 #ifdef LOG_LOCAL1
242 if (zend_string_equals_literal(facility, "LOG_LOCAL1") || zend_string_equals_literal(facility, "local1")) {
243 PG(syslog_facility) = LOG_LOCAL1;
244 return SUCCESS;
245 }
246 #endif
247 #ifdef LOG_LOCAL2
248 if (zend_string_equals_literal(facility, "LOG_LOCAL2") || zend_string_equals_literal(facility, "local2")) {
249 PG(syslog_facility) = LOG_LOCAL2;
250 return SUCCESS;
251 }
252 #endif
253 #ifdef LOG_LOCAL3
254 if (zend_string_equals_literal(facility, "LOG_LOCAL3") || zend_string_equals_literal(facility, "local3")) {
255 PG(syslog_facility) = LOG_LOCAL3;
256 return SUCCESS;
257 }
258 #endif
259 #ifdef LOG_LOCAL4
260 if (zend_string_equals_literal(facility, "LOG_LOCAL4") || zend_string_equals_literal(facility, "local4")) {
261 PG(syslog_facility) = LOG_LOCAL4;
262 return SUCCESS;
263 }
264 #endif
265 #ifdef LOG_LOCAL5
266 if (zend_string_equals_literal(facility, "LOG_LOCAL5") || zend_string_equals_literal(facility, "local5")) {
267 PG(syslog_facility) = LOG_LOCAL5;
268 return SUCCESS;
269 }
270 #endif
271 #ifdef LOG_LOCAL6
272 if (zend_string_equals_literal(facility, "LOG_LOCAL6") || zend_string_equals_literal(facility, "local6")) {
273 PG(syslog_facility) = LOG_LOCAL6;
274 return SUCCESS;
275 }
276 #endif
277 #ifdef LOG_LOCAL7
278 if (zend_string_equals_literal(facility, "LOG_LOCAL7") || zend_string_equals_literal(facility, "local7")) {
279 PG(syslog_facility) = LOG_LOCAL7;
280 return SUCCESS;
281 }
282 #endif
283
284 return FAILURE;
285 }
286 /* }}} */
287
288 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnSetPrecision)289 static PHP_INI_MH(OnSetPrecision)
290 {
291 zend_long i = ZEND_ATOL(ZSTR_VAL(new_value));
292 if (i >= -1) {
293 EG(precision) = i;
294 return SUCCESS;
295 } else {
296 return FAILURE;
297 }
298 }
299 /* }}} */
300
301 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnSetSerializePrecision)302 static PHP_INI_MH(OnSetSerializePrecision)
303 {
304 zend_long i = ZEND_ATOL(ZSTR_VAL(new_value));
305 if (i >= -1) {
306 PG(serialize_precision) = i;
307 return SUCCESS;
308 } else {
309 return FAILURE;
310 }
311 }
312 /* }}} */
313
314 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnChangeMemoryLimit)315 static PHP_INI_MH(OnChangeMemoryLimit)
316 {
317 size_t value;
318 if (new_value) {
319 value = zend_ini_parse_uquantity_warn(new_value, entry->name);
320 } else {
321 value = Z_L(1)<<30; /* effectively, no limit */
322 }
323 if (zend_set_memory_limit(value) == FAILURE) {
324 /* When the memory limit is reset to the original level during deactivation, we may be
325 * using more memory than the original limit while shutdown is still in progress.
326 * Ignore a failure for now, and set the memory limit when the memory manager has been
327 * shut down and the minimal amount of memory is used. */
328 if (stage != ZEND_INI_STAGE_DEACTIVATE) {
329 zend_error(E_WARNING, "Failed to set memory limit to %zd bytes (Current memory usage is %zd bytes)", value, zend_memory_usage(true));
330 return FAILURE;
331 }
332 }
333 PG(memory_limit) = value;
334 return SUCCESS;
335 }
336 /* }}} */
337
338 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnSetLogFilter)339 static PHP_INI_MH(OnSetLogFilter)
340 {
341 const zend_string *filter = new_value;
342
343 if (zend_string_equals_literal(filter, "all")) {
344 PG(syslog_filter) = PHP_SYSLOG_FILTER_ALL;
345 return SUCCESS;
346 }
347 if (zend_string_equals_literal(filter, "no-ctrl")) {
348 PG(syslog_filter) = PHP_SYSLOG_FILTER_NO_CTRL;
349 return SUCCESS;
350 }
351 if (zend_string_equals_literal(filter, "ascii")) {
352 PG(syslog_filter) = PHP_SYSLOG_FILTER_ASCII;
353 return SUCCESS;
354 }
355 if (zend_string_equals_literal(filter, "raw")) {
356 PG(syslog_filter) = PHP_SYSLOG_FILTER_RAW;
357 return SUCCESS;
358 }
359
360 return FAILURE;
361 }
362 /* }}} */
363
364 /* {{{ php_disable_classes */
php_disable_classes(void)365 static void php_disable_classes(void)
366 {
367 char *s = NULL, *e;
368
369 if (!*(INI_STR("disable_classes"))) {
370 return;
371 }
372
373 e = PG(disable_classes) = strdup(INI_STR("disable_classes"));
374
375 while (*e) {
376 switch (*e) {
377 case ' ':
378 case ',':
379 if (s) {
380 *e = '\0';
381 zend_disable_class(s, e-s);
382 s = NULL;
383 }
384 break;
385 default:
386 if (!s) {
387 s = e;
388 }
389 break;
390 }
391 e++;
392 }
393 if (s) {
394 zend_disable_class(s, e-s);
395 }
396 }
397 /* }}} */
398
399 /* {{{ php_binary_init */
php_binary_init(void)400 static void php_binary_init(void)
401 {
402 char *binary_location = NULL;
403 #ifdef PHP_WIN32
404 binary_location = (char *)pemalloc(MAXPATHLEN, 1);
405 if (GetModuleFileName(0, binary_location, MAXPATHLEN) == 0) {
406 pefree(binary_location, 1);
407 binary_location = NULL;
408 }
409 #else
410 if (sapi_module.executable_location) {
411 binary_location = (char *)pemalloc(MAXPATHLEN, 1);
412 if (!strchr(sapi_module.executable_location, '/')) {
413 char *envpath, *path;
414 bool found = false;
415
416 if ((envpath = getenv("PATH")) != NULL) {
417 char *search_dir, search_path[MAXPATHLEN];
418 char *last = NULL;
419 zend_stat_t s = {0};
420
421 path = estrdup(envpath);
422 search_dir = php_strtok_r(path, ":", &last);
423
424 while (search_dir) {
425 snprintf(search_path, MAXPATHLEN, "%s/%s", search_dir, sapi_module.executable_location);
426 if (VCWD_REALPATH(search_path, binary_location) && !VCWD_ACCESS(binary_location, X_OK) && VCWD_STAT(binary_location, &s) == 0 && S_ISREG(s.st_mode)) {
427 found = true;
428 break;
429 }
430 search_dir = php_strtok_r(NULL, ":", &last);
431 }
432 efree(path);
433 }
434 if (!found) {
435 pefree(binary_location, 1);
436 binary_location = NULL;
437 }
438 } else if (!VCWD_REALPATH(sapi_module.executable_location, binary_location) || VCWD_ACCESS(binary_location, X_OK)) {
439 pefree(binary_location, 1);
440 binary_location = NULL;
441 }
442 }
443 #endif
444 PG(php_binary) = binary_location;
445 }
446 /* }}} */
447
448 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateTimeout)449 static PHP_INI_MH(OnUpdateTimeout)
450 {
451 if (stage==PHP_INI_STAGE_STARTUP) {
452 /* Don't set a timeout on startup, only per-request */
453 EG(timeout_seconds) = ZEND_ATOL(ZSTR_VAL(new_value));
454 return SUCCESS;
455 }
456 zend_unset_timeout();
457 EG(timeout_seconds) = ZEND_ATOL(ZSTR_VAL(new_value));
458 if (stage != PHP_INI_STAGE_DEACTIVATE) {
459 /*
460 * If we're restoring INI values, we shouldn't reset the timer.
461 * Otherwise, the timer is active when PHP is idle, such as the
462 * CLI web server or CGI. Running a script will re-activate
463 * the timeout, so it's not needed to do so at script end.
464 */
465 zend_set_timeout(EG(timeout_seconds), 0);
466 }
467 return SUCCESS;
468 }
469 /* }}} */
470
471 /* {{{ php_get_display_errors_mode() helper function */
php_get_display_errors_mode(zend_string * value)472 static uint8_t php_get_display_errors_mode(zend_string *value)
473 {
474 if (!value) {
475 return PHP_DISPLAY_ERRORS_STDOUT;
476 }
477
478 if (zend_string_equals_literal_ci(value, "on")) {
479 return PHP_DISPLAY_ERRORS_STDOUT;
480 }
481 if (zend_string_equals_literal_ci(value, "yes")) {
482 return PHP_DISPLAY_ERRORS_STDOUT;
483 }
484
485 if (zend_string_equals_literal_ci(value, "true")) {
486 return PHP_DISPLAY_ERRORS_STDOUT;
487 }
488 if (zend_string_equals_literal_ci(value, "stderr")) {
489 return PHP_DISPLAY_ERRORS_STDERR;
490 }
491 if (zend_string_equals_literal_ci(value, "stdout")) {
492 return PHP_DISPLAY_ERRORS_STDOUT;
493 }
494
495 uint8_t mode = ZEND_ATOL(ZSTR_VAL(value));
496 if (mode && mode != PHP_DISPLAY_ERRORS_STDOUT && mode != PHP_DISPLAY_ERRORS_STDERR) {
497 return PHP_DISPLAY_ERRORS_STDOUT;
498 }
499
500 return mode;
501 }
502 /* }}} */
503
504 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateDisplayErrors)505 static PHP_INI_MH(OnUpdateDisplayErrors)
506 {
507 PG(display_errors) = php_get_display_errors_mode(new_value);
508
509 return SUCCESS;
510 }
511 /* }}} */
512
513 /* {{{ PHP_INI_DISP */
PHP_INI_DISP(display_errors_mode)514 static PHP_INI_DISP(display_errors_mode)
515 {
516 uint8_t mode;
517 bool cgi_or_cli;
518 zend_string *temporary_value;
519
520 if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
521 temporary_value = (ini_entry->orig_value ? ini_entry->orig_value : NULL );
522 } else if (ini_entry->value) {
523 temporary_value = ini_entry->value;
524 } else {
525 temporary_value = NULL;
526 }
527
528 mode = php_get_display_errors_mode(temporary_value);
529
530 /* Display 'On' for other SAPIs instead of STDOUT or STDERR */
531 cgi_or_cli = (!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg"));
532
533 switch (mode) {
534 case PHP_DISPLAY_ERRORS_STDERR:
535 if (cgi_or_cli ) {
536 PUTS("STDERR");
537 } else {
538 PUTS("On");
539 }
540 break;
541
542 case PHP_DISPLAY_ERRORS_STDOUT:
543 if (cgi_or_cli ) {
544 PUTS("STDOUT");
545 } else {
546 PUTS("On");
547 }
548 break;
549
550 default:
551 PUTS("Off");
552 break;
553 }
554 }
555 /* }}} */
556
php_get_internal_encoding(void)557 PHPAPI const char *php_get_internal_encoding(void) {
558 if (PG(internal_encoding) && PG(internal_encoding)[0]) {
559 return PG(internal_encoding);
560 } else if (SG(default_charset) && SG(default_charset)[0]) {
561 return SG(default_charset);
562 }
563 return "UTF-8";
564 }
565
php_get_input_encoding(void)566 PHPAPI const char *php_get_input_encoding(void) {
567 if (PG(input_encoding) && PG(input_encoding)[0]) {
568 return PG(input_encoding);
569 } else if (SG(default_charset) && SG(default_charset)[0]) {
570 return SG(default_charset);
571 }
572 return "UTF-8";
573 }
574
php_get_output_encoding(void)575 PHPAPI const char *php_get_output_encoding(void) {
576 if (PG(output_encoding) && PG(output_encoding)[0]) {
577 return PG(output_encoding);
578 } else if (SG(default_charset) && SG(default_charset)[0]) {
579 return SG(default_charset);
580 }
581 return "UTF-8";
582 }
583
584 PHPAPI void (*php_internal_encoding_changed)(void) = NULL;
585
586 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateDefaultCharset)587 static PHP_INI_MH(OnUpdateDefaultCharset)
588 {
589 if (memchr(ZSTR_VAL(new_value), '\0', ZSTR_LEN(new_value))
590 || strpbrk(ZSTR_VAL(new_value), "\r\n")) {
591 return FAILURE;
592 }
593 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
594 if (php_internal_encoding_changed) {
595 php_internal_encoding_changed();
596 }
597 if (new_value) {
598 #ifdef PHP_WIN32
599 php_win32_cp_do_update(ZSTR_VAL(new_value));
600 #endif
601 }
602 return SUCCESS;
603 }
604 /* }}} */
605
606 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateDefaultMimeTye)607 static PHP_INI_MH(OnUpdateDefaultMimeTye)
608 {
609 if (memchr(ZSTR_VAL(new_value), '\0', ZSTR_LEN(new_value))
610 || strpbrk(ZSTR_VAL(new_value), "\r\n")) {
611 return FAILURE;
612 }
613 return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
614 }
615 /* }}} */
616
617 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateInternalEncoding)618 static PHP_INI_MH(OnUpdateInternalEncoding)
619 {
620 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
621 if (php_internal_encoding_changed) {
622 php_internal_encoding_changed();
623 }
624 if (new_value) {
625 #ifdef PHP_WIN32
626 php_win32_cp_do_update(ZSTR_VAL(new_value));
627 #endif
628 }
629 return SUCCESS;
630 }
631 /* }}} */
632
633 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateInputEncoding)634 static PHP_INI_MH(OnUpdateInputEncoding)
635 {
636 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
637 if (php_internal_encoding_changed) {
638 php_internal_encoding_changed();
639 }
640 if (new_value) {
641 #ifdef PHP_WIN32
642 php_win32_cp_do_update(NULL);
643 #endif
644 }
645 return SUCCESS;
646 }
647 /* }}} */
648
649 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateOutputEncoding)650 static PHP_INI_MH(OnUpdateOutputEncoding)
651 {
652 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
653 if (php_internal_encoding_changed) {
654 php_internal_encoding_changed();
655 }
656 if (new_value) {
657 #ifdef PHP_WIN32
658 php_win32_cp_do_update(NULL);
659 #endif
660 }
661 return SUCCESS;
662 }
663 /* }}} */
664
665 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateErrorLog)666 static PHP_INI_MH(OnUpdateErrorLog)
667 {
668 /* Only do the safemode/open_basedir check at runtime */
669 if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) &&
670 new_value && zend_string_equals_literal(new_value, "syslog")) {
671 if (PG(open_basedir) && php_check_open_basedir(ZSTR_VAL(new_value))) {
672 return FAILURE;
673 }
674 }
675 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
676 return SUCCESS;
677 }
678 /* }}} */
679
680 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnUpdateMailLog)681 static PHP_INI_MH(OnUpdateMailLog)
682 {
683 /* Only do the safemode/open_basedir check at runtime */
684 if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && new_value) {
685 if (PG(open_basedir) && php_check_open_basedir(ZSTR_VAL(new_value))) {
686 return FAILURE;
687 }
688 }
689 OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
690 return SUCCESS;
691 }
692 /* }}} */
693
694 /* {{{ PHP_INI_MH */
PHP_INI_MH(OnChangeMailForceExtra)695 static PHP_INI_MH(OnChangeMailForceExtra)
696 {
697 /* Check that INI setting does not have any nul bytes */
698 if (new_value && ZSTR_LEN(new_value) != strlen(ZSTR_VAL(new_value))) {
699 /* TODO Emit warning? */
700 return FAILURE;
701 }
702 /* Don't allow changing it in htaccess */
703 if (stage == PHP_INI_STAGE_HTACCESS) {
704 return FAILURE;
705 }
706 return SUCCESS;
707 }
708 /* }}} */
709
710 /* defined in browscap.c */
711 PHP_INI_MH(OnChangeBrowscap);
712
713
714 /* Need to be read from the environment (?):
715 * PHP_AUTO_PREPEND_FILE
716 * PHP_AUTO_APPEND_FILE
717 * PHP_DOCUMENT_ROOT
718 * PHP_USER_DIR
719 * PHP_INCLUDE_PATH
720 */
721
722 /* Windows use the internal mail */
723 #if defined(PHP_WIN32)
724 # define DEFAULT_SENDMAIL_PATH NULL
725 #else
726 # define DEFAULT_SENDMAIL_PATH PHP_PROG_SENDMAIL " -t -i"
727 #endif
728
729 /* {{{ PHP_INI */
730 PHP_INI_BEGIN()
731 PHP_INI_ENTRY_EX("highlight.comment", HL_COMMENT_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
732 PHP_INI_ENTRY_EX("highlight.default", HL_DEFAULT_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
733 PHP_INI_ENTRY_EX("highlight.html", HL_HTML_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
734 PHP_INI_ENTRY_EX("highlight.keyword", HL_KEYWORD_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
735 PHP_INI_ENTRY_EX("highlight.string", HL_STRING_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
736
737 STD_PHP_INI_ENTRY_EX("display_errors", "1", PHP_INI_ALL, OnUpdateDisplayErrors, display_errors, php_core_globals, core_globals, display_errors_mode)
738 STD_PHP_INI_BOOLEAN("display_startup_errors", "1", PHP_INI_ALL, OnUpdateBool, display_startup_errors, php_core_globals, core_globals)
739 STD_PHP_INI_BOOLEAN("enable_dl", "1", PHP_INI_SYSTEM, OnUpdateBool, enable_dl, php_core_globals, core_globals)
740 STD_PHP_INI_BOOLEAN("expose_php", "1", PHP_INI_SYSTEM, OnUpdateBool, expose_php, php_core_globals, core_globals)
741 STD_PHP_INI_ENTRY("docref_root", "", PHP_INI_ALL, OnUpdateString, docref_root, php_core_globals, core_globals)
742 STD_PHP_INI_ENTRY("docref_ext", "", PHP_INI_ALL, OnUpdateString, docref_ext, php_core_globals, core_globals)
743 STD_PHP_INI_BOOLEAN("html_errors", "1", PHP_INI_ALL, OnUpdateBool, html_errors, php_core_globals, core_globals)
744 STD_PHP_INI_BOOLEAN("xmlrpc_errors", "0", PHP_INI_SYSTEM, OnUpdateBool, xmlrpc_errors, php_core_globals, core_globals)
745 STD_PHP_INI_ENTRY("xmlrpc_error_number", "0", PHP_INI_ALL, OnUpdateLong, xmlrpc_error_number, php_core_globals, core_globals)
746 STD_PHP_INI_ENTRY("max_input_time", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, max_input_time, php_core_globals, core_globals)
747 STD_PHP_INI_BOOLEAN("ignore_user_abort", "0", PHP_INI_ALL, OnUpdateBool, ignore_user_abort, php_core_globals, core_globals)
748 STD_PHP_INI_BOOLEAN("implicit_flush", "0", PHP_INI_ALL, OnUpdateBool, implicit_flush, php_core_globals, core_globals)
749 STD_PHP_INI_BOOLEAN("log_errors", "0", PHP_INI_ALL, OnUpdateBool, log_errors, php_core_globals, core_globals)
750 STD_PHP_INI_BOOLEAN("ignore_repeated_errors", "0", PHP_INI_ALL, OnUpdateBool, ignore_repeated_errors, php_core_globals, core_globals)
751 STD_PHP_INI_BOOLEAN("ignore_repeated_source", "0", PHP_INI_ALL, OnUpdateBool, ignore_repeated_source, php_core_globals, core_globals)
752 STD_PHP_INI_BOOLEAN("report_memleaks", "1", PHP_INI_ALL, OnUpdateBool, report_memleaks, php_core_globals, core_globals)
753 STD_PHP_INI_BOOLEAN("report_zend_debug", "0", PHP_INI_ALL, OnUpdateBool, report_zend_debug, php_core_globals, core_globals)
754 STD_PHP_INI_ENTRY("output_buffering", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateLong, output_buffering, php_core_globals, core_globals)
755 STD_PHP_INI_ENTRY("output_handler", NULL, PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateString, output_handler, php_core_globals, core_globals)
756 STD_PHP_INI_BOOLEAN("register_argc_argv", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, register_argc_argv, php_core_globals, core_globals)
757 STD_PHP_INI_BOOLEAN("auto_globals_jit", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, auto_globals_jit, php_core_globals, core_globals)
758 STD_PHP_INI_BOOLEAN("short_open_tag", DEFAULT_SHORT_OPEN_TAG, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, short_tags, zend_compiler_globals, compiler_globals)
759
760 STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateString, unserialize_callback_func, php_core_globals, core_globals)
761 STD_PHP_INI_ENTRY("serialize_precision", "-1", PHP_INI_ALL, OnSetSerializePrecision, serialize_precision, php_core_globals, core_globals)
762 STD_PHP_INI_ENTRY("arg_separator.output", "&", PHP_INI_ALL, OnUpdateStringUnempty, arg_separator.output, php_core_globals, core_globals)
763 STD_PHP_INI_ENTRY("arg_separator.input", "&", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateStringUnempty, arg_separator.input, php_core_globals, core_globals)
764
765 STD_PHP_INI_ENTRY("auto_append_file", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, auto_append_file, php_core_globals, core_globals)
766 STD_PHP_INI_ENTRY("auto_prepend_file", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, auto_prepend_file, php_core_globals, core_globals)
767 STD_PHP_INI_ENTRY("doc_root", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, doc_root, php_core_globals, core_globals)
768 STD_PHP_INI_ENTRY("default_charset", PHP_DEFAULT_CHARSET, PHP_INI_ALL, OnUpdateDefaultCharset, default_charset, sapi_globals_struct, sapi_globals)
769 STD_PHP_INI_ENTRY("default_mimetype", SAPI_DEFAULT_MIMETYPE, PHP_INI_ALL, OnUpdateDefaultMimeTye, default_mimetype, sapi_globals_struct, sapi_globals)
770 STD_PHP_INI_ENTRY("internal_encoding", NULL, PHP_INI_ALL, OnUpdateInternalEncoding, internal_encoding, php_core_globals, core_globals)
771 STD_PHP_INI_ENTRY("input_encoding", NULL, PHP_INI_ALL, OnUpdateInputEncoding, input_encoding, php_core_globals, core_globals)
772 STD_PHP_INI_ENTRY("output_encoding", NULL, PHP_INI_ALL, OnUpdateOutputEncoding, output_encoding, php_core_globals, core_globals)
773 STD_PHP_INI_ENTRY("error_log", NULL, PHP_INI_ALL, OnUpdateErrorLog, error_log, php_core_globals, core_globals)
774 STD_PHP_INI_ENTRY("error_log_mode", "0644", PHP_INI_ALL, OnUpdateLong, error_log_mode, php_core_globals, core_globals)
775 STD_PHP_INI_ENTRY("extension_dir", PHP_EXTENSION_DIR, PHP_INI_SYSTEM, OnUpdateStringUnempty, extension_dir, php_core_globals, core_globals)
776 STD_PHP_INI_ENTRY("sys_temp_dir", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, sys_temp_dir, php_core_globals, core_globals)
777 STD_PHP_INI_ENTRY("include_path", PHP_INCLUDE_PATH, PHP_INI_ALL, OnUpdateStringUnempty, include_path, php_core_globals, core_globals)
778 PHP_INI_ENTRY("max_execution_time", "30", PHP_INI_ALL, OnUpdateTimeout)
779 STD_PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir, open_basedir, php_core_globals, core_globals)
780
781 STD_PHP_INI_BOOLEAN("file_uploads", "1", PHP_INI_SYSTEM, OnUpdateBool, file_uploads, php_core_globals, core_globals)
782 STD_PHP_INI_ENTRY("upload_max_filesize", "2M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, upload_max_filesize, php_core_globals, core_globals)
783 STD_PHP_INI_ENTRY("post_max_size", "8M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, post_max_size, sapi_globals_struct,sapi_globals)
784 STD_PHP_INI_ENTRY("upload_tmp_dir", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, upload_tmp_dir, php_core_globals, core_globals)
785 STD_PHP_INI_ENTRY("max_input_nesting_level", "64", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLongGEZero, max_input_nesting_level, php_core_globals, core_globals)
786 STD_PHP_INI_ENTRY("max_input_vars", "1000", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLongGEZero, max_input_vars, php_core_globals, core_globals)
787
788 STD_PHP_INI_ENTRY("user_dir", NULL, PHP_INI_SYSTEM, OnUpdateString, user_dir, php_core_globals, core_globals)
789 STD_PHP_INI_ENTRY("variables_order", "EGPCS", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateStringUnempty, variables_order, php_core_globals, core_globals)
790 STD_PHP_INI_ENTRY("request_order", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, request_order, php_core_globals, core_globals)
791
792 STD_PHP_INI_ENTRY("error_append_string", NULL, PHP_INI_ALL, OnUpdateString, error_append_string, php_core_globals, core_globals)
793 STD_PHP_INI_ENTRY("error_prepend_string", NULL, PHP_INI_ALL, OnUpdateString, error_prepend_string, php_core_globals, core_globals)
794
795 PHP_INI_ENTRY("SMTP", "localhost",PHP_INI_ALL, NULL)
796 PHP_INI_ENTRY("smtp_port", "25", PHP_INI_ALL, NULL)
797 STD_PHP_INI_BOOLEAN("mail.add_x_header", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_x_header, php_core_globals, core_globals)
798 STD_PHP_INI_BOOLEAN("mail.mixed_lf_and_crlf", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_mixed_lf_and_crlf, php_core_globals, core_globals)
799 STD_PHP_INI_ENTRY("mail.log", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateMailLog, mail_log, php_core_globals, core_globals)
800 PHP_INI_ENTRY("browscap", NULL, PHP_INI_SYSTEM, OnChangeBrowscap)
801 PHP_INI_ENTRY("memory_limit", "128M", PHP_INI_ALL, OnChangeMemoryLimit)
802 PHP_INI_ENTRY("precision", "14", PHP_INI_ALL, OnSetPrecision)
803 PHP_INI_ENTRY("sendmail_from", NULL, PHP_INI_ALL, NULL)
804 PHP_INI_ENTRY("sendmail_path", DEFAULT_SENDMAIL_PATH, PHP_INI_SYSTEM, NULL)
805 PHP_INI_ENTRY("mail.force_extra_parameters",NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnChangeMailForceExtra)
806 PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL)
807 PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL)
808 PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
809 PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
810
811 STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
812 STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
813 STD_PHP_INI_BOOLEAN("enable_post_data_reading", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, enable_post_data_reading, php_core_globals, core_globals)
814
815 STD_PHP_INI_ENTRY("realpath_cache_size", "4096K", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
816 STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_ttl, virtual_cwd_globals, cwd_globals)
817
818 STD_PHP_INI_ENTRY("user_ini.filename", ".user.ini", PHP_INI_SYSTEM, OnUpdateString, user_ini_filename, php_core_globals, core_globals)
819 STD_PHP_INI_ENTRY("user_ini.cache_ttl", "300", PHP_INI_SYSTEM, OnUpdateLong, user_ini_cache_ttl, php_core_globals, core_globals)
820 STD_PHP_INI_ENTRY("hard_timeout", "2", PHP_INI_SYSTEM, OnUpdateLong, hard_timeout, zend_executor_globals, executor_globals)
821 #ifdef PHP_WIN32
822 STD_PHP_INI_BOOLEAN("windows.show_crt_warning", "0", PHP_INI_ALL, OnUpdateBool, windows_show_crt_warning, php_core_globals, core_globals)
823 #endif
824 STD_PHP_INI_ENTRY("syslog.facility", "LOG_USER", PHP_INI_SYSTEM, OnSetFacility, syslog_facility, php_core_globals, core_globals)
825 STD_PHP_INI_ENTRY("syslog.ident", "php", PHP_INI_SYSTEM, OnUpdateString, syslog_ident, php_core_globals, core_globals)
826 STD_PHP_INI_ENTRY("syslog.filter", "no-ctrl", PHP_INI_ALL, OnSetLogFilter, syslog_filter, php_core_globals, core_globals)
827 PHP_INI_END()
828 /* }}} */
829
830 /* True globals (no need for thread safety */
831 /* But don't make them a single int bitfield */
832 static bool module_initialized = false;
833 static bool module_startup = true;
834 static bool module_shutdown = false;
835
836 /* {{{ php_during_module_startup */
php_during_module_startup(void)837 PHPAPI bool php_during_module_startup(void)
838 {
839 return module_startup;
840 }
841 /* }}} */
842
843 /* {{{ php_during_module_shutdown */
php_during_module_shutdown(void)844 PHPAPI bool php_during_module_shutdown(void)
845 {
846 return module_shutdown;
847 }
848 /* }}} */
849
850 /* {{{ php_get_module_initialized */
php_get_module_initialized(void)851 PHPAPI bool php_get_module_initialized(void)
852 {
853 return module_initialized;
854 }
855 /* }}} */
856
857 /* {{{ php_log_err_with_severity */
php_log_err_with_severity(const char * log_message,int syslog_type_int)858 PHPAPI ZEND_COLD void php_log_err_with_severity(const char *log_message, int syslog_type_int)
859 {
860 int fd = -1;
861 time_t error_time;
862
863 if (PG(in_error_log)) {
864 /* prevent recursive invocation */
865 return;
866 }
867 PG(in_error_log) = 1;
868
869 /* Try to use the specified logging location. */
870 if (PG(error_log) != NULL) {
871 int error_log_mode;
872
873 #ifdef HAVE_SYSLOG_H
874 if (!strcmp(PG(error_log), "syslog")) {
875 php_syslog(syslog_type_int, "%s", log_message);
876 PG(in_error_log) = 0;
877 return;
878 }
879 #endif
880
881 error_log_mode = 0644;
882
883 if (PG(error_log_mode) > 0 && PG(error_log_mode) <= 0777) {
884 error_log_mode = PG(error_log_mode);
885 }
886
887 fd = VCWD_OPEN_MODE(PG(error_log), O_CREAT | O_APPEND | O_WRONLY, error_log_mode);
888 if (fd != -1) {
889 char *tmp;
890 size_t len;
891 zend_string *error_time_str;
892
893 time(&error_time);
894 #ifdef ZTS
895 if (!php_during_module_startup()) {
896 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 1);
897 } else {
898 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 0);
899 }
900 #else
901 error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 1);
902 #endif
903 len = spprintf(&tmp, 0, "[%s] %s%s", ZSTR_VAL(error_time_str), log_message, PHP_EOL);
904 #ifdef PHP_WIN32
905 php_flock(fd, LOCK_EX);
906 /* XXX should eventually write in a loop if len > UINT_MAX */
907 php_ignore_value(write(fd, tmp, (unsigned)len));
908 php_flock(fd, LOCK_UN);
909 #else
910 php_ignore_value(write(fd, tmp, len));
911 #endif
912 efree(tmp);
913 zend_string_free(error_time_str);
914 close(fd);
915 PG(in_error_log) = 0;
916 return;
917 }
918 }
919
920 /* Otherwise fall back to the default logging location, if we have one */
921
922 if (sapi_module.log_message) {
923 sapi_module.log_message(log_message, syslog_type_int);
924 }
925 PG(in_error_log) = 0;
926 }
927 /* }}} */
928
929 /* {{{ php_write
930 wrapper for modules to use PHPWRITE */
php_write(void * buf,size_t size)931 PHPAPI size_t php_write(void *buf, size_t size)
932 {
933 return PHPWRITE(buf, size);
934 }
935 /* }}} */
936
937 /* {{{ php_printf */
php_printf(const char * format,...)938 PHPAPI size_t php_printf(const char *format, ...)
939 {
940 va_list args;
941 size_t ret;
942 char *buffer;
943 size_t size;
944
945 va_start(args, format);
946 size = vspprintf(&buffer, 0, format, args);
947 ret = PHPWRITE(buffer, size);
948 efree(buffer);
949 va_end(args);
950
951 return ret;
952 }
953 /* }}} */
954
955 /* {{{ php_printf_unchecked */
php_printf_unchecked(const char * format,...)956 PHPAPI size_t php_printf_unchecked(const char *format, ...)
957 {
958 va_list args;
959 size_t ret;
960 char *buffer;
961 size_t size;
962
963 va_start(args, format);
964 size = vspprintf(&buffer, 0, format, args);
965 ret = PHPWRITE(buffer, size);
966 efree(buffer);
967 va_end(args);
968
969 return ret;
970 }
971 /* }}} */
972
escape_html(const char * buffer,size_t buffer_len)973 static zend_string *escape_html(const char *buffer, size_t buffer_len) {
974 zend_string *result = php_escape_html_entities_ex(
975 (const unsigned char *) buffer, buffer_len, 0, ENT_COMPAT,
976 /* charset_hint */ NULL, /* double_encode */ 1, /* quiet */ 1);
977 if (!result || ZSTR_LEN(result) == 0) {
978 /* Retry with substituting invalid chars on fail. */
979 result = php_escape_html_entities_ex(
980 (const unsigned char *) buffer, buffer_len, 0, ENT_COMPAT | ENT_HTML_SUBSTITUTE_ERRORS,
981 /* charset_hint */ NULL, /* double_encode */ 1, /* quiet */ 1);
982 }
983 return result;
984 }
985
986 /* {{{ php_verror */
987 /* php_verror is called from php_error_docref<n> functions.
988 * Its purpose is to unify error messages and automatically generate clickable
989 * html error messages if corresponding ini setting (html_errors) is activated.
990 * See: CODING_STANDARDS.md for details.
991 */
php_verror(const char * docref,const char * params,int type,const char * format,va_list args)992 PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int type, const char *format, va_list args)
993 {
994 zend_string *replace_origin = NULL;
995 char *docref_buf = NULL, *target = NULL;
996 char *docref_target = "", *docref_root = "";
997 char *p;
998 const char *space = "";
999 const char *class_name = "";
1000 const char *function;
1001 int origin_len;
1002 char *origin;
1003 zend_string *message;
1004 int is_function = 0;
1005
1006 /* get error text into buffer and escape for html if necessary */
1007 zend_string *buffer = vstrpprintf(0, format, args);
1008
1009 if (PG(html_errors)) {
1010 zend_string *replace_buffer = escape_html(ZSTR_VAL(buffer), ZSTR_LEN(buffer));
1011 zend_string_free(buffer);
1012
1013 if (replace_buffer) {
1014 buffer = replace_buffer;
1015 } else {
1016 buffer = zend_empty_string;
1017 }
1018 }
1019
1020 /* which function caused the problem if any at all */
1021 if (php_during_module_startup()) {
1022 function = "PHP Startup";
1023 } else if (php_during_module_shutdown()) {
1024 function = "PHP Shutdown";
1025 } else if (PG(during_request_startup)) {
1026 function = "PHP Request Startup";
1027 } else if (EG(current_execute_data) &&
1028 EG(current_execute_data)->func &&
1029 ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
1030 EG(current_execute_data)->opline &&
1031 EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL
1032 ) {
1033 switch (EG(current_execute_data)->opline->extended_value) {
1034 case ZEND_EVAL:
1035 function = "eval";
1036 is_function = 1;
1037 break;
1038 case ZEND_INCLUDE:
1039 function = "include";
1040 is_function = 1;
1041 break;
1042 case ZEND_INCLUDE_ONCE:
1043 function = "include_once";
1044 is_function = 1;
1045 break;
1046 case ZEND_REQUIRE:
1047 function = "require";
1048 is_function = 1;
1049 break;
1050 case ZEND_REQUIRE_ONCE:
1051 function = "require_once";
1052 is_function = 1;
1053 break;
1054 default:
1055 function = "Unknown";
1056 }
1057 } else if ((function = get_active_function_name()) && strlen(function)) {
1058 is_function = 1;
1059 class_name = get_active_class_name(&space);
1060 } else if (EG(flags) & EG_FLAGS_IN_SHUTDOWN) {
1061 function = "PHP Request Shutdown";
1062 } else {
1063 function = "Unknown";
1064 }
1065
1066 /* if we still have memory then format the origin */
1067 if (is_function) {
1068 origin_len = (int)spprintf(&origin, 0, "%s%s%s(%s)", class_name, space, function, params);
1069 } else {
1070 origin_len = (int)spprintf(&origin, 0, "%s", function);
1071 }
1072
1073 if (PG(html_errors)) {
1074 replace_origin = escape_html(origin, origin_len);
1075 efree(origin);
1076 origin = ZSTR_VAL(replace_origin);
1077 }
1078
1079 /* origin and buffer available, so let's come up with the error message */
1080 if (docref && docref[0] == '#') {
1081 docref_target = strchr(docref, '#');
1082 docref = NULL;
1083 }
1084
1085 /* no docref given but function is known (the default) */
1086 if (!docref && is_function) {
1087 int doclen;
1088 while (*function == '_') {
1089 function++;
1090 }
1091 if (space[0] == '\0') {
1092 doclen = (int)spprintf(&docref_buf, 0, "function.%s", function);
1093 } else {
1094 doclen = (int)spprintf(&docref_buf, 0, "%s.%s", class_name, function);
1095 }
1096 while((p = strchr(docref_buf, '_')) != NULL) {
1097 *p = '-';
1098 }
1099 zend_str_tolower(docref_buf, doclen);
1100 docref = docref_buf;
1101 }
1102
1103 /* we have a docref for a function AND
1104 * - we show errors in html mode AND
1105 * - the user wants to see the links
1106 */
1107 if (docref && is_function && PG(html_errors) && strlen(PG(docref_root))) {
1108 if (strncmp(docref, "http://", 7)) {
1109 /* We don't have 'http://' so we use docref_root */
1110
1111 char *ref; /* temp copy for duplicated docref */
1112
1113 docref_root = PG(docref_root);
1114
1115 ref = estrdup(docref);
1116 if (docref_buf) {
1117 efree(docref_buf);
1118 }
1119 docref_buf = ref;
1120 /* strip of the target if any */
1121 p = strrchr(ref, '#');
1122 if (p) {
1123 target = estrdup(p);
1124 if (target) {
1125 docref_target = target;
1126 *p = '\0';
1127 }
1128 }
1129 /* add the extension if it is set in ini */
1130 if (PG(docref_ext) && strlen(PG(docref_ext))) {
1131 spprintf(&docref_buf, 0, "%s%s", ref, PG(docref_ext));
1132 efree(ref);
1133 }
1134 docref = docref_buf;
1135 }
1136 /* display html formatted or only show the additional links */
1137 if (PG(html_errors)) {
1138 message = zend_strpprintf_unchecked(0, "%s [<a href='%s%s%s'>%s</a>]: %S", origin, docref_root, docref, docref_target, docref, buffer);
1139 } else {
1140 message = zend_strpprintf_unchecked(0, "%s [%s%s%s]: %S", origin, docref_root, docref, docref_target, buffer);
1141 }
1142 if (target) {
1143 efree(target);
1144 }
1145 } else {
1146 message = zend_strpprintf_unchecked(0, "%s: %S", origin, buffer);
1147 }
1148 if (replace_origin) {
1149 zend_string_free(replace_origin);
1150 } else {
1151 efree(origin);
1152 }
1153 if (docref_buf) {
1154 efree(docref_buf);
1155 }
1156
1157 zend_string_free(buffer);
1158
1159 zend_error_zstr(type, message);
1160 zend_string_release(message);
1161 }
1162 /* }}} */
1163
1164 /* {{{ php_error_docref */
1165 /* Generate an error which links to docref or the php.net documentation if docref is NULL */
1166 #define php_error_docref_impl(docref, type, format) do {\
1167 va_list args; \
1168 va_start(args, format); \
1169 php_verror(docref, "", type, format, args); \
1170 va_end(args); \
1171 } while (0)
1172
php_error_docref(const char * docref,int type,const char * format,...)1173 PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format, ...)
1174 {
1175 php_error_docref_impl(docref, type, format);
1176 }
1177
php_error_docref_unchecked(const char * docref,int type,const char * format,...)1178 PHPAPI ZEND_COLD void php_error_docref_unchecked(const char *docref, int type, const char *format, ...)
1179 {
1180 php_error_docref_impl(docref, type, format);
1181 }
1182 /* }}} */
1183
1184 /* {{{ php_error_docref1 */
1185 /* See: CODING_STANDARDS.md for details. */
php_error_docref1(const char * docref,const char * param1,int type,const char * format,...)1186 PHPAPI ZEND_COLD void php_error_docref1(const char *docref, const char *param1, int type, const char *format, ...)
1187 {
1188 va_list args;
1189
1190 va_start(args, format);
1191 php_verror(docref, param1, type, format, args);
1192 va_end(args);
1193 }
1194 /* }}} */
1195
1196 /* {{{ php_error_docref2 */
1197 /* See: CODING_STANDARDS.md for details. */
php_error_docref2(const char * docref,const char * param1,const char * param2,int type,const char * format,...)1198 PHPAPI ZEND_COLD void php_error_docref2(const char *docref, const char *param1, const char *param2, int type, const char *format, ...)
1199 {
1200 char *params;
1201 va_list args;
1202
1203 spprintf(¶ms, 0, "%s,%s", param1, param2);
1204 va_start(args, format);
1205 php_verror(docref, params ? params : "...", type, format, args);
1206 va_end(args);
1207 if (params) {
1208 efree(params);
1209 }
1210 }
1211 /* }}} */
1212
1213 #ifdef PHP_WIN32
php_win32_docref1_from_error(DWORD error,const char * param1)1214 PHPAPI ZEND_COLD void php_win32_docref1_from_error(DWORD error, const char *param1) {
1215 char *buf = php_win32_error_to_msg(error);
1216 size_t buf_len;
1217
1218 buf_len = strlen(buf);
1219 if (buf_len >= 2) {
1220 buf[buf_len - 1] = '\0';
1221 buf[buf_len - 2] = '\0';
1222 }
1223 php_error_docref1(NULL, param1, E_WARNING, "%s (code: %lu)", buf, error);
1224 php_win32_error_msg_free(buf);
1225 }
1226
php_win32_docref2_from_error(DWORD error,const char * param1,const char * param2)1227 PHPAPI ZEND_COLD void php_win32_docref2_from_error(DWORD error, const char *param1, const char *param2) {
1228 char *buf = php_win32_error_to_msg(error);
1229 php_error_docref2(NULL, param1, param2, E_WARNING, "%s (code: %lu)", buf, error);
1230 php_win32_error_msg_free(buf);
1231 }
1232 #endif
1233
1234 /* {{{ php_html_puts */
php_html_puts(const char * str,size_t size)1235 PHPAPI void php_html_puts(const char *str, size_t size)
1236 {
1237 zend_html_puts(str, size);
1238 }
1239 /* }}} */
1240
clear_last_error(void)1241 static void clear_last_error(void) {
1242 if (PG(last_error_message)) {
1243 zend_string_release(PG(last_error_message));
1244 PG(last_error_message) = NULL;
1245 }
1246 if (PG(last_error_file)) {
1247 zend_string_release(PG(last_error_file));
1248 PG(last_error_file) = NULL;
1249 }
1250 }
1251
1252 #if ZEND_DEBUG
1253 /* {{{ report_zend_debug_error_notify_cb */
report_zend_debug_error_notify_cb(int type,zend_string * error_filename,uint32_t error_lineno,zend_string * message)1254 static void report_zend_debug_error_notify_cb(int type, zend_string *error_filename, uint32_t error_lineno, zend_string *message)
1255 {
1256 if (PG(report_zend_debug)) {
1257 bool trigger_break;
1258
1259 switch (type) {
1260 case E_ERROR:
1261 case E_CORE_ERROR:
1262 case E_COMPILE_ERROR:
1263 case E_USER_ERROR:
1264 trigger_break=1;
1265 break;
1266 default:
1267 trigger_break=0;
1268 break;
1269 }
1270
1271 zend_output_debug_string(trigger_break, "%s(%" PRIu32 ") : %s", ZSTR_VAL(error_filename), error_lineno, ZSTR_VAL(message));
1272 }
1273 }
1274 /* }}} */
1275 #endif
1276
1277 /* {{{ php_error_cb
1278 extended error handling function */
php_error_cb(int orig_type,zend_string * error_filename,const uint32_t error_lineno,zend_string * message)1279 static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message)
1280 {
1281 bool display;
1282 int type = orig_type & E_ALL;
1283
1284 /* check for repeated errors to be ignored */
1285 if (PG(ignore_repeated_errors) && PG(last_error_message)) {
1286 /* no check for PG(last_error_file) is needed since it cannot
1287 * be NULL if PG(last_error_message) is not NULL */
1288 if (!zend_string_equals(PG(last_error_message), message)
1289 || (!PG(ignore_repeated_source)
1290 && ((PG(last_error_lineno) != (int)error_lineno)
1291 || !zend_string_equals(PG(last_error_file), error_filename)))) {
1292 display = 1;
1293 } else {
1294 display = 0;
1295 }
1296 } else {
1297 display = 1;
1298 }
1299
1300 /* according to error handling mode, throw exception or show it */
1301 if (EG(error_handling) == EH_THROW) {
1302 switch (type) {
1303 case E_WARNING:
1304 case E_CORE_WARNING:
1305 case E_COMPILE_WARNING:
1306 case E_USER_WARNING:
1307 /* throw an exception if we are in EH_THROW mode and the type is warning.
1308 * fatal errors are real errors and cannot be made exceptions.
1309 * exclude deprecated for the sake of BC to old damaged code.
1310 * notices are no errors and are not treated as such like E_WARNINGS.
1311 * DO NOT overwrite a pending exception.
1312 */
1313 if (!EG(exception)) {
1314 zend_throw_error_exception(EG(exception_class), message, 0, type);
1315 }
1316 return;
1317 default:
1318 break;
1319 }
1320 }
1321
1322 /* store the error if it has changed */
1323 if (display) {
1324 clear_last_error();
1325 if (!error_filename) {
1326 error_filename = ZSTR_KNOWN(ZEND_STR_UNKNOWN_CAPITALIZED);
1327 }
1328 PG(last_error_type) = type;
1329 PG(last_error_message) = zend_string_copy(message);
1330 PG(last_error_file) = zend_string_copy(error_filename);
1331 PG(last_error_lineno) = error_lineno;
1332 }
1333
1334 if (zend_alloc_in_memory_limit_error_reporting()) {
1335 php_output_discard_all();
1336 }
1337
1338 /* display/log the error if necessary */
1339 if (display && ((EG(error_reporting) & type) || (type & E_CORE))
1340 && (PG(log_errors) || PG(display_errors) || (!module_initialized))) {
1341 char *error_type_str;
1342 int syslog_type_int = LOG_NOTICE;
1343
1344 switch (type) {
1345 case E_ERROR:
1346 case E_CORE_ERROR:
1347 case E_COMPILE_ERROR:
1348 case E_USER_ERROR:
1349 error_type_str = "Fatal error";
1350 syslog_type_int = LOG_ERR;
1351 break;
1352 case E_RECOVERABLE_ERROR:
1353 error_type_str = "Recoverable fatal error";
1354 syslog_type_int = LOG_ERR;
1355 break;
1356 case E_WARNING:
1357 case E_CORE_WARNING:
1358 case E_COMPILE_WARNING:
1359 case E_USER_WARNING:
1360 error_type_str = "Warning";
1361 syslog_type_int = LOG_WARNING;
1362 break;
1363 case E_PARSE:
1364 error_type_str = "Parse error";
1365 syslog_type_int = LOG_ERR;
1366 break;
1367 case E_NOTICE:
1368 case E_USER_NOTICE:
1369 error_type_str = "Notice";
1370 syslog_type_int = LOG_NOTICE;
1371 break;
1372 case E_DEPRECATED:
1373 case E_USER_DEPRECATED:
1374 error_type_str = "Deprecated";
1375 syslog_type_int = LOG_INFO;
1376 break;
1377 default:
1378 error_type_str = "Unknown error";
1379 break;
1380 }
1381
1382 if (PG(log_errors)
1383 || (!module_initialized && (!PG(display_startup_errors) || !PG(display_errors)))) {
1384 char *log_buffer;
1385 #ifdef PHP_WIN32
1386 if (type == E_CORE_ERROR || type == E_CORE_WARNING) {
1387 syslog(LOG_ALERT, "PHP %s: %s (%s)", error_type_str, ZSTR_VAL(message), GetCommandLine());
1388 }
1389 #endif
1390 spprintf(&log_buffer, 0, "PHP %s: %s in %s on line %" PRIu32, error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno);
1391 php_log_err_with_severity(log_buffer, syslog_type_int);
1392 efree(log_buffer);
1393 }
1394
1395 if (PG(display_errors) && ((module_initialized && !PG(during_request_startup)) || (PG(display_startup_errors)))) {
1396 if (PG(xmlrpc_errors)) {
1397 php_printf("<?xml version=\"1.0\"?><methodResponse><fault><value><struct><member><name>faultCode</name><value><int>" ZEND_LONG_FMT "</int></value></member><member><name>faultString</name><value><string>%s:%s in %s on line %" PRIu32 "</string></value></member></struct></value></fault></methodResponse>", PG(xmlrpc_error_number), error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno);
1398 } else {
1399 char *prepend_string = INI_STR("error_prepend_string");
1400 char *append_string = INI_STR("error_append_string");
1401
1402 if (PG(html_errors)) {
1403 if (type == E_ERROR || type == E_PARSE) {
1404 zend_string *buf = escape_html(ZSTR_VAL(message), ZSTR_LEN(message));
1405 php_printf("%s<br />\n<b>%s</b>: %s in <b>%s</b> on line <b>%" PRIu32 "</b><br />\n%s", STR_PRINT(prepend_string), error_type_str, ZSTR_VAL(buf), ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
1406 zend_string_free(buf);
1407 } else {
1408 php_printf_unchecked("%s<br />\n<b>%s</b>: %S in <b>%s</b> on line <b>%" PRIu32 "</b><br />\n%s", STR_PRINT(prepend_string), error_type_str, message, ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
1409 }
1410 } else {
1411 /* Write CLI/CGI errors to stderr if display_errors = "stderr" */
1412 if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")) &&
1413 PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR
1414 ) {
1415 fprintf(stderr, "%s: ", error_type_str);
1416 fwrite(ZSTR_VAL(message), sizeof(char), ZSTR_LEN(message), stderr);
1417 fprintf(stderr, " in %s on line %" PRIu32 "\n", ZSTR_VAL(error_filename), error_lineno);
1418 #ifdef PHP_WIN32
1419 fflush(stderr);
1420 #endif
1421 } else {
1422 php_printf_unchecked("%s\n%s: %S in %s on line %" PRIu32 "\n%s", STR_PRINT(prepend_string), error_type_str, message, ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
1423 }
1424 }
1425 }
1426 }
1427 }
1428
1429 /* Bail out if we can't recover */
1430 switch (type) {
1431 case E_CORE_ERROR:
1432 if(!module_initialized) {
1433 /* bad error in module startup - no way we can live with this */
1434 exit(-2);
1435 }
1436 ZEND_FALLTHROUGH;
1437 case E_ERROR:
1438 case E_RECOVERABLE_ERROR:
1439 case E_PARSE:
1440 case E_COMPILE_ERROR:
1441 case E_USER_ERROR:
1442 EG(exit_status) = 255;
1443 if (module_initialized) {
1444 if (!PG(display_errors) &&
1445 !SG(headers_sent) &&
1446 SG(sapi_headers).http_response_code == 200
1447 ) {
1448 sapi_header_line ctr = {0};
1449
1450 ctr.line = "HTTP/1.0 500 Internal Server Error";
1451 ctr.line_len = sizeof("HTTP/1.0 500 Internal Server Error") - 1;
1452 sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
1453 }
1454 /* the parser would return 1 (failure), we can bail out nicely */
1455 if (!(orig_type & E_DONT_BAIL)) {
1456 /* restore memory limit */
1457 zend_set_memory_limit(PG(memory_limit));
1458 zend_objects_store_mark_destructed(&EG(objects_store));
1459 if (CG(in_compilation) && (type == E_COMPILE_ERROR || type == E_PARSE)) {
1460 /* We bailout during compilation which may for example leave stale entries in CG(loop_var_stack).
1461 * If code is compiled during shutdown, we need to make sure the compiler is reset to a clean state,
1462 * otherwise this will lead to incorrect compilation during shutdown.
1463 * We don't do a full re-initialization via init_compiler() because that will also reset streams and resources. */
1464 shutdown_compiler();
1465 zend_init_compiler_data_structures();
1466 }
1467 zend_bailout();
1468 return;
1469 }
1470 }
1471 break;
1472 }
1473 }
1474 /* }}} */
1475
1476 /* {{{ php_get_current_user */
php_get_current_user(void)1477 PHPAPI char *php_get_current_user(void)
1478 {
1479 zend_stat_t *pstat = NULL;
1480
1481 if (SG(request_info).current_user) {
1482 return SG(request_info).current_user;
1483 }
1484
1485 /* FIXME: I need to have this somehow handled if
1486 USE_SAPI is defined, because cgi will also be
1487 interfaced in USE_SAPI */
1488
1489 pstat = sapi_get_stat();
1490
1491 if (!pstat) {
1492 return "";
1493 } else {
1494 #ifdef PHP_WIN32
1495 char *name = php_win32_get_username();
1496 int len;
1497
1498 if (!name) {
1499 return "";
1500 }
1501 len = (int)strlen(name);
1502 name[len] = '\0';
1503 SG(request_info).current_user_length = len;
1504 SG(request_info).current_user = estrndup(name, len);
1505 free(name);
1506 return SG(request_info).current_user;
1507 #else
1508 struct passwd *pwd;
1509 #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
1510 struct passwd _pw;
1511 struct passwd *retpwptr = NULL;
1512 int pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1513 char *pwbuf;
1514 int err;
1515
1516 if (pwbuflen < 1) {
1517 pwbuflen = 1024;
1518 }
1519 # if ZEND_DEBUG
1520 /* Test retry logic */
1521 pwbuflen = 1;
1522 # endif
1523 pwbuf = emalloc(pwbuflen);
1524
1525 try_again:
1526 err = getpwuid_r(pstat->st_uid, &_pw, pwbuf, pwbuflen, &retpwptr);
1527 if (err != 0) {
1528 if (err == ERANGE) {
1529 pwbuflen *= 2;
1530 pwbuf = erealloc(pwbuf, pwbuflen);
1531 goto try_again;
1532 }
1533 efree(pwbuf);
1534 return "";
1535 }
1536 if (retpwptr == NULL) {
1537 efree(pwbuf);
1538 return "";
1539 }
1540 pwd = &_pw;
1541 #else
1542 if ((pwd=getpwuid(pstat->st_uid))==NULL) {
1543 return "";
1544 }
1545 #endif
1546 SG(request_info).current_user_length = strlen(pwd->pw_name);
1547 SG(request_info).current_user = estrndup(pwd->pw_name, SG(request_info).current_user_length);
1548 #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
1549 efree(pwbuf);
1550 #endif
1551 return SG(request_info).current_user;
1552 #endif
1553 }
1554 }
1555 /* }}} */
1556
1557 /* {{{ Sets the maximum time a script can run */
PHP_FUNCTION(set_time_limit)1558 PHP_FUNCTION(set_time_limit)
1559 {
1560 zend_long new_timeout;
1561 char *new_timeout_str;
1562 size_t new_timeout_strlen;
1563 zend_string *key;
1564
1565 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &new_timeout) == FAILURE) {
1566 RETURN_THROWS();
1567 }
1568
1569 new_timeout_strlen = zend_spprintf(&new_timeout_str, 0, ZEND_LONG_FMT, new_timeout);
1570
1571 key = ZSTR_INIT_LITERAL("max_execution_time", 0);
1572 if (zend_alter_ini_entry_chars_ex(key, new_timeout_str, new_timeout_strlen, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == SUCCESS) {
1573 RETVAL_TRUE;
1574 } else {
1575 RETVAL_FALSE;
1576 }
1577 zend_string_release_ex(key, 0);
1578 efree(new_timeout_str);
1579 }
1580 /* }}} */
1581
1582 /* {{{ php_fopen_wrapper_for_zend */
php_fopen_wrapper_for_zend(zend_string * filename,zend_string ** opened_path)1583 static FILE *php_fopen_wrapper_for_zend(zend_string *filename, zend_string **opened_path)
1584 {
1585 *opened_path = filename;
1586 return php_stream_open_wrapper_as_file(ZSTR_VAL(filename), "rb", USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE|STREAM_OPEN_FOR_ZEND_STREAM, opened_path);
1587 }
1588 /* }}} */
1589
php_zend_stream_closer(void * handle)1590 static void php_zend_stream_closer(void *handle) /* {{{ */
1591 {
1592 php_stream_close((php_stream*)handle);
1593 }
1594 /* }}} */
1595
php_zend_stream_fsizer(void * handle)1596 static size_t php_zend_stream_fsizer(void *handle) /* {{{ */
1597 {
1598 php_stream *stream = handle;
1599 php_stream_statbuf ssb;
1600
1601 /* File size reported by stat() may be inaccurate if stream filters are used.
1602 * TODO: Should stat() be generally disabled if filters are used? */
1603 if (stream->readfilters.head) {
1604 return 0;
1605 }
1606
1607 if (php_stream_stat(stream, &ssb) == 0) {
1608 return ssb.sb.st_size;
1609 }
1610 return 0;
1611 }
1612 /* }}} */
1613
php_stream_open_for_zend(zend_file_handle * handle)1614 static zend_result php_stream_open_for_zend(zend_file_handle *handle) /* {{{ */
1615 {
1616 return php_stream_open_for_zend_ex(handle, USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE);
1617 }
1618 /* }}} */
1619
php_stream_open_for_zend_ex(zend_file_handle * handle,int mode)1620 PHPAPI zend_result php_stream_open_for_zend_ex(zend_file_handle *handle, int mode) /* {{{ */
1621 {
1622 zend_string *opened_path;
1623 zend_string *filename;
1624 php_stream *stream;
1625
1626 ZEND_ASSERT(handle->type == ZEND_HANDLE_FILENAME);
1627 opened_path = filename = handle->filename;
1628 stream = php_stream_open_wrapper((char *)ZSTR_VAL(filename), "rb", mode | STREAM_OPEN_FOR_ZEND_STREAM, &opened_path);
1629 if (stream) {
1630 memset(handle, 0, sizeof(zend_file_handle));
1631 handle->type = ZEND_HANDLE_STREAM;
1632 handle->filename = filename;
1633 handle->opened_path = opened_path;
1634 handle->handle.stream.handle = stream;
1635 handle->handle.stream.reader = (zend_stream_reader_t)_php_stream_read;
1636 handle->handle.stream.fsizer = php_zend_stream_fsizer;
1637 handle->handle.stream.isatty = 0;
1638 handle->handle.stream.closer = php_zend_stream_closer;
1639 /* suppress warning if this stream is not explicitly closed */
1640 php_stream_auto_cleanup(stream);
1641 /* Disable buffering to avoid double buffering between PHP and Zend streams. */
1642 php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
1643
1644 return SUCCESS;
1645 }
1646 return FAILURE;
1647 }
1648 /* }}} */
1649
php_resolve_path_for_zend(zend_string * filename)1650 static zend_string *php_resolve_path_for_zend(zend_string *filename) /* {{{ */
1651 {
1652 return php_resolve_path(ZSTR_VAL(filename), ZSTR_LEN(filename), PG(include_path));
1653 }
1654 /* }}} */
1655
1656 /* {{{ php_get_configuration_directive_for_zend */
php_get_configuration_directive_for_zend(zend_string * name)1657 static zval *php_get_configuration_directive_for_zend(zend_string *name)
1658 {
1659 return cfg_get_entry_ex(name);
1660 }
1661 /* }}} */
1662
1663 /* {{{ php_free_request_globals */
php_free_request_globals(void)1664 static void php_free_request_globals(void)
1665 {
1666 clear_last_error();
1667 if (PG(php_sys_temp_dir)) {
1668 efree(PG(php_sys_temp_dir));
1669 PG(php_sys_temp_dir) = NULL;
1670 }
1671
1672 EG(filename_override) = NULL;
1673 EG(lineno_override) = -1;
1674 }
1675 /* }}} */
1676
1677 /* {{{ php_message_handler_for_zend */
php_message_handler_for_zend(zend_long message,const void * data)1678 static ZEND_COLD void php_message_handler_for_zend(zend_long message, const void *data)
1679 {
1680 switch (message) {
1681 case ZMSG_FAILED_INCLUDE_FOPEN: {
1682 char *tmp = estrdup((char *) data);
1683 php_error_docref("function.include", E_WARNING, "Failed opening '%s' for inclusion (include_path='%s')", php_strip_url_passwd(tmp), STR_PRINT(PG(include_path)));
1684 efree(tmp);
1685 break;
1686 }
1687 case ZMSG_FAILED_REQUIRE_FOPEN: {
1688 char *tmp = estrdup((char *) data);
1689 zend_throw_error(NULL, "Failed opening required '%s' (include_path='%s')", php_strip_url_passwd(tmp), STR_PRINT(PG(include_path)));
1690 efree(tmp);
1691 break;
1692 }
1693 case ZMSG_FAILED_HIGHLIGHT_FOPEN: {
1694 char *tmp = estrdup((char *) data);
1695 php_error_docref(NULL, E_WARNING, "Failed opening '%s' for highlighting", php_strip_url_passwd(tmp));
1696 efree(tmp);
1697 break;
1698 }
1699 case ZMSG_MEMORY_LEAK_DETECTED:
1700 case ZMSG_MEMORY_LEAK_REPEATED:
1701 #if ZEND_DEBUG
1702 if (EG(error_reporting) & E_WARNING) {
1703 char memory_leak_buf[1024];
1704
1705 if (message==ZMSG_MEMORY_LEAK_DETECTED) {
1706 zend_leak_info *t = (zend_leak_info *) data;
1707
1708 snprintf(memory_leak_buf, 512, "%s(%" PRIu32 ") : Freeing " ZEND_ADDR_FMT " (%zu bytes), script=%s\n", t->filename, t->lineno, (size_t)t->addr, t->size, SAFE_FILENAME(SG(request_info).path_translated));
1709 if (t->orig_filename) {
1710 char relay_buf[512];
1711
1712 snprintf(relay_buf, 512, "%s(%" PRIu32 ") : Actual location (location was relayed)\n", t->orig_filename, t->orig_lineno);
1713 strlcat(memory_leak_buf, relay_buf, sizeof(memory_leak_buf));
1714 }
1715 } else {
1716 unsigned long leak_count = (uintptr_t) data;
1717
1718 snprintf(memory_leak_buf, 512, "Last leak repeated %lu time%s\n", leak_count, (leak_count>1?"s":""));
1719 }
1720 # if defined(PHP_WIN32)
1721 if (IsDebuggerPresent()) {
1722 OutputDebugString(memory_leak_buf);
1723 } else {
1724 fprintf(stderr, "%s", memory_leak_buf);
1725 }
1726 # else
1727 fprintf(stderr, "%s", memory_leak_buf);
1728 # endif
1729 }
1730 #endif
1731 break;
1732 case ZMSG_MEMORY_LEAKS_GRAND_TOTAL:
1733 #if ZEND_DEBUG
1734 if (EG(error_reporting) & E_WARNING) {
1735 char memory_leak_buf[512];
1736
1737 snprintf(memory_leak_buf, 512, "=== Total %d memory leaks detected ===\n", *((uint32_t *) data));
1738 # if defined(PHP_WIN32)
1739 if (IsDebuggerPresent()) {
1740 OutputDebugString(memory_leak_buf);
1741 } else {
1742 fprintf(stderr, "%s", memory_leak_buf);
1743 }
1744 # else
1745 fprintf(stderr, "%s", memory_leak_buf);
1746 # endif
1747 }
1748 #endif
1749 break;
1750 case ZMSG_LOG_SCRIPT_NAME: {
1751 struct tm *ta, tmbuf;
1752 time_t curtime;
1753 char *datetime_str, asctimebuf[52];
1754 char memory_leak_buf[4096];
1755
1756 time(&curtime);
1757 ta = php_localtime_r(&curtime, &tmbuf);
1758 datetime_str = php_asctime_r(ta, asctimebuf);
1759 if (datetime_str) {
1760 datetime_str[strlen(datetime_str)-1]=0; /* get rid of the trailing newline */
1761 snprintf(memory_leak_buf, sizeof(memory_leak_buf), "[%s] Script: '%s'\n", datetime_str, SAFE_FILENAME(SG(request_info).path_translated));
1762 } else {
1763 snprintf(memory_leak_buf, sizeof(memory_leak_buf), "[null] Script: '%s'\n", SAFE_FILENAME(SG(request_info).path_translated));
1764 }
1765 # if defined(PHP_WIN32)
1766 if (IsDebuggerPresent()) {
1767 OutputDebugString(memory_leak_buf);
1768 } else {
1769 fprintf(stderr, "%s", memory_leak_buf);
1770 }
1771 # else
1772 fprintf(stderr, "%s", memory_leak_buf);
1773 # endif
1774 }
1775 break;
1776 }
1777 }
1778 /* }}} */
1779
1780
php_on_timeout(int seconds)1781 void php_on_timeout(int seconds)
1782 {
1783 PG(connection_status) |= PHP_CONNECTION_TIMEOUT;
1784 }
1785
1786 #if PHP_SIGCHILD
1787 /* {{{ sigchld_handler */
sigchld_handler(int apar)1788 static void sigchld_handler(int apar)
1789 {
1790 int errno_save = errno;
1791
1792 while (waitpid(-1, NULL, WNOHANG) > 0);
1793 signal(SIGCHLD, sigchld_handler);
1794
1795 errno = errno_save;
1796 }
1797 /* }}} */
1798 #endif
1799
1800 /* {{{ php_request_startup */
php_request_startup(void)1801 zend_result php_request_startup(void)
1802 {
1803 zend_result retval = SUCCESS;
1804
1805 zend_interned_strings_activate();
1806
1807 #ifdef HAVE_DTRACE
1808 DTRACE_REQUEST_STARTUP(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
1809 #endif /* HAVE_DTRACE */
1810
1811 #ifdef PHP_WIN32
1812 # if defined(ZTS)
1813 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
1814 # endif
1815 PG(com_initialized) = 0;
1816 #endif
1817
1818 #if PHP_SIGCHILD
1819 signal(SIGCHLD, sigchld_handler);
1820 #endif
1821
1822 zend_try {
1823 PG(in_error_log) = 0;
1824 PG(during_request_startup) = 1;
1825
1826 php_output_activate();
1827
1828 /* initialize global variables */
1829 PG(modules_activated) = 0;
1830 PG(header_is_being_sent) = 0;
1831 PG(connection_status) = PHP_CONNECTION_NORMAL;
1832 PG(in_user_include) = 0;
1833
1834 zend_activate();
1835 sapi_activate();
1836
1837 #ifdef ZEND_SIGNALS
1838 zend_signal_activate();
1839 #endif
1840
1841 if (PG(max_input_time) == -1) {
1842 zend_set_timeout(EG(timeout_seconds), 1);
1843 } else {
1844 zend_set_timeout(PG(max_input_time), 1);
1845 }
1846
1847 /* Disable realpath cache if an open_basedir is set */
1848 if (PG(open_basedir) && *PG(open_basedir)) {
1849 CWDG(realpath_cache_size_limit) = 0;
1850 }
1851
1852 if (PG(expose_php) && !SG(headers_sent)) {
1853 sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1);
1854 }
1855
1856 if (PG(output_handler) && PG(output_handler)[0]) {
1857 zval oh;
1858
1859 ZVAL_STRING(&oh, PG(output_handler));
1860 php_output_start_user(&oh, 0, PHP_OUTPUT_HANDLER_STDFLAGS);
1861 zval_ptr_dtor(&oh);
1862 } else if (PG(output_buffering)) {
1863 php_output_start_user(NULL, PG(output_buffering) > 1 ? PG(output_buffering) : 0, PHP_OUTPUT_HANDLER_STDFLAGS);
1864 } else if (PG(implicit_flush)) {
1865 php_output_set_implicit_flush(1);
1866 }
1867
1868 /* We turn this off in php_execute_script() */
1869 /* PG(during_request_startup) = 0; */
1870
1871 php_hash_environment();
1872 zend_activate_modules();
1873 PG(modules_activated)=1;
1874 } zend_catch {
1875 retval = FAILURE;
1876 } zend_end_try();
1877
1878 SG(sapi_started) = 1;
1879
1880 return retval;
1881 }
1882 /* }}} */
1883
1884 /* {{{ php_request_shutdown */
php_request_shutdown(void * dummy)1885 void php_request_shutdown(void *dummy)
1886 {
1887 bool report_memleaks;
1888
1889 EG(flags) |= EG_FLAGS_IN_SHUTDOWN;
1890
1891 report_memleaks = PG(report_memleaks);
1892
1893 /* EG(current_execute_data) points into nirvana and therefore cannot be safely accessed
1894 * inside zend_executor callback functions.
1895 */
1896 EG(current_execute_data) = NULL;
1897
1898 php_deactivate_ticks();
1899
1900 /* 0. Call any open observer end handlers that are still open after a zend_bailout */
1901 if (ZEND_OBSERVER_ENABLED) {
1902 zend_observer_fcall_end_all();
1903 }
1904
1905 /* 1. Call all possible shutdown functions registered with register_shutdown_function() */
1906 if (PG(modules_activated)) {
1907 php_call_shutdown_functions();
1908 }
1909
1910 /* 2. Call all possible __destruct() functions */
1911 zend_try {
1912 zend_call_destructors();
1913 } zend_end_try();
1914
1915 /* 3. Flush all output buffers */
1916 zend_try {
1917 php_output_end_all();
1918 } zend_end_try();
1919
1920 /* 4. Reset max_execution_time (no longer executing php code after response sent) */
1921 zend_try {
1922 zend_unset_timeout();
1923 } zend_end_try();
1924
1925 /* 5. Call all extensions RSHUTDOWN functions */
1926 if (PG(modules_activated)) {
1927 zend_deactivate_modules();
1928 }
1929
1930 /* 6. Shutdown output layer (send the set HTTP headers, cleanup output handlers, etc.) */
1931 zend_try {
1932 php_output_deactivate();
1933 } zend_end_try();
1934
1935 /* 7. Free shutdown functions */
1936 if (PG(modules_activated)) {
1937 php_free_shutdown_functions();
1938 }
1939
1940 /* 8. Destroy super-globals */
1941 zend_try {
1942 int i;
1943
1944 for (i=0; i<NUM_TRACK_VARS; i++) {
1945 zval_ptr_dtor(&PG(http_globals)[i]);
1946 }
1947 } zend_end_try();
1948
1949 /* 9. Shutdown scanner/executor/compiler and restore ini entries */
1950 zend_deactivate();
1951
1952 /* 10. free request-bound globals */
1953 php_free_request_globals();
1954
1955 /* 11. Call all extensions post-RSHUTDOWN functions */
1956 zend_try {
1957 zend_post_deactivate_modules();
1958 } zend_end_try();
1959
1960 /* 12. SAPI related shutdown*/
1961 zend_try {
1962 sapi_deactivate_module();
1963 } zend_end_try();
1964 /* free SAPI stuff */
1965 sapi_deactivate_destroy();
1966
1967 /* 13. free virtual CWD memory */
1968 virtual_cwd_deactivate();
1969
1970 /* 14. Destroy stream hashes */
1971 zend_try {
1972 php_shutdown_stream_hashes();
1973 } zend_end_try();
1974
1975 /* 15. Free Willy (here be crashes) */
1976 zend_arena_destroy(CG(arena));
1977 zend_interned_strings_deactivate();
1978 zend_try {
1979 shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0);
1980 } zend_end_try();
1981
1982 /* Reset memory limit, as the reset during INI_STAGE_DEACTIVATE may have failed.
1983 * At this point, no memory beyond a single chunk should be in use. */
1984 zend_set_memory_limit(PG(memory_limit));
1985
1986 /* 16. Deactivate Zend signals */
1987 #ifdef ZEND_SIGNALS
1988 zend_signal_deactivate();
1989 #endif
1990
1991 #ifdef PHP_WIN32
1992 if (PG(com_initialized)) {
1993 CoUninitialize();
1994 PG(com_initialized) = 0;
1995 }
1996 #endif
1997
1998 #ifdef HAVE_DTRACE
1999 DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
2000 #endif /* HAVE_DTRACE */
2001 }
2002 /* }}} */
2003
2004 /* {{{ php_com_initialize */
php_com_initialize(void)2005 PHPAPI void php_com_initialize(void)
2006 {
2007 #ifdef PHP_WIN32
2008 if (!PG(com_initialized)) {
2009 if (CoInitialize(NULL) == S_OK) {
2010 PG(com_initialized) = 1;
2011 }
2012 }
2013 #endif
2014 }
2015 /* }}} */
2016
2017 #ifdef ZTS
2018 /* {{{ core_globals_ctor */
core_globals_ctor(php_core_globals * core_globals)2019 static void core_globals_ctor(php_core_globals *core_globals)
2020 {
2021 memset(core_globals, 0, sizeof(*core_globals));
2022 php_startup_ticks();
2023 }
2024 /* }}} */
2025 #endif
2026
2027 /* {{{ core_globals_dtor */
core_globals_dtor(php_core_globals * core_globals)2028 static void core_globals_dtor(php_core_globals *core_globals)
2029 {
2030 /* These should have been freed earlier. */
2031 ZEND_ASSERT(!core_globals->last_error_message);
2032 ZEND_ASSERT(!core_globals->last_error_file);
2033
2034 if (core_globals->disable_classes) {
2035 free(core_globals->disable_classes);
2036 }
2037 if (core_globals->php_binary) {
2038 free(core_globals->php_binary);
2039 }
2040
2041 php_shutdown_ticks(core_globals);
2042 }
2043 /* }}} */
2044
PHP_MINFO_FUNCTION(php_core)2045 PHP_MINFO_FUNCTION(php_core) { /* {{{ */
2046 php_info_print_table_start();
2047 php_info_print_table_row(2, "PHP Version", PHP_VERSION);
2048 php_info_print_table_end();
2049 DISPLAY_INI_ENTRIES();
2050 }
2051 /* }}} */
2052
2053 /* {{{ php_register_extensions */
php_register_extensions(zend_module_entry * const * ptr,int count)2054 zend_result php_register_extensions(zend_module_entry * const * ptr, int count)
2055 {
2056 zend_module_entry * const * end = ptr + count;
2057
2058 while (ptr < end) {
2059 if (*ptr) {
2060 if (zend_register_internal_module(*ptr)==NULL) {
2061 return FAILURE;
2062 }
2063 }
2064 ptr++;
2065 }
2066 return SUCCESS;
2067 }
2068
2069 #ifdef PHP_WIN32
2070 static _invalid_parameter_handler old_invalid_parameter_handler;
2071
dummy_invalid_parameter_handler(const wchar_t * expression,const wchar_t * function,const wchar_t * file,unsigned int line,uintptr_t pReserved)2072 void dummy_invalid_parameter_handler(
2073 const wchar_t *expression,
2074 const wchar_t *function,
2075 const wchar_t *file,
2076 unsigned int line,
2077 uintptr_t pReserved)
2078 {
2079 static int called = 0;
2080 char buf[1024];
2081 int len;
2082
2083 if (!called) {
2084 if(PG(windows_show_crt_warning)) {
2085 called = 1;
2086 if (function) {
2087 if (file) {
2088 len = _snprintf(buf, sizeof(buf)-1, "Invalid parameter detected in CRT function '%ws' (%ws:%u)", function, file, line);
2089 } else {
2090 len = _snprintf(buf, sizeof(buf)-1, "Invalid parameter detected in CRT function '%ws'", function);
2091 }
2092 } else {
2093 len = _snprintf(buf, sizeof(buf)-1, "Invalid CRT parameter detected (function not known)");
2094 }
2095 zend_error(E_WARNING, "%s", buf);
2096 called = 0;
2097 }
2098 }
2099 }
2100 #endif
2101
2102 /* {{{ php_module_startup */
php_module_startup(sapi_module_struct * sf,zend_module_entry * additional_module)2103 zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module)
2104 {
2105 zend_utility_functions zuf;
2106 zend_utility_values zuv;
2107 zend_result retval = SUCCESS;
2108 int module_number = 0;
2109 zend_module_entry *module;
2110
2111 #ifdef PHP_WIN32
2112 WORD wVersionRequested = MAKEWORD(2, 2);
2113 WSADATA wsaData;
2114
2115 old_invalid_parameter_handler =
2116 _set_invalid_parameter_handler(dummy_invalid_parameter_handler);
2117 if (old_invalid_parameter_handler != NULL) {
2118 _set_invalid_parameter_handler(old_invalid_parameter_handler);
2119 }
2120
2121 /* Disable the message box for assertions.*/
2122 _CrtSetReportMode(_CRT_ASSERT, 0);
2123 #endif
2124
2125 #ifdef ZTS
2126 (void)ts_resource(0);
2127 #endif
2128
2129 #ifdef PHP_WIN32
2130 if (!php_win32_init_random_bytes()) {
2131 fprintf(stderr, "\ncrypt algorithm provider initialization failed\n");
2132 return FAILURE;
2133 }
2134 #endif
2135
2136 module_shutdown = false;
2137 module_startup = true;
2138 sapi_initialize_empty_request();
2139 sapi_activate();
2140
2141 if (module_initialized) {
2142 return SUCCESS;
2143 }
2144
2145 sapi_module = *sf;
2146
2147 php_output_startup();
2148
2149 #ifdef ZTS
2150 ts_allocate_fast_id(&core_globals_id, &core_globals_offset, sizeof(php_core_globals), (ts_allocate_ctor) core_globals_ctor, (ts_allocate_dtor) core_globals_dtor);
2151 #ifdef PHP_WIN32
2152 ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor) php_win32_core_globals_ctor, (ts_allocate_dtor) php_win32_core_globals_dtor);
2153 #endif
2154 #else
2155 memset(&core_globals, 0, sizeof(core_globals));
2156 php_startup_ticks();
2157 #endif
2158 gc_globals_ctor();
2159
2160 zend_observer_startup();
2161 #if ZEND_DEBUG
2162 zend_observer_error_register(report_zend_debug_error_notify_cb);
2163 #endif
2164
2165 zuf.error_function = php_error_cb;
2166 zuf.printf_function = php_printf;
2167 zuf.write_function = php_output_write;
2168 zuf.fopen_function = php_fopen_wrapper_for_zend;
2169 zuf.message_handler = php_message_handler_for_zend;
2170 zuf.get_configuration_directive = php_get_configuration_directive_for_zend;
2171 zuf.ticks_function = php_run_ticks;
2172 zuf.on_timeout = php_on_timeout;
2173 zuf.stream_open_function = php_stream_open_for_zend;
2174 zuf.printf_to_smart_string_function = php_printf_to_smart_string;
2175 zuf.printf_to_smart_str_function = php_printf_to_smart_str;
2176 zuf.getenv_function = sapi_getenv;
2177 zuf.resolve_path_function = php_resolve_path_for_zend;
2178 zuf.random_bytes_function = php_random_bytes_ex;
2179 zuf.random_bytes_insecure_function = php_random_bytes_insecure_for_zend;
2180 zend_startup(&zuf);
2181 zend_reset_lc_ctype_locale();
2182 zend_update_current_locale();
2183
2184 #if HAVE_TZSET
2185 tzset();
2186 #endif
2187
2188 #ifdef PHP_WIN32
2189 char *img_err;
2190 if (!php_win32_crt_compatible(&img_err)) {
2191 php_error(E_CORE_WARNING, img_err);
2192 efree(img_err);
2193 return FAILURE;
2194 }
2195
2196 /* start up winsock services */
2197 if (WSAStartup(wVersionRequested, &wsaData) != 0) {
2198 fprintf(stderr, "\nwinsock.dll unusable. %d\n", WSAGetLastError());
2199 return FAILURE;
2200 }
2201
2202 if (UNEXPECTED(HIBYTE(wsaData.wVersion) != 2)) {
2203 fprintf(stderr, "\nversion not found in winsock.dll. %d\n", WSAGetLastError());
2204 WSACleanup();
2205 return FAILURE;
2206 }
2207 php_win32_signal_ctrl_handler_init();
2208 #endif
2209
2210 le_index_ptr = zend_register_list_destructors_ex(NULL, NULL, "index pointer", 0);
2211
2212 php_binary_init();
2213 register_main_symbols(module_number);
2214
2215 /* this will read in php.ini, set up the configuration parameters,
2216 load zend extensions and register php function extensions
2217 to be loaded later */
2218 zend_stream_init();
2219 if (php_init_config() == FAILURE) {
2220 return FAILURE;
2221 }
2222 zend_stream_shutdown();
2223
2224 /* Register PHP core ini entries */
2225 zend_register_ini_entries_ex(ini_entries, module_number, MODULE_PERSISTENT);
2226
2227 /* Register Zend ini entries */
2228 zend_register_standard_ini_entries();
2229
2230 #ifdef ZEND_WIN32
2231 /* Until the current ini values was setup, the current cp is 65001.
2232 If the actual ini values are different, some stuff needs to be updated.
2233 It concerns at least main_cwd_state and there might be more. As we're
2234 still in the startup phase, lets use the chance and reinit the relevant
2235 item according to the current codepage. Still, if ini_set() is used
2236 later on, a more intelligent way to update such stuff is needed.
2237 Startup/shutdown routines could involve touching globals and thus
2238 can't always be used on demand. */
2239 if (!php_win32_cp_use_unicode()) {
2240 virtual_cwd_main_cwd_init(1);
2241 }
2242 #endif
2243
2244 /* Disable realpath cache if an open_basedir is set */
2245 if (PG(open_basedir) && *PG(open_basedir)) {
2246 CWDG(realpath_cache_size_limit) = 0;
2247 }
2248
2249 PG(have_called_openlog) = 0;
2250
2251 /* initialize stream wrappers registry
2252 * (this uses configuration parameters from php.ini)
2253 */
2254 if (php_init_stream_wrappers(module_number) == FAILURE) {
2255 fprintf(stderr, "PHP: Unable to initialize stream url wrappers.\n");
2256 return FAILURE;
2257 }
2258
2259 zuv.html_errors = 1;
2260 php_startup_auto_globals();
2261 zend_set_utility_values(&zuv);
2262 php_startup_sapi_content_types();
2263
2264 /* Begin to fingerprint the process state */
2265 zend_startup_system_id();
2266
2267 /* startup extensions statically compiled in */
2268 if (php_register_internal_extensions_func() == FAILURE) {
2269 fprintf(stderr, "Unable to start builtin modules\n");
2270 return FAILURE;
2271 }
2272
2273 /* start additional PHP extensions */
2274 if (additional_module && (zend_register_internal_module(additional_module) == NULL)) {
2275 return FAILURE;
2276 }
2277
2278 /* load and startup extensions compiled as shared objects (aka DLLs)
2279 as requested by php.ini entries
2280 these are loaded after initialization of internal extensions
2281 as extensions *might* rely on things from ext/standard
2282 which is always an internal extension and to be initialized
2283 ahead of all other internals
2284 */
2285 php_ini_register_extensions();
2286 zend_startup_modules();
2287
2288 /* start Zend extensions */
2289 zend_startup_extensions();
2290
2291 zend_collect_module_handlers();
2292
2293 /* register additional functions */
2294 if (sapi_module.additional_functions) {
2295 if ((module = zend_hash_str_find_ptr(&module_registry, "standard", sizeof("standard")-1)) != NULL) {
2296 EG(current_module) = module;
2297 zend_register_functions(NULL, sapi_module.additional_functions, NULL, MODULE_PERSISTENT);
2298 EG(current_module) = NULL;
2299 }
2300 }
2301
2302 /* disable certain classes and functions as requested by php.ini */
2303 zend_disable_functions(INI_STR("disable_functions"));
2304 php_disable_classes();
2305
2306 /* make core report what it should */
2307 if ((module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core")-1)) != NULL) {
2308 module->version = PHP_VERSION;
2309 module->info_func = PHP_MINFO(php_core);
2310 }
2311
2312 /* freeze the list of observer fcall_init handlers */
2313 zend_observer_post_startup();
2314
2315 /* freeze the list of persistent internal functions */
2316 zend_init_internal_run_time_cache();
2317
2318 /* Extensions that add engine hooks after this point do so at their own peril */
2319 zend_finalize_system_id();
2320
2321 module_initialized = true;
2322
2323 if (zend_post_startup() != SUCCESS) {
2324 return FAILURE;
2325 }
2326
2327 /* Check for deprecated directives */
2328 /* NOTE: If you add anything here, remember to add it to build/Makefile.global! */
2329 {
2330 struct {
2331 const long error_level;
2332 const char *phrase;
2333 const char *directives[18]; /* Remember to change this if the number of directives change */
2334 } directives[2] = {
2335 {
2336 E_DEPRECATED,
2337 "Directive '%s' is deprecated",
2338 {
2339 "allow_url_include",
2340 NULL
2341 }
2342 },
2343 {
2344 E_CORE_ERROR,
2345 "Directive '%s' is no longer available in PHP",
2346 {
2347 "allow_call_time_pass_reference",
2348 "asp_tags",
2349 "define_syslog_variables",
2350 "highlight.bg",
2351 "magic_quotes_gpc",
2352 "magic_quotes_runtime",
2353 "magic_quotes_sybase",
2354 "register_globals",
2355 "register_long_arrays",
2356 "safe_mode",
2357 "safe_mode_gid",
2358 "safe_mode_include_dir",
2359 "safe_mode_exec_dir",
2360 "safe_mode_allowed_env_vars",
2361 "safe_mode_protected_env_vars",
2362 "zend.ze1_compatibility_mode",
2363 "track_errors",
2364 NULL
2365 }
2366 }
2367 };
2368
2369 unsigned int i;
2370
2371 zend_try {
2372 /* 2 = Count of deprecation structs */
2373 for (i = 0; i < 2; i++) {
2374 const char **p = directives[i].directives;
2375
2376 while(*p) {
2377 zend_long value;
2378
2379 if (cfg_get_long((char*)*p, &value) == SUCCESS && value) {
2380 zend_error(directives[i].error_level, directives[i].phrase, *p);
2381 }
2382
2383 ++p;
2384 }
2385 }
2386 } zend_catch {
2387 retval = FAILURE;
2388 } zend_end_try();
2389 }
2390
2391 virtual_cwd_deactivate();
2392
2393 sapi_deactivate();
2394 module_startup = false;
2395
2396 /* Don't leak errors from startup into the per-request phase. */
2397 clear_last_error();
2398 shutdown_memory_manager(1, 0);
2399 virtual_cwd_activate();
2400
2401 zend_interned_strings_switch_storage(1);
2402
2403 #if ZEND_RC_DEBUG
2404 if (retval == SUCCESS) {
2405 zend_rc_debug = 1;
2406 }
2407 #endif
2408
2409 /* we're done */
2410 return retval;
2411 }
2412 /* }}} */
2413
2414 /* {{{ php_module_shutdown_wrapper */
php_module_shutdown_wrapper(sapi_module_struct * sapi_globals)2415 int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals)
2416 {
2417 php_module_shutdown();
2418 return SUCCESS;
2419 }
2420 /* }}} */
2421
2422 /* {{{ php_module_shutdown */
php_module_shutdown(void)2423 void php_module_shutdown(void)
2424 {
2425 int module_number=0;
2426
2427 module_shutdown = true;
2428
2429 if (!module_initialized) {
2430 return;
2431 }
2432
2433 zend_interned_strings_switch_storage(0);
2434
2435 #if ZEND_RC_DEBUG
2436 zend_rc_debug = 0;
2437 #endif
2438
2439 #ifdef PHP_WIN32
2440 (void)php_win32_shutdown_random_bytes();
2441 php_win32_signal_ctrl_handler_shutdown();
2442 #endif
2443
2444 sapi_flush();
2445
2446 zend_shutdown();
2447
2448 #ifdef PHP_WIN32
2449 /*close winsock */
2450 WSACleanup();
2451 #endif
2452
2453 /* Destroys filter & transport registries too */
2454 php_shutdown_stream_wrappers(module_number);
2455
2456 zend_unregister_ini_entries_ex(module_number, MODULE_PERSISTENT);
2457
2458 /* close down the ini config */
2459 php_shutdown_config();
2460 clear_last_error();
2461
2462 #ifndef ZTS
2463 zend_ini_shutdown();
2464 shutdown_memory_manager(CG(unclean_shutdown), 1);
2465 #else
2466 zend_ini_global_shutdown();
2467 #endif
2468
2469 php_output_shutdown();
2470
2471 #ifndef ZTS
2472 zend_interned_strings_dtor();
2473 #endif
2474
2475 if (zend_post_shutdown_cb) {
2476 void (*cb)(void) = zend_post_shutdown_cb;
2477
2478 zend_post_shutdown_cb = NULL;
2479 cb();
2480 }
2481
2482 module_initialized = false;
2483
2484 #ifndef ZTS
2485 core_globals_dtor(&core_globals);
2486 gc_globals_dtor();
2487 #else
2488 ts_free_id(core_globals_id);
2489 #endif
2490
2491 #ifdef PHP_WIN32
2492 if (old_invalid_parameter_handler == NULL) {
2493 _set_invalid_parameter_handler(old_invalid_parameter_handler);
2494 }
2495 #endif
2496
2497 zend_observer_shutdown();
2498 }
2499 /* }}} */
2500
php_execute_script_ex(zend_file_handle * primary_file,zval * retval)2501 PHPAPI bool php_execute_script_ex(zend_file_handle *primary_file, zval *retval)
2502 {
2503 zend_file_handle *prepend_file_p = NULL, *append_file_p = NULL;
2504 zend_file_handle prepend_file, append_file;
2505 #ifdef HAVE_BROKEN_GETCWD
2506 volatile int old_cwd_fd = -1;
2507 #else
2508 char *old_cwd;
2509 ALLOCA_FLAG(use_heap)
2510 #endif
2511 bool result = true;
2512
2513 #ifndef HAVE_BROKEN_GETCWD
2514 # define OLD_CWD_SIZE 4096
2515 old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
2516 old_cwd[0] = '\0';
2517 #endif
2518
2519 zend_try {
2520 char realfile[MAXPATHLEN];
2521
2522 #ifdef PHP_WIN32
2523 if(primary_file->filename) {
2524 UpdateIniFromRegistry(ZSTR_VAL(primary_file->filename));
2525 }
2526 #endif
2527
2528 PG(during_request_startup) = 0;
2529
2530 if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
2531 #ifdef HAVE_BROKEN_GETCWD
2532 /* this looks nasty to me */
2533 old_cwd_fd = open(".", 0);
2534 #else
2535 php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
2536 #endif
2537 VCWD_CHDIR_FILE(ZSTR_VAL(primary_file->filename));
2538 }
2539
2540 /* Only lookup the real file path and add it to the included_files list if already opened
2541 * otherwise it will get opened and added to the included_files list in zend_execute_scripts
2542 */
2543 if (primary_file->filename &&
2544 !zend_string_equals_literal(primary_file->filename, "Standard input code") &&
2545 primary_file->opened_path == NULL &&
2546 primary_file->type != ZEND_HANDLE_FILENAME
2547 ) {
2548 if (expand_filepath(ZSTR_VAL(primary_file->filename), realfile)) {
2549 primary_file->opened_path = zend_string_init(realfile, strlen(realfile), 0);
2550 zend_hash_add_empty_element(&EG(included_files), primary_file->opened_path);
2551 }
2552 }
2553
2554 if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
2555 zend_stream_init_filename(&prepend_file, PG(auto_prepend_file));
2556 prepend_file_p = &prepend_file;
2557 }
2558
2559 if (PG(auto_append_file) && PG(auto_append_file)[0]) {
2560 zend_stream_init_filename(&append_file, PG(auto_append_file));
2561 append_file_p = &append_file;
2562 }
2563 if (PG(max_input_time) != -1) {
2564 #ifdef PHP_WIN32
2565 zend_unset_timeout();
2566 #endif
2567 zend_set_timeout(INI_INT("max_execution_time"), 0);
2568 }
2569
2570 if (prepend_file_p && result) {
2571 result = zend_execute_script(ZEND_REQUIRE, NULL, prepend_file_p) == SUCCESS;
2572 }
2573 if (result) {
2574 result = zend_execute_script(ZEND_REQUIRE, retval, primary_file) == SUCCESS;
2575 }
2576 if (append_file_p && result) {
2577 result = zend_execute_script(ZEND_REQUIRE, NULL, append_file_p) == SUCCESS;
2578 }
2579 } zend_catch {
2580 result = false;
2581 } zend_end_try();
2582
2583 if (prepend_file_p) {
2584 zend_destroy_file_handle(prepend_file_p);
2585 }
2586
2587 if (append_file_p) {
2588 zend_destroy_file_handle(append_file_p);
2589 }
2590
2591 if (EG(exception)) {
2592 zend_try {
2593 zend_exception_error(EG(exception), E_ERROR);
2594 } zend_end_try();
2595 }
2596
2597 #ifdef HAVE_BROKEN_GETCWD
2598 if (old_cwd_fd != -1) {
2599 fchdir(old_cwd_fd);
2600 close(old_cwd_fd);
2601 }
2602 #else
2603 if (old_cwd[0] != '\0') {
2604 php_ignore_value(VCWD_CHDIR(old_cwd));
2605 }
2606 free_alloca(old_cwd, use_heap);
2607 #endif
2608 return result;
2609 }
2610
2611 /* {{{ php_execute_script */
php_execute_script(zend_file_handle * primary_file)2612 PHPAPI bool php_execute_script(zend_file_handle *primary_file)
2613 {
2614 return php_execute_script_ex(primary_file, NULL);
2615 }
2616 /* }}} */
2617
2618 /* {{{ php_execute_simple_script */
php_execute_simple_script(zend_file_handle * primary_file,zval * ret)2619 PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval *ret)
2620 {
2621 char *old_cwd;
2622 ALLOCA_FLAG(use_heap)
2623
2624 EG(exit_status) = 0;
2625 #define OLD_CWD_SIZE 4096
2626 old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
2627 old_cwd[0] = '\0';
2628
2629 zend_try {
2630 #ifdef PHP_WIN32
2631 if(primary_file->filename) {
2632 UpdateIniFromRegistry(ZSTR_VAL(primary_file->filename));
2633 }
2634 #endif
2635
2636 PG(during_request_startup) = 0;
2637
2638 if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
2639 php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
2640 VCWD_CHDIR_FILE(ZSTR_VAL(primary_file->filename));
2641 }
2642 zend_execute_scripts(ZEND_REQUIRE, ret, 1, primary_file);
2643 } zend_end_try();
2644
2645 if (old_cwd[0] != '\0') {
2646 php_ignore_value(VCWD_CHDIR(old_cwd));
2647 }
2648
2649 free_alloca(old_cwd, use_heap);
2650 return EG(exit_status);
2651 }
2652 /* }}} */
2653
2654 /* {{{ php_handle_aborted_connection */
php_handle_aborted_connection(void)2655 PHPAPI void php_handle_aborted_connection(void)
2656 {
2657
2658 PG(connection_status) = PHP_CONNECTION_ABORTED;
2659 php_output_set_status(PHP_OUTPUT_DISABLED);
2660
2661 if (!PG(ignore_user_abort)) {
2662 zend_bailout();
2663 }
2664 }
2665 /* }}} */
2666
2667 /* {{{ php_handle_auth_data */
php_handle_auth_data(const char * auth)2668 PHPAPI int php_handle_auth_data(const char *auth)
2669 {
2670 int ret = -1;
2671 size_t auth_len = auth != NULL ? strlen(auth) : 0;
2672
2673 if (auth && auth_len > 0 && zend_binary_strncasecmp(auth, auth_len, "Basic ", sizeof("Basic ")-1, sizeof("Basic ")-1) == 0) {
2674 char *pass;
2675 zend_string *user;
2676
2677 user = php_base64_decode((const unsigned char*)auth + 6, auth_len - 6);
2678 if (user) {
2679 pass = strchr(ZSTR_VAL(user), ':');
2680 if (pass) {
2681 *pass++ = '\0';
2682 SG(request_info).auth_user = estrndup(ZSTR_VAL(user), ZSTR_LEN(user));
2683 if (strlen(pass) > 0) {
2684 SG(request_info).auth_password = estrdup(pass);
2685 }
2686 ret = 0;
2687 }
2688 zend_string_free(user);
2689 }
2690 }
2691
2692 if (ret == -1) {
2693 SG(request_info).auth_user = SG(request_info).auth_password = NULL;
2694 } else {
2695 SG(request_info).auth_digest = NULL;
2696 }
2697
2698 if (ret == -1 && auth && auth_len > 0 && zend_binary_strncasecmp(auth, auth_len, "Digest ", sizeof("Digest ")-1, sizeof("Digest ")-1) == 0) {
2699 SG(request_info).auth_digest = estrdup(auth + 7);
2700 ret = 0;
2701 }
2702
2703 if (ret == -1) {
2704 SG(request_info).auth_digest = NULL;
2705 }
2706
2707 return ret;
2708 }
2709 /* }}} */
2710
2711 /* {{{ php_lint_script */
php_lint_script(zend_file_handle * file)2712 PHPAPI zend_result php_lint_script(zend_file_handle *file)
2713 {
2714 zend_op_array *op_array;
2715 zend_result retval = FAILURE;
2716
2717 zend_try {
2718 op_array = zend_compile_file(file, ZEND_INCLUDE);
2719
2720 if (op_array) {
2721 destroy_op_array(op_array);
2722 efree(op_array);
2723 retval = SUCCESS;
2724 }
2725 } zend_end_try();
2726 if (EG(exception)) {
2727 zend_exception_error(EG(exception), E_ERROR);
2728 }
2729
2730 return retval;
2731 }
2732 /* }}} */
2733
2734 #ifdef ZTS
2735 /* {{{ php_reserve_tsrm_memory */
php_reserve_tsrm_memory(void)2736 PHPAPI void php_reserve_tsrm_memory(void)
2737 {
2738 tsrm_reserve(
2739 TSRM_ALIGNED_SIZE(sizeof(zend_compiler_globals)) +
2740 TSRM_ALIGNED_SIZE(sizeof(zend_executor_globals)) +
2741 TSRM_ALIGNED_SIZE(sizeof(zend_php_scanner_globals)) +
2742 TSRM_ALIGNED_SIZE(sizeof(zend_ini_scanner_globals)) +
2743 TSRM_ALIGNED_SIZE(sizeof(virtual_cwd_globals)) +
2744 #ifdef ZEND_SIGNALS
2745 TSRM_ALIGNED_SIZE(sizeof(zend_signal_globals_t)) +
2746 #endif
2747 TSRM_ALIGNED_SIZE(zend_mm_globals_size()) +
2748 TSRM_ALIGNED_SIZE(zend_gc_globals_size()) +
2749 TSRM_ALIGNED_SIZE(sizeof(php_core_globals)) +
2750 TSRM_ALIGNED_SIZE(sizeof(sapi_globals_struct))
2751 );
2752 }
2753 /* }}} */
2754
php_tsrm_startup_ex(int expected_threads)2755 PHPAPI bool php_tsrm_startup_ex(int expected_threads)
2756 {
2757 bool ret = tsrm_startup(expected_threads, 1, 0, NULL);
2758 php_reserve_tsrm_memory();
2759 (void)ts_resource(0);
2760 return ret;
2761 }
2762
2763 /* {{{ php_tsrm_startup */
php_tsrm_startup(void)2764 PHPAPI bool php_tsrm_startup(void)
2765 {
2766 return php_tsrm_startup_ex(1);
2767 }
2768 /* }}} */
2769 #endif
2770