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