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