xref: /PHP-8.2/main/main.c (revision 3fbca7fb)
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_ini_parse_uquantity_warn(new_value, entry->name);
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 			bool found = false;
362 
363 			if ((envpath = getenv("PATH")) != NULL) {
364 				char *search_dir, search_path[MAXPATHLEN];
365 				char *last = NULL;
366 				zend_stat_t s = {0};
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 = true;
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("error_log_mode",			"0644",			PHP_INI_ALL,		OnUpdateLong,					error_log_mode,			php_core_globals,	core_globals)
717 	STD_PHP_INI_ENTRY("extension_dir",			PHP_EXTENSION_DIR,		PHP_INI_SYSTEM,		OnUpdateStringUnempty,	extension_dir,			php_core_globals,	core_globals)
718 	STD_PHP_INI_ENTRY("sys_temp_dir",			NULL,		PHP_INI_SYSTEM,		OnUpdateStringUnempty,	sys_temp_dir,			php_core_globals,	core_globals)
719 	STD_PHP_INI_ENTRY("include_path",			PHP_INCLUDE_PATH,		PHP_INI_ALL,		OnUpdateStringUnempty,	include_path,			php_core_globals,	core_globals)
720 	PHP_INI_ENTRY("max_execution_time",			"30",		PHP_INI_ALL,			OnUpdateTimeout)
721 	STD_PHP_INI_ENTRY("open_basedir",			NULL,		PHP_INI_ALL,		OnUpdateBaseDir,			open_basedir,			php_core_globals,	core_globals)
722 
723 	STD_PHP_INI_BOOLEAN("file_uploads",			"1",		PHP_INI_SYSTEM,		OnUpdateBool,			file_uploads,			php_core_globals,	core_globals)
724 	STD_PHP_INI_ENTRY("upload_max_filesize",	"2M",		PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnUpdateLong,			upload_max_filesize,	php_core_globals,	core_globals)
725 	STD_PHP_INI_ENTRY("post_max_size",			"8M",		PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnUpdateLong,			post_max_size,			sapi_globals_struct,sapi_globals)
726 	STD_PHP_INI_ENTRY("upload_tmp_dir",			NULL,		PHP_INI_SYSTEM,		OnUpdateStringUnempty,	upload_tmp_dir,			php_core_globals,	core_globals)
727 	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)
728 	STD_PHP_INI_ENTRY("max_input_vars",			"1000",		PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnUpdateLongGEZero,	max_input_vars,						php_core_globals,	core_globals)
729 
730 	STD_PHP_INI_ENTRY("user_dir",				NULL,		PHP_INI_SYSTEM,		OnUpdateString,			user_dir,				php_core_globals,	core_globals)
731 	STD_PHP_INI_ENTRY("variables_order",		"EGPCS",	PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnUpdateStringUnempty,	variables_order,		php_core_globals,	core_globals)
732 	STD_PHP_INI_ENTRY("request_order",			NULL,		PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnUpdateString,	request_order,		php_core_globals,	core_globals)
733 
734 	STD_PHP_INI_ENTRY("error_append_string",	NULL,		PHP_INI_ALL,		OnUpdateString,			error_append_string,	php_core_globals,	core_globals)
735 	STD_PHP_INI_ENTRY("error_prepend_string",	NULL,		PHP_INI_ALL,		OnUpdateString,			error_prepend_string,	php_core_globals,	core_globals)
736 
737 	PHP_INI_ENTRY("SMTP",						"localhost",PHP_INI_ALL,		NULL)
738 	PHP_INI_ENTRY("smtp_port",					"25",		PHP_INI_ALL,		NULL)
739 	STD_PHP_INI_BOOLEAN("mail.add_x_header",			"0",		PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnUpdateBool,			mail_x_header,			php_core_globals,	core_globals)
740 	STD_PHP_INI_BOOLEAN("mail.mixed_lf_and_crlf",			"0",		PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnUpdateBool,			mail_mixed_lf_and_crlf,			php_core_globals,	core_globals)
741 	STD_PHP_INI_ENTRY("mail.log",					NULL,		PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnUpdateMailLog,			mail_log,			php_core_globals,	core_globals)
742 	PHP_INI_ENTRY("browscap",					NULL,		PHP_INI_SYSTEM,		OnChangeBrowscap)
743 	PHP_INI_ENTRY("memory_limit",				"128M",		PHP_INI_ALL,		OnChangeMemoryLimit)
744 	PHP_INI_ENTRY("precision",					"14",		PHP_INI_ALL,		OnSetPrecision)
745 	PHP_INI_ENTRY("sendmail_from",				NULL,		PHP_INI_ALL,		NULL)
746 	PHP_INI_ENTRY("sendmail_path",	DEFAULT_SENDMAIL_PATH,	PHP_INI_SYSTEM,		NULL)
747 	PHP_INI_ENTRY("mail.force_extra_parameters",NULL,		PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnChangeMailForceExtra)
748 	PHP_INI_ENTRY("disable_functions",			"",			PHP_INI_SYSTEM,		NULL)
749 	PHP_INI_ENTRY("disable_classes",			"",			PHP_INI_SYSTEM,		NULL)
750 	PHP_INI_ENTRY("max_file_uploads",			"20",			PHP_INI_SYSTEM|PHP_INI_PERDIR,		NULL)
751 	PHP_INI_ENTRY("max_multipart_body_parts",	"-1",			PHP_INI_SYSTEM|PHP_INI_PERDIR,		NULL)
752 
753 	STD_PHP_INI_BOOLEAN("allow_url_fopen",		"1",		PHP_INI_SYSTEM,		OnUpdateBool,		allow_url_fopen,		php_core_globals,		core_globals)
754 	STD_PHP_INI_BOOLEAN("allow_url_include",	"0",		PHP_INI_SYSTEM,		OnUpdateBool,		allow_url_include,		php_core_globals,		core_globals)
755 	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)
756 
757 	STD_PHP_INI_ENTRY("realpath_cache_size",	"4096K",	PHP_INI_SYSTEM,		OnUpdateLong,	realpath_cache_size_limit,	virtual_cwd_globals,	cwd_globals)
758 	STD_PHP_INI_ENTRY("realpath_cache_ttl",		"120",		PHP_INI_SYSTEM,		OnUpdateLong,	realpath_cache_ttl,			virtual_cwd_globals,	cwd_globals)
759 
760 	STD_PHP_INI_ENTRY("user_ini.filename",		".user.ini",	PHP_INI_SYSTEM,		OnUpdateString,		user_ini_filename,	php_core_globals,		core_globals)
761 	STD_PHP_INI_ENTRY("user_ini.cache_ttl",		"300",			PHP_INI_SYSTEM,		OnUpdateLong,		user_ini_cache_ttl,	php_core_globals,		core_globals)
762 	STD_PHP_INI_ENTRY("hard_timeout",			"2",			PHP_INI_SYSTEM,		OnUpdateLong,		hard_timeout,		zend_executor_globals,	executor_globals)
763 #ifdef PHP_WIN32
764 	STD_PHP_INI_BOOLEAN("windows.show_crt_warning",		"0",		PHP_INI_ALL,		OnUpdateBool,			windows_show_crt_warning,			php_core_globals,	core_globals)
765 #endif
766 	STD_PHP_INI_ENTRY("syslog.facility",		"LOG_USER",		PHP_INI_SYSTEM,		OnSetFacility,		syslog_facility,	php_core_globals,		core_globals)
767 	STD_PHP_INI_ENTRY("syslog.ident",		"php",			PHP_INI_SYSTEM,		OnUpdateString,		syslog_ident,		php_core_globals,		core_globals)
768 	STD_PHP_INI_ENTRY("syslog.filter",		"no-ctrl",		PHP_INI_ALL,		OnSetLogFilter,		syslog_filter,		php_core_globals, 		core_globals)
769 PHP_INI_END()
770 /* }}} */
771 
772 /* True globals (no need for thread safety */
773 /* But don't make them a single int bitfield */
774 static bool module_initialized = false;
775 static bool module_startup = true;
776 static bool module_shutdown = false;
777 
778 /* {{{ php_during_module_startup */
php_during_module_startup(void)779 PHPAPI bool php_during_module_startup(void)
780 {
781 	return module_startup;
782 }
783 /* }}} */
784 
785 /* {{{ php_during_module_shutdown */
php_during_module_shutdown(void)786 PHPAPI bool php_during_module_shutdown(void)
787 {
788 	return module_shutdown;
789 }
790 /* }}} */
791 
792 /* {{{ php_get_module_initialized */
php_get_module_initialized(void)793 PHPAPI bool php_get_module_initialized(void)
794 {
795 	return module_initialized;
796 }
797 /* }}} */
798 
799 /* {{{ php_log_err_with_severity */
php_log_err_with_severity(const char * log_message,int syslog_type_int)800 PHPAPI ZEND_COLD void php_log_err_with_severity(const char *log_message, int syslog_type_int)
801 {
802 	int fd = -1;
803 	time_t error_time;
804 
805 	if (PG(in_error_log)) {
806 		/* prevent recursive invocation */
807 		return;
808 	}
809 	PG(in_error_log) = 1;
810 
811 	/* Try to use the specified logging location. */
812 	if (PG(error_log) != NULL) {
813 		int error_log_mode;
814 
815 #ifdef HAVE_SYSLOG_H
816 		if (!strcmp(PG(error_log), "syslog")) {
817 			php_syslog(syslog_type_int, "%s", log_message);
818 			PG(in_error_log) = 0;
819 			return;
820 		}
821 #endif
822 
823 		error_log_mode = 0644;
824 
825 		if (PG(error_log_mode) > 0 && PG(error_log_mode) <= 0777) {
826 			error_log_mode = PG(error_log_mode);
827 		}
828 
829 		fd = VCWD_OPEN_MODE(PG(error_log), O_CREAT | O_APPEND | O_WRONLY, error_log_mode);
830 		if (fd != -1) {
831 			char *tmp;
832 			size_t len;
833 			zend_string *error_time_str;
834 
835 			time(&error_time);
836 #ifdef ZTS
837 			if (!php_during_module_startup()) {
838 				error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 1);
839 			} else {
840 				error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 0);
841 			}
842 #else
843 			error_time_str = php_format_date("d-M-Y H:i:s e", 13, error_time, 1);
844 #endif
845 			len = spprintf(&tmp, 0, "[%s] %s%s", ZSTR_VAL(error_time_str), log_message, PHP_EOL);
846 #ifdef PHP_WIN32
847 			php_flock(fd, LOCK_EX);
848 			/* XXX should eventually write in a loop if len > UINT_MAX */
849 			php_ignore_value(write(fd, tmp, (unsigned)len));
850 			php_flock(fd, LOCK_UN);
851 #else
852 			php_ignore_value(write(fd, tmp, len));
853 #endif
854 			efree(tmp);
855 			zend_string_free(error_time_str);
856 			close(fd);
857 			PG(in_error_log) = 0;
858 			return;
859 		}
860 	}
861 
862 	/* Otherwise fall back to the default logging location, if we have one */
863 
864 	if (sapi_module.log_message) {
865 		sapi_module.log_message(log_message, syslog_type_int);
866 	}
867 	PG(in_error_log) = 0;
868 }
869 /* }}} */
870 
871 /* {{{ php_write
872    wrapper for modules to use PHPWRITE */
php_write(void * buf,size_t size)873 PHPAPI size_t php_write(void *buf, size_t size)
874 {
875 	return PHPWRITE(buf, size);
876 }
877 /* }}} */
878 
879 /* {{{ php_printf */
php_printf(const char * format,...)880 PHPAPI size_t php_printf(const char *format, ...)
881 {
882 	va_list args;
883 	size_t ret;
884 	char *buffer;
885 	size_t size;
886 
887 	va_start(args, format);
888 	size = vspprintf(&buffer, 0, format, args);
889 	ret = PHPWRITE(buffer, size);
890 	efree(buffer);
891 	va_end(args);
892 
893 	return ret;
894 }
895 /* }}} */
896 
897 /* {{{ php_printf_unchecked */
php_printf_unchecked(const char * format,...)898 PHPAPI size_t php_printf_unchecked(const char *format, ...)
899 {
900 	va_list args;
901 	size_t ret;
902 	char *buffer;
903 	size_t size;
904 
905 	va_start(args, format);
906 	size = vspprintf(&buffer, 0, format, args);
907 	ret = PHPWRITE(buffer, size);
908 	efree(buffer);
909 	va_end(args);
910 
911 	return ret;
912 }
913 /* }}} */
914 
escape_html(const char * buffer,size_t buffer_len)915 static zend_string *escape_html(const char *buffer, size_t buffer_len) {
916 	zend_string *result = php_escape_html_entities_ex(
917 		(const unsigned char *) buffer, buffer_len, 0, ENT_COMPAT,
918 		/* charset_hint */ NULL, /* double_encode */ 1, /* quiet */ 1);
919 	if (!result || ZSTR_LEN(result) == 0) {
920 		/* Retry with substituting invalid chars on fail. */
921 		result = php_escape_html_entities_ex(
922 			(const unsigned char *) buffer, buffer_len, 0, ENT_COMPAT | ENT_HTML_SUBSTITUTE_ERRORS,
923 			/* charset_hint */ NULL, /* double_encode */ 1, /* quiet */ 1);
924 	}
925 	return result;
926 }
927 
928 /* {{{ php_verror */
929 /* php_verror is called from php_error_docref<n> functions.
930  * Its purpose is to unify error messages and automatically generate clickable
931  * html error messages if corresponding ini setting (html_errors) is activated.
932  * See: CODING_STANDARDS.md for details.
933  */
php_verror(const char * docref,const char * params,int type,const char * format,va_list args)934 PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int type, const char *format, va_list args)
935 {
936 	zend_string *replace_buffer = NULL, *replace_origin = NULL;
937 	char *buffer = NULL, *docref_buf = NULL, *target = NULL;
938 	char *docref_target = "", *docref_root = "";
939 	char *p;
940 	int buffer_len = 0;
941 	const char *space = "";
942 	const char *class_name = "";
943 	const char *function;
944 	int origin_len;
945 	char *origin;
946 	zend_string *message;
947 	int is_function = 0;
948 
949 	/* get error text into buffer and escape for html if necessary */
950 	buffer_len = (int)vspprintf(&buffer, 0, format, args);
951 
952 	if (PG(html_errors)) {
953 		replace_buffer = escape_html(buffer, buffer_len);
954 		efree(buffer);
955 
956 		if (replace_buffer) {
957 			buffer = ZSTR_VAL(replace_buffer);
958 			buffer_len = (int)ZSTR_LEN(replace_buffer);
959 		} else {
960 			buffer = "";
961 			buffer_len = 0;
962 		}
963 	}
964 
965 	/* which function caused the problem if any at all */
966 	if (php_during_module_startup()) {
967 		function = "PHP Startup";
968 	} else if (php_during_module_shutdown()) {
969 		function = "PHP Shutdown";
970 	} else if (PG(during_request_startup)) {
971 		function = "PHP Request Startup";
972 	} else if (EG(current_execute_data) &&
973 				EG(current_execute_data)->func &&
974 				ZEND_USER_CODE(EG(current_execute_data)->func->common.type) &&
975 				EG(current_execute_data)->opline &&
976 				EG(current_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL
977 	) {
978 		switch (EG(current_execute_data)->opline->extended_value) {
979 			case ZEND_EVAL:
980 				function = "eval";
981 				is_function = 1;
982 				break;
983 			case ZEND_INCLUDE:
984 				function = "include";
985 				is_function = 1;
986 				break;
987 			case ZEND_INCLUDE_ONCE:
988 				function = "include_once";
989 				is_function = 1;
990 				break;
991 			case ZEND_REQUIRE:
992 				function = "require";
993 				is_function = 1;
994 				break;
995 			case ZEND_REQUIRE_ONCE:
996 				function = "require_once";
997 				is_function = 1;
998 				break;
999 			default:
1000 				function = "Unknown";
1001 		}
1002 	} else if ((function = get_active_function_name()) && strlen(function)) {
1003 		is_function = 1;
1004 		class_name = get_active_class_name(&space);
1005 	} else if (EG(flags) & EG_FLAGS_IN_SHUTDOWN) {
1006 		function = "PHP Request Shutdown";
1007 	} else {
1008 		function = "Unknown";
1009 	}
1010 
1011 	/* if we still have memory then format the origin */
1012 	if (is_function) {
1013 		origin_len = (int)spprintf(&origin, 0, "%s%s%s(%s)", class_name, space, function, params);
1014 	} else {
1015 		origin_len = (int)spprintf(&origin, 0, "%s", function);
1016 	}
1017 
1018 	if (PG(html_errors)) {
1019 		replace_origin = escape_html(origin, origin_len);
1020 		efree(origin);
1021 		origin = ZSTR_VAL(replace_origin);
1022 	}
1023 
1024 	/* origin and buffer available, so lets come up with the error message */
1025 	if (docref && docref[0] == '#') {
1026 		docref_target = strchr(docref, '#');
1027 		docref = NULL;
1028 	}
1029 
1030 	/* no docref given but function is known (the default) */
1031 	if (!docref && is_function) {
1032 		int doclen;
1033 		while (*function == '_') {
1034 			function++;
1035 		}
1036 		if (space[0] == '\0') {
1037 			doclen = (int)spprintf(&docref_buf, 0, "function.%s", function);
1038 		} else {
1039 			doclen = (int)spprintf(&docref_buf, 0, "%s.%s", class_name, function);
1040 		}
1041 		while((p = strchr(docref_buf, '_')) != NULL) {
1042 			*p = '-';
1043 		}
1044 		zend_str_tolower(docref_buf, doclen);
1045 		docref = docref_buf;
1046 	}
1047 
1048 	/* we have a docref for a function AND
1049 	 * - we show errors in html mode AND
1050 	 * - the user wants to see the links
1051 	 */
1052 	if (docref && is_function && PG(html_errors) && strlen(PG(docref_root))) {
1053 		if (strncmp(docref, "http://", 7)) {
1054 			/* We don't have 'http://' so we use docref_root */
1055 
1056 			char *ref;  /* temp copy for duplicated docref */
1057 
1058 			docref_root = PG(docref_root);
1059 
1060 			ref = estrdup(docref);
1061 			if (docref_buf) {
1062 				efree(docref_buf);
1063 			}
1064 			docref_buf = ref;
1065 			/* strip of the target if any */
1066 			p = strrchr(ref, '#');
1067 			if (p) {
1068 				target = estrdup(p);
1069 				if (target) {
1070 					docref_target = target;
1071 					*p = '\0';
1072 				}
1073 			}
1074 			/* add the extension if it is set in ini */
1075 			if (PG(docref_ext) && strlen(PG(docref_ext))) {
1076 				spprintf(&docref_buf, 0, "%s%s", ref, PG(docref_ext));
1077 				efree(ref);
1078 			}
1079 			docref = docref_buf;
1080 		}
1081 		/* display html formatted or only show the additional links */
1082 		if (PG(html_errors)) {
1083 			message = zend_strpprintf(0, "%s [<a href='%s%s%s'>%s</a>]: %s", origin, docref_root, docref, docref_target, docref, buffer);
1084 		} else {
1085 			message = zend_strpprintf(0, "%s [%s%s%s]: %s", origin, docref_root, docref, docref_target, buffer);
1086 		}
1087 		if (target) {
1088 			efree(target);
1089 		}
1090 	} else {
1091 		message = zend_strpprintf(0, "%s: %s", origin, buffer);
1092 	}
1093 	if (replace_origin) {
1094 		zend_string_free(replace_origin);
1095 	} else {
1096 		efree(origin);
1097 	}
1098 	if (docref_buf) {
1099 		efree(docref_buf);
1100 	}
1101 
1102 	if (replace_buffer) {
1103 		zend_string_free(replace_buffer);
1104 	} else {
1105 		efree(buffer);
1106 	}
1107 
1108 	zend_error_zstr(type, message);
1109 	zend_string_release(message);
1110 }
1111 /* }}} */
1112 
1113 /* {{{ php_error_docref */
1114 /* 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,...)1115 PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format, ...)
1116 {
1117 	va_list args;
1118 
1119 	va_start(args, format);
1120 	php_verror(docref, "", type, format, args);
1121 	va_end(args);
1122 }
1123 /* }}} */
1124 
1125 /* {{{ php_error_docref1 */
1126 /* See: CODING_STANDARDS.md for details. */
php_error_docref1(const char * docref,const char * param1,int type,const char * format,...)1127 PHPAPI ZEND_COLD void php_error_docref1(const char *docref, const char *param1, int type, const char *format, ...)
1128 {
1129 	va_list args;
1130 
1131 	va_start(args, format);
1132 	php_verror(docref, param1, type, format, args);
1133 	va_end(args);
1134 }
1135 /* }}} */
1136 
1137 /* {{{ php_error_docref2 */
1138 /* See: CODING_STANDARDS.md for details. */
php_error_docref2(const char * docref,const char * param1,const char * param2,int type,const char * format,...)1139 PHPAPI ZEND_COLD void php_error_docref2(const char *docref, const char *param1, const char *param2, int type, const char *format, ...)
1140 {
1141 	char *params;
1142 	va_list args;
1143 
1144 	spprintf(&params, 0, "%s,%s", param1, param2);
1145 	va_start(args, format);
1146 	php_verror(docref, params ? params : "...", type, format, args);
1147 	va_end(args);
1148 	if (params) {
1149 		efree(params);
1150 	}
1151 }
1152 /* }}} */
1153 
1154 #ifdef PHP_WIN32
php_win32_docref1_from_error(DWORD error,const char * param1)1155 PHPAPI ZEND_COLD void php_win32_docref1_from_error(DWORD error, const char *param1) {
1156 	char *buf = php_win32_error_to_msg(error);
1157 	size_t buf_len;
1158 
1159 	buf_len = strlen(buf);
1160 	if (buf_len >= 2) {
1161 		buf[buf_len - 1] = '\0';
1162 		buf[buf_len - 2] = '\0';
1163 	}
1164 	php_error_docref1(NULL, param1, E_WARNING, "%s (code: %lu)", buf, error);
1165 	php_win32_error_msg_free(buf);
1166 }
1167 
php_win32_docref2_from_error(DWORD error,const char * param1,const char * param2)1168 PHPAPI ZEND_COLD void php_win32_docref2_from_error(DWORD error, const char *param1, const char *param2) {
1169 	char *buf = php_win32_error_to_msg(error);
1170 	php_error_docref2(NULL, param1, param2, E_WARNING, "%s (code: %lu)", buf, error);
1171 	php_win32_error_msg_free(buf);
1172 }
1173 #endif
1174 
1175 /* {{{ php_html_puts */
php_html_puts(const char * str,size_t size)1176 PHPAPI void php_html_puts(const char *str, size_t size)
1177 {
1178 	zend_html_puts(str, size);
1179 }
1180 /* }}} */
1181 
clear_last_error(void)1182 static void clear_last_error(void) {
1183 	if (PG(last_error_message)) {
1184 		zend_string_release(PG(last_error_message));
1185 		PG(last_error_message) = NULL;
1186 	}
1187 	if (PG(last_error_file)) {
1188 		zend_string_release(PG(last_error_file));
1189 		PG(last_error_file) = NULL;
1190 	}
1191 }
1192 
1193 #if ZEND_DEBUG
1194 /* {{{ 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)1195 static void report_zend_debug_error_notify_cb(int type, zend_string *error_filename, uint32_t error_lineno, zend_string *message)
1196 {
1197 	if (PG(report_zend_debug)) {
1198 		bool trigger_break;
1199 
1200 		switch (type) {
1201 			case E_ERROR:
1202 			case E_CORE_ERROR:
1203 			case E_COMPILE_ERROR:
1204 			case E_USER_ERROR:
1205 				trigger_break=1;
1206 				break;
1207 			default:
1208 				trigger_break=0;
1209 				break;
1210 		}
1211 
1212 		zend_output_debug_string(trigger_break, "%s(%" PRIu32 ") : %s", ZSTR_VAL(error_filename), error_lineno, ZSTR_VAL(message));
1213 	}
1214 }
1215 /* }}} */
1216 #endif
1217 
1218 /* {{{ php_error_cb
1219  extended error handling function */
php_error_cb(int orig_type,zend_string * error_filename,const uint32_t error_lineno,zend_string * message)1220 static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, const uint32_t error_lineno, zend_string *message)
1221 {
1222 	bool display;
1223 	int type = orig_type & E_ALL;
1224 
1225 	/* check for repeated errors to be ignored */
1226 	if (PG(ignore_repeated_errors) && PG(last_error_message)) {
1227 		/* no check for PG(last_error_file) is needed since it cannot
1228 		 * be NULL if PG(last_error_message) is not NULL */
1229 		if (!zend_string_equals(PG(last_error_message), message)
1230 			|| (!PG(ignore_repeated_source)
1231 				&& ((PG(last_error_lineno) != (int)error_lineno)
1232 					|| !zend_string_equals(PG(last_error_file), error_filename)))) {
1233 			display = 1;
1234 		} else {
1235 			display = 0;
1236 		}
1237 	} else {
1238 		display = 1;
1239 	}
1240 
1241 	/* according to error handling mode, throw exception or show it */
1242 	if (EG(error_handling) == EH_THROW) {
1243 		switch (type) {
1244 			case E_WARNING:
1245 			case E_CORE_WARNING:
1246 			case E_COMPILE_WARNING:
1247 			case E_USER_WARNING:
1248 				/* throw an exception if we are in EH_THROW mode and the type is warning.
1249 				 * fatal errors are real errors and cannot be made exceptions.
1250 				 * exclude deprecated for the sake of BC to old damaged code.
1251 				 * notices are no errors and are not treated as such like E_WARNINGS.
1252 				 * DO NOT overwrite a pending exception.
1253 				 */
1254 				if (!EG(exception)) {
1255 					zend_throw_error_exception(EG(exception_class), message, 0, type);
1256 				}
1257 				return;
1258 			default:
1259 				break;
1260 		}
1261 	}
1262 
1263 	/* store the error if it has changed */
1264 	if (display) {
1265 		clear_last_error();
1266 		if (!error_filename) {
1267 			error_filename = ZSTR_KNOWN(ZEND_STR_UNKNOWN_CAPITALIZED);
1268 		}
1269 		PG(last_error_type) = type;
1270 		PG(last_error_message) = zend_string_copy(message);
1271 		PG(last_error_file) = zend_string_copy(error_filename);
1272 		PG(last_error_lineno) = error_lineno;
1273 	}
1274 
1275 	if (zend_alloc_in_memory_limit_error_reporting()) {
1276 		php_output_discard_all();
1277 	}
1278 
1279 	/* display/log the error if necessary */
1280 	if (display && ((EG(error_reporting) & type) || (type & E_CORE))
1281 		&& (PG(log_errors) || PG(display_errors) || (!module_initialized))) {
1282 		char *error_type_str;
1283 		int syslog_type_int = LOG_NOTICE;
1284 
1285 		switch (type) {
1286 			case E_ERROR:
1287 			case E_CORE_ERROR:
1288 			case E_COMPILE_ERROR:
1289 			case E_USER_ERROR:
1290 				error_type_str = "Fatal error";
1291 				syslog_type_int = LOG_ERR;
1292 				break;
1293 			case E_RECOVERABLE_ERROR:
1294 				error_type_str = "Recoverable fatal error";
1295 				syslog_type_int = LOG_ERR;
1296 				break;
1297 			case E_WARNING:
1298 			case E_CORE_WARNING:
1299 			case E_COMPILE_WARNING:
1300 			case E_USER_WARNING:
1301 				error_type_str = "Warning";
1302 				syslog_type_int = LOG_WARNING;
1303 				break;
1304 			case E_PARSE:
1305 				error_type_str = "Parse error";
1306 				syslog_type_int = LOG_ERR;
1307 				break;
1308 			case E_NOTICE:
1309 			case E_USER_NOTICE:
1310 				error_type_str = "Notice";
1311 				syslog_type_int = LOG_NOTICE;
1312 				break;
1313 			case E_STRICT:
1314 				error_type_str = "Strict Standards";
1315 				syslog_type_int = LOG_INFO;
1316 				break;
1317 			case E_DEPRECATED:
1318 			case E_USER_DEPRECATED:
1319 				error_type_str = "Deprecated";
1320 				syslog_type_int = LOG_INFO;
1321 				break;
1322 			default:
1323 				error_type_str = "Unknown error";
1324 				break;
1325 		}
1326 
1327 		if (PG(log_errors)
1328 				|| (!module_initialized && (!PG(display_startup_errors) || !PG(display_errors)))) {
1329 			char *log_buffer;
1330 #ifdef PHP_WIN32
1331 			if (type == E_CORE_ERROR || type == E_CORE_WARNING) {
1332 				syslog(LOG_ALERT, "PHP %s: %s (%s)", error_type_str, ZSTR_VAL(message), GetCommandLine());
1333 			}
1334 #endif
1335 			spprintf(&log_buffer, 0, "PHP %s:  %s in %s on line %" PRIu32, error_type_str, ZSTR_VAL(message), ZSTR_VAL(error_filename), error_lineno);
1336 			php_log_err_with_severity(log_buffer, syslog_type_int);
1337 			efree(log_buffer);
1338 		}
1339 
1340 		if (PG(display_errors) && ((module_initialized && !PG(during_request_startup)) || (PG(display_startup_errors)))) {
1341 			if (PG(xmlrpc_errors)) {
1342 				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);
1343 			} else {
1344 				char *prepend_string = INI_STR("error_prepend_string");
1345 				char *append_string = INI_STR("error_append_string");
1346 
1347 				if (PG(html_errors)) {
1348 					if (type == E_ERROR || type == E_PARSE) {
1349 						zend_string *buf = escape_html(ZSTR_VAL(message), ZSTR_LEN(message));
1350 						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));
1351 						zend_string_free(buf);
1352 					} else {
1353 						zval tmp;
1354 						ZVAL_STR(&tmp, message);
1355 						php_printf_unchecked("%s<br />\n<b>%s</b>:  %Z in <b>%s</b> on line <b>%" PRIu32 "</b><br />\n%s", STR_PRINT(prepend_string), error_type_str, &tmp, ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
1356 					}
1357 				} else {
1358 					/* Write CLI/CGI errors to stderr if display_errors = "stderr" */
1359 					if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")) &&
1360 						PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR
1361 					) {
1362 						fprintf(stderr, "%s: ", error_type_str);
1363 						fwrite(ZSTR_VAL(message), sizeof(char), ZSTR_LEN(message), stderr);
1364 						fprintf(stderr, " in %s on line %" PRIu32 "\n", ZSTR_VAL(error_filename), error_lineno);
1365 #ifdef PHP_WIN32
1366 						fflush(stderr);
1367 #endif
1368 					} else {
1369 						zval tmp;
1370 						ZVAL_STR(&tmp, message);
1371 						php_printf_unchecked("%s\n%s: %Z in %s on line %" PRIu32 "\n%s", STR_PRINT(prepend_string), error_type_str, &tmp, ZSTR_VAL(error_filename), error_lineno, STR_PRINT(append_string));
1372 					}
1373 				}
1374 			}
1375 		}
1376 	}
1377 
1378 	/* Bail out if we can't recover */
1379 	switch (type) {
1380 		case E_CORE_ERROR:
1381 			if(!module_initialized) {
1382 				/* bad error in module startup - no way we can live with this */
1383 				exit(-2);
1384 			}
1385 		ZEND_FALLTHROUGH;
1386 		case E_ERROR:
1387 		case E_RECOVERABLE_ERROR:
1388 		case E_PARSE:
1389 		case E_COMPILE_ERROR:
1390 		case E_USER_ERROR:
1391 			EG(exit_status) = 255;
1392 			if (module_initialized) {
1393 				if (!PG(display_errors) &&
1394 				    !SG(headers_sent) &&
1395 					SG(sapi_headers).http_response_code == 200
1396 				) {
1397 					sapi_header_line ctr = {0};
1398 
1399 					ctr.line = "HTTP/1.0 500 Internal Server Error";
1400 					ctr.line_len = sizeof("HTTP/1.0 500 Internal Server Error") - 1;
1401 					sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
1402 				}
1403 				/* the parser would return 1 (failure), we can bail out nicely */
1404 				if (!(orig_type & E_DONT_BAIL)) {
1405 					/* restore memory limit */
1406 					zend_set_memory_limit(PG(memory_limit));
1407 					zend_objects_store_mark_destructed(&EG(objects_store));
1408 					if (CG(in_compilation) && (type == E_COMPILE_ERROR || type == E_PARSE)) {
1409 						/* We bailout during compilation which may for example leave stale entries in CG(loop_var_stack).
1410 						 * If code is compiled during shutdown, we need to make sure the compiler is reset to a clean state,
1411 						 * otherwise this will lead to incorrect compilation during shutdown.
1412 						 * We don't do a full re-initialization via init_compiler() because that will also reset streams and resources. */
1413 						shutdown_compiler();
1414 						zend_init_compiler_data_structures();
1415 					}
1416 					zend_bailout();
1417 					return;
1418 				}
1419 			}
1420 			break;
1421 	}
1422 }
1423 /* }}} */
1424 
1425 /* {{{ php_get_current_user */
php_get_current_user(void)1426 PHPAPI char *php_get_current_user(void)
1427 {
1428 	zend_stat_t *pstat = NULL;
1429 
1430 	if (SG(request_info).current_user) {
1431 		return SG(request_info).current_user;
1432 	}
1433 
1434 	/* FIXME: I need to have this somehow handled if
1435 	USE_SAPI is defined, because cgi will also be
1436 	interfaced in USE_SAPI */
1437 
1438 	pstat = sapi_get_stat();
1439 
1440 	if (!pstat) {
1441 		return "";
1442 	} else {
1443 #ifdef PHP_WIN32
1444 		char *name = php_win32_get_username();
1445 		int len;
1446 
1447 		if (!name) {
1448 			return "";
1449 		}
1450 		len = (int)strlen(name);
1451 		name[len] = '\0';
1452 		SG(request_info).current_user_length = len;
1453 		SG(request_info).current_user = estrndup(name, len);
1454 		free(name);
1455 		return SG(request_info).current_user;
1456 #else
1457 		struct passwd *pwd;
1458 #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
1459 		struct passwd _pw;
1460 		struct passwd *retpwptr = NULL;
1461 		int pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1462 		char *pwbuf;
1463 		int err;
1464 
1465 		if (pwbuflen < 1) {
1466 			pwbuflen = 1024;
1467 		}
1468 # if ZEND_DEBUG
1469 		/* Test retry logic */
1470 		pwbuflen = 1;
1471 # endif
1472 		pwbuf = emalloc(pwbuflen);
1473 
1474 try_again:
1475 		err = getpwuid_r(pstat->st_uid, &_pw, pwbuf, pwbuflen, &retpwptr);
1476 		if (err != 0) {
1477 			if (err == ERANGE) {
1478 				pwbuflen *= 2;
1479 				pwbuf = erealloc(pwbuf, pwbuflen);
1480 				goto try_again;
1481 			}
1482 			efree(pwbuf);
1483 			return "";
1484 		}
1485 		if (retpwptr == NULL) {
1486 			efree(pwbuf);
1487 			return "";
1488 		}
1489 		pwd = &_pw;
1490 #else
1491 		if ((pwd=getpwuid(pstat->st_uid))==NULL) {
1492 			return "";
1493 		}
1494 #endif
1495 		SG(request_info).current_user_length = strlen(pwd->pw_name);
1496 		SG(request_info).current_user = estrndup(pwd->pw_name, SG(request_info).current_user_length);
1497 #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
1498 		efree(pwbuf);
1499 #endif
1500 		return SG(request_info).current_user;
1501 #endif
1502 	}
1503 }
1504 /* }}} */
1505 
1506 /* {{{ Sets the maximum time a script can run */
PHP_FUNCTION(set_time_limit)1507 PHP_FUNCTION(set_time_limit)
1508 {
1509 	zend_long new_timeout;
1510 	char *new_timeout_str;
1511 	size_t new_timeout_strlen;
1512 	zend_string *key;
1513 
1514 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &new_timeout) == FAILURE) {
1515 		RETURN_THROWS();
1516 	}
1517 
1518 	new_timeout_strlen = zend_spprintf(&new_timeout_str, 0, ZEND_LONG_FMT, new_timeout);
1519 
1520 	key = zend_string_init("max_execution_time", sizeof("max_execution_time")-1, 0);
1521 	if (zend_alter_ini_entry_chars_ex(key, new_timeout_str, new_timeout_strlen, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == SUCCESS) {
1522 		RETVAL_TRUE;
1523 	} else {
1524 		RETVAL_FALSE;
1525 	}
1526 	zend_string_release_ex(key, 0);
1527 	efree(new_timeout_str);
1528 }
1529 /* }}} */
1530 
1531 /* {{{ php_fopen_wrapper_for_zend */
php_fopen_wrapper_for_zend(zend_string * filename,zend_string ** opened_path)1532 static FILE *php_fopen_wrapper_for_zend(zend_string *filename, zend_string **opened_path)
1533 {
1534 	*opened_path = filename;
1535 	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);
1536 }
1537 /* }}} */
1538 
php_zend_stream_closer(void * handle)1539 static void php_zend_stream_closer(void *handle) /* {{{ */
1540 {
1541 	php_stream_close((php_stream*)handle);
1542 }
1543 /* }}} */
1544 
php_zend_stream_fsizer(void * handle)1545 static size_t php_zend_stream_fsizer(void *handle) /* {{{ */
1546 {
1547 	php_stream *stream = handle;
1548 	php_stream_statbuf ssb;
1549 
1550 	/* File size reported by stat() may be inaccurate if stream filters are used.
1551 	 * TODO: Should stat() be generally disabled if filters are used? */
1552 	if (stream->readfilters.head) {
1553 		return 0;
1554 	}
1555 
1556 	if (php_stream_stat(stream, &ssb) == 0) {
1557 		return ssb.sb.st_size;
1558 	}
1559 	return 0;
1560 }
1561 /* }}} */
1562 
php_stream_open_for_zend(zend_file_handle * handle)1563 static zend_result php_stream_open_for_zend(zend_file_handle *handle) /* {{{ */
1564 {
1565 	return php_stream_open_for_zend_ex(handle, USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE);
1566 }
1567 /* }}} */
1568 
php_stream_open_for_zend_ex(zend_file_handle * handle,int mode)1569 PHPAPI zend_result php_stream_open_for_zend_ex(zend_file_handle *handle, int mode) /* {{{ */
1570 {
1571 	zend_string *opened_path;
1572 	zend_string *filename;
1573 	php_stream *stream;
1574 
1575 	ZEND_ASSERT(handle->type == ZEND_HANDLE_FILENAME);
1576 	opened_path = filename = handle->filename;
1577 	stream = php_stream_open_wrapper((char *)ZSTR_VAL(filename), "rb", mode | STREAM_OPEN_FOR_ZEND_STREAM, &opened_path);
1578 	if (stream) {
1579 		memset(handle, 0, sizeof(zend_file_handle));
1580 		handle->type = ZEND_HANDLE_STREAM;
1581 		handle->filename = filename;
1582 		handle->opened_path = opened_path;
1583 		handle->handle.stream.handle  = stream;
1584 		handle->handle.stream.reader  = (zend_stream_reader_t)_php_stream_read;
1585 		handle->handle.stream.fsizer  = php_zend_stream_fsizer;
1586 		handle->handle.stream.isatty  = 0;
1587 		handle->handle.stream.closer = php_zend_stream_closer;
1588 		/* suppress warning if this stream is not explicitly closed */
1589 		php_stream_auto_cleanup(stream);
1590 		/* Disable buffering to avoid double buffering between PHP and Zend streams. */
1591 		php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
1592 
1593 		return SUCCESS;
1594 	}
1595 	return FAILURE;
1596 }
1597 /* }}} */
1598 
php_resolve_path_for_zend(zend_string * filename)1599 static zend_string *php_resolve_path_for_zend(zend_string *filename) /* {{{ */
1600 {
1601 	return php_resolve_path(ZSTR_VAL(filename), ZSTR_LEN(filename), PG(include_path));
1602 }
1603 /* }}} */
1604 
1605 /* {{{ php_get_configuration_directive_for_zend */
php_get_configuration_directive_for_zend(zend_string * name)1606 static zval *php_get_configuration_directive_for_zend(zend_string *name)
1607 {
1608 	return cfg_get_entry_ex(name);
1609 }
1610 /* }}} */
1611 
1612 /* {{{ php_free_request_globals */
php_free_request_globals(void)1613 static void php_free_request_globals(void)
1614 {
1615 	clear_last_error();
1616 	if (PG(php_sys_temp_dir)) {
1617 		efree(PG(php_sys_temp_dir));
1618 		PG(php_sys_temp_dir) = NULL;
1619 	}
1620 
1621 	EG(filename_override) = NULL;
1622 	EG(lineno_override) = -1;
1623 }
1624 /* }}} */
1625 
1626 /* {{{ php_message_handler_for_zend */
php_message_handler_for_zend(zend_long message,const void * data)1627 static ZEND_COLD void php_message_handler_for_zend(zend_long message, const void *data)
1628 {
1629 	switch (message) {
1630 		case ZMSG_FAILED_INCLUDE_FOPEN: {
1631 			char *tmp = estrdup((char *) data);
1632 			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)));
1633 			efree(tmp);
1634 			break;
1635 		}
1636 		case ZMSG_FAILED_REQUIRE_FOPEN: {
1637 			char *tmp = estrdup((char *) data);
1638 			zend_throw_error(NULL, "Failed opening required '%s' (include_path='%s')", php_strip_url_passwd(tmp), STR_PRINT(PG(include_path)));
1639 			efree(tmp);
1640 			break;
1641 		}
1642 		case ZMSG_FAILED_HIGHLIGHT_FOPEN: {
1643 			char *tmp = estrdup((char *) data);
1644 			php_error_docref(NULL, E_WARNING, "Failed opening '%s' for highlighting", php_strip_url_passwd(tmp));
1645 			efree(tmp);
1646 			break;
1647 		}
1648 		case ZMSG_MEMORY_LEAK_DETECTED:
1649 		case ZMSG_MEMORY_LEAK_REPEATED:
1650 #if ZEND_DEBUG
1651 			if (EG(error_reporting) & E_WARNING) {
1652 				char memory_leak_buf[1024];
1653 
1654 				if (message==ZMSG_MEMORY_LEAK_DETECTED) {
1655 					zend_leak_info *t = (zend_leak_info *) data;
1656 
1657 					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));
1658 					if (t->orig_filename) {
1659 						char relay_buf[512];
1660 
1661 						snprintf(relay_buf, 512, "%s(%" PRIu32 ") : Actual location (location was relayed)\n", t->orig_filename, t->orig_lineno);
1662 						strlcat(memory_leak_buf, relay_buf, sizeof(memory_leak_buf));
1663 					}
1664 				} else {
1665 					unsigned long leak_count = (zend_uintptr_t) data;
1666 
1667 					snprintf(memory_leak_buf, 512, "Last leak repeated %lu time%s\n", leak_count, (leak_count>1?"s":""));
1668 				}
1669 #	if defined(PHP_WIN32)
1670 				if (IsDebuggerPresent()) {
1671 					OutputDebugString(memory_leak_buf);
1672 				} else {
1673 					fprintf(stderr, "%s", memory_leak_buf);
1674 				}
1675 #	else
1676 				fprintf(stderr, "%s", memory_leak_buf);
1677 #	endif
1678 			}
1679 #endif
1680 			break;
1681 		case ZMSG_MEMORY_LEAKS_GRAND_TOTAL:
1682 #if ZEND_DEBUG
1683 			if (EG(error_reporting) & E_WARNING) {
1684 				char memory_leak_buf[512];
1685 
1686 				snprintf(memory_leak_buf, 512, "=== Total %d memory leaks detected ===\n", *((uint32_t *) data));
1687 #	if defined(PHP_WIN32)
1688 				if (IsDebuggerPresent()) {
1689 					OutputDebugString(memory_leak_buf);
1690 				} else {
1691 					fprintf(stderr, "%s", memory_leak_buf);
1692 				}
1693 #	else
1694 				fprintf(stderr, "%s", memory_leak_buf);
1695 #	endif
1696 			}
1697 #endif
1698 			break;
1699 		case ZMSG_LOG_SCRIPT_NAME: {
1700 				struct tm *ta, tmbuf;
1701 				time_t curtime;
1702 				char *datetime_str, asctimebuf[52];
1703 				char memory_leak_buf[4096];
1704 
1705 				time(&curtime);
1706 				ta = php_localtime_r(&curtime, &tmbuf);
1707 				datetime_str = php_asctime_r(ta, asctimebuf);
1708 				if (datetime_str) {
1709 					datetime_str[strlen(datetime_str)-1]=0;	/* get rid of the trailing newline */
1710 					snprintf(memory_leak_buf, sizeof(memory_leak_buf), "[%s]  Script:  '%s'\n", datetime_str, SAFE_FILENAME(SG(request_info).path_translated));
1711 				} else {
1712 					snprintf(memory_leak_buf, sizeof(memory_leak_buf), "[null]  Script:  '%s'\n", SAFE_FILENAME(SG(request_info).path_translated));
1713 				}
1714 #	if defined(PHP_WIN32)
1715 				if (IsDebuggerPresent()) {
1716 					OutputDebugString(memory_leak_buf);
1717 				} else {
1718 					fprintf(stderr, "%s", memory_leak_buf);
1719 				}
1720 #	else
1721 				fprintf(stderr, "%s", memory_leak_buf);
1722 #	endif
1723 			}
1724 			break;
1725 	}
1726 }
1727 /* }}} */
1728 
1729 
php_on_timeout(int seconds)1730 void php_on_timeout(int seconds)
1731 {
1732 	PG(connection_status) |= PHP_CONNECTION_TIMEOUT;
1733 }
1734 
1735 #if PHP_SIGCHILD
1736 /* {{{ sigchld_handler */
sigchld_handler(int apar)1737 static void sigchld_handler(int apar)
1738 {
1739 	int errno_save = errno;
1740 
1741 	while (waitpid(-1, NULL, WNOHANG) > 0);
1742 	signal(SIGCHLD, sigchld_handler);
1743 
1744 	errno = errno_save;
1745 }
1746 /* }}} */
1747 #endif
1748 
1749 /* {{{ php_request_startup */
php_request_startup(void)1750 zend_result php_request_startup(void)
1751 {
1752 	zend_result retval = SUCCESS;
1753 
1754 	zend_interned_strings_activate();
1755 
1756 #ifdef HAVE_DTRACE
1757 	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));
1758 #endif /* HAVE_DTRACE */
1759 
1760 #ifdef PHP_WIN32
1761 # if defined(ZTS)
1762 	_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
1763 # endif
1764 	PG(com_initialized) = 0;
1765 #endif
1766 
1767 #if PHP_SIGCHILD
1768 	signal(SIGCHLD, sigchld_handler);
1769 #endif
1770 
1771 	zend_try {
1772 		PG(in_error_log) = 0;
1773 		PG(during_request_startup) = 1;
1774 
1775 		php_output_activate();
1776 
1777 		/* initialize global variables */
1778 		PG(modules_activated) = 0;
1779 		PG(header_is_being_sent) = 0;
1780 		PG(connection_status) = PHP_CONNECTION_NORMAL;
1781 		PG(in_user_include) = 0;
1782 
1783 		zend_activate();
1784 		sapi_activate();
1785 
1786 #ifdef ZEND_SIGNALS
1787 		zend_signal_activate();
1788 #endif
1789 
1790 		if (PG(max_input_time) == -1) {
1791 			zend_set_timeout(EG(timeout_seconds), 1);
1792 		} else {
1793 			zend_set_timeout(PG(max_input_time), 1);
1794 		}
1795 
1796 		/* Disable realpath cache if an open_basedir is set */
1797 		if (PG(open_basedir) && *PG(open_basedir)) {
1798 			CWDG(realpath_cache_size_limit) = 0;
1799 		}
1800 
1801 		if (PG(expose_php) && !SG(headers_sent)) {
1802 			sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1);
1803 		}
1804 
1805 		if (PG(output_handler) && PG(output_handler)[0]) {
1806 			zval oh;
1807 
1808 			ZVAL_STRING(&oh, PG(output_handler));
1809 			php_output_start_user(&oh, 0, PHP_OUTPUT_HANDLER_STDFLAGS);
1810 			zval_ptr_dtor(&oh);
1811 		} else if (PG(output_buffering)) {
1812 			php_output_start_user(NULL, PG(output_buffering) > 1 ? PG(output_buffering) : 0, PHP_OUTPUT_HANDLER_STDFLAGS);
1813 		} else if (PG(implicit_flush)) {
1814 			php_output_set_implicit_flush(1);
1815 		}
1816 
1817 		/* We turn this off in php_execute_script() */
1818 		/* PG(during_request_startup) = 0; */
1819 
1820 		php_hash_environment();
1821 		zend_activate_modules();
1822 		PG(modules_activated)=1;
1823 	} zend_catch {
1824 		retval = FAILURE;
1825 	} zend_end_try();
1826 
1827 	SG(sapi_started) = 1;
1828 
1829 	return retval;
1830 }
1831 /* }}} */
1832 
1833 /* {{{ php_request_shutdown */
php_request_shutdown(void * dummy)1834 void php_request_shutdown(void *dummy)
1835 {
1836 	bool report_memleaks;
1837 
1838 	EG(flags) |= EG_FLAGS_IN_SHUTDOWN;
1839 
1840 	report_memleaks = PG(report_memleaks);
1841 
1842 	/* EG(current_execute_data) points into nirvana and therefore cannot be safely accessed
1843 	 * inside zend_executor callback functions.
1844 	 */
1845 	EG(current_execute_data) = NULL;
1846 
1847 	php_deactivate_ticks();
1848 
1849 	/* 0. Call any open observer end handlers that are still open after a zend_bailout */
1850 	if (ZEND_OBSERVER_ENABLED) {
1851 		zend_observer_fcall_end_all();
1852 	}
1853 
1854 	/* 1. Call all possible shutdown functions registered with register_shutdown_function() */
1855 	if (PG(modules_activated)) {
1856 		php_call_shutdown_functions();
1857 	}
1858 
1859 	/* 2. Call all possible __destruct() functions */
1860 	zend_try {
1861 		zend_call_destructors();
1862 	} zend_end_try();
1863 
1864 	/* 3. Flush all output buffers */
1865 	zend_try {
1866 		php_output_end_all();
1867 	} zend_end_try();
1868 
1869 	/* 4. Reset max_execution_time (no longer executing php code after response sent) */
1870 	zend_try {
1871 		zend_unset_timeout();
1872 	} zend_end_try();
1873 
1874 	/* 5. Call all extensions RSHUTDOWN functions */
1875 	if (PG(modules_activated)) {
1876 		zend_deactivate_modules();
1877 	}
1878 
1879 	/* 6. Shutdown output layer (send the set HTTP headers, cleanup output handlers, etc.) */
1880 	zend_try {
1881 		php_output_deactivate();
1882 	} zend_end_try();
1883 
1884 	/* 7. Free shutdown functions */
1885 	if (PG(modules_activated)) {
1886 		php_free_shutdown_functions();
1887 	}
1888 
1889 	/* 8. Destroy super-globals */
1890 	zend_try {
1891 		int i;
1892 
1893 		for (i=0; i<NUM_TRACK_VARS; i++) {
1894 			zval_ptr_dtor(&PG(http_globals)[i]);
1895 		}
1896 	} zend_end_try();
1897 
1898 	/* 9. Shutdown scanner/executor/compiler and restore ini entries */
1899 	zend_deactivate();
1900 
1901 	/* 10. free request-bound globals */
1902 	php_free_request_globals();
1903 
1904 	/* 11. Call all extensions post-RSHUTDOWN functions */
1905 	zend_try {
1906 		zend_post_deactivate_modules();
1907 	} zend_end_try();
1908 
1909 	/* 12. SAPI related shutdown*/
1910 	zend_try {
1911 		sapi_deactivate_module();
1912 	} zend_end_try();
1913 	/* free SAPI stuff */
1914 	sapi_deactivate_destroy();
1915 
1916 	/* 13. free virtual CWD memory */
1917 	virtual_cwd_deactivate();
1918 
1919 	/* 14. Destroy stream hashes */
1920 	zend_try {
1921 		php_shutdown_stream_hashes();
1922 	} zend_end_try();
1923 
1924 	/* 15. Free Willy (here be crashes) */
1925 	zend_arena_destroy(CG(arena));
1926 	zend_interned_strings_deactivate();
1927 	zend_try {
1928 		shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0);
1929 	} zend_end_try();
1930 
1931 	/* Reset memory limit, as the reset during INI_STAGE_DEACTIVATE may have failed.
1932 	 * At this point, no memory beyond a single chunk should be in use. */
1933 	zend_set_memory_limit(PG(memory_limit));
1934 
1935 	/* 16. Deactivate Zend signals */
1936 #ifdef ZEND_SIGNALS
1937 	zend_signal_deactivate();
1938 #endif
1939 
1940 #ifdef PHP_WIN32
1941 	if (PG(com_initialized)) {
1942 		CoUninitialize();
1943 		PG(com_initialized) = 0;
1944 	}
1945 #endif
1946 
1947 #ifdef HAVE_DTRACE
1948 	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));
1949 #endif /* HAVE_DTRACE */
1950 }
1951 /* }}} */
1952 
1953 /* {{{ php_com_initialize */
php_com_initialize(void)1954 PHPAPI void php_com_initialize(void)
1955 {
1956 #ifdef PHP_WIN32
1957 	if (!PG(com_initialized)) {
1958 		if (CoInitialize(NULL) == S_OK) {
1959 			PG(com_initialized) = 1;
1960 		}
1961 	}
1962 #endif
1963 }
1964 /* }}} */
1965 
1966 #ifdef ZTS
1967 /* {{{ core_globals_ctor */
core_globals_ctor(php_core_globals * core_globals)1968 static void core_globals_ctor(php_core_globals *core_globals)
1969 {
1970 	memset(core_globals, 0, sizeof(*core_globals));
1971 	php_startup_ticks();
1972 }
1973 /* }}} */
1974 #endif
1975 
1976 /* {{{ core_globals_dtor */
core_globals_dtor(php_core_globals * core_globals)1977 static void core_globals_dtor(php_core_globals *core_globals)
1978 {
1979 	/* These should have been freed earlier. */
1980 	ZEND_ASSERT(!core_globals->last_error_message);
1981 	ZEND_ASSERT(!core_globals->last_error_file);
1982 
1983 	if (core_globals->disable_classes) {
1984 		free(core_globals->disable_classes);
1985 	}
1986 	if (core_globals->php_binary) {
1987 		free(core_globals->php_binary);
1988 	}
1989 
1990 	php_shutdown_ticks(core_globals);
1991 }
1992 /* }}} */
1993 
PHP_MINFO_FUNCTION(php_core)1994 PHP_MINFO_FUNCTION(php_core) { /* {{{ */
1995 	php_info_print_table_start();
1996 	php_info_print_table_row(2, "PHP Version", PHP_VERSION);
1997 	php_info_print_table_end();
1998 	DISPLAY_INI_ENTRIES();
1999 }
2000 /* }}} */
2001 
2002 /* {{{ php_register_extensions */
php_register_extensions(zend_module_entry * const * ptr,int count)2003 zend_result php_register_extensions(zend_module_entry * const * ptr, int count)
2004 {
2005 	zend_module_entry * const * end = ptr + count;
2006 
2007 	while (ptr < end) {
2008 		if (*ptr) {
2009 			if (zend_register_internal_module(*ptr)==NULL) {
2010 				return FAILURE;
2011 			}
2012 		}
2013 		ptr++;
2014 	}
2015 	return SUCCESS;
2016 }
2017 
2018 #ifdef PHP_WIN32
2019 static _invalid_parameter_handler old_invalid_parameter_handler;
2020 
dummy_invalid_parameter_handler(const wchar_t * expression,const wchar_t * function,const wchar_t * file,unsigned int line,uintptr_t pReserved)2021 void dummy_invalid_parameter_handler(
2022 		const wchar_t *expression,
2023 		const wchar_t *function,
2024 		const wchar_t *file,
2025 		unsigned int   line,
2026 		uintptr_t      pReserved)
2027 {
2028 	static int called = 0;
2029 	char buf[1024];
2030 	int len;
2031 
2032 	if (!called) {
2033 			if(PG(windows_show_crt_warning)) {
2034 			called = 1;
2035 			if (function) {
2036 				if (file) {
2037 					len = _snprintf(buf, sizeof(buf)-1, "Invalid parameter detected in CRT function '%ws' (%ws:%u)", function, file, line);
2038 				} else {
2039 					len = _snprintf(buf, sizeof(buf)-1, "Invalid parameter detected in CRT function '%ws'", function);
2040 				}
2041 			} else {
2042 				len = _snprintf(buf, sizeof(buf)-1, "Invalid CRT parameter detected (function not known)");
2043 			}
2044 			zend_error(E_WARNING, "%s", buf);
2045 			called = 0;
2046 		}
2047 	}
2048 }
2049 #endif
2050 
2051 /* {{{ php_module_startup */
php_module_startup(sapi_module_struct * sf,zend_module_entry * additional_module)2052 zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module)
2053 {
2054 	zend_utility_functions zuf;
2055 	zend_utility_values zuv;
2056 	zend_result retval = SUCCESS;
2057 	int module_number = 0;
2058 	char *php_os;
2059 	zend_module_entry *module;
2060 
2061 #ifdef PHP_WIN32
2062 	WORD wVersionRequested = MAKEWORD(2, 0);
2063 	WSADATA wsaData;
2064 
2065 	php_os = "WINNT";
2066 
2067 	old_invalid_parameter_handler =
2068 		_set_invalid_parameter_handler(dummy_invalid_parameter_handler);
2069 	if (old_invalid_parameter_handler != NULL) {
2070 		_set_invalid_parameter_handler(old_invalid_parameter_handler);
2071 	}
2072 
2073 	/* Disable the message box for assertions.*/
2074 	_CrtSetReportMode(_CRT_ASSERT, 0);
2075 #else
2076 	php_os = PHP_OS;
2077 #endif
2078 
2079 #ifdef ZTS
2080 	(void)ts_resource(0);
2081 #endif
2082 
2083 #ifdef PHP_WIN32
2084 	if (!php_win32_init_random_bytes()) {
2085 		fprintf(stderr, "\ncrypt algorithm provider initialization failed\n");
2086 		return FAILURE;
2087 	}
2088 #endif
2089 
2090 	module_shutdown = false;
2091 	module_startup = true;
2092 	sapi_initialize_empty_request();
2093 	sapi_activate();
2094 
2095 	if (module_initialized) {
2096 		return SUCCESS;
2097 	}
2098 
2099 	sapi_module = *sf;
2100 
2101 	php_output_startup();
2102 
2103 #ifdef ZTS
2104 	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);
2105 #ifdef PHP_WIN32
2106 	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);
2107 #endif
2108 #else
2109 	memset(&core_globals, 0, sizeof(core_globals));
2110 	php_startup_ticks();
2111 #endif
2112 	gc_globals_ctor();
2113 
2114 	zuf.error_function = php_error_cb;
2115 	zuf.printf_function = php_printf;
2116 	zuf.write_function = php_output_write;
2117 	zuf.fopen_function = php_fopen_wrapper_for_zend;
2118 	zuf.message_handler = php_message_handler_for_zend;
2119 	zuf.get_configuration_directive = php_get_configuration_directive_for_zend;
2120 	zuf.ticks_function = php_run_ticks;
2121 	zuf.on_timeout = php_on_timeout;
2122 	zuf.stream_open_function = php_stream_open_for_zend;
2123 	zuf.printf_to_smart_string_function = php_printf_to_smart_string;
2124 	zuf.printf_to_smart_str_function = php_printf_to_smart_str;
2125 	zuf.getenv_function = sapi_getenv;
2126 	zuf.resolve_path_function = php_resolve_path_for_zend;
2127 	zend_startup(&zuf);
2128 	zend_reset_lc_ctype_locale();
2129 	zend_update_current_locale();
2130 
2131 	zend_observer_startup();
2132 #if ZEND_DEBUG
2133 	zend_observer_error_register(report_zend_debug_error_notify_cb);
2134 #endif
2135 
2136 #if HAVE_TZSET
2137 	tzset();
2138 #endif
2139 
2140 #ifdef PHP_WIN32
2141 	char *img_err;
2142 	if (!php_win32_crt_compatible(&img_err)) {
2143 		php_error(E_CORE_WARNING, img_err);
2144 		efree(img_err);
2145 		return FAILURE;
2146 	}
2147 
2148 	/* start up winsock services */
2149 	if (WSAStartup(wVersionRequested, &wsaData) != 0) {
2150 		php_printf("\nwinsock.dll unusable. %d\n", WSAGetLastError());
2151 		return FAILURE;
2152 	}
2153 	php_win32_signal_ctrl_handler_init();
2154 #endif
2155 
2156 	le_index_ptr = zend_register_list_destructors_ex(NULL, NULL, "index pointer", 0);
2157 
2158 	/* Register constants */
2159 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_VERSION", PHP_VERSION, sizeof(PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS);
2160 	REGISTER_MAIN_LONG_CONSTANT("PHP_MAJOR_VERSION", PHP_MAJOR_VERSION, CONST_PERSISTENT | CONST_CS);
2161 	REGISTER_MAIN_LONG_CONSTANT("PHP_MINOR_VERSION", PHP_MINOR_VERSION, CONST_PERSISTENT | CONST_CS);
2162 	REGISTER_MAIN_LONG_CONSTANT("PHP_RELEASE_VERSION", PHP_RELEASE_VERSION, CONST_PERSISTENT | CONST_CS);
2163 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_EXTRA_VERSION", PHP_EXTRA_VERSION, sizeof(PHP_EXTRA_VERSION) - 1, CONST_PERSISTENT | CONST_CS);
2164 	REGISTER_MAIN_LONG_CONSTANT("PHP_VERSION_ID", PHP_VERSION_ID, CONST_PERSISTENT | CONST_CS);
2165 #ifdef ZTS
2166 	REGISTER_MAIN_LONG_CONSTANT("PHP_ZTS", 1, CONST_PERSISTENT | CONST_CS);
2167 #else
2168 	REGISTER_MAIN_LONG_CONSTANT("PHP_ZTS", 0, CONST_PERSISTENT | CONST_CS);
2169 #endif
2170 	REGISTER_MAIN_LONG_CONSTANT("PHP_DEBUG", PHP_DEBUG, CONST_PERSISTENT | CONST_CS);
2171 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_OS", php_os, strlen(php_os), CONST_PERSISTENT | CONST_CS);
2172 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_OS_FAMILY", PHP_OS_FAMILY, sizeof(PHP_OS_FAMILY)-1, CONST_PERSISTENT | CONST_CS);
2173 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_SAPI", sapi_module.name, strlen(sapi_module.name), CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
2174 	REGISTER_MAIN_STRINGL_CONSTANT("DEFAULT_INCLUDE_PATH", PHP_INCLUDE_PATH, sizeof(PHP_INCLUDE_PATH)-1, CONST_PERSISTENT | CONST_CS);
2175 	REGISTER_MAIN_STRINGL_CONSTANT("PEAR_INSTALL_DIR", PEAR_INSTALLDIR, sizeof(PEAR_INSTALLDIR)-1, CONST_PERSISTENT | CONST_CS);
2176 	REGISTER_MAIN_STRINGL_CONSTANT("PEAR_EXTENSION_DIR", PHP_EXTENSION_DIR, sizeof(PHP_EXTENSION_DIR)-1, CONST_PERSISTENT | CONST_CS);
2177 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_EXTENSION_DIR", PHP_EXTENSION_DIR, sizeof(PHP_EXTENSION_DIR)-1, CONST_PERSISTENT | CONST_CS);
2178 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_PREFIX", PHP_PREFIX, sizeof(PHP_PREFIX)-1, CONST_PERSISTENT | CONST_CS);
2179 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINDIR", PHP_BINDIR, sizeof(PHP_BINDIR)-1, CONST_PERSISTENT | CONST_CS);
2180 #ifndef PHP_WIN32
2181 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_MANDIR", PHP_MANDIR, sizeof(PHP_MANDIR)-1, CONST_PERSISTENT | CONST_CS);
2182 #endif
2183 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_LIBDIR", PHP_LIBDIR, sizeof(PHP_LIBDIR)-1, CONST_PERSISTENT | CONST_CS);
2184 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_DATADIR", PHP_DATADIR, sizeof(PHP_DATADIR)-1, CONST_PERSISTENT | CONST_CS);
2185 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_SYSCONFDIR", PHP_SYSCONFDIR, sizeof(PHP_SYSCONFDIR)-1, CONST_PERSISTENT | CONST_CS);
2186 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_LOCALSTATEDIR", PHP_LOCALSTATEDIR, sizeof(PHP_LOCALSTATEDIR)-1, CONST_PERSISTENT | CONST_CS);
2187 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, strlen(PHP_CONFIG_FILE_PATH), CONST_PERSISTENT | CONST_CS);
2188 	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);
2189 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
2190 	REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
2191 	REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS);
2192 	REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", ZEND_LONG_MAX, CONST_PERSISTENT | CONST_CS);
2193 	REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MIN", ZEND_LONG_MIN, CONST_PERSISTENT | CONST_CS);
2194 	REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", SIZEOF_ZEND_LONG, CONST_PERSISTENT | CONST_CS);
2195 	REGISTER_MAIN_LONG_CONSTANT("PHP_FD_SETSIZE", FD_SETSIZE, CONST_PERSISTENT | CONST_CS);
2196 	REGISTER_MAIN_LONG_CONSTANT("PHP_FLOAT_DIG", DBL_DIG, CONST_PERSISTENT | CONST_CS);
2197 	REGISTER_MAIN_DOUBLE_CONSTANT("PHP_FLOAT_EPSILON", DBL_EPSILON, CONST_PERSISTENT | CONST_CS);
2198 	REGISTER_MAIN_DOUBLE_CONSTANT("PHP_FLOAT_MAX", DBL_MAX, CONST_PERSISTENT | CONST_CS);
2199 	REGISTER_MAIN_DOUBLE_CONSTANT("PHP_FLOAT_MIN", DBL_MIN, CONST_PERSISTENT | CONST_CS);
2200 
2201 #ifdef PHP_WIN32
2202 	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_MAJOR",      EG(windows_version_info).dwMajorVersion, CONST_PERSISTENT | CONST_CS);
2203 	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_MINOR",      EG(windows_version_info).dwMinorVersion, CONST_PERSISTENT | CONST_CS);
2204 	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_BUILD",      EG(windows_version_info).dwBuildNumber, CONST_PERSISTENT | CONST_CS);
2205 	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_PLATFORM",   EG(windows_version_info).dwPlatformId, CONST_PERSISTENT | CONST_CS);
2206 	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SP_MAJOR",   EG(windows_version_info).wServicePackMajor, CONST_PERSISTENT | CONST_CS);
2207 	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SP_MINOR",   EG(windows_version_info).wServicePackMinor, CONST_PERSISTENT | CONST_CS);
2208 	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_SUITEMASK",  EG(windows_version_info).wSuiteMask, CONST_PERSISTENT | CONST_CS);
2209 	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_VERSION_PRODUCTTYPE", EG(windows_version_info).wProductType, CONST_PERSISTENT | CONST_CS);
2210 	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_DOMAIN_CONTROLLER", VER_NT_DOMAIN_CONTROLLER, CONST_PERSISTENT | CONST_CS);
2211 	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_SERVER", VER_NT_SERVER, CONST_PERSISTENT | CONST_CS);
2212 	REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_NT_WORKSTATION", VER_NT_WORKSTATION, CONST_PERSISTENT | CONST_CS);
2213 #endif
2214 
2215 	php_binary_init();
2216 	if (PG(php_binary)) {
2217 		REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", PG(php_binary), strlen(PG(php_binary)), CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
2218 	} else {
2219 		REGISTER_MAIN_STRINGL_CONSTANT("PHP_BINARY", "", 0, CONST_PERSISTENT | CONST_CS | CONST_NO_FILE_CACHE);
2220 	}
2221 
2222 	php_output_register_constants();
2223 	php_rfc1867_register_constants();
2224 
2225 	/* this will read in php.ini, set up the configuration parameters,
2226 	   load zend extensions and register php function extensions
2227 	   to be loaded later */
2228 	zend_stream_init();
2229 	if (php_init_config() == FAILURE) {
2230 		return FAILURE;
2231 	}
2232 	zend_stream_shutdown();
2233 
2234 	/* Register PHP core ini entries */
2235 	zend_register_ini_entries_ex(ini_entries, module_number, MODULE_PERSISTENT);
2236 
2237 	/* Register Zend ini entries */
2238 	zend_register_standard_ini_entries();
2239 
2240 #ifdef ZEND_WIN32
2241 	/* Until the current ini values was setup, the current cp is 65001.
2242 		If the actual ini values are different, some stuff needs to be updated.
2243 		It concerns at least main_cwd_state and there might be more. As we're
2244 		still in the startup phase, lets use the chance and reinit the relevant
2245 		item according to the current codepage. Still, if ini_set() is used
2246 		later on, a more intelligent way to update such stuff is needed.
2247 		Startup/shutdown routines could involve touching globals and thus
2248 		can't always be used on demand. */
2249 	if (!php_win32_cp_use_unicode()) {
2250 		virtual_cwd_main_cwd_init(1);
2251 	}
2252 #endif
2253 
2254 	/* Disable realpath cache if an open_basedir is set */
2255 	if (PG(open_basedir) && *PG(open_basedir)) {
2256 		CWDG(realpath_cache_size_limit) = 0;
2257 	}
2258 
2259 	PG(have_called_openlog) = 0;
2260 
2261 	/* initialize stream wrappers registry
2262 	 * (this uses configuration parameters from php.ini)
2263 	 */
2264 	if (php_init_stream_wrappers(module_number) == FAILURE)	{
2265 		php_printf("PHP:  Unable to initialize stream url wrappers.\n");
2266 		return FAILURE;
2267 	}
2268 
2269 	zuv.html_errors = 1;
2270 	php_startup_auto_globals();
2271 	zend_set_utility_values(&zuv);
2272 	php_startup_sapi_content_types();
2273 
2274 	/* Begin to fingerprint the process state */
2275 	zend_startup_system_id();
2276 
2277 	/* startup extensions statically compiled in */
2278 	if (php_register_internal_extensions_func() == FAILURE) {
2279 		php_printf("Unable to start builtin modules\n");
2280 		return FAILURE;
2281 	}
2282 
2283 	/* start additional PHP extensions */
2284 	if (additional_module && (zend_register_internal_module(additional_module) == NULL)) {
2285 		return FAILURE;
2286 	}
2287 
2288 	/* load and startup extensions compiled as shared objects (aka DLLs)
2289 	   as requested by php.ini entries
2290 	   these are loaded after initialization of internal extensions
2291 	   as extensions *might* rely on things from ext/standard
2292 	   which is always an internal extension and to be initialized
2293 	   ahead of all other internals
2294 	 */
2295 	php_ini_register_extensions();
2296 	zend_startup_modules();
2297 
2298 	/* start Zend extensions */
2299 	zend_startup_extensions();
2300 
2301 	zend_collect_module_handlers();
2302 
2303 	/* register additional functions */
2304 	if (sapi_module.additional_functions) {
2305 		if ((module = zend_hash_str_find_ptr(&module_registry, "standard", sizeof("standard")-1)) != NULL) {
2306 			EG(current_module) = module;
2307 			zend_register_functions(NULL, sapi_module.additional_functions, NULL, MODULE_PERSISTENT);
2308 			EG(current_module) = NULL;
2309 		}
2310 	}
2311 
2312 	/* disable certain classes and functions as requested by php.ini */
2313 	zend_disable_functions(INI_STR("disable_functions"));
2314 	php_disable_classes();
2315 
2316 	/* make core report what it should */
2317 	if ((module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core")-1)) != NULL) {
2318 		module->version = PHP_VERSION;
2319 		module->info_func = PHP_MINFO(php_core);
2320 	}
2321 
2322 	/* freeze the list of observer fcall_init handlers */
2323 	zend_observer_post_startup();
2324 
2325 	/* Extensions that add engine hooks after this point do so at their own peril */
2326 	zend_finalize_system_id();
2327 
2328 	module_initialized = true;
2329 
2330 	if (zend_post_startup() != SUCCESS) {
2331 		return FAILURE;
2332 	}
2333 
2334 	/* Check for deprecated directives */
2335 	/* NOTE: If you add anything here, remember to add it to build/Makefile.global! */
2336 	{
2337 		struct {
2338 			const long error_level;
2339 			const char *phrase;
2340 			const char *directives[18]; /* Remember to change this if the number of directives change */
2341 		} directives[2] = {
2342 			{
2343 				E_DEPRECATED,
2344 				"Directive '%s' is deprecated",
2345 				{
2346 					"allow_url_include",
2347 					NULL
2348 				}
2349 			},
2350 			{
2351 				E_CORE_ERROR,
2352 				"Directive '%s' is no longer available in PHP",
2353 				{
2354 					"allow_call_time_pass_reference",
2355 					"asp_tags",
2356 					"define_syslog_variables",
2357 					"highlight.bg",
2358 					"magic_quotes_gpc",
2359 					"magic_quotes_runtime",
2360 					"magic_quotes_sybase",
2361 					"register_globals",
2362 					"register_long_arrays",
2363 					"safe_mode",
2364 					"safe_mode_gid",
2365 					"safe_mode_include_dir",
2366 					"safe_mode_exec_dir",
2367 					"safe_mode_allowed_env_vars",
2368 					"safe_mode_protected_env_vars",
2369 					"zend.ze1_compatibility_mode",
2370 					"track_errors",
2371 					NULL
2372 				}
2373 			}
2374 		};
2375 
2376 		unsigned int i;
2377 
2378 		zend_try {
2379 			/* 2 = Count of deprecation structs */
2380 			for (i = 0; i < 2; i++) {
2381 				const char **p = directives[i].directives;
2382 
2383 				while(*p) {
2384 					zend_long value;
2385 
2386 					if (cfg_get_long((char*)*p, &value) == SUCCESS && value) {
2387 						zend_error(directives[i].error_level, directives[i].phrase, *p);
2388 					}
2389 
2390 					++p;
2391 				}
2392 			}
2393 		} zend_catch {
2394 			retval = FAILURE;
2395 		} zend_end_try();
2396 	}
2397 
2398 	virtual_cwd_deactivate();
2399 
2400 	sapi_deactivate();
2401 	module_startup = false;
2402 
2403 	/* Don't leak errors from startup into the per-request phase. */
2404 	clear_last_error();
2405 	shutdown_memory_manager(1, 0);
2406 	virtual_cwd_activate();
2407 
2408 	zend_interned_strings_switch_storage(1);
2409 
2410 #if ZEND_RC_DEBUG
2411 	if (retval == SUCCESS) {
2412 		zend_rc_debug = 1;
2413 	}
2414 #endif
2415 
2416 	/* we're done */
2417 	return retval;
2418 }
2419 /* }}} */
2420 
2421 /* {{{ php_module_shutdown_wrapper */
php_module_shutdown_wrapper(sapi_module_struct * sapi_globals)2422 int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals)
2423 {
2424 	php_module_shutdown();
2425 	return SUCCESS;
2426 }
2427 /* }}} */
2428 
2429 /* {{{ php_module_shutdown */
php_module_shutdown(void)2430 void php_module_shutdown(void)
2431 {
2432 	int module_number=0;
2433 
2434 	module_shutdown = true;
2435 
2436 	if (!module_initialized) {
2437 		return;
2438 	}
2439 
2440 	zend_interned_strings_switch_storage(0);
2441 
2442 #if ZEND_RC_DEBUG
2443 	zend_rc_debug = 0;
2444 #endif
2445 
2446 #ifdef PHP_WIN32
2447 	(void)php_win32_shutdown_random_bytes();
2448 	php_win32_signal_ctrl_handler_shutdown();
2449 #endif
2450 
2451 	sapi_flush();
2452 
2453 	zend_shutdown();
2454 
2455 #ifdef PHP_WIN32
2456 	/*close winsock */
2457 	WSACleanup();
2458 #endif
2459 
2460 	/* Destroys filter & transport registries too */
2461 	php_shutdown_stream_wrappers(module_number);
2462 
2463 	zend_unregister_ini_entries_ex(module_number, MODULE_PERSISTENT);
2464 
2465 	/* close down the ini config */
2466 	php_shutdown_config();
2467 	clear_last_error();
2468 
2469 #ifndef ZTS
2470 	zend_ini_shutdown();
2471 	shutdown_memory_manager(CG(unclean_shutdown), 1);
2472 #else
2473 	zend_ini_global_shutdown();
2474 #endif
2475 
2476 	php_output_shutdown();
2477 
2478 #ifndef ZTS
2479 	zend_interned_strings_dtor();
2480 #endif
2481 
2482 	if (zend_post_shutdown_cb) {
2483 		void (*cb)(void) = zend_post_shutdown_cb;
2484 
2485 		zend_post_shutdown_cb = NULL;
2486 		cb();
2487 	}
2488 
2489 	module_initialized = false;
2490 
2491 #ifndef ZTS
2492 	core_globals_dtor(&core_globals);
2493 	gc_globals_dtor();
2494 #else
2495 	ts_free_id(core_globals_id);
2496 #endif
2497 
2498 #ifdef PHP_WIN32
2499 	if (old_invalid_parameter_handler == NULL) {
2500 		_set_invalid_parameter_handler(old_invalid_parameter_handler);
2501 	}
2502 #endif
2503 
2504 	zend_observer_shutdown();
2505 }
2506 /* }}} */
2507 
2508 /* {{{ php_execute_script */
php_execute_script(zend_file_handle * primary_file)2509 PHPAPI bool php_execute_script(zend_file_handle *primary_file)
2510 {
2511 	zend_file_handle *prepend_file_p = NULL, *append_file_p = NULL;
2512 	zend_file_handle prepend_file, append_file;
2513 #ifdef HAVE_BROKEN_GETCWD
2514 	volatile int old_cwd_fd = -1;
2515 #else
2516 	char *old_cwd;
2517 	ALLOCA_FLAG(use_heap)
2518 #endif
2519 	bool retval = false;
2520 
2521 #ifndef HAVE_BROKEN_GETCWD
2522 # define OLD_CWD_SIZE 4096
2523 	old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
2524 	old_cwd[0] = '\0';
2525 #endif
2526 
2527 	zend_try {
2528 		char realfile[MAXPATHLEN];
2529 
2530 #ifdef PHP_WIN32
2531 		if(primary_file->filename) {
2532 			UpdateIniFromRegistry(ZSTR_VAL(primary_file->filename));
2533 		}
2534 #endif
2535 
2536 		PG(during_request_startup) = 0;
2537 
2538 		if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
2539 #ifdef HAVE_BROKEN_GETCWD
2540 			/* this looks nasty to me */
2541 			old_cwd_fd = open(".", 0);
2542 #else
2543 			php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
2544 #endif
2545 			VCWD_CHDIR_FILE(ZSTR_VAL(primary_file->filename));
2546 		}
2547 
2548 		/* Only lookup the real file path and add it to the included_files list if already opened
2549 		 *   otherwise it will get opened and added to the included_files list in zend_execute_scripts
2550 		 */
2551 		if (primary_file->filename &&
2552 			!zend_string_equals_literal(primary_file->filename, "Standard input code") &&
2553 			primary_file->opened_path == NULL &&
2554 			primary_file->type != ZEND_HANDLE_FILENAME
2555 		) {
2556 			if (expand_filepath(ZSTR_VAL(primary_file->filename), realfile)) {
2557 				primary_file->opened_path = zend_string_init(realfile, strlen(realfile), 0);
2558 				zend_hash_add_empty_element(&EG(included_files), primary_file->opened_path);
2559 			}
2560 		}
2561 
2562 		if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
2563 			zend_stream_init_filename(&prepend_file, PG(auto_prepend_file));
2564 			prepend_file_p = &prepend_file;
2565 		}
2566 
2567 		if (PG(auto_append_file) && PG(auto_append_file)[0]) {
2568 			zend_stream_init_filename(&append_file, PG(auto_append_file));
2569 			append_file_p = &append_file;
2570 		}
2571 		if (PG(max_input_time) != -1) {
2572 #ifdef PHP_WIN32
2573 			zend_unset_timeout();
2574 #endif
2575 			zend_set_timeout(INI_INT("max_execution_time"), 0);
2576 		}
2577 
2578 		retval = (zend_execute_scripts(ZEND_REQUIRE, NULL, 3, prepend_file_p, primary_file, append_file_p) == SUCCESS);
2579 	} zend_end_try();
2580 
2581 	if (prepend_file_p) {
2582 		zend_destroy_file_handle(prepend_file_p);
2583 	}
2584 
2585 	if (append_file_p) {
2586 		zend_destroy_file_handle(append_file_p);
2587 	}
2588 
2589 	if (EG(exception)) {
2590 		zend_try {
2591 			zend_exception_error(EG(exception), E_ERROR);
2592 		} zend_end_try();
2593 	}
2594 
2595 #ifdef HAVE_BROKEN_GETCWD
2596 	if (old_cwd_fd != -1) {
2597 		fchdir(old_cwd_fd);
2598 		close(old_cwd_fd);
2599 	}
2600 #else
2601 	if (old_cwd[0] != '\0') {
2602 		php_ignore_value(VCWD_CHDIR(old_cwd));
2603 	}
2604 	free_alloca(old_cwd, use_heap);
2605 #endif
2606 	return retval;
2607 }
2608 /* }}} */
2609 
2610 /* {{{ php_execute_simple_script */
php_execute_simple_script(zend_file_handle * primary_file,zval * ret)2611 PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval *ret)
2612 {
2613 	char *old_cwd;
2614 	ALLOCA_FLAG(use_heap)
2615 
2616 	EG(exit_status) = 0;
2617 #define OLD_CWD_SIZE 4096
2618 	old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
2619 	old_cwd[0] = '\0';
2620 
2621 	zend_try {
2622 #ifdef PHP_WIN32
2623 		if(primary_file->filename) {
2624 			UpdateIniFromRegistry(ZSTR_VAL(primary_file->filename));
2625 		}
2626 #endif
2627 
2628 		PG(during_request_startup) = 0;
2629 
2630 		if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) {
2631 			php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1));
2632 			VCWD_CHDIR_FILE(ZSTR_VAL(primary_file->filename));
2633 		}
2634 		zend_execute_scripts(ZEND_REQUIRE, ret, 1, primary_file);
2635 	} zend_end_try();
2636 
2637 	if (old_cwd[0] != '\0') {
2638 		php_ignore_value(VCWD_CHDIR(old_cwd));
2639 	}
2640 
2641 	free_alloca(old_cwd, use_heap);
2642 	return EG(exit_status);
2643 }
2644 /* }}} */
2645 
2646 /* {{{ php_handle_aborted_connection */
php_handle_aborted_connection(void)2647 PHPAPI void php_handle_aborted_connection(void)
2648 {
2649 
2650 	PG(connection_status) = PHP_CONNECTION_ABORTED;
2651 	php_output_set_status(PHP_OUTPUT_DISABLED);
2652 
2653 	if (!PG(ignore_user_abort)) {
2654 		zend_bailout();
2655 	}
2656 }
2657 /* }}} */
2658 
2659 /* {{{ php_handle_auth_data */
php_handle_auth_data(const char * auth)2660 PHPAPI int php_handle_auth_data(const char *auth)
2661 {
2662 	int ret = -1;
2663 	size_t auth_len = auth != NULL ? strlen(auth) : 0;
2664 
2665 	if (auth && auth_len > 0 && zend_binary_strncasecmp(auth, auth_len, "Basic ", sizeof("Basic ")-1, sizeof("Basic ")-1) == 0) {
2666 		char *pass;
2667 		zend_string *user;
2668 
2669 		user = php_base64_decode((const unsigned char*)auth + 6, auth_len - 6);
2670 		if (user) {
2671 			pass = strchr(ZSTR_VAL(user), ':');
2672 			if (pass) {
2673 				*pass++ = '\0';
2674 				SG(request_info).auth_user = estrndup(ZSTR_VAL(user), ZSTR_LEN(user));
2675 				SG(request_info).auth_password = estrdup(pass);
2676 				ret = 0;
2677 			}
2678 			zend_string_free(user);
2679 		}
2680 	}
2681 
2682 	if (ret == -1) {
2683 		SG(request_info).auth_user = SG(request_info).auth_password = NULL;
2684 	} else {
2685 		SG(request_info).auth_digest = NULL;
2686 	}
2687 
2688 	if (ret == -1 && auth && auth_len > 0 && zend_binary_strncasecmp(auth, auth_len, "Digest ", sizeof("Digest ")-1, sizeof("Digest ")-1) == 0) {
2689 		SG(request_info).auth_digest = estrdup(auth + 7);
2690 		ret = 0;
2691 	}
2692 
2693 	if (ret == -1) {
2694 		SG(request_info).auth_digest = NULL;
2695 	}
2696 
2697 	return ret;
2698 }
2699 /* }}} */
2700 
2701 /* {{{ php_lint_script */
php_lint_script(zend_file_handle * file)2702 PHPAPI zend_result php_lint_script(zend_file_handle *file)
2703 {
2704 	zend_op_array *op_array;
2705 	zend_result retval = FAILURE;
2706 
2707 	zend_try {
2708 		op_array = zend_compile_file(file, ZEND_INCLUDE);
2709 
2710 		if (op_array) {
2711 			destroy_op_array(op_array);
2712 			efree(op_array);
2713 			retval = SUCCESS;
2714 		}
2715 	} zend_end_try();
2716 	if (EG(exception)) {
2717 		zend_exception_error(EG(exception), E_ERROR);
2718 	}
2719 
2720 	return retval;
2721 }
2722 /* }}} */
2723 
2724 #ifdef ZTS
2725 /* {{{ php_reserve_tsrm_memory */
php_reserve_tsrm_memory(void)2726 PHPAPI void php_reserve_tsrm_memory(void)
2727 {
2728 	tsrm_reserve(
2729 		TSRM_ALIGNED_SIZE(sizeof(zend_compiler_globals)) +
2730 		TSRM_ALIGNED_SIZE(sizeof(zend_executor_globals)) +
2731 		TSRM_ALIGNED_SIZE(sizeof(zend_php_scanner_globals)) +
2732 		TSRM_ALIGNED_SIZE(sizeof(zend_ini_scanner_globals)) +
2733 		TSRM_ALIGNED_SIZE(sizeof(virtual_cwd_globals)) +
2734 #ifdef ZEND_SIGNALS
2735 		TSRM_ALIGNED_SIZE(sizeof(zend_signal_globals_t)) +
2736 #endif
2737 		TSRM_ALIGNED_SIZE(zend_mm_globals_size()) +
2738 		TSRM_ALIGNED_SIZE(zend_gc_globals_size()) +
2739 		TSRM_ALIGNED_SIZE(sizeof(php_core_globals)) +
2740 		TSRM_ALIGNED_SIZE(sizeof(sapi_globals_struct))
2741 	);
2742 }
2743 /* }}} */
2744 
2745 /* {{{ php_tsrm_startup */
php_tsrm_startup(void)2746 PHPAPI bool php_tsrm_startup(void)
2747 {
2748 	bool ret = tsrm_startup(1, 1, 0, NULL);
2749 	php_reserve_tsrm_memory();
2750 	(void)ts_resource(0);
2751 	return ret;
2752 }
2753 /* }}} */
2754 #endif
2755