]> git.pld-linux.org Git - packages/php.git/blame - suhosin.patch
- up to 5.3.19
[packages/php.git] / suhosin.patch
CommitLineData
3f3163a9
AM
1diff -Naurp php-5.3.6RC1/configure php-5.3.6RC1.oden/configure
2--- php-5.3.6RC1/configure 2011-02-16 21:30:40.000000000 +0100
3+++ php-5.3.6RC1.oden/configure 2011-02-20 11:50:19.294835319 +0100
4@@ -18979,6 +18979,9 @@ EOF
65be62f2 5
3f3163a9
AM
6 fi
7
8+cat >> confdefs.h <<\EOF
9+#define SUHOSIN_PATCH 1
10+EOF
11
12 echo $ac_n "checking for declared timezone""... $ac_c" 1>&6
13 echo "configure:18985: checking for declared timezone" >&5
14@@ -115340,7 +115343,7 @@ EOF
15 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
16 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
17 network.c php_open_temporary_file.c php_logos.c \
18- output.c getopt.c; do
19+ output.c getopt.c suhosin_patch.c ; do
20
21 IFS=.
22 set $ac_src
23@@ -115544,7 +115547,7 @@ esac
24 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
25 zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
26 zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
27- zend_closures.c zend_float.c; do
28+ zend_closures.c zend_float.c zend_canary.c zend_alloc_canary.c ; do
29
30 IFS=.
31 set $ac_src
32diff -Naurp php-5.3.6RC1/configure.in php-5.3.6RC1.oden/configure.in
33--- php-5.3.6RC1/configure.in 2011-02-20 11:45:04.157489906 +0100
34+++ php-5.3.6RC1.oden/configure.in 2011-02-20 11:50:19.295835459 +0100
35@@ -286,6 +286,7 @@ sinclude(Zend/Zend.m4)
36 sinclude(TSRM/threads.m4)
37 sinclude(TSRM/tsrm.m4)
38
39+sinclude(main/suhosin_patch.m4)
40
41 divert(2)
42
43@@ -1393,7 +1394,7 @@ PHP_ADD_SOURCES(main, main.c snprintf.c
44 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
45 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
46 network.c php_open_temporary_file.c php_logos.c \
47- output.c getopt.c)
48+ output.c getopt.c suhosin_patch.c )
49
50 PHP_ADD_SOURCES(main/streams, streams.c cast.c memory.c filter.c \
51 plain_wrapper.c userspace.c transports.c xp_socket.c mmap.c \
52@@ -1421,7 +1422,7 @@ PHP_ADD_SOURCES(Zend, \
53 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
54 zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
55 zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
56- zend_closures.c zend_float.c)
57+ zend_closures.c zend_float.c zend_canary.c zend_alloc_canary.c )
65be62f2 58
3f3163a9
AM
59 if test -r "$abs_srcdir/Zend/zend_objects.c"; then
60 PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_default_classes.c)
61diff -Naurp php-5.3.6RC1/ext/standard/dl.c php-5.3.6RC1.oden/ext/standard/dl.c
62--- php-5.3.6RC1/ext/standard/dl.c 2011-01-01 03:19:59.000000000 +0100
63+++ php-5.3.6RC1.oden/ext/standard/dl.c 2011-02-20 11:50:19.296835599 +0100
64@@ -254,6 +254,23 @@ PHPAPI int php_load_extension(char *file
65 return FAILURE;
66 }
67 }
68+
65be62f2 69+#if SUHOSIN_PATCH
3f3163a9
AM
70+ if (strncmp("suhosin", module_entry->name, sizeof("suhosin")-1) == 0) {
71+ void *log_func;
72+ /* sucessfully loaded suhosin extension, now check for logging function replacement */
73+ log_func = (void *) DL_FETCH_SYMBOL(handle, "suhosin_log");
74+ if (log_func == NULL) {
75+ log_func = (void *) DL_FETCH_SYMBOL(handle, "_suhosin_log");
76+ }
77+ if (log_func != NULL) {
78+ zend_suhosin_log = log_func;
79+ } else {
80+ zend_suhosin_log(S_MISC, "could not replace logging function");
81+ }
82+ }
83+#endif
65be62f2 84+
3f3163a9 85 return SUCCESS;
65be62f2
ER
86 }
87 /* }}} */
3f3163a9
AM
88diff -Naurp php-5.3.6RC1/ext/standard/info.c php-5.3.6RC1.oden/ext/standard/info.c
89--- php-5.3.6RC1/ext/standard/info.c 2011-02-20 11:45:04.155489624 +0100
90+++ php-5.3.6RC1.oden/ext/standard/info.c 2011-02-20 11:50:19.297835740 +0100
91@@ -885,6 +885,33 @@ PHPAPI void php_print_info(int flag TSRM
92
93 php_info_print_table_end();
65be62f2 94
3f3163a9
AM
95+ /* Suhosin Patch */
96+ php_info_print_box_start(0);
97+ if (expose_php && !sapi_module.phpinfo_as_text) {
98+ PUTS("<a href=\"http://www.suhosin.org\"><img border=\"0\" src=\"");
99+ if (SG(request_info).request_uri) {
100+ char *elem_esc = php_info_html_esc(SG(request_info).request_uri TSRMLS_CC);
101+ PUTS(elem_esc);
102+ efree(elem_esc);
103+ }
104+ PUTS("?="SUHOSIN_LOGO_GUID"\" alt=\"Suhosin logo\" /></a>\n");
105+ }
106+ PUTS("This server is protected with the Suhosin Patch ");
107+ if (sapi_module.phpinfo_as_text) {
108+ PUTS(SUHOSIN_PATCH_VERSION);
109+ } else {
110+ zend_html_puts(SUHOSIN_PATCH_VERSION, strlen(SUHOSIN_PATCH_VERSION) TSRMLS_CC);
111+ }
112+ PUTS(!sapi_module.phpinfo_as_text?"<br />":"\n");
113+ if (sapi_module.phpinfo_as_text) {
114+ PUTS("Copyright (c) 2006-2007 Hardened-PHP Project\n");
115+ PUTS("Copyright (c) 2007-2009 SektionEins GmbH\n");
116+ } else {
117+ PUTS("Copyright (c) 2006-2007 <a href=\"http://www.hardened-php.net/\">Hardened-PHP Project</a>\n");
118+ PUTS("Copyright (c) 2007-2009 <a href=\"http://www.sektioneins.de/\">SektionEins GmbH</a>\n");
119+ }
120+ php_info_print_box_end();
65be62f2 121+
3f3163a9
AM
122 /* Zend Engine */
123 php_info_print_box_start(0);
124 if (expose_php && !sapi_module.phpinfo_as_text) {
125diff -Naurp php-5.3.6RC1/ext/standard/syslog.c php-5.3.6RC1.oden/ext/standard/syslog.c
126--- php-5.3.6RC1/ext/standard/syslog.c 2011-01-01 03:19:59.000000000 +0100
127+++ php-5.3.6RC1.oden/ext/standard/syslog.c 2011-02-20 11:50:19.299836022 +0100
128@@ -42,6 +42,7 @@ static void start_syslog(TSRMLS_D);
129 */
130 PHP_MINIT_FUNCTION(syslog)
131 {
132+#if !SUHOSIN_PATCH
133 /* error levels */
134 REGISTER_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
135 REGISTER_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
136@@ -97,6 +98,7 @@ PHP_MINIT_FUNCTION(syslog)
137 /* AIX doesn't have LOG_PERROR */
138 REGISTER_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
139 #endif
65be62f2 140+#endif
3f3163a9 141 BG(syslog_device)=NULL;
65be62f2 142
3f3163a9
AM
143 return SUCCESS;
144diff -Naurp php-5.3.6RC1/main/fopen_wrappers.c php-5.3.6RC1.oden/main/fopen_wrappers.c
145--- php-5.3.6RC1/main/fopen_wrappers.c 2011-01-18 23:20:09.000000000 +0100
146+++ php-5.3.6RC1.oden/main/fopen_wrappers.c 2011-02-20 11:50:19.299836022 +0100
147@@ -85,13 +85,8 @@ or a tightening during activation/runtim
148 PHPAPI ZEND_INI_MH(OnUpdateBaseDir)
149 {
150 char **p, *pathbuf, *ptr, *end;
151-#ifndef ZTS
152- char *base = (char *) mh_arg2;
153-#else
154- char *base = (char *) ts_resource(*((int *) mh_arg2));
155-#endif
156
157- p = (char **) (base + (size_t) mh_arg1);
158+ p = &PG(open_basedir);
65be62f2 159
3f3163a9
AM
160 if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN || stage == PHP_INI_STAGE_ACTIVATE || stage == PHP_INI_STAGE_DEACTIVATE) {
161 /* We're in a PHP_INI_SYSTEM context, no restrictions */
162diff -Naurp php-5.3.6RC1/main/main.c php-5.3.6RC1.oden/main/main.c
163--- php-5.3.6RC1/main/main.c 2011-02-08 22:40:51.000000000 +0100
164+++ php-5.3.6RC1.oden/main/main.c 2011-02-20 11:50:19.301836304 +0100
165@@ -90,6 +90,9 @@
65be62f2 166
3f3163a9
AM
167 #include "SAPI.h"
168 #include "rfc1867.h"
65be62f2
ER
169+#if SUHOSIN_PATCH
170+#include "suhosin_globals.h"
65be62f2 171+#endif
65be62f2 172
3f3163a9
AM
173 #if HAVE_SYS_MMAN_H
174 # include <sys/mman.h>
175@@ -490,7 +493,7 @@ PHP_INI_BEGIN()
176 STD_PHP_INI_ENTRY("extension_dir", PHP_EXTENSION_DIR, PHP_INI_SYSTEM, OnUpdateStringUnempty, extension_dir, php_core_globals, core_globals)
177 STD_PHP_INI_ENTRY("include_path", PHP_INCLUDE_PATH, PHP_INI_ALL, OnUpdateStringUnempty, include_path, php_core_globals, core_globals)
178 PHP_INI_ENTRY("max_execution_time", "30", PHP_INI_ALL, OnUpdateTimeout)
179- STD_PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir, open_basedir, php_core_globals, core_globals)
180+ PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir)
181 STD_PHP_INI_ENTRY("safe_mode_exec_dir", PHP_SAFE_MODE_EXEC_DIR, PHP_INI_SYSTEM, OnUpdateString, safe_mode_exec_dir, php_core_globals, core_globals)
182
183 STD_PHP_INI_BOOLEAN("file_uploads", "1", PHP_INI_SYSTEM, OnUpdateBool, file_uploads, php_core_globals, core_globals)
184@@ -1781,6 +1784,10 @@ void dummy_invalid_parameter_handler(
185 }
65be62f2
ER
186 #endif
187
188+#if SUHOSIN_PATCH
3f3163a9 189+PHPAPI void suhosin_startup();
65be62f2
ER
190+#endif
191+
3f3163a9
AM
192 /* {{{ php_module_startup
193 */
194 int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules)
195@@ -1825,6 +1832,10 @@ int php_module_startup(sapi_module_struc
196 tsrm_ls = ts_resource(0);
65be62f2
ER
197 #endif
198
3f3163a9
AM
199+#if SUHOSIN_PATCH
200+ suhosin_startup();
65be62f2
ER
201+#endif
202+
3f3163a9
AM
203 module_shutdown = 0;
204 module_startup = 1;
205 sapi_initialize_empty_request(TSRMLS_C);
206@@ -1944,7 +1955,11 @@ int php_module_startup(sapi_module_struc
207 REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
208 REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
209 REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
210- REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS);
65be62f2 211+#if SUHOSIN_PATCH
3f3163a9
AM
212+ REGISTER_MAIN_LONG_CONSTANT("SUHOSIN_PATCH", 1, CONST_PERSISTENT | CONST_CS);
213+ REGISTER_MAIN_STRINGL_CONSTANT("SUHOSIN_PATCH_VERSION", SUHOSIN_PATCH_VERSION, sizeof(SUHOSIN_PATCH_VERSION)-1, CONST_PERSISTENT | CONST_CS);
214+#endif
215+ REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS);
216 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS);
217 REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS);
218 #ifdef ZEND_MULTIBYTE
219diff -Naurp php-5.3.6RC1/main/php_config.h.in php-5.3.6RC1.oden/main/php_config.h.in
220--- php-5.3.6RC1/main/php_config.h.in 2011-02-16 21:30:44.000000000 +0100
221+++ php-5.3.6RC1.oden/main/php_config.h.in 2011-02-20 11:50:19.302836444 +0100
222@@ -851,6 +851,9 @@
223 /* Define if the target system has /dev/urandom device */
224 #undef HAVE_DEV_URANDOM
65be62f2 225
3f3163a9
AM
226+/* Suhosin-Patch for PHP */
227+#undef SUHOSIN_PATCH
65be62f2 228+
3f3163a9
AM
229 /* Whether you have AOLserver */
230 #undef HAVE_AOLSERVER
65be62f2 231
3f3163a9
AM
232diff -Naurp php-5.3.6RC1/main/php.h php-5.3.6RC1.oden/main/php.h
233--- php-5.3.6RC1/main/php.h 2011-01-01 03:19:59.000000000 +0100
234+++ php-5.3.6RC1.oden/main/php.h 2011-02-20 11:50:19.303836584 +0100
235@@ -453,6 +453,10 @@ END_EXTERN_C()
65be62f2 236 #endif
3f3163a9 237 #endif /* !XtOffsetOf */
65be62f2 238
3f3163a9
AM
239+#if SUHOSIN_PATCH
240+#include "suhosin_patch.h"
65be62f2
ER
241+#endif
242+
65be62f2 243 #endif
65be62f2 244
3f3163a9
AM
245 /*
246diff -Naurp php-5.3.6RC1/main/php_logos.c php-5.3.6RC1.oden/main/php_logos.c
247--- php-5.3.6RC1/main/php_logos.c 2011-01-01 03:19:59.000000000 +0100
248+++ php-5.3.6RC1.oden/main/php_logos.c 2011-02-20 11:50:19.303836584 +0100
249@@ -50,6 +50,10 @@ PHPAPI int php_unregister_info_logo(char
250 return zend_hash_del(&phpinfo_logo_hash, logo_string, strlen(logo_string));
65be62f2
ER
251 }
252
65be62f2 253+#if SUHOSIN_PATCH
3f3163a9 254+#include "suhosin_logo.h"
65be62f2 255+#endif
65be62f2 256+
3f3163a9 257 int php_init_info_logos(void)
65be62f2 258 {
3f3163a9
AM
259 if(zend_hash_init(&phpinfo_logo_hash, 0, NULL, NULL, 1)==FAILURE)
260@@ -58,7 +62,9 @@ int php_init_info_logos(void)
261 php_register_info_logo(PHP_EGG_LOGO_GUID, "image/gif", php_egg_logo, sizeof(php_egg_logo));
262 php_register_info_logo(ZEND_LOGO_GUID , "image/gif", zend_logo , sizeof(zend_logo));
263 php_register_info_logo(PLD_LOGO_GUID , "image/png", pld_logo , sizeof(pld_logo));
264-
65be62f2 265+#if SUHOSIN_PATCH
3f3163a9 266+ php_register_info_logo(SUHOSIN_LOGO_GUID, "image/jpeg", suhosin_logo , sizeof(suhosin_logo));
65be62f2 267+#endif
3f3163a9 268 return SUCCESS;
65be62f2
ER
269 }
270
3f3163a9
AM
271diff -Naurp php-5.3.6RC1/main/snprintf.c php-5.3.6RC1.oden/main/snprintf.c
272--- php-5.3.6RC1/main/snprintf.c 2011-01-01 03:19:59.000000000 +0100
273+++ php-5.3.6RC1.oden/main/snprintf.c 2011-02-20 11:50:19.304836724 +0100
274@@ -780,6 +780,10 @@ static int format_converter(register buf
275 */
276 switch (*fmt) {
277 case 'Z':
278+#if SUHOSIN_PATCH
279+ zend_suhosin_log(S_MISC, "'Z' specifier within format string");
280+ goto skip_output;
281+#else
282 zvp = (zval*) va_arg(ap, zval*);
283 zend_make_printable_zval(zvp, &zcopy, &free_zcopy);
284 if (free_zcopy) {
285@@ -790,6 +794,7 @@ static int format_converter(register buf
286 if (adjust_precision && precision < s_len) {
287 s_len = precision;
288 }
289+#endif
290 break;
291 case 'u':
292 switch(modifier) {
293@@ -1091,7 +1096,11 @@ static int format_converter(register buf
65be62f2 294
3f3163a9
AM
295
296 case 'n':
297+#if SUHOSIN_PATCH
298+ zend_suhosin_log(S_MISC, "'n' specifier within format string");
65be62f2 299+#else
3f3163a9 300 *(va_arg(ap, int *)) = cc;
65be62f2 301+#endif
3f3163a9 302 goto skip_output;
65be62f2 303
3f3163a9
AM
304 /*
305diff -Naurp php-5.3.6RC1/main/spprintf.c php-5.3.6RC1.oden/main/spprintf.c
306--- php-5.3.6RC1/main/spprintf.c 2011-01-01 03:19:59.000000000 +0100
307+++ php-5.3.6RC1.oden/main/spprintf.c 2011-02-20 11:50:19.305836865 +0100
308@@ -388,6 +388,10 @@ static void xbuf_format_converter(smart_
309 */
310 switch (*fmt) {
311 case 'Z':
312+#if SUHOSIN_PATCH
313+ zend_suhosin_log(S_MISC, "'Z' specifier within format string");
314+ goto skip_output;
315+#else
316 zvp = (zval*) va_arg(ap, zval*);
317 zend_make_printable_zval(zvp, &zcopy, &free_zcopy);
318 if (free_zcopy) {
319@@ -398,6 +402,7 @@ static void xbuf_format_converter(smart_
320 if (adjust_precision && precision < s_len) {
321 s_len = precision;
322 }
323+#endif
324 break;
325 case 'u':
326 switch(modifier) {
327@@ -698,7 +703,11 @@ static void xbuf_format_converter(smart_
65be62f2 328
65be62f2 329
3f3163a9
AM
330 case 'n':
331+#if SUHOSIN_PATCH
332+ zend_suhosin_log(S_MISC, "'n' specifier within format string");
65be62f2 333+#else
3f3163a9 334 *(va_arg(ap, int *)) = xbuf->len;
65be62f2 335+#endif
3f3163a9 336 goto skip_output;
65be62f2 337
3f3163a9
AM
338 /*
339diff -Naurp php-5.3.6RC1/main/suhosin_globals.h php-5.3.6RC1.oden/main/suhosin_globals.h
340--- php-5.3.6RC1/main/suhosin_globals.h 1970-01-01 01:00:00.000000000 +0100
341+++ php-5.3.6RC1.oden/main/suhosin_globals.h 2011-02-20 11:50:19.306837006 +0100
342@@ -0,0 +1,61 @@
343+/*
344+ +----------------------------------------------------------------------+
345+ | Suhosin-Patch for PHP |
346+ +----------------------------------------------------------------------+
347+ | Copyright (c) 2004-2009 Stefan Esser |
348+ +----------------------------------------------------------------------+
349+ | This source file is subject to version 2.02 of the PHP license, |
350+ | that is bundled with this package in the file LICENSE, and is |
351+ | available at through the world-wide-web at |
352+ | http://www.php.net/license/2_02.txt. |
353+ | If you did not receive a copy of the PHP license and are unable to |
354+ | obtain it through the world-wide-web, please send a note to |
355+ | license@php.net so we can mail you a copy immediately. |
356+ +----------------------------------------------------------------------+
357+ | Author: Stefan Esser <stefan.esser@sektioneins.de> |
358+ +----------------------------------------------------------------------+
359+ */
360+
361+#ifndef SUHOSIN_GLOBALS_H
362+#define SUHOSIN_GLOBALS_H
363+
364+typedef struct _suhosin_patch_globals suhosin_patch_globals_struct;
365+
366+#ifdef ZTS
367+# define SPG(v) TSRMG(suhosin_patch_globals_id, suhosin_patch_globals_struct *, v)
368+extern int suhosin_patch_globals_id;
369+#else
370+# define SPG(v) (suhosin_patch_globals.v)
371+extern struct _suhosin_patch_globals suhosin_patch_globals;
372+#endif
373+
374+
375+struct _suhosin_patch_globals {
376+ /* logging */
377+ int log_syslog;
378+ int log_syslog_facility;
379+ int log_syslog_priority;
380+ int log_sapi;
381+ int log_script;
382+ int log_phpscript;
383+ char *log_scriptname;
384+ char *log_phpscriptname;
385+ zend_bool log_phpscript_is_safe;
386+ zend_bool log_use_x_forwarded_for;
387+
388+ /* memory manager canary protection */
389+ unsigned int canary_1;
390+ unsigned int canary_2;
391+ unsigned int canary_3;
392+ unsigned int dummy;
393+};
394+
395+
396+#endif /* SUHOSIN_GLOBALS_H */
397+
398+/*
399+ * Local variables:
400+ * tab-width: 4
401+ * c-basic-offset: 4
402+ * End:
403+ */
404diff -Naurp php-5.3.6RC1/main/suhosin_logo.h php-5.3.6RC1.oden/main/suhosin_logo.h
405--- php-5.3.6RC1/main/suhosin_logo.h 1970-01-01 01:00:00.000000000 +0100
406+++ php-5.3.6RC1.oden/main/suhosin_logo.h 2011-02-20 11:50:19.306837006 +0100
407@@ -0,0 +1,178 @@
408+static unsigned char suhosin_logo[] =
409+ "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48"
410+ "\x00\x48\x00\x00\xff\xe1\x00\x16\x45\x78\x69\x66\x00\x00\x4d\x4d"
411+ "\x00\x2a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\xff\xdb\x00\x43"
412+ "\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
413+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
414+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
415+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
416+ "\x01\xff\xc0\x00\x0b\x08\x00\x27\x00\x71\x01\x01\x22\x00\xff\xc4"
417+ "\x00\x1e\x00\x00\x02\x02\x02\x03\x01\x01\x00\x00\x00\x00\x00\x00"
418+ "\x00\x00\x00\x00\x09\x06\x08\x05\x07\x02\x03\x0a\x01\x04\xff\xc4"
419+ "\x00\x32\x10\x00\x01\x04\x03\x00\x02\x00\x05\x01\x05\x09\x01\x00"
420+ "\x00\x00\x00\x05\x02\x03\x04\x06\x01\x07\x08\x00\x09\x11\x12\x13"
421+ "\x14\x21\x15\x0a\x16\x31\x56\x96\x17\x18\x19\x23\x32\x41\x58\x98"
422+ "\xd4\xd6\xff\xda\x00\x08\x01\x01\x00\x00\x3f\x00\xf4\xc1\xe1\xe5"
423+ "\x69\xe9\x3e\xb9\xd1\x7c\x8a\x2e\x9d\x66\xe8\x3b\x29\x4d\x7f\x46"
424+ "\xba\x58\x55\x54\x8d\xb1\x5f\xaa\xd9\x8d\x51\x2b\xb6\x27\x5a\x69"
425+ "\xd1\x43\xaf\x16\x1a\xf0\xb2\xb1\xe9\x6d\x9f\xc2\xa4\x36\x18\xb5"
426+ "\x85\x10\x41\xbe\xfc\x09\xac\x49\x29\x11\xd4\x32\x97\xec\x08\x13"
427+ "\xc1\x2d\x20\xc3\x59\xeb\x26\x05\xd8\x6b\x76\x31\x43\x8f\x57\xcf"
428+ "\x84\x9f\x14\xa8\x53\x81\x0b\xc3\x64\x80\xa3\x02\x0a\x41\x75\xf8"
429+ "\x44\x85\x93\x81\x22\x3c\xd8\x13\xe1\xbe\xf4\x59\x91\x1f\x6a\x44"
430+ "\x77\x5c\x69\xc4\x2f\x39\x5f\x0f\x2a\x8d\xeb\xba\xf8\xc3\x56\x6c"
431+ "\x3b\x36\xa7\xda\xbd\x4d\xa1\xb5\x4e\xc6\xa7\xa4\x3a\xec\x15\x2d"
432+ "\xa5\xb3\xea\x5a\xdc\xac\x46\xac\x01\x60\xd8\x43\xc8\x8e\x8b\xb1"
433+ "\x40\x4c\x95\x8b\x34\x41\x28\x52\x91\x28\x43\xd3\xa3\xb6\xa7\x55"
434+ "\x15\xe7\x5a\x96\xcb\xf1\xda\xe5\x55\xee\xfe\x1e\xbd\xd9\x41\xd3"
435+ "\x28\xfd\x97\xca\x57\x2b\x85\x9c\xa4\x30\x95\xaa\xa5\x57\xa2\x35"
436+ "\x15\x86\xcb\x61\x34\x41\xe4\xc7\x80\x20\x18\x21\x17\x09\x85\x0b"
437+ "\x14\x9d\x21\x68\x62\x1c\x08\x11\x64\x4b\x92\xf2\xd2\xd3\x2d\x2d"
438+ "\x6a\xc2\x73\x6b\x3c\x3c\x8b\x9e\xbc\x52\xaa\xa4\xab\x81\x6c\xf6"
439+ "\xfa\xbd\x70\xc5\xc6\x7b\xc2\xaa\x22\x4f\x58\x04\x87\x25\x6a\x27"
440+ "\x1d\xa4\x3d\x20\x75\x72\x01\x09\x71\xe5\x1c\x9e\xc3\x2e\x36\xf3"
441+ "\xd0\xc6\x35\x2a\x43\x4d\x2d\x0e\x2d\xb4\xa1\x49\xce\x65\x1e\x52"
442+ "\x9e\xa1\xf6\x09\xcc\xdc\x63\x66\xa8\x01\xe9\x3b\x0d\xd7\x5a\x85"
443+ "\xbb\xc5\x65\xc0\x7b\x2e\x46\xa9\xd9\x56\x1d\x4c\x92\x72\x26\x4e"
444+ "\x86\xd5\x68\xae\xc4\xaa\x55\xce\xd7\x83\x59\xb3\x81\xee\xce\x74"
445+ "\x39\x39\x31\x9f\x8a\x25\xe8\xa5\xa5\xe5\x81\xf2\x11\x23\xcb\xa1"
446+ "\x1e\x43\x12\xe3\xb1\x2a\x2b\xcd\xc8\x8d\x25\x96\xa4\x47\x7d\x95"
447+ "\xa5\xc6\x9f\x61\xe4\x25\xc6\x5e\x69\xc4\xe7\x29\x5b\x6e\xb6\xa4"
448+ "\xad\x0b\x4e\x72\x95\x25\x58\x56\x33\x9c\x67\xce\xef\x0f\x17\xbf"
449+ "\x4c\x7b\x2d\xe6\xfe\x76\x35\x27\x5a\x07\x97\x67\xe8\xae\x8d\x71"
450+ "\x0f\xb2\x13\x99\xb9\xbc\x14\xad\xb3\xb7\xe6\x11\x6f\xe0\xda\x58"
451+ "\xb1\x08\xac\xa6\x6c\x2d\x7f\x05\xb7\x56\xd2\xe6\xcf\xbb\x4d\x0c"
452+ "\xe3\x50\xb2\xec\x91\xf0\x4a\xb8\xd6\x22\xb8\xa7\xf6\x67\xaf\xcf"
453+ "\x63\x7e\xd7\xe7\x42\xd8\xbd\xc3\x71\xa1\xf2\x7e\x9b\xa8\x97\x83"
454+ "\x6e\xd1\xdc\x4b\x06\x11\x2d\xae\x26\x61\x98\x72\x10\xf4\x42\x5d"
455+ "\x20\x4a\xa3\x73\xd7\xf2\xcd\x3c\x48\x32\xe4\x03\x9f\x80\x37\x08"
456+ "\x36\x11\xd0\xcb\x97\x6c\x08\xed\x6d\x33\x24\xa2\x1b\xb4\x77\xdf"
457+ "\x61\x5d\x5f\xc1\x43\xc2\x82\xeb\x0f\x5d\x84\x08\x68\xaa\xa4\x01"
458+ "\xe1\x19\xdf\xbc\x31\x65\xfe\xd1\xf5\x7d\x7a\xb2\x2a\x33\x50\x21"
459+ "\x2a\x56\x9d\xb1\x81\xab\xdb\x35\x78\x30\x83\xd9\x89\x1d\x31\xac"
460+ "\x96\x14\x07\x61\xbc\x20\x68\x42\x85\x33\x19\xac\xbe\xdb\x34\x56"
461+ "\xf1\xd5\xfd\x29\xa9\x28\xdb\xcb\x4c\x5a\x23\xdc\xf5\x96\xc5\x10"
462+ "\xa3\x35\x5b\x14\x68\xd3\x61\x62\x64\x76\x26\xcb\x17\x3e\x34\x98"
463+ "\x04\xa3\xc4\x20\x38\x90\x92\xe3\xc8\x07\x2c\x36\x74\x66\x26\x0e"
464+ "\x29\x02\x64\x29\x2d\x21\xe6\x16\x9c\x6b\xce\xa3\x89\xd9\x4f\xd3"
465+ "\xc4\xbd\xc5\x87\x79\x9c\x65\xf6\x39\x45\x60\xe8\xce\x9e\xab\x6d"
466+ "\x13\x15\x22\xe1\x5e\x4b\x38\x42\xc4\x1e\xd5\x76\xe0\xc5\xeb\x85"
467+ "\x07\x2d\x0f\xb8\xb6\xa6\xd6\x6d\x71\x0d\xa2\x43\x4c\x25\xea\xfa"
468+ "\xa1\xae\x4c\xe4\x7d\xbd\x76\xa9\xfb\x06\xc2\x83\x42\xeb\xad\xe7"
469+ "\xe9\x5f\x68\x6f\xba\xfb\x2f\x07\xce\xb8\x13\xc1\x9b\xeb\xb0\x76"
470+ "\x45\x57\x28\x7b\xea\xbe\x0f\xf4\x30\x7b\xa0\xed\xe4\x22\x93\x21"
471+ "\xfc\xbc\xe0\xb9\x75\xc1\x4f\xfc\xef\xb6\xfa\xa1\xfc\x64\xa1\x4a"
472+ "\x82\xc7\x33\xad\x75\xed\x82\xbd\x3d\xdb\xf7\xa8\xbe\x5e\xbb\x36"
473+ "\x62\x04\x9a\x2e\xc5\xd9\x9e\x9c\x3a\x0b\x98\x0b\x57\xac\xf1\x24"
474+ "\x62\x58\x83\x15\x5b\xa6\xf2\xda\x34\x70\x03\xce\x0f\x93\x1b\x12"
475+ "\xc7\xce\x54\x87\x33\x15\xd6\x53\x25\x1f\x2a\x90\x87\x12\xe3\x78"
476+ "\xef\x55\x77\x4d\x4a\xd8\x7e\xef\xd2\xfd\xd1\xaf\x3a\xaf\x55\xdb"
477+ "\x6a\x2d\x3d\x42\xac\x51\x79\xee\x91\xab\xe1\x05\x2d\x3c\x80\xa2"
478+ "\x43\xad\x22\x2e\xd5\x33\x13\xa4\x9e\x00\xe0\x04\x10\x84\xc8\xf2"
479+ "\x19\x30\x92\x1f\xaa\xc3\x28\xc9\x76\x30\x3f\xe9\x10\x61\x5e\x79"
480+ "\xd5\xf7\xdf\xd0\x54\xdb\xae\xb6\xae\xfa\xe8\xa3\x57\xe0\x6c\x2d"
481+ "\xf7\xbd\x49\xd6\x6e\x76\x79\xcc\x54\x0c\x5f\xff\x00\xbb\x06\x98"
482+ "\xa6\x9e\x89\x61\xb4\x6f\xc3\xe3\x6a\xc2\x4f\x59\x03\xc9\x80\x2c"
483+ "\x59\x24\x44\x70\x38\xd5\x96\x6a\x9e\x8b\x81\x64\xe5\xbc\xa0\x3c"
484+ "\x33\xaf\x17\x9d\xff\x00\x71\x1a\xd1\x3a\x80\x66\xb3\xd9\x31\x77"
485+ "\x0d\x12\xbd\xae\x29\xb5\x6a\xd6\xcf\x8d\x68\x87\x75\xcd\xe8\x65"
486+ "\x5a\xbe\x3c\x04\x7b\x34\xdb\x54\x19\xa4\x63\x9c\x2a\x5d\x23\xbe"
487+ "\xf4\xb1\x1c\x4d\x90\xec\x92\x2f\x49\x71\xf7\x14\xf2\x97\x9f\x15"
488+ "\x57\xed\x13\x21\x2a\xf5\x33\xd1\x2a\x52\x52\xac\xb7\x62\xd1\xcb"
489+ "\x46\x73\x8c\x67\x28\x56\x77\x86\xbf\x6f\x2a\x4e\x73\xfe\x95\x65"
490+ "\x0b\x5a\x3e\x38\xfc\xfc\xaa\x56\x3f\x86\x73\xe3\xb9\x4a\x52\x84"
491+ "\xa5\x08\x4e\x12\x94\x27\x09\x4a\x53\x8c\x61\x29\x4a\x71\xf0\x4a"
492+ "\x53\x8c\x7e\x31\x8c\x63\x18\xc6\x31\x8f\xc6\x31\xf8\xc7\x9f\x7c"
493+ "\xd5\xbb\xae\x5e\xe2\x1f\xab\x6e\x24\x34\x00\x8a\x25\x83\x70\x40"
494+ "\x1c\xcc\xda\x45\x7f\x66\x4e\x30\x2e\x94\x7e\x74\x49\xf0\xe4\x4e"
495+ "\x06\x5c\xa8\x2f\x89\x21\x2e\x98\x0e\xd9\x21\xc2\x0b\x21\x0f\xc4"
496+ "\x16\x6e\x48\xd9\xe4\xe3\x4a\x19\x1e\x64\x67\x54\xff\x00\x3a\x6d"
497+ "\x4f\x62\xb5\x00\x4a\xaa\x51\xfd\x2d\xe8\x0e\x6c\xaf\xc6\x7d\x6d"
498+ "\xc8\x88\xc7\x67\xea\x8a\x58\x02\x73\xe3\x65\x4d\xc9\x24\xc0\x3d"
499+ "\x57\xa3\x2e\x53\x16\x99\x4f\xe5\xe7\x19\x97\x3e\x3b\xcf\xc9\x4b"
500+ "\x99\x7f\x33\x25\xa5\xdf\xba\x77\x2b\xd3\x3e\xc2\x7b\x8b\x94\x07"
501+ "\xe9\x52\x5b\x43\x87\x34\x14\x86\x37\xcf\x41\x6b\x8e\x6a\xa5\x22"
502+ "\xab\xdb\x96\xa2\xcf\x46\xd8\x9b\x45\x93\xef\xd6\xdf\x3e\x99\x9c"
503+ "\x7e\x29\x10\x6b\x6c\xa2\xb8\x43\x05\x09\x44\x70\x8c\xb8\xaa\x54"
504+ "\x7c\x30\x36\x5e\x1c\x5e\x5b\x9f\x6c\x0d\x81\xee\xa0\x93\x8d\x67"
505+ "\x55\xf3\x87\xaf\xaa\x6b\x58\xf9\xbe\xb2\x36\x07\x42\x6e\xbd\x96"
506+ "\xe3\x9f\x1f\x8f\xc9\xf4\x9d\xae\x6a\x7d\x4c\x96\xbe\x5f\xc7\xcd"
507+ "\xf3\xb2\xf7\xcd\xf0\xcf\xc3\xe4\xf8\xfe\x37\x4f\x1c\x4d\xf6\x40"
508+ "\xf1\x6b\x7c\x4e\xe0\xa6\x71\xad\x56\xa7\x1c\x5c\x15\x6b\xfc\xf3"
509+ "\x01\x5d\xac\xf1\x75\x9a\x72\x6b\xaa\x28\xc5\x88\x6d\xfb\x33\x85"
510+ "\xe0\x4e\x61\xab\xeb\x31\x2c\x71\x08\x73\x11\x3b\xfc\xb5\xc0\x96"
511+ "\xcc\x87\x24\x44\xb5\x9b\x9e\xb3\x71\xba\xe9\xed\xb1\x4e\xd7\x76"
512+ "\x6c\xd2\xb6\x05\xb7\x5a\xde\xeb\x34\x5b\x96\x16\xfb\x59\xa9\x5c"
513+ "\x4f\x55\xca\x8a\xac\x59\xb0\xe4\x54\x39\x25\xbc\x81\x37\x2a\x09"
514+ "\x5f\x9e\x3b\x6b\x7d\x1f\x69\xf3\x34\x85\x39\x84\xa7\x28\x0b\xd3"
515+ "\xfd\xfb\x4b\x7a\xea\xe7\xd2\x3c\xd3\xda\x15\x68\xbc\x73\xd3\x22"
516+ "\x6f\xd7\x72\x5b\x2b\x66\xee\xa8\x0d\x54\xe8\x5b\xf9\x92\x96\x92"
517+ "\x93\xea\x97\x4a\xc7\x43\x10\x46\x35\xc5\xc0\x60\x8a\xe4\xc1\xb5"
518+ "\x36\xc6\xae\xed\xf7\x70\xa5\x86\x99\x3d\x91\xf8\xfd\x4e\x53\xeb"
519+ "\xbb\xbd\x6d\xec\x8f\xd7\x89\x3d\x31\x7f\xd7\x78\xba\x50\xbb\x74"
520+ "\x9d\xf6\xac\x4e\xb9\x03\x9c\x79\xd5\xe1\xbd\x17\x68\xd9\x13\x0b"
521+ "\x45\x75\x88\x00\x1d\x1f\xae\x73\x6a\x1d\x5c\x6e\x44\x9f\xa6\xfa"
522+ "\x4e\xd8\x25\x8b\xc0\xbc\xb2\x99\xe3\x17\x24\xb3\x23\xe2\x48\x8b"
523+ "\xfa\x22\xe7\x7e\x8f\xe6\x3f\x5f\x55\x0d\x75\xd3\x51\x0b\xd7\xed"
524+ "\xd3\x6f\x97\x3b\x85\x42\x80\x7e\x5f\xdc\x1b\xd6\xba\xee\xc4\x80"
525+ "\xce\x06\xa9\x15\x8c\x97\x5f\x40\x69\xb2\x4d\xc5\xb2\x5c\x1e\x01"
526+ "\x87\x7e\xe0\x36\x6d\x78\x80\x4e\x3c\x02\xec\x90\x1d\x11\x81\x74"
527+ "\xa5\x8b\xa4\xa0\x56\x06\xd5\x79\x72\x85\x57\x3b\xb2\x2e\xae\x90"
528+ "\x18\x8d\x91\xb2\x0e\x44\x19\xaa\xb4\xcc\x08\xed\x46\xfa\xd7\x2b"
529+ "\x78\x58\x72\x5d\xbb\x5e\x49\xe7\xee\xf3\x8a\x9d\x22\xa4\x19\xc8"
530+ "\xe7\x08\xc3\x90\x9b\x35\x9a\xa4\x25\x8c\x4b\x9b\xa7\xf8\xbf\x81"
531+ "\xf5\xdf\x22\x66\xf1\x7e\x9f\x66\x3d\xbb\xfa\x73\x73\x4d\xfd\x67"
532+ "\x7b\xf4\xce\xc3\x62\x2e\x6f\xbb\x0c\xa2\xdc\x69\xfc\x8a\x17\x0e"
533+ "\x3a\x9e\x83\x46\xd7\xe3\x5e\x65\x86\xc0\x51\x00\xbb\x91\xe3\xe1"
534+ "\xc1\x16\xc4\xe9\x65\x5c\x14\x3e\x44\x6a\x6b\xd1\x1e\xb0\x36\xdd"
535+ "\x0b\x7d\x8a\xeb\xaf\x58\x5b\x64\x3f\x38\xed\x52\x76\xe8\x46\xf7"
536+ "\x86\x84\xb3\x93\xb1\x0b\xe5\xfd\xfd\x0d\xe9\x6d\xe4\xf1\x1b\x1d"
537+ "\x56\xb4\x34\xe4\x6a\xf5\xa4\x9c\x2c\xc9\x64\x94\xc1\xf5\x79\x6d"
538+ "\x12\x96\xf3\x47\xc5\x48\xa8\xdb\xd8\x95\x64\x29\xcf\xf6\x88\xf1"
539+ "\x95\x7a\x98\xe8\xbc\x27\x19\xce\x73\x61\xd1\xb8\xc6\x31\x8c\xe7"
540+ "\x39\xce\x77\x9e\xbc\xc6\x31\x8c\x63\xf3\x9c\xe7\x39\xc6\x31\x8f"
541+ "\xf7\xce\x7e\x1e\x3b\x7f\x0f\x0f\x0f\x13\x57\xb9\x0a\xe1\x0b\x64"
542+ "\x5f\x58\x40\xc6\xc7\x7a\x4b\xf2\x3d\xbc\x71\xf4\xa7\xd2\xca\x14"
543+ "\xe2\x98\x1a\x30\x1e\xe0\x26\x5a\x6a\xf0\x9c\x67\x38\x66\x00\xb8"
544+ "\x72\xe6\xbe\xac\xfe\x12\xd3\x0b\x56\x73\x8c\x63\xc7\x2b\xe1\xe2"
545+ "\xe8\xdd\x7b\xff\x00\xd8\xe5\x23\x6c\xce\xa8\x69\xcf\x5e\x3a\xef"
546+ "\x77\xea\xe5\xab\x0e\x82\xdb\xd9\xed\x7a\x9e\xb8\x6d\x51\x32\xdb"
547+ "\x79\xc3\x36\x9a\x2d\xa3\x50\x39\x65\x0a\x63\x0e\xe5\xd4\x39\x12"
548+ "\xbf\x8b\x98\xa4\xa1\x2d\xad\xb3\xcf\x65\x6a\x43\x78\xb3\x3b\x07"
549+ "\xd8\xd5\xea\xae\x76\xad\x6f\xf5\xff\x00\xca\x93\xab\x96\xb0\x64"
550+ "\xeb\xd6\x4a\xd5\x87\xba\xec\x24\x60\x97\x06\x76\x03\xe3\x4c\x07"
551+ "\x29\x11\x8e\x34\x25\x02\x64\x29\xf0\x25\x48\x85\x3a\x33\x8b\x7a"
552+ "\x3c\x86\x1e\x75\xa5\x61\xc6\x97\x9f\x8d\x25\xf5\xc9\xcd\xde\xc9"
553+ "\x7d\x77\xf2\xc8\x7e\x70\xaf\x73\x5f\x2d\xec\xa2\x51\x2d\x96\xfb"
554+ "\x89\xad\x80\x57\xb2\x36\x1d\x7d\x83\x45\xac\xf3\xdb\xcc\x6c\x31"
555+ "\x4f\xcf\x30\x58\xd0\x12\x28\x90\x50\x42\x86\xfb\x48\x16\x3c\xc5"
556+ "\x9c\xf8\xe7\xcc\x29\x88\xb3\x4a\x4b\x4e\x6c\xbc\xdb\xc7\xbb\xe9"
557+ "\xb6\xa0\x8b\x11\xa1\x7d\x73\xd7\xe9\xbf\x7e\xc2\x6c\x10\x8d\xee"
558+ "\x9d\xef\x63\x3a\xe0\xf5\xbe\x8c\x3e\xa1\xc7\xc5\xd1\x00\x44\x1e"
559+ "\xf3\x51\xf2\xe2\xb0\xe3\xb5\x13\x7f\x32\xf1\x8c\xa6\x22\xfe\x1f"
560+ "\x49\x4d\xbb\xcf\x3a\x5d\xed\x4c\xd2\xfc\x85\xed\x23\xd6\xc7\x50"
561+ "\xb6\x5b\x3a\x16\x83\xb8\x6f\xfd\x32\x3f\xaa\x36\x34\xbb\xf5\x96"
562+ "\xa9\xab\xcf\x9f\x8f\xac\xc3\xca\xd5\x8b\xd8\x48\x9e\x79\xaa\x30"
563+ "\x87\xca\x58\x4d\x59\x96\xb9\x4f\xc5\x1b\x1c\xd2\xda\x5b\xe6\x57"
564+ "\x29\xa1\x28\x7a\x2b\x5b\xff\x00\x12\x2f\x5e\x3f\xf3\xbb\x8e\x7f"
565+ "\xec\xc6\x98\xff\x00\xed\x3c\xa6\xdd\xa9\xdc\x7e\xa0\xf7\xd6\x99"
566+ "\x31\xa2\xf7\xaf\x6b\xe9\x82\x74\x4b\x3d\x8f\x5e\x58\x0b\x33\xab"
567+ "\xef\xc3\xaf\x84\x64\xb9\xae\xb6\x25\x5f\x62\x8f\x1c\xe3\xf4\x51"
568+ "\xb7\x96\xe3\x0e\x30\x42\xa9\x18\x39\xbf\x9e\x2a\x1f\x74\x19\x02"
569+ "\x2d\x43\x93\x06\x63\xb1\xa7\x47\x6a\xfa\x9b\x6c\xeb\xbd\xe9\xae"
570+ "\x6a\x7b\x6f\x53\x5a\x60\x5d\xb5\xcd\xe8\x67\xeb\x35\x3b\x48\xc6"
571+ "\xa6\xb3\x04\xc8\xdf\xb8\x7e\x26\x64\xb0\xc9\x18\xb0\xa7\x33\xf2"
572+ "\x4a\x8b\x22\x3b\x8d\x4b\x89\x1d\xf6\x9d\x65\xc4\x38\xd2\x54\x9c"
573+ "\xe3\xcd\x89\xe1\xe1\xe6\x3e\x70\x81\x45\x1d\x18\xf9\x31\x83\xc8"
574+ "\xbe\x14\x82\x4b\x87\x7a\x74\x28\xd2\xdd\x12\x55\x30\xe6\x0e\x49"
575+ "\x31\x8e\x48\x69\xc5\xc0\x20\x91\xe4\x48\x41\x4c\xd8\xb9\x6a\x4e"
576+ "\x21\xce\x99\x1b\x0e\xfd\x09\x4f\xa1\x79\x0f\x0f\x0f\x0f\x0f\x0f"
577+ "\x0f\x3f\x3c\xb8\x71\x27\xc7\x72\x24\xe8\xb1\xa6\xc5\x7b\x18\xc3"
578+ "\xb1\xa5\xb0\xd4\x98\xee\xe3\x19\xc6\x71\x87\x19\x79\x2b\x6d\x78"
579+ "\xc6\x71\x8c\xe3\x0a\x4e\x71\x8c\xe3\x19\xfe\x38\xf2\x3b\xfb\x8b"
580+ "\x48\xfe\x4e\xaa\xff\x00\x4f\x08\xff\x00\xc7\xe1\xfb\x8b\x48\xfe"
581+ "\x4e\xaa\xff\x00\x4f\x08\xff\x00\xc7\xe4\x95\x86\x18\x8a\xcb\x31"
582+ "\xa3\x32\xd4\x78\xf1\xdb\x43\x2c\x47\x61\xb4\x32\xcb\x2c\xb4\x9c"
583+ "\x21\xb6\x99\x69\xbc\x25\xb6\xdb\x6d\x18\xc2\x10\xda\x12\x94\xa1"
584+ "\x38\xc2\x53\x8c\x63\x18\xc7\x9d\xbe\x7f\xff\xd9"
585+ ;
586diff -Naurp php-5.3.6RC1/main/suhosin_patch.c php-5.3.6RC1.oden/main/suhosin_patch.c
587--- php-5.3.6RC1/main/suhosin_patch.c 1970-01-01 01:00:00.000000000 +0100
588+++ php-5.3.6RC1.oden/main/suhosin_patch.c 2011-02-20 11:50:19.307837147 +0100
589@@ -0,0 +1,470 @@
590+/*
591+ +----------------------------------------------------------------------+
592+ | Suhosin Patch for PHP |
593+ +----------------------------------------------------------------------+
594+ | Copyright (c) 2004-2010 Stefan Esser |
595+ +----------------------------------------------------------------------+
596+ | This source file is subject to version 2.02 of the PHP license, |
597+ | that is bundled with this package in the file LICENSE, and is |
598+ | available at through the world-wide-web at |
599+ | http://www.php.net/license/2_02.txt. |
600+ | If you did not receive a copy of the PHP license and are unable to |
601+ | obtain it through the world-wide-web, please send a note to |
602+ | license@php.net so we can mail you a copy immediately. |
603+ +----------------------------------------------------------------------+
604+ | Author: Stefan Esser <sesser@hardened-php.net> |
605+ +----------------------------------------------------------------------+
606+ */
607+/* $Id$ */
608+
609+#include "php.h"
610+
611+#include <stdio.h>
612+#include <stdlib.h>
613+#include <sys/mman.h>
614+
615+#if HAVE_UNISTD_H
616+#include <unistd.h>
617+#endif
618+#include "SAPI.h"
619+#include "php_globals.h"
620+
621+#if SUHOSIN_PATCH
622+
623+#ifdef HAVE_SYS_SOCKET_H
624+#include <sys/socket.h>
625+#endif
626+
627+#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
628+#undef AF_UNIX
629+#endif
630+
631+#if defined(AF_UNIX)
632+#include <sys/un.h>
633+#endif
634+
635+#define SYSLOG_PATH "/dev/log"
636+
637+#ifdef PHP_WIN32
638+static HANDLE log_source = 0;
639+#endif
640+
641+#include "snprintf.h"
642+
643+#include "suhosin_patch.h"
644+
645+#ifdef ZTS
646+#include "suhosin_globals.h"
647+int suhosin_patch_globals_id;
648+#else
649+struct _suhosin_patch_globals suhosin_patch_globals;
650+#endif
651+
652+static char *suhosin_config = NULL;
653+
654+static zend_intptr_t SUHOSIN_POINTER_GUARD = 0;
655+
656+static void php_security_log(int loglevel, char *fmt, ...);
657+
658+static void suhosin_patch_globals_ctor(suhosin_patch_globals_struct *suhosin_patch_globals TSRMLS_DC)
659+{
660+ memset(suhosin_patch_globals, 0, sizeof(*suhosin_patch_globals));
65be62f2 661+}
3f3163a9
AM
662+
663+ZEND_API char suhosin_get_config(int element)
65be62f2 664+{
3f3163a9
AM
665+ return ((char *)SUHOSIN_MANGLE_PTR(suhosin_config))[element];
666+}
667+
668+static void suhosin_set_config(int element, char value)
669+{
670+ ((char *)SUHOSIN_MANGLE_PTR(suhosin_config))[element] = value;
671+}
672+
673+static void suhosin_read_configuration_from_environment()
674+{
675+ char *tmp;
676+
677+ /* check if canary protection should be activated or not */
678+ tmp = getenv("SUHOSIN_MM_USE_CANARY_PROTECTION");
679+ /* default to activated */
680+ suhosin_set_config(SUHOSIN_MM_USE_CANARY_PROTECTION, 1);
681+ if (tmp) {
682+ int flag = zend_atoi(tmp, 0);
683+ suhosin_set_config(SUHOSIN_MM_USE_CANARY_PROTECTION, flag);
65be62f2 684+ }
3f3163a9
AM
685+
686+ /* check if free memory should be overwritten with 0xFF or not */
687+ tmp = getenv("SUHOSIN_MM_DESTROY_FREE_MEMORY");
688+ /* default to deactivated */
689+ suhosin_set_config(SUHOSIN_MM_DESTROY_FREE_MEMORY, 0);
690+ if (tmp) {
691+ int flag = zend_atoi(tmp, 0);
692+ suhosin_set_config(SUHOSIN_MM_DESTROY_FREE_MEMORY, flag);
693+ }
694+
695+ /* check if canary violations should be ignored */
696+ tmp = getenv("SUHOSIN_MM_IGNORE_CANARY_VIOLATION");
697+ /* default to NOT ignore */
698+ suhosin_set_config(SUHOSIN_MM_IGNORE_CANARY_VIOLATION, 0);
699+ if (tmp) {
700+ int flag = zend_atoi(tmp, 0);
701+ suhosin_set_config(SUHOSIN_MM_IGNORE_CANARY_VIOLATION, flag);
702+ }
703+
704+ /* check if invalid hashtable destructors should be ignored */
705+ tmp = getenv("SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR");
706+ /* default to NOT ignore */
707+ suhosin_set_config(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR, 0);
708+ if (tmp) {
709+ int flag = zend_atoi(tmp, 0);
710+ suhosin_set_config(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR, flag);
711+ }
712+
713+ /* check if invalid linkedlist destructors should be ignored */
714+ tmp = getenv("SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR");
715+ /* default to NOT ignore */
716+ suhosin_set_config(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR, 0);
717+ if (tmp) {
718+ int flag = zend_atoi(tmp, 0);
719+ suhosin_set_config(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR, flag);
720+ }
721+
722+ suhosin_set_config(SUHOSIN_CONFIG_SET, 1);
65be62f2
ER
723+}
724+
3f3163a9
AM
725+static void suhosin_write_protect_configuration()
726+{
727+ /* check return value of mprotect() to ensure memory is read only now */
728+ if (mprotect(SUHOSIN_MANGLE_PTR(suhosin_config), sysconf(_SC_PAGESIZE), PROT_READ) != 0) {
729+ perror("suhosin");
730+ _exit(1);
731+ }
732+}
65be62f2 733+
3f3163a9
AM
734+PHPAPI void suhosin_startup()
735+{
736+#ifdef ZTS
737+ ts_allocate_id(&suhosin_patch_globals_id, sizeof(suhosin_patch_globals_struct), (ts_allocate_ctor) suhosin_patch_globals_ctor, NULL);
65be62f2 738+#else
3f3163a9 739+ suhosin_patch_globals_ctor(&suhosin_patch_globals TSRMLS_CC);
65be62f2 740+#endif
3f3163a9
AM
741+ zend_suhosin_log = php_security_log;
742+
743+ /* get the pointer guardian and ensure low 3 bits are 1 */
744+ if (SUHOSIN_POINTER_GUARD == 0) {
745+ zend_canary(&SUHOSIN_POINTER_GUARD, sizeof(SUHOSIN_POINTER_GUARD));
746+ SUHOSIN_POINTER_GUARD |= 7;
65be62f2 747+ }
3f3163a9
AM
748+
749+ if (!suhosin_config) {
750+#ifndef MAP_ANONYMOUS
751+#define MAP_ANONYMOUS MAP_ANON
752+#endif
753+ suhosin_config = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
754+ if (suhosin_config == MAP_FAILED) {
755+ perror("suhosin");
756+ _exit(1);
757+ }
758+ suhosin_config = SUHOSIN_MANGLE_PTR(suhosin_config);
759+ }
760+ if (!SUHOSIN_CONFIG(SUHOSIN_CONFIG_SET)) {
761+ suhosin_read_configuration_from_environment();
762+ suhosin_write_protect_configuration();
763+ }
65be62f2 764+}
65be62f2 765+
3f3163a9
AM
766+static char *loglevel2string(int loglevel)
767+{
768+ switch (loglevel) {
769+ case S_FILES:
770+ return "FILES";
771+ case S_INCLUDE:
772+ return "INCLUDE";
773+ case S_MEMORY:
774+ return "MEMORY";
775+ case S_MISC:
776+ return "MISC";
777+ case S_SESSION:
778+ return "SESSION";
779+ case S_SQL:
780+ return "SQL";
781+ case S_EXECUTOR:
782+ return "EXECUTOR";
783+ case S_VARS:
784+ return "VARS";
785+ default:
786+ return "UNKNOWN";
787+ }
788+}
789+
790+static void php_security_log(int loglevel, char *fmt, ...)
791+{
792+ int s, r, i=0;
793+#if defined(AF_UNIX)
794+ struct sockaddr_un saun;
65be62f2 795+#endif
3f3163a9
AM
796+#ifdef PHP_WIN32
797+ LPTSTR strs[2];
798+ unsigned short etype;
799+ DWORD evid;
65be62f2 800+#endif
3f3163a9
AM
801+ char buf[4096+64];
802+ char error[4096+100];
803+ char *ip_address;
804+ char *fname;
805+ char *alertstring;
806+ int lineno;
807+ va_list ap;
808+ TSRMLS_FETCH();
809+
810+ /*SDEBUG("(suhosin_log) loglevel: %d log_syslog: %u - log_sapi: %u - log_script: %u", loglevel, SPG(log_syslog), SPG(log_sapi), SPG(log_script));*/
811+
812+ if (SPG(log_use_x_forwarded_for)) {
813+ ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
814+ if (ip_address == NULL) {
815+ ip_address = "X-FORWARDED-FOR not set";
816+ }
817+ } else {
818+ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
819+ if (ip_address == NULL) {
820+ ip_address = "REMOTE_ADDR not set";
821+ }
822+ }
823+
824+
825+ va_start(ap, fmt);
826+ ap_php_vsnprintf(error, sizeof(error), fmt, ap);
827+ va_end(ap);
828+ while (error[i]) {
829+ if (error[i] < 32) error[i] = '.';
830+ i++;
831+ }
832+
833+/* if (SPG(simulation)) {
834+ alertstring = "ALERT-SIMULATION";
835+ } else { */
836+ alertstring = "ALERT";
837+/* }*/
838+
839+ if (zend_is_executing(TSRMLS_C)) {
840+ if (EG(current_execute_data)) {
841+ lineno = EG(current_execute_data)->opline->lineno;
842+ fname = EG(current_execute_data)->op_array->filename;
843+ } else {
844+ lineno = zend_get_executed_lineno(TSRMLS_C);
845+ fname = zend_get_executed_filename(TSRMLS_C);
846+ }
847+ ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s', line %u)", alertstring, error, ip_address, fname, lineno);
848+ } else {
849+ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
850+ if (fname==NULL) {
851+ fname = "unknown";
852+ }
853+ ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s')", alertstring, error, ip_address, fname);
854+ }
855+
856+ /* Syslog-Logging disabled? */
857+ if (((SPG(log_syslog)|S_INTERNAL) & loglevel)==0) {
858+ goto log_sapi;
859+ }
860+
861+#if defined(AF_UNIX)
862+ ap_php_snprintf(error, sizeof(error), "<%u>suhosin[%u]: %s\n", (unsigned int)(SPG(log_syslog_facility)|SPG(log_syslog_priority)),getpid(),buf);
863+
864+ s = socket(AF_UNIX, SOCK_DGRAM, 0);
865+ if (s == -1) {
866+ goto log_sapi;
867+ }
65be62f2 868+
3f3163a9
AM
869+ memset(&saun, 0, sizeof(saun));
870+ saun.sun_family = AF_UNIX;
871+ strcpy(saun.sun_path, SYSLOG_PATH);
872+ /*saun.sun_len = sizeof(saun);*/
65be62f2 873+
3f3163a9
AM
874+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
875+ if (r) {
876+ close(s);
877+ s = socket(AF_UNIX, SOCK_STREAM, 0);
878+ if (s == -1) {
879+ goto log_sapi;
880+ }
881+
882+ memset(&saun, 0, sizeof(saun));
883+ saun.sun_family = AF_UNIX;
884+ strcpy(saun.sun_path, SYSLOG_PATH);
885+ /*saun.sun_len = sizeof(saun);*/
886+
887+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
888+ if (r) {
889+ close(s);
890+ goto log_sapi;
891+ }
892+ }
893+ send(s, error, strlen(error), 0);
894+
895+ close(s);
65be62f2 896+#endif
3f3163a9
AM
897+#ifdef PHP_WIN32
898+ ap_php_snprintf(error, sizeof(error), "suhosin[%u]: %s", getpid(),buf);
899+
900+ switch (SPG(log_syslog_priority)) { /* translate UNIX type into NT type */
901+ case 1: /*LOG_ALERT:*/
902+ etype = EVENTLOG_ERROR_TYPE;
903+ break;
904+ case 6: /*LOG_INFO:*/
905+ etype = EVENTLOG_INFORMATION_TYPE;
906+ break;
907+ default:
908+ etype = EVENTLOG_WARNING_TYPE;
909+ }
910+ evid = loglevel;
911+ strs[0] = error;
912+ /* report the event */
913+ if (log_source == NULL) {
914+ log_source = RegisterEventSource(NULL, "Suhosin-Patch-" SUHOSIN_PATCH_VERSION);
915+ }
916+ ReportEvent(log_source, etype, (unsigned short) SPG(log_syslog_priority), evid, NULL, 1, 0, strs, NULL);
917+
65be62f2 918+#endif
3f3163a9
AM
919+log_sapi:
920+ /* SAPI Logging activated? */
921+ /*SDEBUG("(suhosin_log) log_syslog: %u - log_sapi: %u - log_script: %u - log_phpscript: %u", SPG(log_syslog), SPG(log_sapi), SPG(log_script), SPG(log_phpscript));*/
922+ if (((SPG(log_sapi)|S_INTERNAL) & loglevel)!=0) {
923+ sapi_module.log_message(buf);
924+ }
925+
926+/*log_script:*/
927+ /* script logging activaed? */
928+ if (((SPG(log_script) & loglevel)!=0) && SPG(log_scriptname)!=NULL) {
929+ char cmd[8192], *cmdpos, *bufpos;
930+ FILE *in;
931+ int space;
932+
933+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", SPG(log_scriptname), loglevel2string(loglevel));
934+ space = sizeof(cmd) - strlen(cmd);
935+ cmdpos = cmd + strlen(cmd);
936+ bufpos = buf;
937+ if (space <= 1) return;
938+ while (space > 2 && *bufpos) {
939+ if (*bufpos == '\'') {
940+ if (space<=5) break;
941+ *cmdpos++ = '\'';
942+ *cmdpos++ = '\\';
943+ *cmdpos++ = '\'';
944+ *cmdpos++ = '\'';
945+ bufpos++;
946+ space-=4;
947+ } else {
948+ *cmdpos++ = *bufpos++;
949+ space--;
950+ }
951+ }
952+ *cmdpos++ = '\'';
953+ *cmdpos = 0;
954+
955+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
956+ php_security_log(S_INTERNAL, "Unable to execute logging shell script: %s", SPG(log_scriptname));
957+ return;
958+ }
959+ /* read and forget the result */
960+ while (1) {
961+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
962+ if (readbytes<=0) {
963+ break;
964+ }
965+ }
966+ pclose(in);
967+ }
968+/*log_phpscript:*/
969+ if ((SPG(log_phpscript) & loglevel)!=0 && EG(in_execution) && SPG(log_phpscriptname) && SPG(log_phpscriptname)[0]) {
970+ zend_file_handle file_handle;
971+ zend_op_array *new_op_array;
972+ zval *result = NULL;
973+
974+ /*long orig_execution_depth = SPG(execution_depth);*/
975+ zend_bool orig_safe_mode = PG(safe_mode);
976+ char *orig_basedir = PG(open_basedir);
977+
978+ char *phpscript = SPG(log_phpscriptname);
979+/*SDEBUG("scriptname %s", SPG(log_phpscriptname));`*/
980+#ifdef ZEND_ENGINE_2
981+ if (zend_stream_open(phpscript, &file_handle TSRMLS_CC) == SUCCESS) {
65be62f2 982+#else
3f3163a9
AM
983+ if (zend_open(phpscript, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
984+ file_handle.filename = phpscript;
985+ file_handle.free_filename = 0;
986+#endif
987+ if (!file_handle.opened_path) {
988+ file_handle.opened_path = estrndup(phpscript, strlen(phpscript));
989+ }
990+ new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
991+ zend_destroy_file_handle(&file_handle TSRMLS_CC);
992+ if (new_op_array) {
993+ HashTable *active_symbol_table = EG(active_symbol_table);
994+ zval *zerror, *zerror_class;
995+
996+ if (active_symbol_table == NULL) {
997+ active_symbol_table = &EG(symbol_table);
998+ }
999+ EG(return_value_ptr_ptr) = &result;
1000+ EG(active_op_array) = new_op_array;
1001+
1002+ MAKE_STD_ZVAL(zerror);
1003+ MAKE_STD_ZVAL(zerror_class);
1004+ ZVAL_STRING(zerror, buf, 1);
1005+ ZVAL_LONG(zerror_class, loglevel);
1006+
1007+ zend_hash_update(active_symbol_table, "SUHOSIN_ERROR", sizeof("SUHOSIN_ERROR"), (void **)&zerror, sizeof(zval *), NULL);
1008+ zend_hash_update(active_symbol_table, "SUHOSIN_ERRORCLASS", sizeof("SUHOSIN_ERRORCLASS"), (void **)&zerror_class, sizeof(zval *), NULL);
1009+
1010+ /*SPG(execution_depth) = 0;*/
1011+ if (SPG(log_phpscript_is_safe)) {
1012+ PG(safe_mode) = 0;
1013+ PG(open_basedir) = NULL;
1014+ }
1015+
1016+ zend_execute(new_op_array TSRMLS_CC);
1017+
1018+ /*SPG(execution_depth) = orig_execution_depth;*/
1019+ PG(safe_mode) = orig_safe_mode;
1020+ PG(open_basedir) = orig_basedir;
1021+
1022+#ifdef ZEND_ENGINE_2
1023+ destroy_op_array(new_op_array TSRMLS_CC);
1024+#else
1025+ destroy_op_array(new_op_array);
65be62f2 1026+#endif
3f3163a9
AM
1027+ efree(new_op_array);
1028+#ifdef ZEND_ENGINE_2
1029+ if (!EG(exception))
1030+#endif
1031+ {
1032+ if (EG(return_value_ptr_ptr)) {
1033+ zval_ptr_dtor(EG(return_value_ptr_ptr));
1034+ EG(return_value_ptr_ptr) = NULL;
1035+ }
1036+ }
1037+ } else {
1038+ php_security_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SPG(log_phpscriptname));
1039+ return;
1040+ }
1041+ } else {
1042+ php_security_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SPG(log_phpscriptname));
1043+ return;
1044+ }
1045+ }
1046+
1047+}
1048+
1049+
65be62f2 1050+#endif
3f3163a9
AM
1051+
1052+/*
1053+ * Local variables:
1054+ * tab-width: 4
1055+ * c-basic-offset: 4
1056+ * End:
1057+ * vim600: sw=4 ts=4 fdm=marker
1058+ * vim<600: sw=4 ts=4
1059+ */
1060diff -Naurp php-5.3.6RC1/main/suhosin_patch.h php-5.3.6RC1.oden/main/suhosin_patch.h
1061--- php-5.3.6RC1/main/suhosin_patch.h 1970-01-01 01:00:00.000000000 +0100
1062+++ php-5.3.6RC1.oden/main/suhosin_patch.h 2011-02-20 11:50:19.308837288 +0100
1063@@ -0,0 +1,59 @@
1064+/*
1065+ +----------------------------------------------------------------------+
1066+ | Suhosin Patch for PHP |
1067+ +----------------------------------------------------------------------+
1068+ | Copyright (c) 2004-2010 Stefan Esser |
1069+ +----------------------------------------------------------------------+
1070+ | This source file is subject to version 2.02 of the PHP license, |
1071+ | that is bundled with this package in the file LICENSE, and is |
1072+ | available at through the world-wide-web at |
1073+ | http://www.php.net/license/2_02.txt. |
1074+ | If you did not receive a copy of the PHP license and are unable to |
1075+ | obtain it through the world-wide-web, please send a note to |
1076+ | license@php.net so we can mail you a copy immediately. |
1077+ +----------------------------------------------------------------------+
1078+ | Author: Stefan Esser <stefan.esser@sektioneins.de> |
1079+ +----------------------------------------------------------------------+
1080+ */
1081+
1082+#ifndef SUHOSIN_PATCH_H
1083+#define SUHOSIN_PATCH_H
1084+
65be62f2 1085+#if SUHOSIN_PATCH
3f3163a9
AM
1086+
1087+#include "zend.h"
1088+
1089+#define SUHOSIN_PATCH_VERSION "0.9.10"
1090+
1091+#define SUHOSIN_LOGO_GUID "SUHO8567F54-D428-14d2-A769-00DA302A5F18"
1092+
1093+#define SUHOSIN_CONFIG(idx) (suhosin_get_config(idx))
1094+
1095+#define SUHOSIN_MM_USE_CANARY_PROTECTION 0
1096+#define SUHOSIN_MM_DESTROY_FREE_MEMORY 1
1097+#define SUHOSIN_MM_IGNORE_CANARY_VIOLATION 2
1098+#define SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR 3
1099+#define SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR 4
1100+
1101+#define SUHOSIN_CONFIG_SET 100
1102+
1103+#include <sys/types.h>
1104+#include <sys/stat.h>
1105+#include <sys/mman.h>
1106+
1107+#if defined(DARWIN)
1108+#include <mach/vm_param.h>
65be62f2
ER
1109+#endif
1110+
3f3163a9
AM
1111+#define SUHOSIN_MANGLE_PTR(ptr) (ptr==NULL?NULL:((void *)((zend_intptr_t)(ptr)^SUHOSIN_POINTER_GUARD)))
1112+
65be62f2 1113+#endif
3f3163a9
AM
1114+
1115+#endif /* SUHOSIN_PATCH_H */
1116+
1117+/*
1118+ * Local variables:
1119+ * tab-width: 4
1120+ * c-basic-offset: 4
1121+ * End:
1122+ */
1123diff -Naurp php-5.3.6RC1/main/suhosin_patch.m4 php-5.3.6RC1.oden/main/suhosin_patch.m4
1124--- php-5.3.6RC1/main/suhosin_patch.m4 1970-01-01 01:00:00.000000000 +0100
1125+++ php-5.3.6RC1.oden/main/suhosin_patch.m4 2011-02-20 11:50:19.308837288 +0100
1126@@ -0,0 +1,8 @@
1127+dnl
1128+dnl $Id$
1129+dnl
1130+dnl This file contains Suhosin Patch for PHP specific autoconf functions.
1131+dnl
1132+
1133+AC_DEFINE(SUHOSIN_PATCH, 1, [Suhosin Patch])
1134+
1135diff -Naurp php-5.3.6RC1/sapi/apache/mod_php5.c php-5.3.6RC1.oden/sapi/apache/mod_php5.c
1136--- php-5.3.6RC1/sapi/apache/mod_php5.c 2011-01-01 03:19:59.000000000 +0100
1137+++ php-5.3.6RC1.oden/sapi/apache/mod_php5.c 2011-02-20 11:50:19.309837429 +0100
1138@@ -969,7 +969,11 @@ static void php_init_handler(server_rec
1139 {
1140 TSRMLS_FETCH();
1141 if (PG(expose_php)) {
65be62f2 1142+#if SUHOSIN_PATCH
3f3163a9 1143+ ap_add_version_component("PHP/" PHP_VERSION " with Suhosin-Patch");
65be62f2 1144+#else
3f3163a9 1145 ap_add_version_component("PHP/" PHP_VERSION);
65be62f2 1146+#endif
3f3163a9
AM
1147 }
1148 }
65be62f2 1149 #endif
3f3163a9
AM
1150diff -Naurp php-5.3.6RC1/sapi/apache2filter/sapi_apache2.c php-5.3.6RC1.oden/sapi/apache2filter/sapi_apache2.c
1151--- php-5.3.6RC1/sapi/apache2filter/sapi_apache2.c 2011-01-01 03:19:59.000000000 +0100
1152+++ php-5.3.6RC1.oden/sapi/apache2filter/sapi_apache2.c 2011-02-20 11:50:19.309837429 +0100
1153@@ -583,7 +583,11 @@ static void php_apache_add_version(apr_p
65be62f2 1154 {
3f3163a9
AM
1155 TSRMLS_FETCH();
1156 if (PG(expose_php)) {
65be62f2 1157+#if SUHOSIN_PATCH
3f3163a9 1158+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Suhosin-Patch");
65be62f2 1159+#else
3f3163a9 1160 ap_add_version_component(p, "PHP/" PHP_VERSION);
65be62f2 1161+#endif
65be62f2 1162 }
65be62f2
ER
1163 }
1164
3f3163a9
AM
1165diff -Naurp php-5.3.6RC1/sapi/apache2handler/sapi_apache2.c php-5.3.6RC1.oden/sapi/apache2handler/sapi_apache2.c
1166--- php-5.3.6RC1/sapi/apache2handler/sapi_apache2.c 2011-02-20 11:45:04.141487654 +0100
1167+++ php-5.3.6RC1.oden/sapi/apache2handler/sapi_apache2.c 2011-02-20 11:50:19.310837570 +0100
1168@@ -407,7 +407,11 @@ static void php_apache_add_version(apr_p
65be62f2 1169 {
3f3163a9
AM
1170 TSRMLS_FETCH();
1171 if (PG(expose_php)) {
1172+#if SUHOSIN_PATCH
1173+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Suhosin-Patch");
1174+#else
1175 ap_add_version_component(p, "PHP/" PHP_VERSION);
65be62f2 1176+#endif
3f3163a9 1177 }
65be62f2
ER
1178 }
1179
3f3163a9
AM
1180diff -Naurp php-5.3.6RC1/sapi/apache_hooks/mod_php5.c php-5.3.6RC1.oden/sapi/apache_hooks/mod_php5.c
1181--- php-5.3.6RC1/sapi/apache_hooks/mod_php5.c 2011-01-01 03:19:59.000000000 +0100
1182+++ php-5.3.6RC1.oden/sapi/apache_hooks/mod_php5.c 2011-02-20 11:50:19.311837711 +0100
1183@@ -1256,7 +1256,11 @@ static void php_init_handler(server_rec
1184 {
1185 TSRMLS_FETCH();
1186 if (PG(expose_php)) {
1187+#if SUHOSIN_PATCH
1188+ ap_add_version_component("PHP/" PHP_VERSION " with Suhosin-Patch");
1189+#else
1190 ap_add_version_component("PHP/" PHP_VERSION);
65be62f2 1191+#endif
3f3163a9
AM
1192 }
1193 }
1194 #endif
6d7958ec
ER
1195--- php-5.3.9/sapi/cgi/cgi_main.c~ 2012-01-11 21:40:09.000000000 +0200
1196+++ php-5.3.9/sapi/cgi/cgi_main.c 2012-01-11 21:43:37.468650443 +0200
1197@@ -1948,11 +1948,19 @@
3f3163a9
AM
1198 SG(headers_sent) = 1;
1199 SG(request_info).no_headers = 1;
1200 }
1201+#if SUHOSIN_PATCH
6d7958ec
ER
1202+#if ZEND_DEBUG
1203+ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
1204+#else
1205+ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
65be62f2 1206+#endif
3f3163a9 1207+#else
6d7958ec
ER
1208 #if ZEND_DEBUG
1209 php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
1210 #else
1211 php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
3f3163a9 1212 #endif
6d7958ec 1213+#endif
3f3163a9
AM
1214 php_request_shutdown((void *) 0);
1215 fcgi_shutdown();
6d7958ec
ER
1216 exit_status = 0;
1217--- php-5.3.9/sapi/cli/php_cli.c~ 2012-01-01 15:15:04.000000000 +0200
1218+++ php-5.3.9/sapi/cli/php_cli.c 2012-01-11 21:44:56.122264808 +0200
1219@@ -826,7 +826,11 @@
3f3163a9 1220 }
65be62f2 1221
3f3163a9 1222 request_started = 1;
6d7958ec 1223- php_printf("PHP %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2012 The PHP Group\n%s",
3f3163a9
AM
1224+ php_printf("PHP %s "
1225+#if SUHOSIN_PATCH
6d7958ec 1226+ "with Suhosin-Patch "
3f3163a9 1227+#endif
6d7958ec 1228+ "(%s) (built: %s %s) %s\nCopyright (c) 1997-2012 The PHP Group\n%s",
3f3163a9
AM
1229 PHP_VERSION, sapi_module.name, __DATE__, __TIME__,
1230 #if ZEND_DEBUG && defined(HAVE_GCOV)
1231 "(DEBUG GCOV)",
1232diff -Naurp php-5.3.6RC1/Zend/Makefile.am php-5.3.6RC1.oden/Zend/Makefile.am
1233--- php-5.3.6RC1/Zend/Makefile.am 2009-03-18 11:18:10.000000000 +0100
1234+++ php-5.3.6RC1.oden/Zend/Makefile.am 2011-02-20 11:50:19.316838414 +0100
1235@@ -17,7 +17,7 @@ libZend_la_SOURCES=\
1236 zend_objects_API.c zend_ts_hash.c zend_stream.c \
1237 zend_default_classes.c \
1238 zend_iterators.c zend_interfaces.c zend_exceptions.c \
1239- zend_strtod.c zend_closures.c zend_float.c
1240+ zend_strtod.c zend_closures.c zend_float.c zend_canary.c zend_alloc_canary.c
65be62f2 1241
3f3163a9
AM
1242 libZend_la_LDFLAGS =
1243 libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
1244diff -Naurp php-5.3.6RC1/Zend/zend_alloc.c php-5.3.6RC1.oden/Zend/zend_alloc.c
1245--- php-5.3.6RC1/Zend/zend_alloc.c 2011-02-07 11:25:34.000000000 +0100
1246+++ php-5.3.6RC1.oden/Zend/zend_alloc.c 2011-02-20 11:50:19.318838696 +0100
1247@@ -32,6 +32,10 @@
1248 # include <unistd.h>
65be62f2
ER
1249 #endif
1250
3f3163a9
AM
1251+#if SUHOSIN_PATCH
1252+#include "suhosin_patch.h"
65be62f2 1253+#endif
3f3163a9
AM
1254+
1255 #ifdef ZEND_WIN32
1256 # include <wincrypt.h>
1257 # include <process.h>
1258@@ -59,6 +63,7 @@
1259 # define PTR_FMT "0x%0.8lx"
65be62f2
ER
1260 #endif
1261
1262+#ifndef SUHOSIN_MM_CLONE_FILE
3f3163a9
AM
1263 #if ZEND_DEBUG
1264 void zend_debug_alloc_output(char *format, ...)
65be62f2 1265 {
3f3163a9
AM
1266@@ -76,6 +81,7 @@ void zend_debug_alloc_output(char *forma
1267 #endif
65be62f2
ER
1268 }
1269 #endif
1270+#endif
1271
3f3163a9
AM
1272 #if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
1273 static void zend_mm_panic(const char *message) __attribute__ ((noreturn));
1274@@ -134,6 +140,8 @@ static void zend_mm_panic(const char *me
1275 # endif
1276 #endif
65be62f2 1277
3f3163a9 1278+static zend_intptr_t SUHOSIN_POINTER_GUARD = 0;
65be62f2 1279+
3f3163a9
AM
1280 static zend_mm_storage* zend_mm_mem_dummy_init(void *params)
1281 {
1282 return malloc(sizeof(zend_mm_storage));
1283@@ -332,13 +340,28 @@ static const zend_mm_mem_handlers mem_ha
1284 #define MEM_BLOCK_GUARD 0x2A8FCC84
1285 #define MEM_BLOCK_LEAK 0x6C5E8F2D
65be62f2 1286
3f3163a9
AM
1287+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1288+# define CANARY_SIZE sizeof(size_t)
65be62f2 1289+#else
3f3163a9 1290+# define CANARY_SIZE 0
65be62f2
ER
1291+#endif
1292+
3f3163a9
AM
1293 /* mm block type */
1294 typedef struct _zend_mm_block_info {
1295 #if ZEND_MM_COOKIES
1296 size_t _cookie;
1297 #endif
1298- size_t _size;
1299- size_t _prev;
1300+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1301+ size_t canary_1;
65be62f2 1302+#endif
3f3163a9
AM
1303+ size_t _size;
1304+ size_t _prev;
1305+#if SUHOSIN_PATCH
1306+ size_t size;
1307+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1308+ size_t canary_2;
65be62f2 1309+#endif
3f3163a9
AM
1310+#endif
1311 } zend_mm_block_info;
1312
1313 #if ZEND_DEBUG
1314@@ -412,7 +435,7 @@ typedef struct _zend_mm_free_block {
1315 # define ZEND_MM_CACHE_STAT 0
1316 #endif
1317
1318-struct _zend_mm_heap {
1319+typedef struct _zend_mm_heap {
1320 int use_zend_alloc;
1321 void *(*_malloc)(size_t);
1322 void (*_free)(void*);
1323@@ -447,6 +470,9 @@ struct _zend_mm_heap {
1324 int miss;
1325 } cache_stat[ZEND_MM_NUM_BUCKETS+1];
1326 #endif
1327+#if SUHOSIN_PATCH
1328+ size_t canary_1,canary_2,canary_3;
1329+#endif
1330 };
1331
1332 #define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \
1333@@ -520,18 +546,31 @@ static unsigned int _zend_mm_cookie = 0;
1334 /* optimized access */
1335 #define ZEND_MM_FREE_BLOCK_SIZE(b) (b)->info._size
1336
1337+#ifndef ZEND_MM_ALIGNMENT
1338+# define ZEND_MM_ALIGNMENT 8
1339+# define ZEND_MM_ALIGNMENT_LOG2 3
1340+#elif ZEND_MM_ALIGNMENT < 4
1341+# undef ZEND_MM_ALIGNMENT
1342+# undef ZEND_MM_ALIGNMENT_LOG2
1343+# define ZEND_MM_ALIGNMENT 4
1344+# define ZEND_MM_ALIGNMENT_LOG2 2
65be62f2
ER
1345+#endif
1346+
3f3163a9 1347+#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1)
65be62f2 1348+
3f3163a9
AM
1349 /* Aligned header size */
1350+#define ZEND_MM_ALIGNED_SIZE(size) ((size + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK)
1351 #define ZEND_MM_ALIGNED_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block))
1352 #define ZEND_MM_ALIGNED_FREE_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_small_free_block))
1353-#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE)
1354+#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE + CANARY_SIZE)
1355 #define ZEND_MM_ALIGNED_MIN_HEADER_SIZE (ZEND_MM_MIN_ALLOC_BLOCK_SIZE>ZEND_MM_ALIGNED_FREE_HEADER_SIZE?ZEND_MM_MIN_ALLOC_BLOCK_SIZE:ZEND_MM_ALIGNED_FREE_HEADER_SIZE)
1356 #define ZEND_MM_ALIGNED_SEGMENT_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_segment))
1357
1358-#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE)):0)
1359+#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)):0)
1360
1361 #define ZEND_MM_MAX_SMALL_SIZE ((ZEND_MM_NUM_BUCKETS<<ZEND_MM_ALIGNMENT_LOG2)+ZEND_MM_ALIGNED_MIN_HEADER_SIZE)
1362
1363-#define ZEND_MM_TRUE_SIZE(size) ((size<ZEND_MM_MIN_SIZE)?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE):(ZEND_MM_ALIGNED_SIZE(size+ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE)))
1364+#define ZEND_MM_TRUE_SIZE(size) ((size<ZEND_MM_MIN_SIZE)?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE):(ZEND_MM_ALIGNED_SIZE(size+ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)))
1365
1366 #define ZEND_MM_BUCKET_INDEX(true_size) ((true_size>>ZEND_MM_ALIGNMENT_LOG2)-(ZEND_MM_ALIGNED_MIN_HEADER_SIZE>>ZEND_MM_ALIGNMENT_LOG2))
1367
1368@@ -593,6 +632,44 @@ static unsigned int _zend_mm_cookie = 0;
1369
1370 #endif
1371
1372+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
65be62f2 1373+
3f3163a9
AM
1374+# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION) do { \
1375+ char *p = SUHOSIN_MM_END_CANARY_PTR(block); size_t check; \
1376+ if (((block)->info.canary_1 != heap->canary_1) || ((block)->info.canary_2 != heap->canary_2)) { \
1377+ canary_mismatch: \
1378+ zend_suhosin_log(S_MEMORY, "canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \
1379+ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { (block)->info.canary_1 = heap->canary_1; (block)->info.canary_2 = heap->canary_2; }\
1380+ } \
1381+ memcpy(&check, p, CANARY_SIZE); \
1382+ if (check != heap->canary_3) { \
1383+ zend_suhosin_log(S_MEMORY, "end canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \
1384+ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { memcpy(p, heap->canary_3, CANARY_SIZE); } \
1385+ } \
1386+ } while (0)
65be62f2 1387+
3f3163a9
AM
1388+# define SUHOSIN_MM_SET_CANARIES(block) do { \
1389+ (block)->info.canary_1 = heap->canary_1; \
1390+ (block)->info.canary_2 = heap->canary_2; \
1391+ } while (0)
65be62f2 1392+
3f3163a9
AM
1393+# define SUHOSIN_MM_END_CANARY_PTR(block) \
1394+ (char *)(((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block*)(block))->info.size + END_MAGIC_SIZE)
65be62f2 1395+
3f3163a9
AM
1396+# define SUHOSIN_MM_SET_END_CANARY(block) do { \
1397+ char *p = SUHOSIN_MM_END_CANARY_PTR(block); \
1398+ memcpy(p, &heap->canary_3, CANARY_SIZE); \
1399+ } while (0)
65be62f2 1400+
3f3163a9 1401+#else
65be62f2 1402+
3f3163a9
AM
1403+# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION)
1404+# define SUHOSIN_MM_SET_CANARIES(block)
1405+# define SUHOSIN_MM_END_CANARY_PTR(block)
1406+# define SUHOSIN_MM_SET_END_CANARY(block)
65be62f2
ER
1407+
1408+#endif
1409+
3f3163a9
AM
1410
1411 #if ZEND_MM_HEAP_PROTECTION
1412
1413@@ -715,7 +792,7 @@ static inline unsigned int zend_mm_low_b
1414 #endif
1415 }
1416
1417-static inline void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
1418+static void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
1419 {
1420 zend_mm_free_block *prev, *next;
1421
1422@@ -725,14 +802,14 @@ static inline void zend_mm_add_to_rest_l
1423 mm_block->parent = NULL;
1424 }
1425
1426- prev = heap->rest_buckets[0];
1427- next = prev->next_free_block;
1428- mm_block->prev_free_block = prev;
1429- mm_block->next_free_block = next;
1430- prev->next_free_block = next->prev_free_block = mm_block;
1431+ prev = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]);
1432+ next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
1433+ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
1434+ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
1435+ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
1436 }
1437
1438-static inline void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
1439+static void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
1440 {
1441 size_t size;
1442 size_t index;
1443@@ -749,7 +826,7 @@ static inline void zend_mm_add_to_free_l
1444 if (!*p) {
1445 *p = mm_block;
1446 mm_block->parent = p;
1447- mm_block->prev_free_block = mm_block->next_free_block = mm_block;
1448+ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block);
1449 heap->large_free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
1450 } else {
1451 size_t m;
1452@@ -762,15 +839,15 @@ static inline void zend_mm_add_to_free_l
1453 if (!*p) {
1454 *p = mm_block;
1455 mm_block->parent = p;
1456- mm_block->prev_free_block = mm_block->next_free_block = mm_block;
1457+ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block);
1458 break;
1459 }
1460 } else {
1461- zend_mm_free_block *next = prev->next_free_block;
1462+ zend_mm_free_block *next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
1463
1464- prev->next_free_block = next->prev_free_block = mm_block;
1465- mm_block->next_free_block = next;
1466- mm_block->prev_free_block = prev;
1467+ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
1468+ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
1469+ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
1470 mm_block->parent = NULL;
1471 break;
1472 }
1473@@ -782,27 +859,33 @@ static inline void zend_mm_add_to_free_l
1474 index = ZEND_MM_BUCKET_INDEX(size);
1475
1476 prev = ZEND_MM_SMALL_FREE_BUCKET(heap, index);
1477- if (prev->prev_free_block == prev) {
1478+ if (SUHOSIN_MANGLE_PTR(prev->prev_free_block) == prev) {
1479 heap->free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
1480 }
1481- next = prev->next_free_block;
1482+ next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
1483
1484- mm_block->prev_free_block = prev;
1485- mm_block->next_free_block = next;
1486- prev->next_free_block = next->prev_free_block = mm_block;
1487+ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
1488+ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
1489+ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
1490 }
1491 }
1492
1493-static inline void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
1494+static void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
1495 {
1496- zend_mm_free_block *prev = mm_block->prev_free_block;
1497- zend_mm_free_block *next = mm_block->next_free_block;
1498+ zend_mm_free_block *prev = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block);
1499+ zend_mm_free_block *next = SUHOSIN_MANGLE_PTR(mm_block->next_free_block);
1500
1501 ZEND_MM_CHECK_MAGIC(mm_block, MEM_BLOCK_FREED);
1502
1503 if (EXPECTED(prev == mm_block)) {
1504 zend_mm_free_block **rp, **cp;
1505
1506+#if SUHOSIN_PATCH
1507+ if (next != mm_block) {
1508+ zend_suhosin_log(S_MEMORY, "zend_mm_heap corrupted at %p", mm_block);
1509+ _exit(1);
1510+ }
1511+#endif
1512 #if ZEND_MM_SAFE_UNLINKING
1513 if (UNEXPECTED(next != mm_block)) {
1514 zend_mm_panic("zend_mm_heap corrupted");
1515@@ -841,14 +924,21 @@ subst_block:
1516 }
1517 } else {
1518
1519+#if SUHOSIN_PATCH
1520+ if (SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block || SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block) {
1521+ zend_suhosin_log(S_MEMORY, "zend_mm_head corrupted at %p", mm_block);
1522+ _exit(1);
1523+ }
1524+#endif
65be62f2 1525+
3f3163a9
AM
1526 #if ZEND_MM_SAFE_UNLINKING
1527- if (UNEXPECTED(prev->next_free_block != mm_block) || UNEXPECTED(next->prev_free_block != mm_block)) {
1528+ if (UNEXPECTED(SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block) || UNEXPECTED(SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block)) {
1529 zend_mm_panic("zend_mm_heap corrupted");
1530 }
1531 #endif
1532
1533- prev->next_free_block = next;
1534- next->prev_free_block = prev;
1535+ prev->next_free_block = SUHOSIN_MANGLE_PTR(next);
1536+ next->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
1537
1538 if (EXPECTED(ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block)))) {
1539 if (EXPECTED(prev == next)) {
1540@@ -864,7 +954,7 @@ subst_block:
1541 }
1542 }
1543
1544-static inline void zend_mm_init(zend_mm_heap *heap)
1545+static void zend_mm_init(zend_mm_heap *heap)
1546 {
1547 zend_mm_free_block* p;
1548 int i;
1549@@ -882,12 +972,19 @@ static inline void zend_mm_init(zend_mm_
1550 #endif
1551 p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
1552 for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
1553- p->next_free_block = p;
1554- p->prev_free_block = p;
1555+ p->next_free_block = SUHOSIN_MANGLE_PTR(p);
1556+ p->prev_free_block = SUHOSIN_MANGLE_PTR(p);
1557 p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2);
1558 heap->large_free_buckets[i] = NULL;
1559 }
1560- heap->rest_buckets[0] = heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(heap);
1561+ heap->rest_buckets[0] = heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(heap));
1562+#if SUHOSIN_PATCH
1563+ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
1564+ zend_canary(&heap->canary_1, sizeof(heap->canary_1));
1565+ zend_canary(&heap->canary_2, sizeof(heap->canary_2));
1566+ zend_canary(&heap->canary_3, sizeof(heap->canary_3));
65be62f2 1567+ }
3f3163a9
AM
1568+#endif
1569 }
1570
1571 static void zend_mm_del_segment(zend_mm_heap *heap, zend_mm_segment *segment)
1572@@ -908,12 +1005,13 @@ static void zend_mm_free_cache(zend_mm_h
1573 int i;
1574
1575 for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
1576+ /* NULL means NULL even MANGLED */
1577 if (heap->cache[i]) {
1578- zend_mm_free_block *mm_block = heap->cache[i];
1579+ zend_mm_free_block *mm_block = SUHOSIN_MANGLE_PTR(heap->cache[i]);
1580
1581 while (mm_block) {
1582 size_t size = ZEND_MM_BLOCK_SIZE(mm_block);
1583- zend_mm_free_block *q = mm_block->prev_free_block;
1584+ zend_mm_free_block *q = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block);
1585 zend_mm_block *next_block = ZEND_MM_NEXT_BLOCK(mm_block);
1586
1587 heap->cached -= size;
1588@@ -1009,14 +1107,20 @@ static void zend_mm_random(unsigned char
1589 /* }}} */
1590 #endif
1591
65be62f2 1592+
3f3163a9
AM
1593 /* Notes:
1594 * - This function may alter the block_sizes values to match platform alignment
1595 * - This function does *not* perform sanity checks on the arguments
1596 */
1597-ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
1598+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1599+zend_mm_heap *__zend_mm_startup_canary_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
1600+#else
1601+static zend_mm_heap *__zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
65be62f2 1602+#endif
3f3163a9
AM
1603 {
1604 zend_mm_storage *storage;
1605 zend_mm_heap *heap;
1606+ zend_mm_free_block *tmp;
1607
1608 #if 0
1609 int i;
1610@@ -1050,6 +1154,12 @@ ZEND_API zend_mm_heap *zend_mm_startup_e
1611 }
1612 #endif
1613
1614+ /* get the pointer guardian and ensure low 3 bits are 1 */
1615+ if (SUHOSIN_POINTER_GUARD == 0) {
1616+ zend_canary(&SUHOSIN_POINTER_GUARD, sizeof(SUHOSIN_POINTER_GUARD));
1617+ SUHOSIN_POINTER_GUARD |= 7;
1618+ }
65be62f2 1619+
3f3163a9
AM
1620 if (zend_mm_low_bit(block_size) != zend_mm_high_bit(block_size)) {
1621 fprintf(stderr, "'block_size' must be a power of two\n");
1622 /* See http://support.microsoft.com/kb/190351 */
1623@@ -1097,12 +1207,12 @@ ZEND_API zend_mm_heap *zend_mm_startup_e
1624 heap->reserve = NULL;
1625 heap->reserve_size = reserve_size;
1626 if (reserve_size > 0) {
1627- heap->reserve = _zend_mm_alloc_int(heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1628+ heap->reserve = _zend_mm_alloc(heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1629 }
1630 if (internal) {
1631 int i;
1632 zend_mm_free_block *p, *q, *orig;
1633- zend_mm_heap *mm_heap = _zend_mm_alloc_int(heap, sizeof(zend_mm_heap) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1634+ zend_mm_heap *mm_heap = _zend_mm_alloc(heap, sizeof(zend_mm_heap) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1635
1636 *mm_heap = *heap;
1637
1638@@ -1110,22 +1220,22 @@ ZEND_API zend_mm_heap *zend_mm_startup_e
1639 orig = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
1640 for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
1641 q = p;
1642- while (q->prev_free_block != orig) {
1643- q = q->prev_free_block;
1644+ while (SUHOSIN_MANGLE_PTR(q->prev_free_block) != orig) {
1645+ q = SUHOSIN_MANGLE_PTR(q->prev_free_block);
1646 }
1647- q->prev_free_block = p;
1648+ q->prev_free_block = SUHOSIN_MANGLE_PTR(p);
1649 q = p;
1650- while (q->next_free_block != orig) {
1651- q = q->next_free_block;
1652+ while (SUHOSIN_MANGLE_PTR(q->next_free_block) != orig) {
1653+ q = SUHOSIN_MANGLE_PTR(q->next_free_block);
1654 }
1655- q->next_free_block = p;
1656+ q->next_free_block = SUHOSIN_MANGLE_PTR(p);
1657 p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2);
1658 orig = (zend_mm_free_block*)((char*)orig + sizeof(zend_mm_free_block*) * 2);
1659 if (mm_heap->large_free_buckets[i]) {
1660 mm_heap->large_free_buckets[i]->parent = &mm_heap->large_free_buckets[i];
1661 }
1662 }
1663- mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(mm_heap);
1664+ mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(mm_heap));
1665
1666 free(heap);
1667 heap = mm_heap;
1668@@ -1133,7 +1243,11 @@ ZEND_API zend_mm_heap *zend_mm_startup_e
1669 return heap;
1670 }
1671
1672-ZEND_API zend_mm_heap *zend_mm_startup(void)
1673+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1674+zend_mm_heap *__zend_mm_startup_canary(void)
1675+#else
1676+static zend_mm_heap *__zend_mm_startup(void)
1677+#endif
1678 {
1679 int i;
1680 size_t seg_size;
1681@@ -1203,6 +1317,27 @@ ZEND_API zend_mm_heap *zend_mm_startup(v
1682 return heap;
1683 }
1684
1685+#ifndef SUHOSIN_MM_CLONE_FILE
1686+zend_mm_heap_canary *__zend_mm_startup_canary_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params);
1687+zend_mm_heap_canary *__zend_mm_startup_canary(void);
65be62f2 1688+
3f3163a9 1689+ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
65be62f2 1690+{
3f3163a9
AM
1691+ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
1692+ return (zend_mm_heap *)__zend_mm_startup_canary_ex(handlers, block_size, reserve_size, internal, params);
1693+ }
1694+ return __zend_mm_startup_ex(handlers, block_size, reserve_size, internal, params);
65be62f2 1695+}
3f3163a9 1696+ZEND_API zend_mm_heap *zend_mm_startup(void)
65be62f2 1697+{
3f3163a9
AM
1698+ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
1699+ return (zend_mm_heap *)__zend_mm_startup_canary();
1700+ }
1701+ return __zend_mm_startup();
65be62f2
ER
1702+}
1703+
3f3163a9
AM
1704+#endif
1705+
1706 #if ZEND_DEBUG
1707 static long zend_mm_find_leaks(zend_mm_segment *segment, zend_mm_block *b)
1708 {
1709@@ -1571,7 +1706,11 @@ static int zend_mm_check_heap(zend_mm_he
1710 }
1711 #endif
1712
1713-ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
1714+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1715+void __zend_mm_shutdown_canary(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
1716+#else
1717+static void __zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
1718+#endif
1719 {
1720 zend_mm_storage *storage;
1721 zend_mm_segment *segment;
1722@@ -1581,7 +1720,7 @@ ZEND_API void zend_mm_shutdown(zend_mm_h
1723 if (heap->reserve) {
1724 #if ZEND_DEBUG
1725 if (!silent) {
1726- _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1727+ _zend_mm_free(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1728 }
1729 #endif
1730 heap->reserve = NULL;
1731@@ -1664,12 +1803,23 @@ ZEND_API void zend_mm_shutdown(zend_mm_h
1732 heap->size = 0;
1733 heap->peak = 0;
1734 if (heap->reserve_size) {
1735- heap->reserve = _zend_mm_alloc_int(heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1736+ heap->reserve = _zend_mm_alloc(heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1737 }
1738 heap->overflow = 0;
1739 }
1740 }
1741
1742+#ifndef SUHOSIN_MM_CLONE_FILE
1743+ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
65be62f2 1744+{
3f3163a9
AM
1745+ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
1746+ __zend_mm_shutdown_canary(heap, full_shutdown, silent TSRMLS_CC);
1747+ return;
1748+ }
1749+ __zend_mm_shutdown(heap, full_shutdown, silent TSRMLS_CC);
65be62f2 1750+}
65be62f2
ER
1751+#endif
1752+
3f3163a9
AM
1753 static void zend_mm_safe_error(zend_mm_heap *heap,
1754 const char *format,
1755 size_t limit,
1756@@ -1680,7 +1830,11 @@ static void zend_mm_safe_error(zend_mm_h
1757 size_t size)
1758 {
1759 if (heap->reserve) {
1760+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
1761+ _zend_mm_free_canary_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
1762+#else
1763 _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
65be62f2 1764+#endif
3f3163a9
AM
1765 heap->reserve = NULL;
1766 }
1767 if (heap->overflow == 0) {
1768@@ -1755,7 +1909,7 @@ static zend_mm_free_block *zend_mm_searc
1769 p = heap->large_free_buckets[index];
1770 for (m = true_size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
1771 if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
1772- return p->next_free_block;
1773+ return SUHOSIN_MANGLE_PTR(p->next_free_block);
1774 } else if (ZEND_MM_FREE_BLOCK_SIZE(p) >= true_size &&
1775 ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
1776 best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
1777@@ -1779,7 +1933,7 @@ static zend_mm_free_block *zend_mm_searc
1778
1779 for (p = rst; p; p = p->child[p->child[0] != NULL]) {
1780 if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
1781- return p->next_free_block;
1782+ return SUHOSIN_MANGLE_PTR(p->next_free_block);
1783 } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
1784 ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
1785 best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
1786@@ -1788,7 +1942,7 @@ static zend_mm_free_block *zend_mm_searc
1787 }
1788
1789 if (best_fit) {
1790- return best_fit->next_free_block;
1791+ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block);
1792 }
1793 bitmap = bitmap >> 1;
1794 if (!bitmap) {
1795@@ -1804,9 +1958,12 @@ static zend_mm_free_block *zend_mm_searc
1796 best_fit = p;
1797 }
1798 }
1799- return best_fit->next_free_block;
1800+ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block);
1801 }
1802
1803+#if SUHOSIN_PATCH
1804+void *_zend_mm_alloc_canary_int(zend_mm_heap_canary *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
65be62f2 1805+#endif
3f3163a9
AM
1806 static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
1807 {
1808 zend_mm_free_block *best_fit;
1809@@ -1816,7 +1973,7 @@ static void *_zend_mm_alloc_int(zend_mm_
1810 size_t segment_size;
1811 zend_mm_segment *segment;
1812 int keep_rest = 0;
1813-
1814+
1815 if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) {
1816 size_t index = ZEND_MM_BUCKET_INDEX(true_size);
1817 size_t bitmap;
1818@@ -1831,9 +1988,14 @@ static void *_zend_mm_alloc_int(zend_mm_
1819 heap->cache_stat[index].count--;
1820 heap->cache_stat[index].hit++;
1821 #endif
1822- best_fit = heap->cache[index];
1823+ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]);
1824 heap->cache[index] = best_fit->prev_free_block;
1825 heap->cached -= true_size;
1826+#if SUHOSIN_PATCH
1827+ SUHOSIN_MM_SET_CANARIES(best_fit);
1828+ ((zend_mm_block*)best_fit)->info.size = size;
1829+ SUHOSIN_MM_SET_END_CANARY(best_fit);
1830+#endif
1831 ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
1832 ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
1833 return ZEND_MM_DATA_OF(best_fit);
1834@@ -1847,7 +2009,7 @@ static void *_zend_mm_alloc_int(zend_mm_
1835 if (bitmap) {
1836 /* Found some "small" free block that can be used */
1837 index += zend_mm_low_bit(bitmap);
1838- best_fit = heap->free_buckets[index*2];
1839+ best_fit = SUHOSIN_MANGLE_PTR(heap->free_buckets[index*2]);
1840 #if ZEND_MM_CACHE_STAT
1841 heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit++;
1842 #endif
1843@@ -1862,7 +2024,7 @@ static void *_zend_mm_alloc_int(zend_mm_
1844 best_fit = zend_mm_search_large_block(heap, true_size);
1845
1846 if (!best_fit && heap->real_size >= heap->limit - heap->block_size) {
1847- zend_mm_free_block *p = heap->rest_buckets[0];
1848+ zend_mm_free_block *p = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]);
1849 size_t best_size = -1;
1850
1851 while (p != ZEND_MM_REST_BUCKET(heap)) {
1852@@ -1874,7 +2036,7 @@ static void *_zend_mm_alloc_int(zend_mm_
1853 best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
1854 best_fit = p;
1855 }
1856- p = p->prev_free_block;
1857+ p = SUHOSIN_MANGLE_PTR(p->prev_free_block);
1858 }
1859 }
1860
1861@@ -1973,13 +2135,19 @@ zend_mm_finished_searching_for_block:
1862
1863 ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1);
1864
1865+#if SUHOSIN_PATCH
1866+ SUHOSIN_MM_SET_CANARIES(best_fit);
1867+ ((zend_mm_block*)best_fit)->info.size = size;
1868+ SUHOSIN_MM_SET_END_CANARY(best_fit);
65be62f2 1869+#endif
3f3163a9
AM
1870+
1871 heap->size += true_size;
1872 if (heap->peak < heap->size) {
1873 heap->peak = heap->size;
1874 }
1875
1876 HANDLE_UNBLOCK_INTERRUPTIONS();
1877-
1878+
1879 return ZEND_MM_DATA_OF(best_fit);
1880 }
1881
1882@@ -1996,19 +2164,26 @@ static void _zend_mm_free_int(zend_mm_he
1883
1884 mm_block = ZEND_MM_HEADER_OF(p);
1885 size = ZEND_MM_BLOCK_SIZE(mm_block);
1886+#if SUHOSIN_PATCH
1887+ SUHOSIN_MM_CHECK_CANARIES(mm_block, "efree()");
1888+#endif
1889 ZEND_MM_CHECK_PROTECTION(mm_block);
1890
1891 #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
1892 memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->debug.size);
1893 #endif
1894-
1895+#if SUHOSIN_PATCH
1896+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_DESTROY_FREE_MEMORY))) {
1897+ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->info.size);
1898+ }
65be62f2 1899+#endif
3f3163a9
AM
1900 #if ZEND_MM_CACHE
1901 if (EXPECTED(ZEND_MM_SMALL_SIZE(size)) && EXPECTED(heap->cached < ZEND_MM_CACHE_SIZE)) {
1902 size_t index = ZEND_MM_BUCKET_INDEX(size);
1903 zend_mm_free_block **cache = &heap->cache[index];
1904
1905 ((zend_mm_free_block*)mm_block)->prev_free_block = *cache;
1906- *cache = (zend_mm_free_block*)mm_block;
1907+ *cache = (zend_mm_free_block*)SUHOSIN_MANGLE_PTR(mm_block);
1908 heap->cached += size;
1909 ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
1910 #if ZEND_MM_CACHE_STAT
1911@@ -2044,6 +2219,9 @@ static void _zend_mm_free_int(zend_mm_he
1912 HANDLE_UNBLOCK_INTERRUPTIONS();
1913 }
1914
1915+#if SUHOSIN_PATCH
1916+void *_zend_mm_realloc_canary_int(zend_mm_heap_canary *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
65be62f2 1917+#endif
3f3163a9
AM
1918 static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
1919 {
1920 zend_mm_block *mm_block = ZEND_MM_HEADER_OF(p);
1921@@ -2053,11 +2231,18 @@ static void *_zend_mm_realloc_int(zend_m
1922 void *ptr;
1923
1924 if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) {
1925+#ifdef SUHOSIN_MM_WITH_CANARY_PROTECTION
1926+ return _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
1927+#else
1928 return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
65be62f2 1929+#endif
3f3163a9
AM
1930 }
1931 mm_block = ZEND_MM_HEADER_OF(p);
1932 true_size = ZEND_MM_TRUE_SIZE(size);
1933 orig_size = ZEND_MM_BLOCK_SIZE(mm_block);
65be62f2 1934+#if SUHOSIN_PATCH
3f3163a9
AM
1935+ SUHOSIN_MM_CHECK_CANARIES(mm_block, "erealloc()");
1936+#endif
1937 ZEND_MM_CHECK_PROTECTION(mm_block);
1938
1939 if (UNEXPECTED(true_size < size)) {
1940@@ -2089,6 +2274,11 @@ static void *_zend_mm_realloc_int(zend_m
1941 HANDLE_UNBLOCK_INTERRUPTIONS();
1942 }
1943 ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
1944+#if SUHOSIN_PATCH
1945+ SUHOSIN_MM_SET_CANARIES(mm_block);
1946+ ((zend_mm_block*)mm_block)->info.size = size;
1947+ SUHOSIN_MM_SET_END_CANARY(mm_block);
65be62f2 1948+#endif
3f3163a9
AM
1949 return p;
1950 }
1951
1952@@ -2104,17 +2294,22 @@ static void *_zend_mm_realloc_int(zend_m
1953 heap->cache_stat[index].count--;
1954 heap->cache_stat[index].hit++;
1955 #endif
1956- best_fit = heap->cache[index];
1957+ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]);
1958 heap->cache[index] = best_fit->prev_free_block;
1959 ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
1960- ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
1961-
1962+ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
1963+#if SUHOSIN_PATCH
1964+ SUHOSIN_MM_SET_CANARIES(best_fit);
1965+ ((zend_mm_block*)best_fit)->info.size = size;
1966+ SUHOSIN_MM_SET_END_CANARY(best_fit);
65be62f2 1967+#endif
65be62f2 1968+
3f3163a9
AM
1969 ptr = ZEND_MM_DATA_OF(best_fit);
1970
1971 #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
1972 memcpy(ptr, p, mm_block->debug.size);
1973 #else
1974- memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
1975+ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE);
1976 #endif
1977
1978 heap->cached -= true_size - orig_size;
1979@@ -2123,14 +2318,13 @@ static void *_zend_mm_realloc_int(zend_m
1980 cache = &heap->cache[index];
1981
1982 ((zend_mm_free_block*)mm_block)->prev_free_block = *cache;
1983- *cache = (zend_mm_free_block*)mm_block;
1984+ *cache = (zend_mm_free_block*)SUHOSIN_MANGLE_PTR(mm_block);
1985 ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
1986 #if ZEND_MM_CACHE_STAT
1987 if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
1988 heap->cache_stat[index].max_count = heap->cache_stat[index].count;
1989 }
1990 #endif
1991-
1992 return ptr;
1993 }
1994 }
1995@@ -2173,6 +2367,11 @@ static void *_zend_mm_realloc_int(zend_m
1996 heap->peak = heap->size;
1997 }
1998 HANDLE_UNBLOCK_INTERRUPTIONS();
1999+#if SUHOSIN_PATCH
2000+ SUHOSIN_MM_SET_CANARIES(mm_block);
2001+ ((zend_mm_block*)mm_block)->info.size = size;
2002+ SUHOSIN_MM_SET_END_CANARY(mm_block);
65be62f2 2003+#endif
3f3163a9
AM
2004 return p;
2005 } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
2006 ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) {
2007@@ -2275,38 +2474,90 @@ out_of_memory:
2008 }
2009
2010 HANDLE_UNBLOCK_INTERRUPTIONS();
2011+#if SUHOSIN_PATCH
2012+ SUHOSIN_MM_SET_CANARIES(mm_block);
2013+ ((zend_mm_block*)mm_block)->info.size = size;
2014+ SUHOSIN_MM_SET_END_CANARY(mm_block);
65be62f2 2015+#endif
3f3163a9
AM
2016 return ZEND_MM_DATA_OF(mm_block);
2017 }
2018
2019+#ifdef SUHOSIN_MM_WITH_CANARY_PROTECTION
2020+ ptr = _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2021+#else
2022 ptr = _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
65be62f2 2023+#endif
3f3163a9
AM
2024 #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
2025 memcpy(ptr, p, mm_block->debug.size);
2026 #else
2027- memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
2028+ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE);
2029 #endif
2030+#ifdef SUHOSIN_MM_WITH_CANARY_PROTECTION
2031+ _zend_mm_free_canary_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2032+#else
2033 _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
65be62f2 2034+#endif
3f3163a9
AM
2035 return ptr;
2036 }
2037
2038+#ifndef SUHOSIN_MM_CLONE_FILE
2039 ZEND_API void *_zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2040 {
2041- return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2042+#if SUHOSIN_PATCH
2043+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
65be62f2 2044+#endif
3f3163a9
AM
2045+ return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2046+#if SUHOSIN_PATCH
2047+ return _zend_mm_alloc_canary_int((zend_mm_heap_canary *)heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
65be62f2 2048+#endif
3f3163a9
AM
2049 }
2050
2051 ZEND_API void _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2052 {
2053- _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2054+#if SUHOSIN_PATCH
2055+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
65be62f2 2056+#endif
3f3163a9 2057+ { _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return; }
65be62f2 2058+#if SUHOSIN_PATCH
3f3163a9 2059+ _zend_mm_free_canary_int((zend_mm_heap_canary *)heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
65be62f2 2060+#endif
3f3163a9
AM
2061 }
2062
2063 ZEND_API void *_zend_mm_realloc(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2064 {
2065- return _zend_mm_realloc_int(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2066+#if SUHOSIN_PATCH
2067+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
2068+#endif
2069+ return _zend_mm_realloc_int(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2070+#if SUHOSIN_PATCH
2071+ return _zend_mm_realloc_canary_int((zend_mm_heap_canary *)heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2072+#endif
2073 }
2074
2075 ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2076 {
2077 zend_mm_block *mm_block;
2078
2079+ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) != 0) {
2080+ return _zend_mm_block_size_canary((zend_mm_heap_canary *)heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
65be62f2 2081+ }
65be62f2 2082+
3f3163a9
AM
2083+ if (!ZEND_MM_VALID_PTR(p)) {
2084+ return 0;
2085+ }
2086+ mm_block = ZEND_MM_HEADER_OF(p);
2087+ ZEND_MM_CHECK_PROTECTION(mm_block);
2088+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
2089+ return mm_block->debug.size;
65be62f2 2090+#else
3f3163a9 2091+ return ZEND_MM_BLOCK_SIZE(mm_block);
65be62f2 2092+#endif
3f3163a9 2093+}
65be62f2 2094+#else
3f3163a9
AM
2095+ZEND_API size_t _zend_mm_block_size_canary(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2096+{
2097+ zend_mm_block *mm_block;
65be62f2 2098+
3f3163a9
AM
2099 if (!ZEND_MM_VALID_PTR(p)) {
2100 return 0;
2101 }
2102@@ -2319,6 +2570,8 @@ ZEND_API size_t _zend_mm_block_size(zend
2103 #endif
2104 }
2105
2106+#endif
65be62f2 2107+
3f3163a9
AM
2108 /**********************/
2109 /* Allocation Manager */
2110 /**********************/
2111@@ -2335,6 +2588,7 @@ static int alloc_globals_id;
2112 static zend_alloc_globals alloc_globals;
2113 #endif
2114
2115+#ifndef SUHOSIN_MM_CLONE_FILE
2116 ZEND_API int is_zend_mm(TSRMLS_D)
2117 {
2118 return AG(mm_heap)->use_zend_alloc;
2119@@ -2347,7 +2601,13 @@ ZEND_API void *_emalloc(size_t size ZEND
2120 if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
2121 return AG(mm_heap)->_malloc(size);
2122 }
2123+#if SUHOSIN_PATCH
2124+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
2125+#endif
2126 return _zend_mm_alloc_int(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2127+#if SUHOSIN_PATCH
2128+ return _zend_mm_alloc_canary_int((zend_mm_heap_canary *)AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2129+#endif
2130 }
2131
2132 ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2133@@ -2358,7 +2618,13 @@ ZEND_API void _efree(void *ptr ZEND_FILE
2134 AG(mm_heap)->_free(ptr);
2135 return;
2136 }
2137- _zend_mm_free_int(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2138+#if SUHOSIN_PATCH
2139+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
2140+#endif
2141+ { _zend_mm_free_int(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return; }
2142+#if SUHOSIN_PATCH
2143+ _zend_mm_free_canary_int((zend_mm_heap_canary *)AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2144+#endif
2145 }
2146
2147 ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2148@@ -2368,7 +2634,13 @@ ZEND_API void *_erealloc(void *ptr, size
2149 if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
2150 return AG(mm_heap)->_realloc(ptr, size);
2151 }
2152+#if SUHOSIN_PATCH
2153+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
2154+#endif
2155 return _zend_mm_realloc_int(AG(mm_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2156+#if SUHOSIN_PATCH
2157+ return _zend_mm_realloc_canary_int((zend_mm_heap_canary *)AG(mm_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2158+#endif
2159 }
2160
2161 ZEND_API size_t _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2162@@ -2376,8 +2648,15 @@ ZEND_API size_t _zend_mem_block_size(voi
2163 if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
2164 return 0;
2165 }
2166- return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2167+#if SUHOSIN_PATCH
2168+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0))
2169+#endif
2170+ return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2171+#if SUHOSIN_PATCH
2172+ return _zend_mm_block_size_canary((zend_mm_heap_canary *)AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
2173+#endif
2174 }
2175+#endif
2176
2177 #if defined(__GNUC__) && defined(i386)
2178
2179@@ -2448,7 +2727,7 @@ static inline size_t safe_address(size_t
2180 }
2181 #endif
2182
2183-
2184+#ifndef SUHOSIN_MM_CLONE_FILE
2185 ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
2186 {
2187 return emalloc_rel(safe_address(nmemb, size, offset));
2188@@ -2561,6 +2840,7 @@ ZEND_API void shutdown_memory_manager(in
2189 {
2190 zend_mm_shutdown(AG(mm_heap), full_shutdown, silent TSRMLS_CC);
2191 }
2192+#endif
2193
2194 static void alloc_globals_ctor(zend_alloc_globals *alloc_globals TSRMLS_DC)
2195 {
2196@@ -2585,6 +2865,7 @@ static void alloc_globals_dtor(zend_allo
2197 }
2198 #endif
2199
2200+#ifndef SUHOSIN_MM_CLONE_FILE
2201 ZEND_API void start_memory_manager(TSRMLS_D)
2202 {
2203 #ifdef ZTS
2204@@ -2649,6 +2930,7 @@ ZEND_API void _full_mem_check(int silent
2205 zend_debug_alloc_output("------------------------------------------------\n");
2206 }
2207 #endif
2208+#endif
2209
2210 /*
2211 * Local variables:
2212diff -Naurp php-5.3.6RC1/Zend/zend_alloc_canary.c php-5.3.6RC1.oden/Zend/zend_alloc_canary.c
2213--- php-5.3.6RC1/Zend/zend_alloc_canary.c 1970-01-01 01:00:00.000000000 +0100
2214+++ php-5.3.6RC1.oden/Zend/zend_alloc_canary.c 2011-02-20 11:50:19.320838976 +0100
2215@@ -0,0 +1,2498 @@
2216+/*
2217+ +----------------------------------------------------------------------+
2218+ | Suhosin-Patch for PHP |
2219+ +----------------------------------------------------------------------+
2220+ | Copyright (c) 2004-2010 Stefan Esser |
2221+ +----------------------------------------------------------------------+
2222+ | This source file is subject to version 2.02 of the PHP license, |
2223+ | that is bundled with this package in the file LICENSE, and is |
2224+ | available at through the world-wide-web at |
2225+ | http://www.php.net/license/2_02.txt. |
2226+ | If you did not receive a copy of the PHP license and are unable to |
2227+ | obtain it through the world-wide-web, please send a note to |
2228+ | license@php.net so we can mail you a copy immediately. |
2229+ +----------------------------------------------------------------------+
2230+ | Author: Stefan Esser <stefan.esser@sektioneins.de> |
2231+ +----------------------------------------------------------------------+
2232+ */
2233+/* $Id$ */
65be62f2 2234+
3f3163a9
AM
2235+#include "zend.h"
2236+#include "zend_alloc.h"
2237+#include "zend_globals.h"
2238+#include "zend_operators.h"
65be62f2 2239+
3f3163a9
AM
2240+#ifdef HAVE_SIGNAL_H
2241+# include <signal.h>
2242+#endif
2243+#ifdef HAVE_UNISTD_H
2244+# include <unistd.h>
65be62f2
ER
2245+#endif
2246+
3f3163a9
AM
2247+#if SUHOSIN_PATCH
2248+#include "suhosin_patch.h"
2249+#endif
65be62f2 2250+
3f3163a9
AM
2251+#ifdef ZEND_WIN32
2252+# include <wincrypt.h>
2253+# include <process.h>
2254+#endif
65be62f2 2255+
3f3163a9
AM
2256+#ifndef ZEND_MM_HEAP_PROTECTION
2257+# define ZEND_MM_HEAP_PROTECTION ZEND_DEBUG
2258+#endif
65be62f2 2259+
3f3163a9
AM
2260+#ifndef ZEND_MM_SAFE_UNLINKING
2261+# define ZEND_MM_SAFE_UNLINKING 1
2262+#endif
65be62f2 2263+
3f3163a9
AM
2264+#ifndef ZEND_MM_COOKIES
2265+# define ZEND_MM_COOKIES ZEND_DEBUG
2266+#endif
65be62f2 2267+
3f3163a9
AM
2268+#ifdef _WIN64
2269+# define PTR_FMT "0x%0.16I64x"
2270+/*
2271+#elif sizeof(long) == 8
2272+# define PTR_FMT "0x%0.16lx"
2273+*/
65be62f2 2274+#else
3f3163a9
AM
2275+# define PTR_FMT "0x%0.8lx"
2276+#endif
65be62f2 2277+
3f3163a9 2278+#define SUHOSIN_MM_WITH_CANARY_PROTECTION 1
65be62f2 2279+
3f3163a9
AM
2280+#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
2281+static void zend_mm_panic(const char *message) __attribute__ ((noreturn));
65be62f2
ER
2282+#endif
2283+
3f3163a9
AM
2284+static void zend_mm_panic(const char *message)
2285+{
2286+ fprintf(stderr, "%s\n", message);
2287+/* See http://support.microsoft.com/kb/190351 */
2288+#ifdef PHP_WIN32
2289+ fflush(stderr);
2290+#endif
2291+#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
2292+ kill(getpid(), SIGSEGV);
2293+#endif
2294+ exit(1);
2295+}
65be62f2 2296+
3f3163a9
AM
2297+/*******************/
2298+/* Storage Manager */
2299+/*******************/
65be62f2 2300+
3f3163a9
AM
2301+#ifdef ZEND_WIN32
2302+# define HAVE_MEM_WIN32 /* use VirtualAlloc() to allocate memory */
2303+#endif
2304+#define HAVE_MEM_MALLOC /* use malloc() to allocate segments */
65be62f2 2305+
3f3163a9
AM
2306+#include <sys/types.h>
2307+#include <sys/stat.h>
2308+#if HAVE_LIMITS_H
2309+#include <limits.h>
2310+#endif
2311+#include <fcntl.h>
2312+#include <errno.h>
65be62f2 2313+
3f3163a9
AM
2314+#if defined(HAVE_MEM_MMAP_ANON) || defined(HAVE_MEM_MMAP_ZERO)
2315+# ifdef HAVE_MREMAP
2316+# ifndef _GNU_SOURCE
2317+# define _GNU_SOURCE
2318+# endif
2319+# ifndef __USE_GNU
2320+# define __USE_GNU
2321+# endif
2322+# endif
2323+# include <sys/mman.h>
2324+# ifndef MAP_ANON
2325+# ifdef MAP_ANONYMOUS
2326+# define MAP_ANON MAP_ANONYMOUS
2327+# endif
2328+# endif
2329+# ifndef MREMAP_MAYMOVE
2330+# define MREMAP_MAYMOVE 0
2331+# endif
2332+# ifndef MAP_FAILED
2333+# define MAP_FAILED ((void*)-1)
2334+# endif
2335+#endif
65be62f2 2336+
3f3163a9 2337+static zend_intptr_t SUHOSIN_POINTER_GUARD = 0;
65be62f2 2338+
3f3163a9
AM
2339+static zend_mm_storage* zend_mm_mem_dummy_init(void *params)
2340+{
2341+ return malloc(sizeof(zend_mm_storage));
2342+}
65be62f2 2343+
3f3163a9
AM
2344+static void zend_mm_mem_dummy_dtor(zend_mm_storage *storage)
2345+{
2346+ free(storage);
2347+}
65be62f2 2348+
3f3163a9
AM
2349+static void zend_mm_mem_dummy_compact(zend_mm_storage *storage)
2350+{
2351+}
65be62f2 2352+
3f3163a9 2353+#if defined(HAVE_MEM_MMAP_ANON) || defined(HAVE_MEM_MMAP_ZERO)
65be62f2 2354+
3f3163a9
AM
2355+static zend_mm_segment* zend_mm_mem_mmap_realloc(zend_mm_storage *storage, zend_mm_segment* segment, size_t size)
2356+{
2357+ zend_mm_segment *ret;
2358+#ifdef HAVE_MREMAP
2359+#if defined(__NetBSD__)
2360+ /* NetBSD 5 supports mremap but takes an extra newp argument */
2361+ ret = (zend_mm_segment*)mremap(segment, segment->size, segment, size, MREMAP_MAYMOVE);
2362+#else
2363+ ret = (zend_mm_segment*)mremap(segment, segment->size, size, MREMAP_MAYMOVE);
65be62f2 2364+#endif
3f3163a9
AM
2365+ if (ret == MAP_FAILED) {
2366+#endif
2367+ ret = storage->handlers->_alloc(storage, size);
2368+ if (ret) {
2369+ memcpy(ret, segment, size > segment->size ? segment->size : size);
2370+ storage->handlers->_free(storage, segment);
2371+ }
2372+#ifdef HAVE_MREMAP
65be62f2 2373+ }
65be62f2 2374+#endif
3f3163a9
AM
2375+ return ret;
2376+}
65be62f2 2377+
3f3163a9
AM
2378+static void zend_mm_mem_mmap_free(zend_mm_storage *storage, zend_mm_segment* segment)
2379+{
2380+ munmap((void*)segment, segment->size);
2381+}
65be62f2 2382+
3f3163a9 2383+#endif
65be62f2 2384+
3f3163a9 2385+#ifdef HAVE_MEM_MMAP_ANON
65be62f2 2386+
3f3163a9 2387+static zend_mm_segment* zend_mm_mem_mmap_anon_alloc(zend_mm_storage *storage, size_t size)
65be62f2 2388+{
3f3163a9
AM
2389+ zend_mm_segment *ret = (zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
2390+ if (ret == MAP_FAILED) {
2391+ ret = NULL;
65be62f2 2392+ }
3f3163a9 2393+ return ret;
65be62f2
ER
2394+}
2395+
3f3163a9 2396+# define ZEND_MM_MEM_MMAP_ANON_DSC {"mmap_anon", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_anon_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free}
65be62f2 2397+
3f3163a9 2398+#endif
65be62f2 2399+
3f3163a9 2400+#ifdef HAVE_MEM_MMAP_ZERO
65be62f2 2401+
3f3163a9
AM
2402+static int zend_mm_dev_zero_fd = -1;
2403+
2404+static zend_mm_storage* zend_mm_mem_mmap_zero_init(void *params)
2405+{
2406+ if (zend_mm_dev_zero_fd != -1) {
2407+ zend_mm_dev_zero_fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
2408+ }
2409+ if (zend_mm_dev_zero_fd >= 0) {
2410+ return malloc(sizeof(zend_mm_storage));
2411+ } else {
2412+ return NULL;
65be62f2 2413+ }
3f3163a9 2414+}
65be62f2 2415+
3f3163a9
AM
2416+static void zend_mm_mem_mmap_zero_dtor(zend_mm_storage *storage)
2417+{
2418+ close(zend_mm_dev_zero_fd);
2419+ free(storage);
65be62f2
ER
2420+}
2421+
3f3163a9 2422+static zend_mm_segment* zend_mm_mem_mmap_zero_alloc(zend_mm_storage *storage, size_t size)
65be62f2 2423+{
3f3163a9
AM
2424+ zend_mm_segment *ret = (zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zend_mm_dev_zero_fd, 0);
2425+ if (ret == MAP_FAILED) {
2426+ ret = NULL;
2427+ }
2428+ return ret;
2429+}
65be62f2 2430+
3f3163a9 2431+# define ZEND_MM_MEM_MMAP_ZERO_DSC {"mmap_zero", zend_mm_mem_mmap_zero_init, zend_mm_mem_mmap_zero_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_zero_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free}
65be62f2 2432+
3f3163a9
AM
2433+#endif
2434+
2435+#ifdef HAVE_MEM_WIN32
2436+
2437+static zend_mm_storage* zend_mm_mem_win32_init(void *params)
2438+{
2439+ HANDLE heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
2440+ zend_mm_storage* storage;
65be62f2 2441+
3f3163a9
AM
2442+ if (heap == NULL) {
2443+ return NULL;
2444+ }
2445+ storage = (zend_mm_storage*)malloc(sizeof(zend_mm_storage));
2446+ storage->data = (void*) heap;
2447+ return storage;
65be62f2
ER
2448+}
2449+
3f3163a9 2450+static void zend_mm_mem_win32_dtor(zend_mm_storage *storage)
65be62f2 2451+{
3f3163a9
AM
2452+ HeapDestroy((HANDLE)storage->data);
2453+ free(storage);
2454+}
65be62f2 2455+
3f3163a9
AM
2456+static void zend_mm_mem_win32_compact(zend_mm_storage *storage)
2457+{
2458+ HeapDestroy((HANDLE)storage->data);
2459+ storage->data = (void*)HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
2460+}
65be62f2 2461+
3f3163a9
AM
2462+static zend_mm_segment* zend_mm_mem_win32_alloc(zend_mm_storage *storage, size_t size)
2463+{
2464+ return (zend_mm_segment*) HeapAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, size);
2465+}
65be62f2 2466+
3f3163a9
AM
2467+static void zend_mm_mem_win32_free(zend_mm_storage *storage, zend_mm_segment* segment)
2468+{
2469+ HeapFree((HANDLE)storage->data, HEAP_NO_SERIALIZE, segment);
2470+}
65be62f2 2471+
3f3163a9
AM
2472+static zend_mm_segment* zend_mm_mem_win32_realloc(zend_mm_storage *storage, zend_mm_segment* segment, size_t size)
2473+{
2474+ return (zend_mm_segment*) HeapReAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, segment, size);
2475+}
65be62f2 2476+
3f3163a9 2477+# define ZEND_MM_MEM_WIN32_DSC {"win32", zend_mm_mem_win32_init, zend_mm_mem_win32_dtor, zend_mm_mem_win32_compact, zend_mm_mem_win32_alloc, zend_mm_mem_win32_realloc, zend_mm_mem_win32_free}
65be62f2 2478+
3f3163a9 2479+#endif
65be62f2 2480+
3f3163a9 2481+#ifdef HAVE_MEM_MALLOC
65be62f2 2482+
3f3163a9
AM
2483+static zend_mm_segment* zend_mm_mem_malloc_alloc(zend_mm_storage *storage, size_t size)
2484+{
2485+ return (zend_mm_segment*)malloc(size);
2486+}
65be62f2 2487+
3f3163a9
AM
2488+static zend_mm_segment* zend_mm_mem_malloc_realloc(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size)
2489+{
2490+ return (zend_mm_segment*)realloc(ptr, size);
65be62f2
ER
2491+}
2492+
3f3163a9 2493+static void zend_mm_mem_malloc_free(zend_mm_storage *storage, zend_mm_segment *ptr)
65be62f2 2494+{
3f3163a9
AM
2495+ free(ptr);
2496+}
65be62f2 2497+
3f3163a9 2498+# define ZEND_MM_MEM_MALLOC_DSC {"malloc", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_malloc_alloc, zend_mm_mem_malloc_realloc, zend_mm_mem_malloc_free}
65be62f2 2499+
3f3163a9 2500+#endif
65be62f2 2501+
3f3163a9
AM
2502+static const zend_mm_mem_handlers mem_handlers[] = {
2503+#ifdef HAVE_MEM_WIN32
2504+ ZEND_MM_MEM_WIN32_DSC,
65be62f2 2505+#endif
3f3163a9
AM
2506+#ifdef HAVE_MEM_MALLOC
2507+ ZEND_MM_MEM_MALLOC_DSC,
2508+#endif
2509+#ifdef HAVE_MEM_MMAP_ANON
2510+ ZEND_MM_MEM_MMAP_ANON_DSC,
2511+#endif
2512+#ifdef HAVE_MEM_MMAP_ZERO
2513+ ZEND_MM_MEM_MMAP_ZERO_DSC,
65be62f2 2514+#endif
3f3163a9
AM
2515+ {NULL, NULL, NULL, NULL, NULL, NULL}
2516+};
65be62f2 2517+
3f3163a9
AM
2518+# define ZEND_MM_STORAGE_DTOR() heap->storage->handlers->dtor(heap->storage)
2519+# define ZEND_MM_STORAGE_ALLOC(size) heap->storage->handlers->_alloc(heap->storage, size)
2520+# define ZEND_MM_STORAGE_REALLOC(ptr, size) heap->storage->handlers->_realloc(heap->storage, ptr, size)
2521+# define ZEND_MM_STORAGE_FREE(ptr) heap->storage->handlers->_free(heap->storage, ptr)
65be62f2 2522+
3f3163a9
AM
2523+/****************/
2524+/* Heap Manager */
2525+/****************/
65be62f2 2526+
3f3163a9
AM
2527+#define MEM_BLOCK_VALID 0x7312F8DC
2528+#define MEM_BLOCK_FREED 0x99954317
2529+#define MEM_BLOCK_CACHED 0xFB8277DC
2530+#define MEM_BLOCK_GUARD 0x2A8FCC84
2531+#define MEM_BLOCK_LEAK 0x6C5E8F2D
2532+
2533+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
2534+# define CANARY_SIZE sizeof(size_t)
2535+#else
2536+# define CANARY_SIZE 0
2537+#endif
65be62f2 2538+
3f3163a9
AM
2539+/* mm block type */
2540+typedef struct _zend_mm_block_info_canary {
2541+#if ZEND_MM_COOKIES
2542+ size_t _cookie;
2543+#endif
2544+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
2545+ size_t canary_1;
2546+#endif
2547+ size_t _size;
2548+ size_t _prev;
65be62f2 2549+#if SUHOSIN_PATCH
3f3163a9
AM
2550+ size_t size;
2551+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
2552+ size_t canary_2;
2553+#endif
2554+#endif
2555+} zend_mm_block_info_canary;
65be62f2 2556+
3f3163a9
AM
2557+#if ZEND_DEBUG
2558+
2559+typedef struct _zend_mm_debug_info_canary {
2560+ char *filename;
2561+ uint lineno;
2562+ char *orig_filename;
2563+ uint orig_lineno;
2564+ size_t size;
2565+#if ZEND_MM_HEAP_PROTECTION
2566+ unsigned int start_magic;
2567+#endif
2568+} zend_mm_debug_info_canary;
2569+
2570+#elif ZEND_MM_HEAP_PROTECTION
2571+
2572+typedef struct _zend_mm_debug_info_canary {
2573+ size_t size;
2574+ unsigned int start_magic;
2575+} zend_mm_debug_info_canary;
2576+
2577+#endif
2578+
2579+typedef struct _zend_mm_block_canary {
2580+ zend_mm_block_info_canary info;
2581+#if ZEND_DEBUG
2582+ unsigned int magic;
2583+# ifdef ZTS
2584+ THREAD_T thread_id;
2585+# endif
2586+ zend_mm_debug_info_canary debug;
2587+#elif ZEND_MM_HEAP_PROTECTION
2588+ zend_mm_debug_info_canary debug;
2589+#endif
2590+} zend_mm_block_canary;
2591+
2592+typedef struct _zend_mm_small_free_block_canary {
2593+ zend_mm_block_info_canary info;
2594+#if ZEND_DEBUG
2595+ unsigned int magic;
2596+# ifdef ZTS
2597+ THREAD_T thread_id;
2598+# endif
2599+#endif
2600+ struct _zend_mm_free_block_canary *prev_free_block;
2601+ struct _zend_mm_free_block_canary *next_free_block;
2602+} zend_mm_small_free_block_canary;
2603+
2604+typedef struct _zend_mm_free_block_canary {
2605+ zend_mm_block_info_canary info;
2606+#if ZEND_DEBUG
2607+ unsigned int magic;
2608+# ifdef ZTS
2609+ THREAD_T thread_id;
2610+# endif
65be62f2 2611+#endif
3f3163a9
AM
2612+ struct _zend_mm_free_block_canary *prev_free_block;
2613+ struct _zend_mm_free_block_canary *next_free_block;
65be62f2 2614+
3f3163a9
AM
2615+ struct _zend_mm_free_block_canary **parent;
2616+ struct _zend_mm_free_block_canary *child[2];
2617+} zend_mm_free_block_canary;
65be62f2 2618+
3f3163a9 2619+#define ZEND_MM_NUM_BUCKETS (sizeof(size_t) << 3)
65be62f2 2620+
3f3163a9
AM
2621+#define ZEND_MM_CACHE 1
2622+#define ZEND_MM_CACHE_SIZE (ZEND_MM_NUM_BUCKETS * 4 * 1024)
65be62f2 2623+
3f3163a9
AM
2624+#ifndef ZEND_MM_CACHE_STAT
2625+# define ZEND_MM_CACHE_STAT 0
2626+#endif
65be62f2 2627+
3f3163a9
AM
2628+typedef struct _zend_mm_heap_canary {
2629+ int use_zend_alloc;
2630+ void *(*_malloc)(size_t);
2631+ void (*_free)(void*);
2632+ void *(*_realloc)(void*, size_t);
2633+ size_t free_bitmap;
2634+ size_t large_free_bitmap;
2635+ size_t block_size;
2636+ size_t compact_size;
2637+ zend_mm_segment *segments_list;
2638+ zend_mm_storage *storage;
2639+ size_t real_size;
2640+ size_t real_peak;
2641+ size_t limit;
2642+ size_t size;
2643+ size_t peak;
2644+ size_t reserve_size;
2645+ void *reserve;
2646+ int overflow;
2647+ int internal;
65be62f2 2648+#if ZEND_MM_CACHE
3f3163a9
AM
2649+ unsigned int cached;
2650+ zend_mm_free_block_canary *cache[ZEND_MM_NUM_BUCKETS];
65be62f2 2651+#endif
3f3163a9
AM
2652+ zend_mm_free_block_canary *free_buckets[ZEND_MM_NUM_BUCKETS*2];
2653+ zend_mm_free_block_canary *large_free_buckets[ZEND_MM_NUM_BUCKETS];
2654+ zend_mm_free_block_canary *rest_buckets[2];
65be62f2 2655+#if ZEND_MM_CACHE_STAT
3f3163a9
AM
2656+ struct {
2657+ int count;
2658+ int max_count;
2659+ int hit;
2660+ int miss;
2661+ } cache_stat[ZEND_MM_NUM_BUCKETS+1];
65be62f2 2662+#endif
65be62f2 2663+#if SUHOSIN_PATCH
3f3163a9 2664+ size_t canary_1,canary_2,canary_3;
65be62f2 2665+#endif
3f3163a9 2666+};
65be62f2 2667+
3f3163a9
AM
2668+#define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \
2669+ (zend_mm_free_block_canary*) ((char*)&heap->free_buckets[index * 2] + \
2670+ sizeof(zend_mm_free_block_canary*) * 2 - \
2671+ sizeof(zend_mm_small_free_block_canary))
65be62f2 2672+
3f3163a9
AM
2673+#define ZEND_MM_REST_BUCKET(heap) \
2674+ (zend_mm_free_block_canary*)((char*)&heap->rest_buckets[0] + \
2675+ sizeof(zend_mm_free_block_canary*) * 2 - \
2676+ sizeof(zend_mm_small_free_block_canary))
65be62f2 2677+
3f3163a9 2678+#if ZEND_MM_COOKIES
65be62f2 2679+
3f3163a9 2680+static unsigned int _zend_mm_cookie = 0;
65be62f2 2681+
3f3163a9
AM
2682+# define ZEND_MM_COOKIE(block) \
2683+ (((size_t)(block)) ^ _zend_mm_cookie)
2684+# define ZEND_MM_SET_COOKIE(block) \
2685+ (block)->info._cookie = ZEND_MM_COOKIE(block)
2686+# define ZEND_MM_CHECK_COOKIE(block) \
2687+ if (UNEXPECTED((block)->info._cookie != ZEND_MM_COOKIE(block))) { \
2688+ zend_mm_panic("zend_mm_heap corrupted"); \
65be62f2 2689+ }
3f3163a9
AM
2690+#else
2691+# define ZEND_MM_SET_COOKIE(block)
2692+# define ZEND_MM_CHECK_COOKIE(block)
65be62f2
ER
2693+#endif
2694+
3f3163a9
AM
2695+/* Default memory segment size */
2696+#define ZEND_MM_SEG_SIZE (256 * 1024)
65be62f2 2697+
3f3163a9
AM
2698+/* Reserved space for error reporting in case of memory overflow */
2699+#define ZEND_MM_RESERVE_SIZE (8*1024)
65be62f2 2700+
3f3163a9
AM
2701+#ifdef _WIN64
2702+# define ZEND_MM_LONG_CONST(x) (x##i64)
2703+#else
2704+# define ZEND_MM_LONG_CONST(x) (x##L)
65be62f2
ER
2705+#endif
2706+
3f3163a9 2707+#define ZEND_MM_TYPE_MASK ZEND_MM_LONG_CONST(0x3)
65be62f2 2708+
3f3163a9
AM
2709+#define ZEND_MM_FREE_BLOCK ZEND_MM_LONG_CONST(0x0)
2710+#define ZEND_MM_USED_BLOCK ZEND_MM_LONG_CONST(0x1)
2711+#define ZEND_MM_GUARD_BLOCK ZEND_MM_LONG_CONST(0x3)
65be62f2 2712+
3f3163a9
AM
2713+#define ZEND_MM_BLOCK(b, type, size) do { \
2714+ size_t _size = (size); \
2715+ (b)->info._size = (type) | _size; \
2716+ ZEND_MM_BLOCK_AT(b, _size)->info._prev = (type) | _size; \
2717+ ZEND_MM_SET_COOKIE(b); \
2718+ } while (0);
2719+#define ZEND_MM_LAST_BLOCK(b) do { \
2720+ (b)->info._size = ZEND_MM_GUARD_BLOCK | ZEND_MM_ALIGNED_HEADER_SIZE; \
2721+ ZEND_MM_SET_MAGIC(b, MEM_BLOCK_GUARD); \
2722+ } while (0);
2723+#define ZEND_MM_BLOCK_SIZE(b) ((b)->info._size & ~ZEND_MM_TYPE_MASK)
2724+#define ZEND_MM_IS_FREE_BLOCK(b) (!((b)->info._size & ZEND_MM_USED_BLOCK))
2725+#define ZEND_MM_IS_USED_BLOCK(b) ((b)->info._size & ZEND_MM_USED_BLOCK)
2726+#define ZEND_MM_IS_GUARD_BLOCK(b) (((b)->info._size & ZEND_MM_TYPE_MASK) == ZEND_MM_GUARD_BLOCK)
65be62f2 2727+
3f3163a9
AM
2728+#define ZEND_MM_NEXT_BLOCK(b) ZEND_MM_BLOCK_AT(b, ZEND_MM_BLOCK_SIZE(b))
2729+#define ZEND_MM_PREV_BLOCK(b) ZEND_MM_BLOCK_AT(b, -(int)((b)->info._prev & ~ZEND_MM_TYPE_MASK))
65be62f2 2730+
3f3163a9 2731+#define ZEND_MM_PREV_BLOCK_IS_FREE(b) (!((b)->info._prev & ZEND_MM_USED_BLOCK))
65be62f2 2732+
3f3163a9
AM
2733+#define ZEND_MM_MARK_FIRST_BLOCK(b) ((b)->info._prev = ZEND_MM_GUARD_BLOCK)
2734+#define ZEND_MM_IS_FIRST_BLOCK(b) ((b)->info._prev == ZEND_MM_GUARD_BLOCK)
65be62f2 2735+
3f3163a9
AM
2736+/* optimized access */
2737+#define ZEND_MM_FREE_BLOCK_SIZE(b) (b)->info._size
65be62f2 2738+
3f3163a9
AM
2739+#ifndef ZEND_MM_ALIGNMENT
2740+# define ZEND_MM_ALIGNMENT 8
2741+# define ZEND_MM_ALIGNMENT_LOG2 3
2742+#elif ZEND_MM_ALIGNMENT < 4
2743+# undef ZEND_MM_ALIGNMENT
2744+# undef ZEND_MM_ALIGNMENT_LOG2
2745+# define ZEND_MM_ALIGNMENT 4
2746+# define ZEND_MM_ALIGNMENT_LOG2 2
2747+#endif
65be62f2 2748+
3f3163a9 2749+#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1)
65be62f2 2750+
3f3163a9
AM
2751+/* Aligned header size */
2752+#define ZEND_MM_ALIGNED_SIZE(size) ((size + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK)
2753+#define ZEND_MM_ALIGNED_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block_canary))
2754+#define ZEND_MM_ALIGNED_FREE_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_small_free_block_canary))
2755+#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE + CANARY_SIZE)
2756+#define ZEND_MM_ALIGNED_MIN_HEADER_SIZE (ZEND_MM_MIN_ALLOC_BLOCK_SIZE>ZEND_MM_ALIGNED_FREE_HEADER_SIZE?ZEND_MM_MIN_ALLOC_BLOCK_SIZE:ZEND_MM_ALIGNED_FREE_HEADER_SIZE)
2757+#define ZEND_MM_ALIGNED_SEGMENT_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_segment))
65be62f2 2758+
3f3163a9 2759+#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)):0)
65be62f2 2760+
3f3163a9 2761+#define ZEND_MM_MAX_SMALL_SIZE ((ZEND_MM_NUM_BUCKETS<<ZEND_MM_ALIGNMENT_LOG2)+ZEND_MM_ALIGNED_MIN_HEADER_SIZE)
65be62f2 2762+
3f3163a9 2763+#define ZEND_MM_TRUE_SIZE(size) ((size<ZEND_MM_MIN_SIZE)?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE):(ZEND_MM_ALIGNED_SIZE(size+ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)))
65be62f2 2764+
3f3163a9 2765+#define ZEND_MM_BUCKET_INDEX(true_size) ((true_size>>ZEND_MM_ALIGNMENT_LOG2)-(ZEND_MM_ALIGNED_MIN_HEADER_SIZE>>ZEND_MM_ALIGNMENT_LOG2))
65be62f2 2766+
3f3163a9 2767+#define ZEND_MM_SMALL_SIZE(true_size) (true_size < ZEND_MM_MAX_SMALL_SIZE)
65be62f2 2768+
3f3163a9
AM
2769+/* Memory calculations */
2770+#define ZEND_MM_BLOCK_AT(blk, offset) ((zend_mm_block_canary *) (((char *) (blk))+(offset)))
2771+#define ZEND_MM_DATA_OF(p) ((void *) (((char *) (p))+ZEND_MM_ALIGNED_HEADER_SIZE))
2772+#define ZEND_MM_HEADER_OF(blk) ZEND_MM_BLOCK_AT(blk, -(int)ZEND_MM_ALIGNED_HEADER_SIZE)
65be62f2 2773+
3f3163a9 2774+/* Debug output */
65be62f2 2775+#if ZEND_DEBUG
65be62f2 2776+
3f3163a9
AM
2777+# ifdef ZTS
2778+# define ZEND_MM_SET_THREAD_ID(block) \
2779+ ((zend_mm_block_canary*)(block))->thread_id = tsrm_thread_id()
2780+# define ZEND_MM_BAD_THREAD_ID(block) ((block)->thread_id != tsrm_thread_id())
2781+# else
2782+# define ZEND_MM_SET_THREAD_ID(block)
2783+# define ZEND_MM_BAD_THREAD_ID(block) 0
2784+# endif
65be62f2 2785+
3f3163a9
AM
2786+# define ZEND_MM_VALID_PTR(block) \
2787+ zend_mm_check_ptr(heap, block, 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)
65be62f2 2788+
3f3163a9
AM
2789+# define ZEND_MM_SET_MAGIC(block, val) do { \
2790+ (block)->magic = (val); \
2791+ } while (0)
65be62f2 2792+
3f3163a9
AM
2793+# define ZEND_MM_CHECK_MAGIC(block, val) do { \
2794+ if ((block)->magic != (val)) { \
2795+ zend_mm_panic("zend_mm_heap corrupted"); \
2796+ } \
2797+ } while (0)
65be62f2 2798+
3f3163a9
AM
2799+# define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) do { \
2800+ ((zend_mm_block_canary*)(block))->debug.filename = __zend_filename; \
2801+ ((zend_mm_block_canary*)(block))->debug.lineno = __zend_lineno; \
2802+ ((zend_mm_block_canary*)(block))->debug.orig_filename = __zend_orig_filename; \
2803+ ((zend_mm_block_canary*)(block))->debug.orig_lineno = __zend_orig_lineno; \
2804+ ZEND_MM_SET_BLOCK_SIZE(block, __size); \
2805+ if (set_valid) { \
2806+ ZEND_MM_SET_MAGIC(block, MEM_BLOCK_VALID); \
2807+ } \
2808+ if (set_thread) { \
2809+ ZEND_MM_SET_THREAD_ID(block); \
2810+ } \
2811+ } while (0)
65be62f2 2812+
3f3163a9 2813+#else
65be62f2 2814+
3f3163a9 2815+# define ZEND_MM_VALID_PTR(ptr) EXPECTED(ptr != NULL)
65be62f2 2816+
3f3163a9 2817+# define ZEND_MM_SET_MAGIC(block, val)
65be62f2 2818+
3f3163a9
AM
2819+# define ZEND_MM_CHECK_MAGIC(block, val)
2820+
2821+# define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) ZEND_MM_SET_BLOCK_SIZE(block, __size)
65be62f2 2822+
65be62f2
ER
2823+#endif
2824+
3f3163a9 2825+#if SUHOSIN_MM_WITH_CANARY_PROTECTION
65be62f2 2826+
3f3163a9
AM
2827+# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION) do { \
2828+ char *p = SUHOSIN_MM_END_CANARY_PTR(block); size_t check; \
2829+ if (((block)->info.canary_1 != heap->canary_1) || ((block)->info.canary_2 != heap->canary_2)) { \
2830+ canary_mismatch: \
2831+ zend_suhosin_log(S_MEMORY, "canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \
2832+ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { (block)->info.canary_1 = heap->canary_1; (block)->info.canary_2 = heap->canary_2; }\
2833+ } \
2834+ memcpy(&check, p, CANARY_SIZE); \
2835+ if (check != heap->canary_3) { \
2836+ zend_suhosin_log(S_MEMORY, "end canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \
2837+ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { memcpy(p, heap->canary_3, CANARY_SIZE); } \
2838+ } \
2839+ } while (0)
65be62f2 2840+
3f3163a9
AM
2841+# define SUHOSIN_MM_SET_CANARIES(block) do { \
2842+ (block)->info.canary_1 = heap->canary_1; \
2843+ (block)->info.canary_2 = heap->canary_2; \
2844+ } while (0)
2845+
2846+# define SUHOSIN_MM_END_CANARY_PTR(block) \
2847+ (char *)(((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block_canary*)(block))->info.size + END_MAGIC_SIZE)
2848+
2849+# define SUHOSIN_MM_SET_END_CANARY(block) do { \
2850+ char *p = SUHOSIN_MM_END_CANARY_PTR(block); \
2851+ memcpy(p, &heap->canary_3, CANARY_SIZE); \
2852+ } while (0)
2853+
2854+#else
2855+
2856+# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION)
2857+# define SUHOSIN_MM_SET_CANARIES(block)
2858+# define SUHOSIN_MM_END_CANARY_PTR(block)
2859+# define SUHOSIN_MM_SET_END_CANARY(block)
2860+
2861+#endif
65be62f2 2862+
65be62f2
ER
2863+
2864+#if ZEND_MM_HEAP_PROTECTION
65be62f2 2865+
3f3163a9
AM
2866+# define ZEND_MM_CHECK_PROTECTION(block) \
2867+ do { \
2868+ if ((block)->debug.start_magic != _mem_block_start_magic || \
2869+ memcmp(ZEND_MM_END_MAGIC_PTR(block), &_mem_block_end_magic, END_MAGIC_SIZE) != 0) { \
2870+ zend_mm_panic("zend_mm_heap corrupted"); \
2871+ } \
2872+ } while (0)
65be62f2 2873+
3f3163a9
AM
2874+# define ZEND_MM_END_MAGIC_PTR(block) \
2875+ (((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block_canary*)(block))->debug.size)
65be62f2 2876+
3f3163a9
AM
2877+# define END_MAGIC_SIZE sizeof(unsigned int)
2878+
2879+# define ZEND_MM_SET_BLOCK_SIZE(block, __size) do { \
2880+ char *p; \
2881+ ((zend_mm_block_canary*)(block))->debug.size = (__size); \
2882+ p = ZEND_MM_END_MAGIC_PTR(block); \
2883+ ((zend_mm_block_canary*)(block))->debug.start_magic = _mem_block_start_magic; \
2884+ memcpy(p, &_mem_block_end_magic, END_MAGIC_SIZE); \
2885+ } while (0)
2886+
2887+static unsigned int _mem_block_start_magic = 0;
2888+static unsigned int _mem_block_end_magic = 0;
2889+
2890+#else
65be62f2 2891+
3f3163a9
AM
2892+# if ZEND_DEBUG
2893+# define ZEND_MM_SET_BLOCK_SIZE(block, _size) \
2894+ ((zend_mm_block_canary*)(block))->debug.size = (_size)
2895+# else
2896+# define ZEND_MM_SET_BLOCK_SIZE(block, _size)
2897+# endif
65be62f2 2898+
3f3163a9 2899+# define ZEND_MM_CHECK_PROTECTION(block)
65be62f2 2900+
3f3163a9 2901+# define END_MAGIC_SIZE 0
65be62f2 2902+
3f3163a9 2903+#endif
65be62f2 2904+
3f3163a9
AM
2905+#if ZEND_MM_SAFE_UNLINKING
2906+# define ZEND_MM_CHECK_BLOCK_LINKAGE(block) \
2907+ if (UNEXPECTED((block)->info._size != ZEND_MM_BLOCK_AT(block, ZEND_MM_FREE_BLOCK_SIZE(block))->info._prev) || \
2908+ UNEXPECTED(!UNEXPECTED(ZEND_MM_IS_FIRST_BLOCK(block)) && \
2909+ UNEXPECTED(ZEND_MM_PREV_BLOCK(block)->info._size != (block)->info._prev))) { \
2910+ zend_mm_panic("zend_mm_heap corrupted"); \
65be62f2 2911+ }
3f3163a9
AM
2912+#define ZEND_MM_CHECK_TREE(block) \
2913+ if (UNEXPECTED(*((block)->parent) != (block))) { \
2914+ zend_mm_panic("zend_mm_heap corrupted"); \
65be62f2 2915+ }
3f3163a9
AM
2916+#else
2917+# define ZEND_MM_CHECK_BLOCK_LINKAGE(block)
2918+# define ZEND_MM_CHECK_TREE(block)
65be62f2
ER
2919+#endif
2920+
3f3163a9 2921+#define ZEND_MM_LARGE_BUCKET_INDEX(S) zend_mm_high_bit(S)
65be62f2 2922+
3f3163a9
AM
2923+void *_zend_mm_alloc_canary_int(zend_mm_heap_canary *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
2924+void _zend_mm_free_canary_int(zend_mm_heap_canary *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
2925+void *_zend_mm_realloc_canary_int(zend_mm_heap_canary *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
65be62f2 2926+
65be62f2 2927+
3f3163a9
AM
2928+static inline unsigned int zend_mm_high_bit(size_t _size)
2929+{
2930+#if defined(__GNUC__) && defined(i386)
2931+ unsigned int n;
65be62f2 2932+
3f3163a9
AM
2933+ __asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm" (_size));
2934+ return n;
2935+#elif defined(__GNUC__) && defined(__x86_64__)
2936+ unsigned long n;
65be62f2 2937+
3f3163a9
AM
2938+ __asm__("bsrq %1,%0\n\t" : "=r" (n) : "rm" (_size));
2939+ return (unsigned int)n;
2940+#elif defined(_MSC_VER) && defined(_M_IX86)
2941+ __asm {
2942+ bsr eax, _size
65be62f2 2943+ }
3f3163a9
AM
2944+#else
2945+ unsigned int n = 0;
2946+ while (_size != 0) {
2947+ _size = _size >> 1;
2948+ n++;
65be62f2 2949+ }
3f3163a9
AM
2950+ return n-1;
2951+#endif
65be62f2
ER
2952+}
2953+
3f3163a9 2954+static inline unsigned int zend_mm_low_bit(size_t _size)
65be62f2 2955+{
3f3163a9
AM
2956+#if defined(__GNUC__) && defined(i386)
2957+ unsigned int n;
2958+
2959+ __asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm" (_size));
2960+ return n;
2961+#elif defined(__GNUC__) && defined(__x86_64__)
2962+ unsigned long n;
2963+
2964+ __asm__("bsfq %1,%0\n\t" : "=r" (n) : "rm" (_size));
2965+ return (unsigned int)n;
2966+#elif defined(_MSC_VER) && defined(_M_IX86)
2967+ __asm {
2968+ bsf eax, _size
2969+ }
2970+#else
2971+ static const int offset[16] = {4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
2972+ unsigned int n;
2973+ unsigned int index = 0;
2974+
2975+ n = offset[_size & 15];
2976+ while (n == 4) {
2977+ _size >>= 4;
2978+ index += n;
2979+ n = offset[_size & 15];
65be62f2 2980+ }
3f3163a9
AM
2981+
2982+ return index + n;
2983+#endif
65be62f2
ER
2984+}
2985+
3f3163a9 2986+static void zend_mm_add_to_rest_list(zend_mm_heap_canary *heap, zend_mm_free_block_canary *mm_block)
65be62f2 2987+{
3f3163a9 2988+ zend_mm_free_block_canary *prev, *next;
65be62f2 2989+
3f3163a9
AM
2990+ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
2991+
2992+ if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block))) {
2993+ mm_block->parent = NULL;
65be62f2
ER
2994+ }
2995+
3f3163a9
AM
2996+ prev = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]);
2997+ next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
2998+ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
2999+ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
3000+ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
3001+}
65be62f2 3002+
3f3163a9
AM
3003+static void zend_mm_add_to_free_list(zend_mm_heap_canary *heap, zend_mm_free_block_canary *mm_block)
3004+{
3005+ size_t size;
3006+ size_t index;
3007+
3008+ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
3009+
3010+ size = ZEND_MM_FREE_BLOCK_SIZE(mm_block);
3011+ if (EXPECTED(!ZEND_MM_SMALL_SIZE(size))) {
3012+ zend_mm_free_block_canary **p;
3013+
3014+ index = ZEND_MM_LARGE_BUCKET_INDEX(size);
3015+ p = &heap->large_free_buckets[index];
3016+ mm_block->child[0] = mm_block->child[1] = NULL;
3017+ if (!*p) {
3018+ *p = mm_block;
3019+ mm_block->parent = p;
3020+ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block);
3021+ heap->large_free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
3022+ } else {
3023+ size_t m;
3024+
3025+ for (m = size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
3026+ zend_mm_free_block_canary *prev = *p;
3027+
3028+ if (ZEND_MM_FREE_BLOCK_SIZE(prev) != size) {
3029+ p = &prev->child[(m >> (ZEND_MM_NUM_BUCKETS-1)) & 1];
3030+ if (!*p) {
3031+ *p = mm_block;
3032+ mm_block->parent = p;
3033+ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block);
3034+ break;
3035+ }
65be62f2 3036+ } else {
3f3163a9
AM
3037+ zend_mm_free_block_canary *next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
3038+
3039+ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
3040+ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
3041+ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
3042+ mm_block->parent = NULL;
65be62f2
ER
3043+ break;
3044+ }
65be62f2
ER
3045+ }
3046+ }
3f3163a9
AM
3047+ } else {
3048+ zend_mm_free_block_canary *prev, *next;
65be62f2 3049+
3f3163a9
AM
3050+ index = ZEND_MM_BUCKET_INDEX(size);
3051+
3052+ prev = ZEND_MM_SMALL_FREE_BUCKET(heap, index);
3053+ if (SUHOSIN_MANGLE_PTR(prev->prev_free_block) == prev) {
3054+ heap->free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
3055+ }
3056+ next = SUHOSIN_MANGLE_PTR(prev->next_free_block);
3057+
3058+ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
3059+ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next);
3060+ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block);
3061+ }
3062+}
3063+
3064+static void zend_mm_remove_from_free_list(zend_mm_heap_canary *heap, zend_mm_free_block_canary *mm_block)
3065+{
3066+ zend_mm_free_block_canary *prev = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block);
3067+ zend_mm_free_block_canary *next = SUHOSIN_MANGLE_PTR(mm_block->next_free_block);
3068+
3069+ ZEND_MM_CHECK_MAGIC(mm_block, MEM_BLOCK_FREED);
3070+
3071+ if (EXPECTED(prev == mm_block)) {
3072+ zend_mm_free_block_canary **rp, **cp;
3073+
3074+#if SUHOSIN_PATCH
3075+ if (next != mm_block) {
3076+ zend_suhosin_log(S_MEMORY, "zend_mm_heap corrupted at %p", mm_block);
3077+ _exit(1);
3078+ }
3079+#endif
3080+#if ZEND_MM_SAFE_UNLINKING
3081+ if (UNEXPECTED(next != mm_block)) {
3082+ zend_mm_panic("zend_mm_heap corrupted");
3083+ }
3084+#endif
3085+
3086+ rp = &mm_block->child[mm_block->child[1] != NULL];
3087+ prev = *rp;
3088+ if (EXPECTED(prev == NULL)) {
3089+ size_t index = ZEND_MM_LARGE_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block));
3090+
3091+ ZEND_MM_CHECK_TREE(mm_block);
3092+ *mm_block->parent = NULL;
3093+ if (mm_block->parent == &heap->large_free_buckets[index]) {
3094+ heap->large_free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
3095+ }
3096+ } else {
3097+ while (*(cp = &(prev->child[prev->child[1] != NULL])) != NULL) {
3098+ prev = *cp;
3099+ rp = cp;
3100+ }
3101+ *rp = NULL;
3102+
3103+subst_block:
3104+ ZEND_MM_CHECK_TREE(mm_block);
3105+ *mm_block->parent = prev;
3106+ prev->parent = mm_block->parent;
3107+ if ((prev->child[0] = mm_block->child[0])) {
3108+ ZEND_MM_CHECK_TREE(prev->child[0]);
3109+ prev->child[0]->parent = &prev->child[0];
3110+ }
3111+ if ((prev->child[1] = mm_block->child[1])) {
3112+ ZEND_MM_CHECK_TREE(prev->child[1]);
3113+ prev->child[1]->parent = &prev->child[1];
65be62f2
ER
3114+ }
3115+ }
3f3163a9 3116+ } else {
65be62f2 3117+
3f3163a9
AM
3118+#if SUHOSIN_PATCH
3119+ if (SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block || SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block) {
3120+ zend_suhosin_log(S_MEMORY, "zend_mm_head corrupted at %p", mm_block);
3121+ _exit(1);
3122+ }
3123+#endif
3124+
3125+#if ZEND_MM_SAFE_UNLINKING
3126+ if (UNEXPECTED(SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block) || UNEXPECTED(SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block)) {
3127+ zend_mm_panic("zend_mm_heap corrupted");
65be62f2 3128+ }
3f3163a9
AM
3129+#endif
3130+
3131+ prev->next_free_block = SUHOSIN_MANGLE_PTR(next);
3132+ next->prev_free_block = SUHOSIN_MANGLE_PTR(prev);
3133+
3134+ if (EXPECTED(ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block)))) {
3135+ if (EXPECTED(prev == next)) {
3136+ size_t index = ZEND_MM_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block));
3137+
3138+ if (EXPECTED(heap->free_buckets[index*2] == heap->free_buckets[index*2+1])) {
3139+ heap->free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
3140+ }
3141+ }
3142+ } else if (UNEXPECTED(mm_block->parent != NULL)) {
3143+ goto subst_block;
65be62f2 3144+ }
65be62f2 3145+ }
3f3163a9 3146+}
65be62f2 3147+
3f3163a9
AM
3148+static void zend_mm_init(zend_mm_heap_canary *heap)
3149+{
3150+ zend_mm_free_block_canary* p;
3151+ int i;
3152+
3153+ heap->free_bitmap = 0;
3154+ heap->large_free_bitmap = 0;
3155+#if ZEND_MM_CACHE
3156+ heap->cached = 0;
3157+ memset(heap->cache, 0, sizeof(heap->cache));
3158+#endif
3159+#if ZEND_MM_CACHE_STAT
3160+ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
3161+ heap->cache_stat[i].count = 0;
3162+ }
3163+#endif
3164+ p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
3165+ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
3166+ p->next_free_block = SUHOSIN_MANGLE_PTR(p);
3167+ p->prev_free_block = SUHOSIN_MANGLE_PTR(p);
3168+ p = (zend_mm_free_block_canary*)((char*)p + sizeof(zend_mm_free_block_canary*) * 2);
3169+ heap->large_free_buckets[i] = NULL;
3170+ }
3171+ heap->rest_buckets[0] = heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(heap));
3172+#if SUHOSIN_PATCH
3173+ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) {
3174+ zend_canary(&heap->canary_1, sizeof(heap->canary_1));
3175+ zend_canary(&heap->canary_2, sizeof(heap->canary_2));
3176+ zend_canary(&heap->canary_3, sizeof(heap->canary_3));
65be62f2 3177+ }
3f3163a9 3178+#endif
65be62f2
ER
3179+}
3180+
3f3163a9 3181+static void zend_mm_del_segment(zend_mm_heap_canary *heap, zend_mm_segment *segment)
65be62f2 3182+{
3f3163a9
AM
3183+ zend_mm_segment **p = &heap->segments_list;
3184+
3185+ while (*p != segment) {
3186+ p = &(*p)->next_segment;
3187+ }
3188+ *p = segment->next_segment;
3189+ heap->real_size -= segment->size;
3190+ ZEND_MM_STORAGE_FREE(segment);
3191+}
3192+
3193+#if ZEND_MM_CACHE
3194+static void zend_mm_free_cache(zend_mm_heap_canary *heap)
3195+{
3196+ int i;
3197+
3198+ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
3199+ /* SUHOSIN_MANGLE_PTR should NOT affect NULL pointers */
3200+ if (heap->cache[i]) {
3201+ zend_mm_free_block_canary *mm_block = SUHOSIN_MANGLE_PTR(heap->cache[i]);
3202+
3203+ while (mm_block) {
3204+ size_t size = ZEND_MM_BLOCK_SIZE(mm_block);
3205+ zend_mm_free_block_canary *q = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block);
3206+ zend_mm_block_canary *next_block = ZEND_MM_NEXT_BLOCK(mm_block);
3207+
3208+ heap->cached -= size;
3209+
3210+ if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) {
3211+ mm_block = (zend_mm_free_block_canary*)ZEND_MM_PREV_BLOCK(mm_block);
3212+ size += ZEND_MM_FREE_BLOCK_SIZE(mm_block);
3213+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) mm_block);
3214+ }
3215+ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
3216+ size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
3217+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
3218+ }
3219+ ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size);
65be62f2 3220+
3f3163a9
AM
3221+ if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
3222+ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_NEXT_BLOCK(mm_block))) {
3223+ zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE));
3224+ } else {
3225+ zend_mm_add_to_free_list(heap, (zend_mm_free_block_canary *) mm_block);
3226+ }
65be62f2 3227+
3f3163a9
AM
3228+ mm_block = q;
3229+ }
3230+ heap->cache[i] = NULL;
65be62f2 3231+#if ZEND_MM_CACHE_STAT
3f3163a9 3232+ heap->cache_stat[i].count = 0;
65be62f2 3233+#endif
65be62f2
ER
3234+ }
3235+ }
3f3163a9 3236+}
65be62f2
ER
3237+#endif
3238+
3f3163a9
AM
3239+#if ZEND_MM_HEAP_PROTECTION || ZEND_MM_COOKIES
3240+static void zend_mm_random(unsigned char *buf, size_t size) /* {{{ */
3241+{
3242+ size_t i = 0;
3243+ unsigned char t;
65be62f2 3244+
3f3163a9
AM
3245+#ifdef ZEND_WIN32
3246+ HCRYPTPROV hCryptProv;
3247+ int has_context = 0;
3248+
3249+ if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
3250+ /* Could mean that the key container does not exist, let try
3251+ again by asking for a new one */
3252+ if (GetLastError() == NTE_BAD_KEYSET) {
3253+ if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
3254+ has_context = 1;
65be62f2 3255+ }
65be62f2 3256+ }
3f3163a9
AM
3257+ } else {
3258+ has_context = 1;
65be62f2 3259+ }
3f3163a9
AM
3260+ if (has_context) {
3261+ do {
3262+ BOOL ret = CryptGenRandom(hCryptProv, size, buf);
3263+ CryptReleaseContext(hCryptProv, 0);
3264+ if (ret) {
3265+ while (i < size && buf[i] != 0) {
3266+ i++;
3267+ }
3268+ if (i == size) {
3269+ return;
3270+ }
3271+ }
3272+ } while (0);
3273+ }
3274+#elif defined(HAVE_DEV_URANDOM)
3275+ int fd = open("/dev/urandom", 0);
65be62f2 3276+
3f3163a9
AM
3277+ if (fd >= 0) {
3278+ if (read(fd, buf, size) == size) {
3279+ while (i < size && buf[i] != 0) {
3280+ i++;
3281+ }
3282+ if (i == size) {
3283+ close(fd);
3284+ return;
3285+ }
65be62f2 3286+ }
3f3163a9
AM
3287+ close(fd);
3288+ }
65be62f2 3289+#endif
3f3163a9
AM
3290+ t = (unsigned char)getpid();
3291+ while (i < size) {
3292+ do {
3293+ buf[i] = ((unsigned char)rand()) ^ t;
3294+ } while (buf[i] == 0);
3295+ t = buf[i++] << 1;
3296+ }
3297+}
3298+/* }}} */
65be62f2 3299+#endif
65be62f2 3300+
65be62f2 3301+
3f3163a9
AM
3302+/* Notes:
3303+ * - This function may alter the block_sizes values to match platform alignment
3304+ * - This function does *not* perform sanity checks on the arguments
3305+ */
3306+zend_mm_heap_canary *__zend_mm_startup_canary_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params)
3307+{
3308+ zend_mm_storage *storage;
3309+ zend_mm_heap_canary *heap;
3310+ zend_mm_free_block_canary *tmp;
65be62f2 3311+
3f3163a9
AM
3312+#if 0
3313+ int i;
65be62f2 3314+
3f3163a9
AM
3315+ printf("ZEND_MM_ALIGNMENT=%d\n", ZEND_MM_ALIGNMENT);
3316+ printf("ZEND_MM_ALIGNMENT_LOG2=%d\n", ZEND_MM_ALIGNMENT_LOG2);
3317+ printf("ZEND_MM_MIN_SIZE=%d\n", ZEND_MM_MIN_SIZE);
3318+ printf("ZEND_MM_MAX_SMALL_SIZE=%d\n", ZEND_MM_MAX_SMALL_SIZE);
3319+ printf("ZEND_MM_ALIGNED_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_HEADER_SIZE);
3320+ printf("ZEND_MM_ALIGNED_FREE_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_FREE_HEADER_SIZE);
3321+ printf("ZEND_MM_MIN_ALLOC_BLOCK_SIZE=%d\n", ZEND_MM_MIN_ALLOC_BLOCK_SIZE);
3322+ printf("ZEND_MM_ALIGNED_MIN_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_MIN_HEADER_SIZE);
3323+ printf("ZEND_MM_ALIGNED_SEGMENT_SIZE=%d\n", ZEND_MM_ALIGNED_SEGMENT_SIZE);
3324+ for (i = 0; i < ZEND_MM_MAX_SMALL_SIZE; i++) {
3325+ printf("%3d%c: %3ld %d %2ld\n", i, (i == ZEND_MM_MIN_SIZE?'*':' '), (long)ZEND_MM_TRUE_SIZE(i), ZEND_MM_SMALL_SIZE(ZEND_MM_TRUE_SIZE(i)), (long)ZEND_MM_BUCKET_INDEX(ZEND_MM_TRUE_SIZE(i)));
3326+ }
3327+ exit(0);
3328+#endif
65be62f2 3329+
3f3163a9
AM
3330+#if ZEND_MM_HEAP_PROTECTION
3331+ if (_mem_block_start_magic == 0) {
3332+ zend_mm_random((unsigned char*)&_mem_block_start_magic, sizeof(_mem_block_start_magic));
3333+ }
3334+ if (_mem_block_end_magic == 0) {
3335+ zend_mm_random((unsigned char*)&_mem_block_end_magic, sizeof(_mem_block_end_magic));
3336+ }
3337+#endif
3338+#if ZEND_MM_COOKIES
3339+ if (_zend_mm_cookie == 0) {
3340+ zend_mm_random((unsigned char*)&_zend_mm_cookie, sizeof(_zend_mm_cookie));
3341+ }
3342+#endif
65be62f2 3343+
3f3163a9
AM
3344+ /* get the pointer guardian and ensure low 3 bits are 1 */
3345+ if (SUHOSIN_POINTER_GUARD == 0) {
3346+ zend_canary(&SUHOSIN_POINTER_GUARD, sizeof(SUHOSIN_POINTER_GUARD));
3347+ SUHOSIN_POINTER_GUARD |= 7;
3348+ }
65be62f2 3349+
3f3163a9
AM
3350+ if (zend_mm_low_bit(block_size) != zend_mm_high_bit(block_size)) {
3351+ fprintf(stderr, "'block_size' must be a power of two\n");
3352+/* See http://support.microsoft.com/kb/190351 */
3353+#ifdef PHP_WIN32
3354+ fflush(stderr);
3355+#endif
3356+ exit(255);
65be62f2 3357+ }
3f3163a9
AM
3358+ storage = handlers->init(params);
3359+ if (!storage) {
3360+ fprintf(stderr, "Cannot initialize zend_mm storage [%s]\n", handlers->name);
3361+/* See http://support.microsoft.com/kb/190351 */
3362+#ifdef PHP_WIN32
3363+ fflush(stderr);
3364+#endif
3365+ exit(255);
3366+ }
3367+ storage->handlers = handlers;
65be62f2 3368+
3f3163a9 3369+ heap = malloc(sizeof(struct _zend_mm_heap_canary));
65be62f2 3370+
3f3163a9
AM
3371+ heap->storage = storage;
3372+ heap->block_size = block_size;
3373+ heap->compact_size = 0;
3374+ heap->segments_list = NULL;
3375+ zend_mm_init(heap);
3376+# if ZEND_MM_CACHE_STAT
3377+ memset(heap->cache_stat, 0, sizeof(heap->cache_stat));
3378+# endif
65be62f2 3379+
3f3163a9
AM
3380+ heap->use_zend_alloc = 1;
3381+ heap->real_size = 0;
3382+ heap->overflow = 0;
3383+ heap->real_peak = 0;
3384+ heap->limit = ZEND_MM_LONG_CONST(1)<<(ZEND_MM_NUM_BUCKETS-2);
3385+ heap->size = 0;
3386+ heap->peak = 0;
3387+ heap->internal = internal;
3388+ heap->reserve = NULL;
3389+ heap->reserve_size = reserve_size;
3390+ if (reserve_size > 0) {
3391+ heap->reserve = _zend_mm_alloc((zend_mm_heap *)heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
65be62f2 3392+ }
3f3163a9
AM
3393+ if (internal) {
3394+ int i;
3395+ zend_mm_free_block_canary *p, *q, *orig;
3396+ zend_mm_heap_canary *mm_heap = _zend_mm_alloc((zend_mm_heap *)heap, sizeof(zend_mm_heap_canary) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
65be62f2 3397+
3f3163a9 3398+ *mm_heap = *heap;
65be62f2 3399+
3f3163a9
AM
3400+ p = ZEND_MM_SMALL_FREE_BUCKET(mm_heap, 0);
3401+ orig = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
3402+ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
3403+ q = p;
3404+ while (SUHOSIN_MANGLE_PTR(q->prev_free_block) != orig) {
3405+ q = SUHOSIN_MANGLE_PTR(q->prev_free_block);
3406+ }
3407+ q->prev_free_block = SUHOSIN_MANGLE_PTR(p);
3408+ q = p;
3409+ while (SUHOSIN_MANGLE_PTR(q->next_free_block) != orig) {
3410+ q = SUHOSIN_MANGLE_PTR(q->next_free_block);
3411+ }
3412+ q->next_free_block = SUHOSIN_MANGLE_PTR(p);
3413+ p = (zend_mm_free_block_canary*)((char*)p + sizeof(zend_mm_free_block_canary*) * 2);
3414+ orig = (zend_mm_free_block_canary*)((char*)orig + sizeof(zend_mm_free_block_canary*) * 2);
3415+ if (mm_heap->large_free_buckets[i]) {
3416+ mm_heap->large_free_buckets[i]->parent = &mm_heap->large_free_buckets[i];
3417+ }
3418+ }
3419+ mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(mm_heap));
65be62f2 3420+
3f3163a9
AM
3421+ free(heap);
3422+ heap = mm_heap;
3423+ }
3424+ return heap;
65be62f2
ER
3425+}
3426+
3f3163a9 3427+zend_mm_heap_canary *__zend_mm_startup_canary(void)
65be62f2 3428+{
3f3163a9
AM
3429+ int i;
3430+ size_t seg_size;
3431+ char *mem_type = getenv("ZEND_MM_MEM_TYPE");
3432+ char *tmp;
3433+ const zend_mm_mem_handlers *handlers;
3434+ zend_mm_heap_canary *heap;
65be62f2 3435+
3f3163a9
AM
3436+ if (mem_type == NULL) {
3437+ i = 0;
3438+ } else {
3439+ for (i = 0; mem_handlers[i].name; i++) {
3440+ if (strcmp(mem_handlers[i].name, mem_type) == 0) {
3441+ break;
3442+ }
3443+ }
3444+ if (!mem_handlers[i].name) {
3445+ fprintf(stderr, "Wrong or unsupported zend_mm storage type '%s'\n", mem_type);
3446+ fprintf(stderr, " supported types:\n");
3447+/* See http://support.microsoft.com/kb/190351 */
3448+#ifdef PHP_WIN32
3449+ fflush(stderr);
3450+#endif
3451+ for (i = 0; mem_handlers[i].name; i++) {
3452+ fprintf(stderr, " '%s'\n", mem_handlers[i].name);
3453+ }
3454+/* See http://support.microsoft.com/kb/190351 */
3455+#ifdef PHP_WIN32
3456+ fflush(stderr);
3457+#endif
3458+ exit(255);
3459+ }
65be62f2 3460+ }
3f3163a9 3461+ handlers = &mem_handlers[i];
65be62f2 3462+
3f3163a9
AM
3463+ tmp = getenv("ZEND_MM_SEG_SIZE");
3464+ if (tmp) {
3465+ seg_size = zend_atoi(tmp, 0);
3466+ if (zend_mm_low_bit(seg_size) != zend_mm_high_bit(seg_size)) {
3467+ fprintf(stderr, "ZEND_MM_SEG_SIZE must be a power of two\n");
3468+/* See http://support.microsoft.com/kb/190351 */
3469+#ifdef PHP_WIN32
3470+ fflush(stderr);
65be62f2 3471+#endif
3f3163a9
AM
3472+ exit(255);
3473+ } else if (seg_size < ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE) {
3474+ fprintf(stderr, "ZEND_MM_SEG_SIZE is too small\n");
3475+/* See http://support.microsoft.com/kb/190351 */
3476+#ifdef PHP_WIN32
3477+ fflush(stderr);
65be62f2 3478+#endif
3f3163a9 3479+ exit(255);
65be62f2 3480+ }
3f3163a9
AM
3481+ } else {
3482+ seg_size = ZEND_MM_SEG_SIZE;
65be62f2 3483+ }
65be62f2 3484+
3f3163a9
AM
3485+ heap = __zend_mm_startup_canary_ex(handlers, seg_size, ZEND_MM_RESERVE_SIZE, 0, NULL);
3486+ if (heap) {
3487+ tmp = getenv("ZEND_MM_COMPACT");
3488+ if (tmp) {
3489+ heap->compact_size = zend_atoi(tmp, 0);
3490+ } else {
3491+ heap->compact_size = 2 * 1024 * 1024;
3492+ }
65be62f2 3493+ }
3f3163a9 3494+ return heap;
65be62f2
ER
3495+}
3496+
3f3163a9
AM
3497+#if ZEND_DEBUG
3498+static long zend_mm_find_leaks(zend_mm_segment *segment, zend_mm_block_canary *b)
65be62f2 3499+{
3f3163a9
AM
3500+ long leaks = 0;
3501+ zend_mm_block_canary *p, *q;
65be62f2 3502+
3f3163a9
AM
3503+ p = ZEND_MM_NEXT_BLOCK(b);
3504+ while (1) {
3505+ if (ZEND_MM_IS_GUARD_BLOCK(p)) {
3506+ ZEND_MM_CHECK_MAGIC(p, MEM_BLOCK_GUARD);
3507+ segment = segment->next_segment;
3508+ if (!segment) {
3509+ break;
3510+ }
3511+ p = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
3512+ continue;
3513+ }
3514+ q = ZEND_MM_NEXT_BLOCK(p);
3515+ if (q <= p ||
3516+ (char*)q > (char*)segment + segment->size ||
3517+ p->info._size != q->info._prev) {
3518+ zend_mm_panic("zend_mm_heap corrupted");
3519+ }
3520+ if (!ZEND_MM_IS_FREE_BLOCK(p)) {
3521+ if (p->magic == MEM_BLOCK_VALID) {
3522+ if (p->debug.filename==b->debug.filename && p->debug.lineno==b->debug.lineno) {
3523+ ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK);
3524+ leaks++;
3525+ }
3526+#if ZEND_MM_CACHE
3527+ } else if (p->magic == MEM_BLOCK_CACHED) {
3528+ /* skip it */
3529+#endif
3530+ } else if (p->magic != MEM_BLOCK_LEAK) {
3531+ zend_mm_panic("zend_mm_heap corrupted");
3532+ }
3533+ }
3534+ p = q;
65be62f2 3535+ }
3f3163a9
AM
3536+ return leaks;
3537+}
65be62f2 3538+
3f3163a9
AM
3539+static void zend_mm_check_leaks(zend_mm_heap_canary *heap TSRMLS_DC)
3540+{
3541+ zend_mm_segment *segment = heap->segments_list;
3542+ zend_mm_block_canary *p, *q;
3543+ zend_uint total = 0;
3544+
3545+ if (!segment) {
3546+ return;
65be62f2 3547+ }
3f3163a9
AM
3548+ p = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
3549+ while (1) {
3550+ q = ZEND_MM_NEXT_BLOCK(p);
3551+ if (q <= p ||
3552+ (char*)q > (char*)segment + segment->size ||
3553+ p->info._size != q->info._prev) {
3554+ zend_mm_panic("zend_mm_heap corrupted");
3555+ }
3556+ if (!ZEND_MM_IS_FREE_BLOCK(p)) {
3557+ if (p->magic == MEM_BLOCK_VALID) {
3558+ long repeated;
3559+ zend_leak_info leak;
65be62f2 3560+
3f3163a9 3561+ ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK);
65be62f2 3562+
3f3163a9
AM
3563+ leak.addr = ZEND_MM_DATA_OF(p);
3564+ leak.size = p->debug.size;
3565+ leak.filename = p->debug.filename;
3566+ leak.lineno = p->debug.lineno;
3567+ leak.orig_filename = p->debug.orig_filename;
3568+ leak.orig_lineno = p->debug.orig_lineno;
65be62f2 3569+
3f3163a9
AM
3570+ zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
3571+ zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, &leak TSRMLS_CC);
3572+ repeated = zend_mm_find_leaks(segment, p);
3573+ total += 1 + repeated;
3574+ if (repeated) {
3575+ zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(zend_uintptr_t)repeated TSRMLS_CC);
3576+ }
3577+#if ZEND_MM_CACHE
3578+ } else if (p->magic == MEM_BLOCK_CACHED) {
3579+ /* skip it */
3580+#endif
3581+ } else if (p->magic != MEM_BLOCK_LEAK) {
3582+ zend_mm_panic("zend_mm_heap corrupted");
65be62f2 3583+ }
65be62f2 3584+ }
3f3163a9
AM
3585+ if (ZEND_MM_IS_GUARD_BLOCK(q)) {
3586+ segment = segment->next_segment;
3587+ if (!segment) {
3588+ break;
3589+ }
3590+ q = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
3591+ }
3592+ p = q;
65be62f2 3593+ }
3f3163a9
AM
3594+ if (total) {
3595+ zend_message_dispatcher(ZMSG_MEMORY_LEAKS_GRAND_TOTAL, &total TSRMLS_CC);
3596+ }
3597+}
65be62f2 3598+
3f3163a9
AM
3599+static int zend_mm_check_ptr(zend_mm_heap_canary *heap, void *ptr, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
3600+{
3601+ zend_mm_block_canary *p;
3602+ int no_cache_notice = 0;
3603+ int had_problems = 0;
3604+ int valid_beginning = 1;
65be62f2 3605+
3f3163a9
AM
3606+ if (silent==2) {
3607+ silent = 1;
3608+ no_cache_notice = 1;
3609+ } else if (silent==3) {
3610+ silent = 0;
3611+ no_cache_notice = 1;
3612+ }
3613+ if (!silent) {
3614+ TSRMLS_FETCH();
3615+
3616+ zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
3617+ zend_debug_alloc_output("---------------------------------------\n");
3618+ zend_debug_alloc_output("%s(%d) : Block "PTR_FMT" status:\n" ZEND_FILE_LINE_RELAY_CC, ptr);
3619+ if (__zend_orig_filename) {
3620+ zend_debug_alloc_output("%s(%d) : Actual location (location was relayed)\n" ZEND_FILE_LINE_ORIG_RELAY_CC);
3621+ }
3622+ if (!ptr) {
3623+ zend_debug_alloc_output("NULL\n");
3624+ zend_debug_alloc_output("---------------------------------------\n");
3625+ return 0;
3626+ }
3627+ }
65be62f2 3628+
3f3163a9
AM
3629+ if (!ptr) {
3630+ if (silent) {
3631+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3632+ }
3633+ }
65be62f2 3634+
3f3163a9 3635+ p = ZEND_MM_HEADER_OF(ptr);
65be62f2 3636+
3f3163a9
AM
3637+#ifdef ZTS
3638+ if (ZEND_MM_BAD_THREAD_ID(p)) {
3639+ if (!silent) {
3640+ zend_debug_alloc_output("Invalid pointer: ((thread_id=0x%0.8X) != (expected=0x%0.8X))\n", (long)p->thread_id, (long)tsrm_thread_id());
3641+ had_problems = 1;
3642+ } else {
3643+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
65be62f2
ER
3644+ }
3645+ }
3646+#endif
3647+
3f3163a9
AM
3648+ if (p->info._size != ZEND_MM_NEXT_BLOCK(p)->info._prev) {
3649+ if (!silent) {
3650+ zend_debug_alloc_output("Invalid pointer: ((size="PTR_FMT") != (next.prev="PTR_FMT"))\n", p->info._size, ZEND_MM_NEXT_BLOCK(p)->info._prev);
3651+ had_problems = 1;
3652+ } else {
3653+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3654+ }
3655+ }
3656+ if (p->info._prev != ZEND_MM_GUARD_BLOCK &&
3657+ ZEND_MM_PREV_BLOCK(p)->info._size != p->info._prev) {
3658+ if (!silent) {
3659+ zend_debug_alloc_output("Invalid pointer: ((prev="PTR_FMT") != (prev.size="PTR_FMT"))\n", p->info._prev, ZEND_MM_PREV_BLOCK(p)->info._size);
3660+ had_problems = 1;
3661+ } else {
3662+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3663+ }
3664+ }
65be62f2 3665+
3f3163a9
AM
3666+ if (had_problems) {
3667+ zend_debug_alloc_output("---------------------------------------\n");
3668+ return 0;
3669+ }
65be62f2 3670+
3f3163a9
AM
3671+ if (!silent) {
3672+ zend_debug_alloc_output("%10s\t","Beginning: ");
3673+ }
65be62f2 3674+
3f3163a9
AM
3675+ if (!ZEND_MM_IS_USED_BLOCK(p)) {
3676+ if (!silent) {
3677+ if (p->magic != MEM_BLOCK_FREED) {
3678+ zend_debug_alloc_output("Freed (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED);
65be62f2 3679+ } else {
3f3163a9 3680+ zend_debug_alloc_output("Freed\n");
65be62f2 3681+ }
3f3163a9 3682+ had_problems = 1;
65be62f2 3683+ } else {
3f3163a9 3684+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
65be62f2 3685+ }
3f3163a9
AM
3686+ } else if (ZEND_MM_IS_GUARD_BLOCK(p)) {
3687+ if (!silent) {
3688+ if (p->magic != MEM_BLOCK_FREED) {
3689+ zend_debug_alloc_output("Guard (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED);
3690+ } else {
3691+ zend_debug_alloc_output("Guard\n");
65be62f2 3692+ }
3f3163a9
AM
3693+ had_problems = 1;
3694+ } else {
3695+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
65be62f2 3696+ }
3f3163a9
AM
3697+ } else {
3698+ switch (p->magic) {
3699+ case MEM_BLOCK_VALID:
3700+ case MEM_BLOCK_LEAK:
3701+ if (!silent) {
3702+ zend_debug_alloc_output("OK (allocated on %s:%d, %d bytes)\n", p->debug.filename, p->debug.lineno, (int)p->debug.size);
3703+ }
3704+ break; /* ok */
3705+ case MEM_BLOCK_CACHED:
3706+ if (!no_cache_notice) {
3707+ if (!silent) {
3708+ zend_debug_alloc_output("Cached\n");
3709+ had_problems = 1;
3710+ } else {
3711+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3712+ }
3713+ }
3714+ case MEM_BLOCK_FREED:
3715+ if (!silent) {
3716+ zend_debug_alloc_output("Freed (invalid)\n");
3717+ had_problems = 1;
3718+ } else {
3719+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3720+ }
3721+ break;
3722+ case MEM_BLOCK_GUARD:
3723+ if (!silent) {
3724+ zend_debug_alloc_output("Guard (invalid)\n");
3725+ had_problems = 1;
3726+ } else {
3727+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3728+ }
3729+ break;
3730+ default:
3731+ if (!silent) {
3732+ zend_debug_alloc_output("Unknown (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_VALID);
3733+ had_problems = 1;
3734+ valid_beginning = 0;
3735+ } else {
3736+ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3737+ }
3738+ break;
65be62f2 3739+ }
3f3163a9
AM
3740+ }
3741+
3742+#if ZEND_MM_HEAP_PROTECTION
3743+ if (!valid_beginning) {
3744+ if (!silent) {
3745+ zend_debug_alloc_output("%10s\t", "Start:");
3746+ zend_debug_alloc_output("Unknown\n");
3747+ zend_debug_alloc_output("%10s\t", "End:");
3748+ zend_debug_alloc_output("Unknown\n");
65be62f2 3749+ }
3f3163a9
AM
3750+ } else {
3751+ char *end_magic = ZEND_MM_END_MAGIC_PTR(p);
65be62f2 3752+
3f3163a9
AM
3753+ if (p->debug.start_magic == _mem_block_start_magic) {
3754+ if (!silent) {
3755+ zend_debug_alloc_output("%10s\t", "Start:");
3756+ zend_debug_alloc_output("OK\n");
3757+ }
3758+ } else {
3759+ char *overflow_ptr, *magic_ptr=(char *) &_mem_block_start_magic;
3760+ int overflows=0;
3761+ int i;
65be62f2 3762+
3f3163a9
AM
3763+ if (silent) {
3764+ return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3765+ }
3766+ had_problems = 1;
3767+ overflow_ptr = (char *) &p->debug.start_magic;
3768+ i = END_MAGIC_SIZE;
3769+ while (--i >= 0) {
3770+ if (overflow_ptr[i]!=magic_ptr[i]) {
3771+ overflows++;
3772+ }
3773+ }
3774+ zend_debug_alloc_output("%10s\t", "Start:");
3775+ zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", p->debug.start_magic, _mem_block_start_magic);
3776+ zend_debug_alloc_output("%10s\t","");
3777+ if (overflows >= END_MAGIC_SIZE) {
3778+ zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
3779+ } else {
3780+ zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
65be62f2 3781+ }
65be62f2 3782+ }
3f3163a9
AM
3783+ if (memcmp(end_magic, &_mem_block_end_magic, END_MAGIC_SIZE)==0) {
3784+ if (!silent) {
3785+ zend_debug_alloc_output("%10s\t", "End:");
3786+ zend_debug_alloc_output("OK\n");
3787+ }
65be62f2 3788+ } else {
3f3163a9
AM
3789+ char *overflow_ptr, *magic_ptr=(char *) &_mem_block_end_magic;
3790+ int overflows=0;
3791+ int i;
65be62f2 3792+
3f3163a9
AM
3793+ if (silent) {
3794+ return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
3795+ }
3796+ had_problems = 1;
3797+ overflow_ptr = (char *) end_magic;
65be62f2 3798+
3f3163a9
AM
3799+ for (i=0; i < END_MAGIC_SIZE; i++) {
3800+ if (overflow_ptr[i]!=magic_ptr[i]) {
3801+ overflows++;
3802+ }
3803+ }
65be62f2 3804+
3f3163a9
AM
3805+ zend_debug_alloc_output("%10s\t", "End:");
3806+ zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", *end_magic, _mem_block_end_magic);
3807+ zend_debug_alloc_output("%10s\t","");
3808+ if (overflows >= END_MAGIC_SIZE) {
3809+ zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
3810+ } else {
3811+ zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
3812+ }
65be62f2 3813+ }
65be62f2 3814+ }
65be62f2 3815+#endif
65be62f2 3816+
3f3163a9
AM
3817+ if (!silent) {
3818+ zend_debug_alloc_output("---------------------------------------\n");
65be62f2 3819+ }
3f3163a9 3820+ return ((!had_problems) ? 1 : 0);
65be62f2
ER
3821+}
3822+
3f3163a9 3823+static int zend_mm_check_heap(zend_mm_heap_canary *heap, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
65be62f2 3824+{
3f3163a9
AM
3825+ zend_mm_segment *segment = heap->segments_list;
3826+ zend_mm_block_canary *p, *q;
3827+ int errors = 0;
65be62f2 3828+
3f3163a9 3829+ if (!segment) {
65be62f2 3830+ return 0;
3f3163a9
AM
3831+ }
3832+ p = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
3833+ while (1) {
3834+ q = ZEND_MM_NEXT_BLOCK(p);
3835+ if (q <= p ||
3836+ (char*)q > (char*)segment + segment->size ||
3837+ p->info._size != q->info._prev) {
3838+ zend_mm_panic("zend_mm_heap corrupted");
3839+ }
3840+ if (!ZEND_MM_IS_FREE_BLOCK(p)) {
3841+ if (p->magic == MEM_BLOCK_VALID || p->magic == MEM_BLOCK_LEAK) {
3842+ if (!zend_mm_check_ptr(heap, ZEND_MM_DATA_OF(p), (silent?2:3) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)) {
3843+ errors++;
3844+ }
3845+#if ZEND_MM_CACHE
3846+ } else if (p->magic == MEM_BLOCK_CACHED) {
3847+ /* skip it */
3848+#endif
3849+ } else if (p->magic != MEM_BLOCK_LEAK) {
3850+ zend_mm_panic("zend_mm_heap corrupted");
3851+ }
3852+ }
3853+ if (ZEND_MM_IS_GUARD_BLOCK(q)) {
3854+ segment = segment->next_segment;
3855+ if (!segment) {
3856+ return errors;
3857+ }
3858+ q = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
65be62f2 3859+ }
3f3163a9 3860+ p = q;
65be62f2 3861+ }
65be62f2 3862+}
65be62f2
ER
3863+#endif
3864+
3f3163a9
AM
3865+void __zend_mm_shutdown_canary(zend_mm_heap_canary *heap, int full_shutdown, int silent TSRMLS_DC)
3866+{
3867+ zend_mm_storage *storage;
3868+ zend_mm_segment *segment;
3869+ zend_mm_segment *prev;
3870+ int internal;
65be62f2 3871+
3f3163a9
AM
3872+ if (heap->reserve) {
3873+#if ZEND_DEBUG
3874+ if (!silent) {
3875+ _zend_mm_free(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
3876+ }
65be62f2 3877+#endif
3f3163a9
AM
3878+ heap->reserve = NULL;
3879+ }
65be62f2 3880+
3f3163a9
AM
3881+#if ZEND_MM_CACHE_STAT
3882+ if (full_shutdown) {
3883+ FILE *f;
65be62f2 3884+
3f3163a9
AM
3885+ f = fopen("zend_mm.log", "w");
3886+ if (f) {
3887+ int i,j;
3888+ size_t size, true_size, min_size, max_size;
3889+ int hit = 0, miss = 0;
65be62f2 3890+
3f3163a9
AM
3891+ fprintf(f, "\nidx min_size max_size true_size max_len hits misses\n");
3892+ size = 0;
3893+ while (1) {
3894+ true_size = ZEND_MM_TRUE_SIZE(size);
3895+ if (ZEND_MM_SMALL_SIZE(true_size)) {
3896+ min_size = size;
3897+ i = ZEND_MM_BUCKET_INDEX(true_size);
3898+ size++;
3899+ while (1) {
3900+ true_size = ZEND_MM_TRUE_SIZE(size);
3901+ if (ZEND_MM_SMALL_SIZE(true_size)) {
3902+ j = ZEND_MM_BUCKET_INDEX(true_size);
3903+ if (j > i) {
3904+ max_size = size-1;
3905+ break;
3906+ }
3907+ } else {
3908+ max_size = size-1;
3909+ break;
3910+ }
3911+ size++;
3912+ }
3913+ hit += heap->cache_stat[i].hit;
3914+ miss += heap->cache_stat[i].miss;
3915+ fprintf(f, "%2d %8d %8d %9d %8d %8d %8d\n", i, (int)min_size, (int)max_size, ZEND_MM_TRUE_SIZE(max_size), heap->cache_stat[i].max_count, heap->cache_stat[i].hit, heap->cache_stat[i].miss);
3916+ } else {
3917+ break;
3918+ }
3919+ }
3920+ fprintf(f, " %8d %8d\n", hit, miss);
3921+ fprintf(f, " %8d %8d\n", heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit, heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss);
3922+ fclose(f);
3923+ }
3924+ }
65be62f2
ER
3925+#endif
3926+
3f3163a9
AM
3927+#if ZEND_DEBUG
3928+ if (!silent) {
3929+ zend_mm_check_leaks(heap TSRMLS_CC);
3930+ }
65be62f2 3931+#endif
65be62f2 3932+
3f3163a9
AM
3933+ internal = heap->internal;
3934+ storage = heap->storage;
3935+ segment = heap->segments_list;
3936+ while (segment) {
3937+ prev = segment;
3938+ segment = segment->next_segment;
3939+ ZEND_MM_STORAGE_FREE(prev);
3940+ }
3941+ if (full_shutdown) {
3942+ storage->handlers->dtor(storage);
3943+ if (!internal) {
3944+ free(heap);
3945+ }
3946+ } else {
3947+ if (heap->compact_size &&
3948+ heap->real_peak > heap->compact_size) {
3949+ storage->handlers->compact(storage);
3950+ }
3951+ heap->segments_list = NULL;
3952+ zend_mm_init(heap);
3953+ heap->real_size = 0;
3954+ heap->real_peak = 0;
3955+ heap->size = 0;
3956+ heap->peak = 0;
3957+ if (heap->reserve_size) {
3958+ heap->reserve = _zend_mm_alloc((zend_mm_heap *)heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
3959+ }
3960+ heap->overflow = 0;
65be62f2 3961+ }
65be62f2
ER
3962+}
3963+
3f3163a9
AM
3964+static void zend_mm_safe_error(zend_mm_heap_canary *heap,
3965+ const char *format,
3966+ size_t limit,
3967+#if ZEND_DEBUG
3968+ const char *filename,
3969+ uint lineno,
3970+#endif
3971+ size_t size)
65be62f2 3972+{
3f3163a9
AM
3973+ if (heap->reserve) {
3974+ _zend_mm_free_canary_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
3975+ heap->reserve = NULL;
65be62f2 3976+ }
3f3163a9
AM
3977+ if (heap->overflow == 0) {
3978+ char *error_filename;
3979+ uint error_lineno;
3980+ TSRMLS_FETCH();
3981+ if (zend_is_compiling(TSRMLS_C)) {
3982+ error_filename = zend_get_compiled_filename(TSRMLS_C);
3983+ error_lineno = zend_get_compiled_lineno(TSRMLS_C);
3984+ } else if (EG(in_execution)) {
3985+ error_filename = EG(active_op_array)?EG(active_op_array)->filename:NULL;
3986+ error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0;
3987+ } else {
3988+ error_filename = NULL;
3989+ error_lineno = 0;
3990+ }
3991+ if (!error_filename) {
3992+ error_filename = "Unknown";
3993+ }
3994+ heap->overflow = 1;
3995+ zend_try {
3996+ zend_error_noreturn(E_ERROR,
3997+ format,
3998+ limit,
3999+#if ZEND_DEBUG
4000+ filename,
4001+ lineno,
65be62f2 4002+#endif
3f3163a9
AM
4003+ size);
4004+ } zend_catch {
4005+ if (heap->overflow == 2) {
4006+ fprintf(stderr, "\nFatal error: ");
4007+ fprintf(stderr,
4008+ format,
4009+ limit,
4010+#if ZEND_DEBUG
4011+ filename,
4012+ lineno,
65be62f2 4013+#endif
3f3163a9
AM
4014+ size);
4015+ fprintf(stderr, " in %s on line %d\n", error_filename, error_lineno);
4016+ }
4017+/* See http://support.microsoft.com/kb/190351 */
4018+#ifdef PHP_WIN32
4019+ fflush(stderr);
65be62f2 4020+#endif
3f3163a9
AM
4021+ } zend_end_try();
4022+ } else {
4023+ heap->overflow = 2;
4024+ }
4025+ zend_bailout();
65be62f2
ER
4026+}
4027+
3f3163a9 4028+static zend_mm_free_block_canary *zend_mm_search_large_block(zend_mm_heap_canary *heap, size_t true_size)
65be62f2 4029+{
3f3163a9
AM
4030+ zend_mm_free_block_canary *best_fit;
4031+ size_t index = ZEND_MM_LARGE_BUCKET_INDEX(true_size);
4032+ size_t bitmap = heap->large_free_bitmap >> index;
4033+ zend_mm_free_block_canary *p;
65be62f2 4034+
3f3163a9
AM
4035+ if (bitmap == 0) {
4036+ return NULL;
65be62f2 4037+ }
65be62f2 4038+
3f3163a9
AM
4039+ if (UNEXPECTED((bitmap & 1) != 0)) {
4040+ /* Search for best "large" free block */
4041+ zend_mm_free_block_canary *rst = NULL;
4042+ size_t m;
4043+ size_t best_size = -1;
4044+
4045+ best_fit = NULL;
4046+ p = heap->large_free_buckets[index];
4047+ for (m = true_size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
4048+ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
4049+ return SUHOSIN_MANGLE_PTR(p->next_free_block);
4050+ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) >= true_size &&
4051+ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
4052+ best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
4053+ best_fit = p;
65be62f2 4054+ }
3f3163a9
AM
4055+ if ((m & (ZEND_MM_LONG_CONST(1) << (ZEND_MM_NUM_BUCKETS-1))) == 0) {
4056+ if (p->child[1]) {
4057+ rst = p->child[1];
4058+ }
4059+ if (p->child[0]) {
4060+ p = p->child[0];
4061+ } else {
4062+ break;
4063+ }
4064+ } else if (p->child[1]) {
4065+ p = p->child[1];
65be62f2 4066+ } else {
3f3163a9 4067+ break;
65be62f2
ER
4068+ }
4069+ }
65be62f2 4070+
3f3163a9
AM
4071+ for (p = rst; p; p = p->child[p->child[0] != NULL]) {
4072+ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
4073+ return SUHOSIN_MANGLE_PTR(p->next_free_block);
4074+ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
4075+ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
4076+ best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
4077+ best_fit = p;
4078+ }
65be62f2 4079+ }
65be62f2 4080+
3f3163a9
AM
4081+ if (best_fit) {
4082+ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block);
65be62f2 4083+ }
3f3163a9
AM
4084+ bitmap = bitmap >> 1;
4085+ if (!bitmap) {
4086+ return NULL;
65be62f2 4087+ }
3f3163a9
AM
4088+ index++;
4089+ }
4090+
4091+ /* Search for smallest "large" free block */
4092+ best_fit = p = heap->large_free_buckets[index + zend_mm_low_bit(bitmap)];
4093+ while ((p = p->child[p->child[0] != NULL])) {
4094+ if (ZEND_MM_FREE_BLOCK_SIZE(p) < ZEND_MM_FREE_BLOCK_SIZE(best_fit)) {
4095+ best_fit = p;
65be62f2 4096+ }
65be62f2 4097+ }
3f3163a9 4098+ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block);
65be62f2
ER
4099+}
4100+
3f3163a9
AM
4101+void *_zend_mm_alloc_canary_int(zend_mm_heap_canary *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
4102+{
4103+ zend_mm_free_block_canary *best_fit;
4104+ size_t true_size = ZEND_MM_TRUE_SIZE(size);
4105+ size_t block_size;
4106+ size_t remaining_size;
4107+ size_t segment_size;
4108+ zend_mm_segment *segment;
4109+ int keep_rest = 0;
4110+
4111+ if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) {
4112+ size_t index = ZEND_MM_BUCKET_INDEX(true_size);
4113+ size_t bitmap;
4114+
4115+ if (UNEXPECTED(true_size < size)) {
4116+ goto out_of_memory;
4117+ }
4118+#if ZEND_MM_CACHE
4119+ if (EXPECTED(heap->cache[index] != NULL)) {
4120+ /* Get block from cache */
4121+#if ZEND_MM_CACHE_STAT
4122+ heap->cache_stat[index].count--;
4123+ heap->cache_stat[index].hit++;
65be62f2 4124+#endif
3f3163a9
AM
4125+ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]);
4126+ heap->cache[index] = best_fit->prev_free_block;
4127+ heap->cached -= true_size;
65be62f2 4128+#if SUHOSIN_PATCH
3f3163a9
AM
4129+ SUHOSIN_MM_SET_CANARIES(best_fit);
4130+ ((zend_mm_block_canary*)best_fit)->info.size = size;
4131+ SUHOSIN_MM_SET_END_CANARY(best_fit);
4132+#endif
4133+ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
4134+ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
4135+ return ZEND_MM_DATA_OF(best_fit);
4136+ }
4137+#if ZEND_MM_CACHE_STAT
4138+ heap->cache_stat[index].miss++;
4139+#endif
65be62f2 4140+#endif
65be62f2 4141+
3f3163a9
AM
4142+ bitmap = heap->free_bitmap >> index;
4143+ if (bitmap) {
4144+ /* Found some "small" free block that can be used */
4145+ index += zend_mm_low_bit(bitmap);
4146+ best_fit = SUHOSIN_MANGLE_PTR(heap->free_buckets[index*2]);
4147+#if ZEND_MM_CACHE_STAT
4148+ heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit++;
4149+#endif
4150+ goto zend_mm_finished_searching_for_block;
4151+ }
65be62f2 4152+ }
3f3163a9
AM
4153+
4154+#if ZEND_MM_CACHE_STAT
4155+ heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss++;
65be62f2 4156+#endif
65be62f2 4157+
3f3163a9
AM
4158+ best_fit = zend_mm_search_large_block(heap, true_size);
4159+
4160+ if (!best_fit && heap->real_size >= heap->limit - heap->block_size) {
4161+ zend_mm_free_block_canary *p = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]);
4162+ size_t best_size = -1;
4163+
4164+ while (p != ZEND_MM_REST_BUCKET(heap)) {
4165+ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
4166+ best_fit = p;
4167+ goto zend_mm_finished_searching_for_block;
4168+ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
4169+ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
4170+ best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
4171+ best_fit = p;
4172+ }
4173+ p = SUHOSIN_MANGLE_PTR(p->prev_free_block);
4174+ }
65be62f2 4175+ }
65be62f2 4176+
3f3163a9
AM
4177+ if (!best_fit) {
4178+ if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
4179+ /* Make sure we add a memory block which is big enough,
4180+ segment must have header "size" and trailer "guard" block */
4181+ segment_size = true_size + ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE;
4182+ segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
4183+ keep_rest = 1;
4184+ } else {
4185+ segment_size = heap->block_size;
4186+ }
4187+
4188+ HANDLE_BLOCK_INTERRUPTIONS();
4189+
4190+ if (segment_size < true_size ||
4191+ heap->real_size + segment_size > heap->limit) {
4192+ /* Memory limit overflow */
4193+#if ZEND_MM_CACHE
4194+ zend_mm_free_cache(heap);
65be62f2 4195+#endif
3f3163a9
AM
4196+ HANDLE_UNBLOCK_INTERRUPTIONS();
4197+#if ZEND_DEBUG
4198+ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %lu bytes)", heap->limit, __zend_filename, __zend_lineno, size);
4199+#else
4200+ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %lu bytes)", heap->limit, size);
4201+#endif
4202+ }
65be62f2 4203+
3f3163a9
AM
4204+ segment = (zend_mm_segment *) ZEND_MM_STORAGE_ALLOC(segment_size);
4205+
4206+ if (!segment) {
4207+ /* Storage manager cannot allocate memory */
4208+#if ZEND_MM_CACHE
4209+ zend_mm_free_cache(heap);
65be62f2 4210+#endif
3f3163a9
AM
4211+ HANDLE_UNBLOCK_INTERRUPTIONS();
4212+out_of_memory:
4213+#if ZEND_DEBUG
4214+ zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
4215+#else
4216+ zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, size);
4217+#endif
4218+ return NULL;
4219+ }
65be62f2 4220+
3f3163a9
AM
4221+ heap->real_size += segment_size;
4222+ if (heap->real_size > heap->real_peak) {
4223+ heap->real_peak = heap->real_size;
4224+ }
65be62f2 4225+
3f3163a9
AM
4226+ segment->size = segment_size;
4227+ segment->next_segment = heap->segments_list;
4228+ heap->segments_list = segment;
4229+
4230+ best_fit = (zend_mm_free_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
4231+ ZEND_MM_MARK_FIRST_BLOCK(best_fit);
4232+
4233+ block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
4234+
4235+ ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(best_fit, block_size));
4236+
4237+ } else {
4238+zend_mm_finished_searching_for_block:
4239+ /* remove from free list */
4240+ HANDLE_BLOCK_INTERRUPTIONS();
4241+ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_FREED);
4242+ ZEND_MM_CHECK_COOKIE(best_fit);
4243+ ZEND_MM_CHECK_BLOCK_LINKAGE(best_fit);
4244+ zend_mm_remove_from_free_list(heap, best_fit);
4245+
4246+ block_size = ZEND_MM_FREE_BLOCK_SIZE(best_fit);
65be62f2 4247+ }
65be62f2 4248+
3f3163a9
AM
4249+ remaining_size = block_size - true_size;
4250+
4251+ if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
4252+ true_size = block_size;
4253+ ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size);
65be62f2 4254+ } else {
3f3163a9 4255+ zend_mm_free_block_canary *new_free_block;
65be62f2 4256+
3f3163a9
AM
4257+ /* prepare new free block */
4258+ ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size);
4259+ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(best_fit, true_size);
4260+ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
4261+
4262+ /* add the new free block to the free list */
4263+ if (EXPECTED(!keep_rest)) {
4264+ zend_mm_add_to_free_list(heap, new_free_block);
4265+ } else {
4266+ zend_mm_add_to_rest_list(heap, new_free_block);
65be62f2
ER
4267+ }
4268+ }
3f3163a9
AM
4269+
4270+ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1);
4271+
4272+#if SUHOSIN_PATCH
4273+ SUHOSIN_MM_SET_CANARIES(best_fit);
4274+ ((zend_mm_block_canary*)best_fit)->info.size = size;
4275+ SUHOSIN_MM_SET_END_CANARY(best_fit);
4276+#endif
4277+
4278+ heap->size += true_size;
4279+ if (heap->peak < heap->size) {
4280+ heap->peak = heap->size;
4281+ }
4282+
4283+ HANDLE_UNBLOCK_INTERRUPTIONS();
4284+ return ZEND_MM_DATA_OF(best_fit);
65be62f2
ER
4285+}
4286+
3f3163a9
AM
4287+
4288+void _zend_mm_free_canary_int(zend_mm_heap_canary *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
65be62f2 4289+{
3f3163a9
AM
4290+ zend_mm_block_canary *mm_block;
4291+ zend_mm_block_canary *next_block;
4292+ size_t size;
65be62f2 4293+
3f3163a9
AM
4294+ if (!ZEND_MM_VALID_PTR(p)) {
4295+ return;
65be62f2 4296+ }
65be62f2 4297+
3f3163a9
AM
4298+ mm_block = ZEND_MM_HEADER_OF(p);
4299+ size = ZEND_MM_BLOCK_SIZE(mm_block);
65be62f2 4300+#if SUHOSIN_PATCH
3f3163a9
AM
4301+ SUHOSIN_MM_CHECK_CANARIES(mm_block, "efree()");
4302+#endif
4303+ ZEND_MM_CHECK_PROTECTION(mm_block);
4304+
4305+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
4306+ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->debug.size);
4307+#endif
65be62f2 4308+#if SUHOSIN_PATCH
3f3163a9
AM
4309+ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_DESTROY_FREE_MEMORY))) {
4310+ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->info.size);
4311+ }
65be62f2 4312+#endif
3f3163a9
AM
4313+#if ZEND_MM_CACHE
4314+ if (EXPECTED(ZEND_MM_SMALL_SIZE(size)) && EXPECTED(heap->cached < ZEND_MM_CACHE_SIZE)) {
4315+ size_t index = ZEND_MM_BUCKET_INDEX(size);
4316+ zend_mm_free_block_canary **cache = &heap->cache[index];
65be62f2 4317+
3f3163a9
AM
4318+ ((zend_mm_free_block_canary*)mm_block)->prev_free_block = *cache;
4319+ *cache = (zend_mm_free_block_canary*)SUHOSIN_MANGLE_PTR(mm_block);
4320+ heap->cached += size;
4321+ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
4322+#if ZEND_MM_CACHE_STAT
4323+ if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
4324+ heap->cache_stat[index].max_count = heap->cache_stat[index].count;
65be62f2 4325+ }
3f3163a9
AM
4326+#endif
4327+ return;
4328+ }
4329+#endif
4330+
4331+ HANDLE_BLOCK_INTERRUPTIONS();
4332+
4333+ heap->size -= size;
4334+
4335+ next_block = ZEND_MM_BLOCK_AT(mm_block, size);
4336+ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
4337+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
4338+ size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
4339+ }
4340+ if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) {
4341+ mm_block = ZEND_MM_PREV_BLOCK(mm_block);
4342+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) mm_block);
4343+ size += ZEND_MM_FREE_BLOCK_SIZE(mm_block);
4344+ }
4345+ if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
4346+ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(mm_block, size))) {
4347+ zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE));
4348+ } else {
4349+ ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size);
4350+ zend_mm_add_to_free_list(heap, (zend_mm_free_block_canary *) mm_block);
4351+ }
4352+ HANDLE_UNBLOCK_INTERRUPTIONS();
4353+}
4354+
4355+void *_zend_mm_realloc_canary_int(zend_mm_heap_canary *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
4356+{
4357+ zend_mm_block_canary *mm_block = ZEND_MM_HEADER_OF(p);
4358+ zend_mm_block_canary *next_block;
4359+ size_t true_size;
4360+ size_t orig_size;
4361+ void *ptr;
4362+
4363+ if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) {
4364+ return _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
65be62f2 4365+ }
3f3163a9
AM
4366+ mm_block = ZEND_MM_HEADER_OF(p);
4367+ true_size = ZEND_MM_TRUE_SIZE(size);
4368+ orig_size = ZEND_MM_BLOCK_SIZE(mm_block);
4369+#if SUHOSIN_PATCH
4370+ SUHOSIN_MM_CHECK_CANARIES(mm_block, "erealloc()");
65be62f2 4371+#endif
3f3163a9 4372+ ZEND_MM_CHECK_PROTECTION(mm_block);
65be62f2 4373+
3f3163a9
AM
4374+ if (UNEXPECTED(true_size < size)) {
4375+ goto out_of_memory;
4376+ }
4377+
4378+ if (true_size <= orig_size) {
4379+ size_t remaining_size = orig_size - true_size;
4380+
4381+ if (remaining_size >= ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
4382+ zend_mm_free_block_canary *new_free_block;
4383+
4384+ HANDLE_BLOCK_INTERRUPTIONS();
4385+ next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
4386+ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
4387+ remaining_size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
4388+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
65be62f2 4389+ }
65be62f2 4390+
3f3163a9
AM
4391+ /* prepare new free block */
4392+ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
4393+ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(mm_block, true_size);
4394+
4395+ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
4396+
4397+ /* add the new free block to the free list */
4398+ zend_mm_add_to_free_list(heap, new_free_block);
4399+ heap->size += (true_size - orig_size);
4400+ HANDLE_UNBLOCK_INTERRUPTIONS();
4401+ }
4402+ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
65be62f2 4403+#if SUHOSIN_PATCH
3f3163a9
AM
4404+ SUHOSIN_MM_SET_CANARIES(mm_block);
4405+ ((zend_mm_block_canary*)mm_block)->info.size = size;
4406+ SUHOSIN_MM_SET_END_CANARY(mm_block);
65be62f2 4407+#endif
3f3163a9
AM
4408+ return p;
4409+ }
4410+
4411+#if ZEND_MM_CACHE
4412+ if (ZEND_MM_SMALL_SIZE(true_size)) {
4413+ size_t index = ZEND_MM_BUCKET_INDEX(true_size);
4414+
4415+ if (heap->cache[index] != NULL) {
4416+ zend_mm_free_block_canary *best_fit;
4417+ zend_mm_free_block_canary **cache;
4418+
4419+#if ZEND_MM_CACHE_STAT
4420+ heap->cache_stat[index].count--;
4421+ heap->cache_stat[index].hit++;
4422+#endif
4423+ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]);
4424+ heap->cache[index] = best_fit->prev_free_block;
4425+ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
4426+ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
65be62f2 4427+#if SUHOSIN_PATCH
3f3163a9
AM
4428+ SUHOSIN_MM_SET_CANARIES(best_fit);
4429+ ((zend_mm_block_canary*)best_fit)->info.size = size;
4430+ SUHOSIN_MM_SET_END_CANARY(best_fit);
65be62f2
ER
4431+#endif
4432+
3f3163a9
AM
4433+ ptr = ZEND_MM_DATA_OF(best_fit);
4434+
4435+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
4436+ memcpy(ptr, p, mm_block->debug.size);
4437+#else
4438+ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE);
65be62f2
ER
4439+#endif
4440+
3f3163a9
AM
4441+ heap->cached -= true_size - orig_size;
4442+
4443+ index = ZEND_MM_BUCKET_INDEX(orig_size);
4444+ cache = &heap->cache[index];
4445+
4446+ ((zend_mm_free_block_canary*)mm_block)->prev_free_block = *cache;
4447+ *cache = (zend_mm_free_block_canary*)SUHOSIN_MANGLE_PTR(mm_block);
4448+ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
4449+#if ZEND_MM_CACHE_STAT
4450+ if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
4451+ heap->cache_stat[index].max_count = heap->cache_stat[index].count;
4452+ }
4453+#endif
4454+ return ptr;
4455+ }
4456+ }
65be62f2
ER
4457+#endif
4458+
3f3163a9 4459+ next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
65be62f2 4460+
3f3163a9
AM
4461+ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
4462+ ZEND_MM_CHECK_COOKIE(next_block);
4463+ ZEND_MM_CHECK_BLOCK_LINKAGE(next_block);
4464+ if (orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block) >= true_size) {
4465+ size_t block_size = orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block);
4466+ size_t remaining_size = block_size - true_size;
4467+
4468+ HANDLE_BLOCK_INTERRUPTIONS();
4469+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
4470+
4471+ if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
4472+ true_size = block_size;
4473+ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
4474+ } else {
4475+ zend_mm_free_block_canary *new_free_block;
4476+
4477+ /* prepare new free block */
4478+ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
4479+ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(mm_block, true_size);
4480+ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
4481+
4482+ /* add the new free block to the free list */
4483+ if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
4484+ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(new_free_block, remaining_size))) {
4485+ zend_mm_add_to_rest_list(heap, new_free_block);
4486+ } else {
4487+ zend_mm_add_to_free_list(heap, new_free_block);
4488+ }
4489+ }
4490+ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
4491+ heap->size = heap->size + true_size - orig_size;
4492+ if (heap->peak < heap->size) {
4493+ heap->peak = heap->size;
4494+ }
4495+ HANDLE_UNBLOCK_INTERRUPTIONS();
65be62f2 4496+#if SUHOSIN_PATCH
3f3163a9
AM
4497+ SUHOSIN_MM_SET_CANARIES(mm_block);
4498+ ((zend_mm_block_canary*)mm_block)->info.size = size;
4499+ SUHOSIN_MM_SET_END_CANARY(mm_block);
65be62f2 4500+#endif
3f3163a9
AM
4501+ return p;
4502+ } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
4503+ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) {
4504+ HANDLE_BLOCK_INTERRUPTIONS();
4505+ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block);
4506+ goto realloc_segment;
4507+ }
4508+ } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ZEND_MM_IS_GUARD_BLOCK(next_block)) {
4509+ zend_mm_segment *segment;
4510+ zend_mm_segment *segment_copy;
4511+ size_t segment_size;
4512+ size_t block_size;
4513+ size_t remaining_size;
65be62f2 4514+
3f3163a9
AM
4515+ HANDLE_BLOCK_INTERRUPTIONS();
4516+realloc_segment:
4517+ /* segment size, size of block and size of guard block */
4518+ if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
4519+ segment_size = true_size+ZEND_MM_ALIGNED_SEGMENT_SIZE+ZEND_MM_ALIGNED_HEADER_SIZE;
4520+ segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
4521+ } else {
4522+ segment_size = heap->block_size;
4523+ }
4524+
4525+ segment_copy = (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE);
4526+ if (segment_size < true_size ||
4527+ heap->real_size + segment_size - segment_copy->size > heap->limit) {
4528+ if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
4529+ zend_mm_add_to_free_list(heap, (zend_mm_free_block_canary *) next_block);
4530+ }
4531+#if ZEND_MM_CACHE
4532+ zend_mm_free_cache(heap);
65be62f2 4533+#endif
3f3163a9
AM
4534+ HANDLE_UNBLOCK_INTERRUPTIONS();
4535+#if ZEND_DEBUG
4536+ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %ld bytes)", heap->limit, __zend_filename, __zend_lineno, size);
65be62f2 4537+#else
3f3163a9 4538+ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %ld bytes)", heap->limit, size);
65be62f2 4539+#endif
3f3163a9
AM
4540+ return NULL;
4541+ }
4542+
4543+ segment = ZEND_MM_STORAGE_REALLOC(segment_copy, segment_size);
4544+ if (!segment) {
4545+#if ZEND_MM_CACHE
4546+ zend_mm_free_cache(heap);
4547+#endif
4548+ HANDLE_UNBLOCK_INTERRUPTIONS();
4549+out_of_memory:
4550+#if ZEND_DEBUG
4551+ zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %ld bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
65be62f2 4552+#else
3f3163a9 4553+ zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %ld bytes)", heap->real_size, size);
65be62f2 4554+#endif
3f3163a9
AM
4555+ return NULL;
4556+ }
4557+ heap->real_size += segment_size - segment->size;
4558+ if (heap->real_size > heap->real_peak) {
4559+ heap->real_peak = heap->real_size;
4560+ }
4561+
4562+ segment->size = segment_size;
4563+
4564+ if (segment != segment_copy) {
4565+ zend_mm_segment **seg = &heap->segments_list;
4566+ while (*seg != segment_copy) {
4567+ seg = &(*seg)->next_segment;
4568+ }
4569+ *seg = segment;
4570+ mm_block = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
4571+ ZEND_MM_MARK_FIRST_BLOCK(mm_block);
4572+ }
4573+
4574+ block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
4575+ remaining_size = block_size - true_size;
4576+
4577+ /* setup guard block */
4578+ ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(mm_block, block_size));
4579+
4580+ if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
4581+ true_size = block_size;
4582+ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
4583+ } else {
4584+ zend_mm_free_block_canary *new_free_block;
4585+
4586+ /* prepare new free block */
4587+ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
4588+ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(mm_block, true_size);
4589+ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
4590+
4591+ /* add the new free block to the free list */
4592+ zend_mm_add_to_rest_list(heap, new_free_block);
4593+ }
4594+
4595+ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 1, 1);
4596+
4597+ heap->size = heap->size + true_size - orig_size;
4598+ if (heap->peak < heap->size) {
4599+ heap->peak = heap->size;
4600+ }
4601+
4602+ HANDLE_UNBLOCK_INTERRUPTIONS();
4603+#if SUHOSIN_PATCH
4604+ SUHOSIN_MM_SET_CANARIES(mm_block);
4605+ ((zend_mm_block_canary*)mm_block)->info.size = size;
4606+ SUHOSIN_MM_SET_END_CANARY(mm_block);
4607+#endif
4608+ return ZEND_MM_DATA_OF(mm_block);
4609+ }
65be62f2 4610+
3f3163a9
AM
4611+ ptr = _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
4612+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
4613+ memcpy(ptr, p, mm_block->debug.size);
4614+#else
4615+ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE);
4616+#endif
4617+ _zend_mm_free_canary_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
4618+ return ptr;
4619+}
65be62f2 4620+
3f3163a9
AM
4621+ZEND_API size_t _zend_mm_block_size_canary(zend_mm_heap_canary *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
4622+{
4623+ zend_mm_block_canary *mm_block;
65be62f2 4624+
3f3163a9
AM
4625+ if (!ZEND_MM_VALID_PTR(p)) {
4626+ return 0;
4627+ }
4628+ mm_block = ZEND_MM_HEADER_OF(p);
4629+ ZEND_MM_CHECK_PROTECTION(mm_block);
4630+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
4631+ return mm_block->debug.size;
65be62f2 4632+#else
3f3163a9 4633+ return ZEND_MM_BLOCK_SIZE(mm_block);
65be62f2 4634+#endif
3f3163a9 4635+}
65be62f2 4636+
3f3163a9 4637+#if defined(__GNUC__) && defined(i386)
65be62f2 4638+
3f3163a9
AM
4639+static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
4640+{
4641+ size_t res = nmemb;
4642+ unsigned long overflow = 0;
4643+
4644+ __asm__ ("mull %3\n\taddl %4,%0\n\tadcl %1,%1"
4645+ : "=&a"(res), "=&d" (overflow)
4646+ : "%0"(res),
4647+ "rm"(size),
4648+ "rm"(offset));
65be62f2 4649+
3f3163a9
AM
4650+ if (UNEXPECTED(overflow)) {
4651+ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
4652+ return 0;
4653+ }
4654+ return res;
4655+}
65be62f2 4656+
3f3163a9 4657+#elif defined(__GNUC__) && defined(__x86_64__)
65be62f2 4658+
3f3163a9
AM
4659+static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
4660+{
4661+ size_t res = nmemb;
4662+ unsigned long overflow = 0;
65be62f2 4663+
3f3163a9
AM
4664+ __asm__ ("mulq %3\n\taddq %4,%0\n\tadcq %1,%1"
4665+ : "=&a"(res), "=&d" (overflow)
4666+ : "%0"(res),
4667+ "rm"(size),
4668+ "rm"(offset));
4669+
4670+ if (UNEXPECTED(overflow)) {
4671+ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
4672+ return 0;
4673+ }
4674+ return res;
4675+}
4676+
4677+#elif SIZEOF_SIZE_T == 4 && defined(HAVE_ZEND_LONG64)
4678+
4679+static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
4680+{
4681+ zend_ulong64 res = (zend_ulong64)nmemb * (zend_ulong64)size + (zend_ulong64)offset;
4682+
4683+ if (UNEXPECTED(res > (zend_ulong64)0xFFFFFFFFL)) {
4684+ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
4685+ return 0;
4686+ }
4687+ return (size_t) res;
4688+}
4689+
4690+#else
4691+
4692+static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
4693+{
4694+ size_t res = nmemb * size + offset;
4695+ double _d = (double)nmemb * (double)size + (double)offset;
4696+ double _delta = (double)res - _d;
4697+
4698+ if (UNEXPECTED((_d + _delta ) != _d)) {
4699+ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
4700+ return 0;
4701+ }
4702+ return res;
4703+}
4704+#endif
4705+
4706+/*
4707+ * Local variables:
4708+ * tab-width: 4
4709+ * c-basic-offset: 4
4710+ * indent-tabs-mode: t
4711+ * End:
4712+ */
4713+
4714diff -Naurp php-5.3.6RC1/Zend/zend_alloc.h php-5.3.6RC1.oden/Zend/zend_alloc.h
4715--- php-5.3.6RC1/Zend/zend_alloc.h 2011-01-01 03:19:59.000000000 +0100
4716+++ php-5.3.6RC1.oden/Zend/zend_alloc.h 2011-02-20 11:50:19.320838976 +0100
4717@@ -203,6 +203,8 @@ END_EXTERN_C()
4718
4719 /* Heap functions */
4720 typedef struct _zend_mm_heap zend_mm_heap;
4721+typedef struct _zend_mm_heap_canary zend_mm_heap_canary;
4722+
4723
4724 ZEND_API zend_mm_heap *zend_mm_startup(void);
4725 ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC);
4726diff -Naurp php-5.3.6RC1/Zend/zend.c php-5.3.6RC1.oden/Zend/zend.c
4727--- php-5.3.6RC1/Zend/zend.c 2011-01-01 03:19:59.000000000 +0100
4728+++ php-5.3.6RC1.oden/Zend/zend.c 2011-02-20 11:50:19.321839116 +0100
4729@@ -60,6 +60,10 @@ int (*zend_vspprintf)(char **pbuf, size_
4730 ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
4731 ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);
4732
4733+#if SUHOSIN_PATCH
4734+ZEND_API void (*zend_suhosin_log)(int loglevel, char *fmt, ...);
4735+#endif
4736+
4737 void (*zend_on_timeout)(int seconds TSRMLS_DC);
4738
4739 static void (*zend_message_dispatcher_p)(long message, void *data TSRMLS_DC);
4740@@ -88,6 +92,74 @@ static ZEND_INI_MH(OnUpdateGCEnabled) /*
4741 }
4742 /* }}} */
4743
4744+#if SUHOSIN_PATCH
4745+static ZEND_INI_MH(OnUpdateSuhosin_log_syslog)
4746+{
4747+ if (!new_value) {
4748+ SPG(log_syslog) = S_ALL & ~S_SQL | S_MEMORY;
4749+ } else {
4750+ SPG(log_syslog) = atoi(new_value) | S_MEMORY;
4751+ }
4752+ return SUCCESS;
4753+}
4754+static ZEND_INI_MH(OnUpdateSuhosin_log_syslog_facility)
4755+{
4756+ if (!new_value) {
4757+ SPG(log_syslog_facility) = LOG_USER;
4758+ } else {
4759+ SPG(log_syslog_facility) = atoi(new_value);
4760+ }
4761+ return SUCCESS;
4762+}
4763+static ZEND_INI_MH(OnUpdateSuhosin_log_syslog_priority)
4764+{
4765+ if (!new_value) {
4766+ SPG(log_syslog_priority) = LOG_ALERT;
4767+ } else {
4768+ SPG(log_syslog_priority) = atoi(new_value);
4769+ }
4770+ return SUCCESS;
4771+}
4772+static ZEND_INI_MH(OnUpdateSuhosin_log_sapi)
4773+{
4774+ if (!new_value) {
4775+ SPG(log_sapi) = S_ALL & ~S_SQL;
4776+ } else {
4777+ SPG(log_sapi) = atoi(new_value);
4778+ }
4779+ return SUCCESS;
4780+}
4781+static ZEND_INI_MH(OnUpdateSuhosin_log_script)
4782+{
4783+ if (!new_value) {
4784+ SPG(log_script) = S_ALL & ~S_MEMORY;
4785+ } else {
4786+ SPG(log_script) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL);
4787+ }
4788+ return SUCCESS;
4789+}
4790+static ZEND_INI_MH(OnUpdateSuhosin_log_scriptname)
4791+{
4792+ if (SPG(log_scriptname)) {
4793+ pefree(SPG(log_scriptname),1);
4794+ }
4795+ SPG(log_scriptname) = NULL;
4796+ if (new_value) {
4797+ SPG(log_scriptname) = pestrdup(new_value,1);
4798+ }
4799+ return SUCCESS;
4800+}
4801+static ZEND_INI_MH(OnUpdateSuhosin_log_phpscript)
4802+{
4803+ if (!new_value) {
4804+ SPG(log_phpscript) = S_ALL & ~S_MEMORY;
4805+ } else {
4806+ SPG(log_phpscript) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL);
4807+ }
4808+ return SUCCESS;
4809+}
4810+#endif
4811+
4812 ZEND_INI_BEGIN()
4813 ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
4814 STD_ZEND_INI_BOOLEAN("zend.enable_gc", "1", ZEND_INI_ALL, OnUpdateGCEnabled, gc_enabled, zend_gc_globals, gc_globals)
4815diff -Naurp php-5.3.6RC1/Zend/zend_canary.c php-5.3.6RC1.oden/Zend/zend_canary.c
4816--- php-5.3.6RC1/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100
4817+++ php-5.3.6RC1.oden/Zend/zend_canary.c 2011-02-20 11:50:19.322839257 +0100
4818@@ -0,0 +1,66 @@
65be62f2
ER
4819+/*
4820+ +----------------------------------------------------------------------+
3f3163a9 4821+ | Suhosin-Patch for PHP |
65be62f2 4822+ +----------------------------------------------------------------------+
3f3163a9 4823+ | Copyright (c) 2004-2009 Stefan Esser |
65be62f2
ER
4824+ +----------------------------------------------------------------------+
4825+ | This source file is subject to version 2.02 of the PHP license, |
4826+ | that is bundled with this package in the file LICENSE, and is |
4827+ | available at through the world-wide-web at |
4828+ | http://www.php.net/license/2_02.txt. |
4829+ | If you did not receive a copy of the PHP license and are unable to |
4830+ | obtain it through the world-wide-web, please send a note to |
4831+ | license@php.net so we can mail you a copy immediately. |
4832+ +----------------------------------------------------------------------+
3f3163a9 4833+ | Author: Stefan Esser <stefan.esser@sektioneins.de> |
65be62f2
ER
4834+ +----------------------------------------------------------------------+
4835+ */
4836+/* $Id$ */
4837+
3f3163a9 4838+#include "zend.h"
65be62f2
ER
4839+
4840+#include <stdio.h>
4841+#include <stdlib.h>
4842+
65be62f2
ER
4843+
4844+#if SUHOSIN_PATCH
4845+
3f3163a9
AM
4846+static size_t last_canary = 0x73625123;
4847+
4848+/* will be replaced later with more compatible method */
4849+ZEND_API void zend_canary(void *buf, int len)
4850+{
4851+ time_t t;
4852+ size_t canary;
4853+ int fd;
4854+
4855+#ifndef PHP_WIN32
4856+ fd = open("/dev/urandom", 0);
4857+ if (fd != -1) {
4858+ int r = read(fd, buf, len);
4859+ close(fd);
4860+ if (r == len) {
4861+ return;
4862+ }
4863+ }
4864+#endif
4865+ /* not good but we never want to do this */
4866+ time(&t);
4867+ canary = *(unsigned int *)&t + getpid() << 16 + last_canary;
4868+ last_canary ^= (canary << 5) | (canary >> (32-5));
4869+ /* When we ensure full win32 compatibility in next version
4870+ we will replace this with the random number code from zend_alloc.c */
4871+ memcpy(buf, &canary, len);
4872+}
4873+
65be62f2
ER
4874+#endif
4875+
3f3163a9
AM
4876+
4877+/*
4878+ * Local variables:
4879+ * tab-width: 4
4880+ * c-basic-offset: 4
4881+ * End:
4882+ * vim600: sw=4 ts=4 fdm=marker
4883+ * vim<600: sw=4 ts=4
4884+ */
4885diff -Naurp php-5.3.6RC1/Zend/zend_compile.c php-5.3.6RC1.oden/Zend/zend_compile.c
4886--- php-5.3.6RC1/Zend/zend_compile.c 2011-01-19 18:17:52.000000000 +0100
4887+++ php-5.3.6RC1.oden/Zend/zend_compile.c 2011-02-20 11:50:19.323839398 +0100
4888@@ -73,6 +73,11 @@ static void zend_destroy_property_info_i
4889 }
4890 /* }}} */
4891
4892+#if SUHOSIN_PATCH
4893+void *suhosin_zend_destroy_property_info_internal = zend_destroy_property_info_internal;
4894+void *suhosin_zend_destroy_property_info = zend_destroy_property_info;
65be62f2
ER
4895+#endif
4896+
3f3163a9
AM
4897 static void build_runtime_defined_function_key(zval *result, const char *name, int name_length TSRMLS_DC) /* {{{ */
4898 {
4899 char char_pos_buf[32];
4900diff -Naurp php-5.3.6RC1/Zend/zend_compile.h php-5.3.6RC1.oden/Zend/zend_compile.h
4901--- php-5.3.6RC1/Zend/zend_compile.h 2011-01-01 03:19:59.000000000 +0100
4902+++ php-5.3.6RC1.oden/Zend/zend_compile.h 2011-02-20 11:50:19.324839539 +0100
4903@@ -606,6 +606,11 @@ ZEND_API zend_bool zend_is_auto_global(c
4904 ZEND_API int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC);
4905 ZEND_API size_t zend_dirname(char *path, size_t len);
4906
4907+#if SUHOSIN_PATCH
4908+extern void *suhosin_zend_destroy_property_info_internal;
4909+extern void *suhosin_zend_destroy_property_info;
65be62f2
ER
4910+#endif
4911+
3f3163a9
AM
4912 int zendlex(znode *zendlval TSRMLS_DC);
4913
4914 /* BEGIN: OPCODES */
4915diff -Naurp php-5.3.6RC1/Zend/zend_constants.c php-5.3.6RC1.oden/Zend/zend_constants.c
4916--- php-5.3.6RC1/Zend/zend_constants.c 2011-01-16 21:39:22.000000000 +0100
4917+++ php-5.3.6RC1.oden/Zend/zend_constants.c 2011-02-20 11:52:28.887065479 +0100
4918@@ -115,6 +115,77 @@ void zend_register_standard_constants(TS
4919
4920 REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS);
4921 REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS);
65be62f2 4922+
3f3163a9
AM
4923+#if SUHOSIN_PATCH
4924+ REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS);
4925+ REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS);
4926+ REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_FILES, CONST_PERSISTENT | CONST_CS);
4927+ REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS);
4928+ REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS);
4929+ REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS);
4930+ REGISTER_MAIN_LONG_CONSTANT("S_MAIL", S_MAIL, CONST_PERSISTENT | CONST_CS);
4931+ REGISTER_MAIN_LONG_CONSTANT("S_SESSION", S_SESSION, CONST_PERSISTENT | CONST_CS);
4932+ REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS);
4933+ REGISTER_MAIN_LONG_CONSTANT("S_INTERNAL", S_INTERNAL, CONST_PERSISTENT | CONST_CS);
4934+ REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS);
4935+
4936+ /* error levels */
4937+ REGISTER_MAIN_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
4938+ REGISTER_MAIN_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
4939+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRIT", LOG_CRIT, CONST_CS | CONST_PERSISTENT); /* critical conditions */
4940+ REGISTER_MAIN_LONG_CONSTANT("LOG_ERR", LOG_ERR, CONST_CS | CONST_PERSISTENT);
4941+ REGISTER_MAIN_LONG_CONSTANT("LOG_WARNING", LOG_WARNING, CONST_CS | CONST_PERSISTENT);
4942+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOTICE", LOG_NOTICE, CONST_CS | CONST_PERSISTENT);
4943+ REGISTER_MAIN_LONG_CONSTANT("LOG_INFO", LOG_INFO, CONST_CS | CONST_PERSISTENT);
4944+ REGISTER_MAIN_LONG_CONSTANT("LOG_DEBUG", LOG_DEBUG, CONST_CS | CONST_PERSISTENT);
4945+ /* facility: type of program logging the message */
4946+ REGISTER_MAIN_LONG_CONSTANT("LOG_KERN", LOG_KERN, CONST_CS | CONST_PERSISTENT);
4947+ REGISTER_MAIN_LONG_CONSTANT("LOG_USER", LOG_USER, CONST_CS | CONST_PERSISTENT); /* generic user level */
4948+ REGISTER_MAIN_LONG_CONSTANT("LOG_MAIL", LOG_MAIL, CONST_CS | CONST_PERSISTENT); /* log to email */
4949+ REGISTER_MAIN_LONG_CONSTANT("LOG_DAEMON", LOG_DAEMON, CONST_CS | CONST_PERSISTENT); /* other system daemons */
4950+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTH", LOG_AUTH, CONST_CS | CONST_PERSISTENT);
4951+ REGISTER_MAIN_LONG_CONSTANT("LOG_SYSLOG", LOG_SYSLOG, CONST_CS | CONST_PERSISTENT);
4952+ REGISTER_MAIN_LONG_CONSTANT("LOG_LPR", LOG_LPR, CONST_CS | CONST_PERSISTENT);
4953+#ifdef LOG_NEWS
4954+ /* No LOG_NEWS on HP-UX */
4955+ REGISTER_MAIN_LONG_CONSTANT("LOG_NEWS", LOG_NEWS, CONST_CS | CONST_PERSISTENT); /* usenet new */
4956+#endif
4957+#ifdef LOG_UUCP
4958+ /* No LOG_UUCP on HP-UX */
4959+ REGISTER_MAIN_LONG_CONSTANT("LOG_UUCP", LOG_UUCP, CONST_CS | CONST_PERSISTENT);
4960+#endif
4961+#ifdef LOG_CRON
4962+ /* apparently some systems don't have this one */
4963+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRON", LOG_CRON, CONST_CS | CONST_PERSISTENT);
4964+#endif
4965+#ifdef LOG_AUTHPRIV
4966+ /* AIX doesn't have LOG_AUTHPRIV */
4967+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT);
65be62f2 4968+#endif
3f3163a9
AM
4969+#ifndef PHP_WIN32
4970+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT);
4971+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT);
4972+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT);
4973+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL3", LOG_LOCAL3, CONST_CS | CONST_PERSISTENT);
4974+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL4", LOG_LOCAL4, CONST_CS | CONST_PERSISTENT);
4975+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL5", LOG_LOCAL5, CONST_CS | CONST_PERSISTENT);
4976+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL6", LOG_LOCAL6, CONST_CS | CONST_PERSISTENT);
4977+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL7", LOG_LOCAL7, CONST_CS | CONST_PERSISTENT);
65be62f2 4978+#endif
3f3163a9
AM
4979+ /* options */
4980+ REGISTER_MAIN_LONG_CONSTANT("LOG_PID", LOG_PID, CONST_CS | CONST_PERSISTENT);
4981+ REGISTER_MAIN_LONG_CONSTANT("LOG_CONS", LOG_CONS, CONST_CS | CONST_PERSISTENT);
4982+ REGISTER_MAIN_LONG_CONSTANT("LOG_ODELAY", LOG_ODELAY, CONST_CS | CONST_PERSISTENT);
4983+ REGISTER_MAIN_LONG_CONSTANT("LOG_NDELAY", LOG_NDELAY, CONST_CS | CONST_PERSISTENT);
4984+#ifdef LOG_NOWAIT
4985+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOWAIT", LOG_NOWAIT, CONST_CS | CONST_PERSISTENT);
65be62f2 4986+#endif
3f3163a9
AM
4987+#ifdef LOG_PERROR
4988+ /* AIX doesn't have LOG_PERROR */
4989+ REGISTER_MAIN_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
65be62f2 4990+#endif
65be62f2 4991+#endif
65be62f2 4992+
3f3163a9
AM
4993 /* true/false constants */
4994 {
4995 zend_constant c;
4996diff -Naurp php-5.3.6RC1/Zend/zend_errors.h php-5.3.6RC1.oden/Zend/zend_errors.h
4997--- php-5.3.6RC1/Zend/zend_errors.h 2011-01-01 03:19:59.000000000 +0100
4998+++ php-5.3.6RC1.oden/Zend/zend_errors.h 2011-02-20 11:50:19.326839821 +0100
4999@@ -41,6 +41,20 @@
5000 #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_RECOVERABLE_ERROR | E_DEPRECATED | E_USER_DEPRECATED)
5001 #define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
5002
5003+#if SUHOSIN_PATCH
5004+#define S_MEMORY (1<<0L)
5005+#define S_MISC (1<<1L)
5006+#define S_VARS (1<<2L)
5007+#define S_FILES (1<<3L)
5008+#define S_INCLUDE (1<<4L)
5009+#define S_SQL (1<<5L)
5010+#define S_EXECUTOR (1<<6L)
5011+#define S_MAIL (1<<7L)
5012+#define S_SESSION (1<<8L)
5013+#define S_INTERNAL (1<<29L)
5014+#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MAIL | S_SESSION | S_MISC | S_SQL | S_EXECUTOR)
65be62f2 5015+#endif
65be62f2 5016+
3f3163a9
AM
5017 #endif /* ZEND_ERRORS_H */
5018
5019 /*
5020diff -Naurp php-5.3.6RC1/Zend/zend.h php-5.3.6RC1.oden/Zend/zend.h
5021--- php-5.3.6RC1/Zend/zend.h 2011-02-20 11:45:04.146488357 +0100
5022+++ php-5.3.6RC1.oden/Zend/zend.h 2011-02-20 11:50:19.327839962 +0100
5023@@ -627,6 +627,9 @@ extern ZEND_API int (*zend_stream_open_f
5024 extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
5025 extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
5026 extern ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);
5027+#if SUHOSIN_PATCH
5028+extern ZEND_API void (*zend_suhosin_log)(int loglevel, char *fmt, ...);
65be62f2 5029+#endif
3f3163a9
AM
5030
5031 ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
5032
5033@@ -774,6 +777,16 @@ ZEND_API void zend_restore_error_handlin
5034 #define DEBUG_BACKTRACE_PROVIDE_OBJECT (1<<0)
5035 #define DEBUG_BACKTRACE_IGNORE_ARGS (1<<1)
5036
5037+#if SUHOSIN_PATCH
5038+#include "suhosin_globals.h"
5039+#include "suhosin_patch.h"
5040+#include "php_syslog.h"
65be62f2 5041+
3f3163a9
AM
5042+ZEND_API void zend_canary(void *buf, int len);
5043+ZEND_API char suhosin_get_config(int element);
65be62f2 5044+
65be62f2 5045+#endif
65be62f2 5046+
3f3163a9
AM
5047 #endif /* ZEND_H */
5048
5049 /*
5050diff -Naurp php-5.3.6RC1/Zend/zend_hash.c php-5.3.6RC1.oden/Zend/zend_hash.c
5051--- php-5.3.6RC1/Zend/zend_hash.c 2011-01-01 03:19:59.000000000 +0100
5052+++ php-5.3.6RC1.oden/Zend/zend_hash.c 2011-02-20 11:50:19.328840102 +0100
5053@@ -20,6 +20,7 @@
5054 /* $Id$ */
5055
5056 #include "zend.h"
5057+#include "zend_compile.h"
5058
5059 #define CONNECT_TO_BUCKET_DLLIST(element, list_head) \
5060 (element)->pNext = (list_head); \
5061@@ -136,6 +137,199 @@ ZEND_API ulong zend_hash_func(const char
5062 }
5063
5064
5065+#if SUHOSIN_PATCH
5066+#ifdef ZTS
5067+static MUTEX_T zend_hash_dprot_mx_reader;
5068+static MUTEX_T zend_hash_dprot_mx_writer;
5069+static unsigned int zend_hash_dprot_reader;
5070+#endif
5071+static unsigned int zend_hash_dprot_counter;
5072+static unsigned int zend_hash_dprot_curmax;
5073+static dtor_func_t *zend_hash_dprot_table = NULL;
65be62f2 5074+
3f3163a9
AM
5075+static void zend_hash_dprot_begin_read()
5076+{
5077+#ifdef ZTS
5078+ tsrm_mutex_lock(zend_hash_dprot_mx_reader);
5079+ if ((++(zend_hash_dprot_reader)) == 1) {
5080+ tsrm_mutex_lock(zend_hash_dprot_mx_writer);
65be62f2 5081+ }
3f3163a9 5082+ tsrm_mutex_unlock(zend_hash_dprot_mx_reader);
65be62f2 5083+#endif
3f3163a9 5084+}
65be62f2 5085+
3f3163a9
AM
5086+static void zend_hash_dprot_end_read()
5087+{
5088+#ifdef ZTS
5089+ tsrm_mutex_lock(zend_hash_dprot_mx_reader);
5090+ if ((--(zend_hash_dprot_reader)) == 0) {
5091+ tsrm_mutex_unlock(zend_hash_dprot_mx_writer);
65be62f2 5092+ }
3f3163a9
AM
5093+ tsrm_mutex_unlock(zend_hash_dprot_mx_reader);
5094+#endif
5095+}
5096+
5097+static void zend_hash_dprot_begin_write()
5098+{
5099+#ifdef ZTS
5100+ tsrm_mutex_lock(zend_hash_dprot_mx_writer);
5101+#endif
5102+}
5103+
5104+static void zend_hash_dprot_end_write()
5105+{
5106+#ifdef ZTS
5107+ tsrm_mutex_unlock(zend_hash_dprot_mx_writer);
5108+#endif
5109+}
5110+
5111+/*ZEND_API void zend_hash_dprot_dtor()
5112+{
5113+#ifdef ZTS
5114+ tsrm_mutex_free(zend_hash_dprot_mx_reader);
5115+ tsrm_mutex_free(zend_hash_dprot_mx_writer);
5116+#endif
5117+ free(zend_hash_dprot_table);
5118+}*/
5119+
5120+static void zend_hash_add_destructor(dtor_func_t pDestructor)
5121+{
5122+ int left, right, mid;
5123+ zend_bool found = 0;
5124+ unsigned long value;
5125+
5126+ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR || pDestructor == ZVAL_INTERNAL_PTR_DTOR
5127+ || pDestructor == ZEND_FUNCTION_DTOR || pDestructor == ZEND_CLASS_DTOR) {
5128+ return;
65be62f2 5129+ }
65be62f2 5130+
3f3163a9
AM
5131+ if (zend_hash_dprot_table == NULL) {
5132+#ifdef ZTS
5133+ zend_hash_dprot_mx_reader = tsrm_mutex_alloc();
5134+ zend_hash_dprot_mx_writer = tsrm_mutex_alloc();
5135+ zend_hash_dprot_reader = 0;
5136+#endif
5137+ zend_hash_dprot_counter = 0;
5138+ zend_hash_dprot_curmax = 256;
5139+ zend_hash_dprot_table = (dtor_func_t *) malloc(256 * sizeof(dtor_func_t));
65be62f2 5140+ }
3f3163a9
AM
5141+
5142+ zend_hash_dprot_begin_write();
65be62f2 5143+
3f3163a9
AM
5144+ if (zend_hash_dprot_counter == 0) {
5145+ zend_hash_dprot_counter++;
5146+ zend_hash_dprot_table[0] = pDestructor;
5147+ } else {
5148+ value = (unsigned long) pDestructor;
5149+ left = 0;
5150+ right = zend_hash_dprot_counter-1;
5151+ mid = 0;
65be62f2 5152+
3f3163a9
AM
5153+ while (left < right) {
5154+ mid = (right - left) >> 1;
5155+ mid += left;
5156+ if ((unsigned long)zend_hash_dprot_table[mid] == value) {
5157+ found = 1;
5158+ break;
5159+ }
5160+ if (value < (unsigned long)zend_hash_dprot_table[mid]) {
5161+ right = mid-1;
65be62f2 5162+ } else {
3f3163a9 5163+ left = mid+1;
65be62f2
ER
5164+ }
5165+ }
3f3163a9
AM
5166+ if ((unsigned long)zend_hash_dprot_table[left] == value) {
5167+ found = 1;
65be62f2 5168+ }
65be62f2 5169+
3f3163a9 5170+ if (!found) {
65be62f2 5171+
3f3163a9
AM
5172+ if (zend_hash_dprot_counter >= zend_hash_dprot_curmax) {
5173+ zend_hash_dprot_curmax += 256;
5174+ zend_hash_dprot_table = (dtor_func_t *) realloc(zend_hash_dprot_table, zend_hash_dprot_curmax * sizeof(dtor_func_t));
5175+ }
5176+
5177+ if ((unsigned long)zend_hash_dprot_table[left] < value) {
5178+ memmove(zend_hash_dprot_table+left+2, zend_hash_dprot_table+left+1, (zend_hash_dprot_counter-left-1)*sizeof(dtor_func_t));
5179+ zend_hash_dprot_table[left+1] = pDestructor;
5180+ } else {
5181+ memmove(zend_hash_dprot_table+left+1, zend_hash_dprot_table+left, (zend_hash_dprot_counter-left)*sizeof(dtor_func_t));
5182+ zend_hash_dprot_table[left] = pDestructor;
65be62f2 5183+ }
65be62f2 5184+
3f3163a9
AM
5185+ zend_hash_dprot_counter++;
5186+ }
5187+ }
5188+
5189+ zend_hash_dprot_end_write();
5190+}
5191+
5192+static void zend_hash_check_destructor(dtor_func_t pDestructor)
5193+{
5194+ unsigned long value;
5195+
5196+ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR || pDestructor == ZVAL_INTERNAL_PTR_DTOR
65be62f2 5197+#ifdef ZEND_ENGINE_2
3f3163a9 5198+ || pDestructor == suhosin_zend_destroy_property_info_internal || pDestructor == suhosin_zend_destroy_property_info
65be62f2 5199+#endif
3f3163a9
AM
5200+ || pDestructor == ZEND_FUNCTION_DTOR || pDestructor == ZEND_CLASS_DTOR) {
5201+ return;
5202+ }
5203+
5204+ zend_hash_dprot_begin_read();
5205+
5206+ if (zend_hash_dprot_counter > 0) {
5207+ int left, right, mid;
5208+ zend_bool found = 0;
5209+
5210+ value = (unsigned long) pDestructor;
5211+ left = 0;
5212+ right = zend_hash_dprot_counter-1;
5213+
5214+ while (left < right) {
5215+ mid = (right - left) >> 1;
5216+ mid += left;
5217+ if ((unsigned long)zend_hash_dprot_table[mid] == value) {
5218+ found = 1;
5219+ break;
5220+ }
5221+ if (value < (unsigned long)zend_hash_dprot_table[mid]) {
5222+ right = mid-1;
65be62f2 5223+ } else {
3f3163a9 5224+ left = mid+1;
65be62f2 5225+ }
3f3163a9
AM
5226+ }
5227+ if ((unsigned long)zend_hash_dprot_table[left] == value) {
5228+ found = 1;
5229+ }
5230+
5231+ if (!found) {
5232+ zend_hash_dprot_end_read();
5233+
5234+ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown Hashtable destructor");
5235+ if (SUHOSIN_CONFIG(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR) == 0) {
5236+ _exit(1);
5237+ }
65be62f2
ER
5238+ return;
5239+ }
3f3163a9
AM
5240+
5241+ } else {
5242+ zend_hash_dprot_end_read();
5243+
5244+ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown Hashtable destructor");
5245+ if (SUHOSIN_CONFIG(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR) == 0) {
5246+ _exit(1);
5247+ }
5248+ return;
65be62f2 5249+ }
3f3163a9
AM
5250+
5251+ zend_hash_dprot_end_read();
65be62f2
ER
5252+}
5253+
3f3163a9
AM
5254+#else
5255+#define zend_hash_add_destructor(pDestructor) do {} while(0)
5256+#define zend_hash_check_destructor(pDestructor) do {} while(0)
65be62f2 5257+#endif
3f3163a9
AM
5258
5259 ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
5260 {
5261@@ -156,6 +350,7 @@ ZEND_API int _zend_hash_init(HashTable *
5262
5263 ht->nTableMask = ht->nTableSize - 1;
5264 ht->pDestructor = pDestructor;
5265+ zend_hash_add_destructor(pDestructor);
5266 ht->arBuckets = NULL;
5267 ht->pListHead = NULL;
5268 ht->pListTail = NULL;
5269@@ -233,6 +428,7 @@ ZEND_API int _zend_hash_add_or_update(Ha
5270 return FAILURE;
5271 }
5272 #endif
5273+ zend_hash_check_destructor(ht->pDestructor);
5274 if (ht->pDestructor) {
5275 ht->pDestructor(p->pData);
5276 }
5277@@ -298,6 +494,7 @@ ZEND_API int _zend_hash_quick_add_or_upd
5278 return FAILURE;
5279 }
5280 #endif
5281+ zend_hash_check_destructor(ht->pDestructor);
5282 if (ht->pDestructor) {
5283 ht->pDestructor(p->pData);
5284 }
5285@@ -373,6 +570,7 @@ ZEND_API int _zend_hash_index_update_or_
5286 return FAILURE;
5287 }
5288 #endif
5289+ zend_hash_check_destructor(ht->pDestructor);
5290 if (ht->pDestructor) {
5291 ht->pDestructor(p->pData);
5292 }
5293@@ -496,6 +694,7 @@ ZEND_API int zend_hash_del_key_or_index(
5294 if (ht->pInternalPointer == p) {
5295 ht->pInternalPointer = p->pListNext;
5296 }
5297+ zend_hash_check_destructor(ht->pDestructor);
5298 if (ht->pDestructor) {
5299 ht->pDestructor(p->pData);
5300 }
5301@@ -522,6 +721,7 @@ ZEND_API void zend_hash_destroy(HashTabl
5302 SET_INCONSISTENT(HT_IS_DESTROYING);
5303
5304 p = ht->pListHead;
5305+ zend_hash_check_destructor(ht->pDestructor);
5306 while (p != NULL) {
5307 q = p;
5308 p = p->pListNext;
5309@@ -548,6 +748,7 @@ ZEND_API void zend_hash_clean(HashTable
5310 SET_INCONSISTENT(HT_CLEANING);
5311
5312 p = ht->pListHead;
5313+ zend_hash_check_destructor(ht->pDestructor);
5314 while (p != NULL) {
5315 q = p;
5316 p = p->pListNext;
ebd0ee03
AM
5317--- x/Zend/zend_hash.c~ 2011-08-20 18:08:23.000000000 +0200
5318+++ x/Zend/zend_hash.c 2011-08-20 18:09:01.292927307 +0200
5319@@ -808,6 +808,7 @@
3f3163a9
AM
5320 ht->nNumOfElements--;
5321 HANDLE_UNBLOCK_INTERRUPTIONS();
5322
ebd0ee03 5323+ zend_hash_check_destructor(ht->pDestructor);
3f3163a9
AM
5324 if (ht->pDestructor) {
5325 ht->pDestructor(p->pData);
5326 }
5327diff -Naurp php-5.3.6RC1/Zend/zend_llist.c php-5.3.6RC1.oden/Zend/zend_llist.c
5328--- php-5.3.6RC1/Zend/zend_llist.c 2011-01-01 03:19:59.000000000 +0100
5329+++ php-5.3.6RC1.oden/Zend/zend_llist.c 2011-02-20 11:50:19.329840242 +0100
5330@@ -23,6 +23,194 @@
5331 #include "zend_llist.h"
5332 #include "zend_qsort.h"
5333
65be62f2 5334+#if SUHOSIN_PATCH
3f3163a9
AM
5335+#ifdef ZTS
5336+static MUTEX_T zend_llist_dprot_mx_reader;
5337+static MUTEX_T zend_llist_dprot_mx_writer;
5338+static unsigned int zend_llist_dprot_reader;
5339+#endif
5340+static unsigned int zend_llist_dprot_counter;
5341+static unsigned int zend_llist_dprot_curmax;
5342+static llist_dtor_func_t *zend_llist_dprot_table = NULL;
65be62f2 5343+
3f3163a9
AM
5344+static void zend_llist_dprot_begin_read()
5345+{
5346+#ifdef ZTS
5347+ tsrm_mutex_lock(zend_llist_dprot_mx_reader);
5348+ if ((++(zend_llist_dprot_reader)) == 1) {
5349+ tsrm_mutex_lock(zend_llist_dprot_mx_writer);
5350+ }
5351+ tsrm_mutex_unlock(zend_llist_dprot_mx_reader);
5352+#endif
5353+}
65be62f2 5354+
3f3163a9
AM
5355+static void zend_llist_dprot_end_read()
5356+{
5357+#ifdef ZTS
5358+ tsrm_mutex_lock(zend_llist_dprot_mx_reader);
5359+ if ((--(zend_llist_dprot_reader)) == 0) {
5360+ tsrm_mutex_unlock(zend_llist_dprot_mx_writer);
5361+ }
5362+ tsrm_mutex_unlock(zend_llist_dprot_mx_reader);
5363+#endif
5364+}
65be62f2 5365+
3f3163a9
AM
5366+static void zend_llist_dprot_begin_write()
5367+{
5368+#ifdef ZTS
5369+ tsrm_mutex_lock(zend_llist_dprot_mx_writer);
65be62f2 5370+#endif
3f3163a9 5371+}
65be62f2 5372+
3f3163a9
AM
5373+static void zend_llist_dprot_end_write()
5374+{
5375+#ifdef ZTS
5376+ tsrm_mutex_unlock(zend_llist_dprot_mx_writer);
65be62f2 5377+#endif
3f3163a9 5378+}
65be62f2 5379+
3f3163a9
AM
5380+/*ZEND_API void zend_llist_dprot_dtor()
5381+{
5382+#ifdef ZTS
5383+ tsrm_mutex_free(zend_llist_dprot_mx_reader);
5384+ tsrm_mutex_free(zend_llist_dprot_mx_writer);
5385+#endif
5386+ free(zend_llist_dprot_table);
5387+}*/
65be62f2 5388+
3f3163a9
AM
5389+static void zend_llist_add_destructor(llist_dtor_func_t pDestructor)
5390+{
5391+ int left, right, mid;
5392+ zend_bool found = 0;
5393+ unsigned long value;
5394+
5395+ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR) {
5396+ return;
5397+ }
5398+
5399+ if (zend_llist_dprot_table == NULL) {
5400+#ifdef ZTS
5401+ zend_llist_dprot_mx_reader = tsrm_mutex_alloc();
5402+ zend_llist_dprot_mx_writer = tsrm_mutex_alloc();
5403+ zend_llist_dprot_reader = 0;
5404+#endif
5405+ zend_llist_dprot_counter = 0;
5406+ zend_llist_dprot_curmax = 256;
5407+ zend_llist_dprot_table = (llist_dtor_func_t *) malloc(256 * sizeof(llist_dtor_func_t));
5408+ }
5409+
5410+ zend_llist_dprot_begin_write();
65be62f2 5411+
3f3163a9
AM
5412+ if (zend_llist_dprot_counter == 0) {
5413+ zend_llist_dprot_counter++;
5414+ zend_llist_dprot_table[0] = pDestructor;
5415+ } else {
5416+ value = (unsigned long) pDestructor;
5417+ left = 0;
5418+ right = zend_llist_dprot_counter-1;
5419+ mid = 0;
5420+
5421+ while (left < right) {
5422+ mid = (right - left) >> 1;
5423+ mid += left;
5424+ if ((unsigned long)zend_llist_dprot_table[mid] == value) {
5425+ found = 1;
5426+ break;
5427+ }
5428+ if (value < (unsigned long)zend_llist_dprot_table[mid]) {
5429+ right = mid-1;
5430+ } else {
5431+ left = mid+1;
5432+ }
5433+ }
5434+ if ((unsigned long)zend_llist_dprot_table[left] == value) {
5435+ found = 1;
5436+ }
5437+
5438+ if (!found) {
5439+
5440+ if (zend_llist_dprot_counter >= zend_llist_dprot_curmax) {
5441+ zend_llist_dprot_curmax += 256;
5442+ zend_llist_dprot_table = (llist_dtor_func_t *) realloc(zend_llist_dprot_table, zend_llist_dprot_curmax * sizeof(llist_dtor_func_t));
5443+ }
5444+
5445+ if ((unsigned long)zend_llist_dprot_table[left] < value) {
5446+ memmove(zend_llist_dprot_table+left+2, zend_llist_dprot_table+left+1, (zend_llist_dprot_counter-left-1)*sizeof(llist_dtor_func_t));
5447+ zend_llist_dprot_table[left+1] = pDestructor;
5448+ } else {
5449+ memmove(zend_llist_dprot_table+left+1, zend_llist_dprot_table+left, (zend_llist_dprot_counter-left)*sizeof(llist_dtor_func_t));
5450+ zend_llist_dprot_table[left] = pDestructor;
5451+ }
65be62f2 5452+
3f3163a9
AM
5453+ zend_llist_dprot_counter++;
5454+ }
5455+ }
5456+
5457+ zend_llist_dprot_end_write();
5458+}
65be62f2 5459+
3f3163a9
AM
5460+static void zend_llist_check_destructor(llist_dtor_func_t pDestructor)
5461+{
5462+ unsigned long value;
5463+
5464+ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR) {
5465+ return;
5466+ }
65be62f2 5467+
3f3163a9
AM
5468+ zend_llist_dprot_begin_read();
5469+
5470+ if (zend_llist_dprot_counter > 0) {
5471+ int left, right, mid;
5472+ zend_bool found = 0;
5473+
5474+ value = (unsigned long) pDestructor;
5475+ left = 0;
5476+ right = zend_llist_dprot_counter-1;
5477+
5478+ while (left < right) {
5479+ mid = (right - left) >> 1;
5480+ mid += left;
5481+ if ((unsigned long)zend_llist_dprot_table[mid] == value) {
5482+ found = 1;
5483+ break;
5484+ }
5485+ if (value < (unsigned long)zend_llist_dprot_table[mid]) {
5486+ right = mid-1;
5487+ } else {
5488+ left = mid+1;
5489+ }
5490+ }
5491+ if ((unsigned long)zend_llist_dprot_table[left] == value) {
5492+ found = 1;
5493+ }
5494+
5495+ if (!found) {
5496+ zend_llist_dprot_end_read();
5497+
5498+ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown llist destructor");
5499+ if (SUHOSIN_CONFIG(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR) == 0) {
5500+ _exit(1);
5501+ }
5502+ return;
5503+ }
5504+
5505+ } else {
5506+ zend_llist_dprot_end_read();
5507+
5508+ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown llist destructor");
5509+ if (SUHOSIN_CONFIG(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR) == 0) {
5510+ _exit(1);
5511+ }
5512+ return;
5513+ }
5514+
5515+ zend_llist_dprot_end_read();
5516+}
65be62f2 5517+#else
3f3163a9
AM
5518+#define zend_llist_add_destructor(pDestructor) do {} while(0)
5519+#define zend_llist_check_destructor(pDestructor) do {} while(0)
65be62f2 5520+#endif
3f3163a9
AM
5521+
5522 ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
65be62f2 5523 {
3f3163a9
AM
5524 l->head = NULL;
5525@@ -30,6 +218,7 @@ ZEND_API void zend_llist_init(zend_llist
5526 l->count = 0;
5527 l->size = size;
5528 l->dtor = dtor;
5529+ zend_llist_add_destructor(dtor);
5530 l->persistent = persistent;
65be62f2
ER
5531 }
5532
3f3163a9
AM
5533@@ -81,6 +270,7 @@ ZEND_API void zend_llist_prepend_element
5534 } else {\
5535 (l)->tail = (current)->prev;\
5536 }\
5537+ zend_llist_check_destructor((l)->dtor); \
5538 if ((l)->dtor) {\
5539 (l)->dtor((current)->data);\
5540 }\
5541@@ -108,6 +298,7 @@ ZEND_API void zend_llist_destroy(zend_ll
65be62f2 5542 {
3f3163a9
AM
5543 zend_llist_element *current=l->head, *next;
5544
5545+ zend_llist_check_destructor(l->dtor);
5546 while (current) {
5547 next = current->next;
5548 if (l->dtor) {
5549@@ -133,6 +324,7 @@ ZEND_API void *zend_llist_remove_tail(ze
5550 zend_llist_element *old_tail;
5551 void *data;
5552
5553+ zend_llist_check_destructor((l)->dtor);
5554 if ((old_tail = l->tail)) {
5555 if (old_tail->prev) {
5556 old_tail->prev->next = NULL;
5557diff -Naurp php-5.3.6RC1/Zend/zend_operators.c php-5.3.6RC1.oden/Zend/zend_operators.c
5558--- php-5.3.6RC1/Zend/zend_operators.c 2011-01-01 03:19:59.000000000 +0100
5559+++ php-5.3.6RC1.oden/Zend/zend_operators.c 2011-02-20 11:50:19.330840383 +0100
5560@@ -153,9 +153,14 @@ ZEND_API void convert_scalar_to_number(z
5561 case IS_STRING:
5562 {
5563 char *strval;
5564+ int strl;
5565
5566 strval = Z_STRVAL_P(op);
5567- if ((Z_TYPE_P(op)=is_numeric_string(strval, Z_STRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
5568+ strl = Z_STRLEN_P(op);
65be62f2 5569+#if SUHOSIN_PATCH
3f3163a9 5570+ Z_STRLEN_P(op) = 0;
65be62f2 5571+#endif
3f3163a9
AM
5572+ if ((Z_TYPE_P(op)=is_numeric_string(strval, strl, &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
5573 ZVAL_LONG(op, 0);
5574 }
5575 STR_FREE(strval);
5576@@ -187,7 +192,8 @@ ZEND_API void convert_scalar_to_number(z
5577 } else { \
5578 switch (Z_TYPE_P(op)) { \
5579 case IS_STRING: \
5580- { \
5581+ { \
5582+ Z_STRLEN(holder) = 0; \
5583 if ((Z_TYPE(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) { \
5584 ZVAL_LONG(&(holder), 0); \
5585 } \
5586@@ -229,6 +235,7 @@ ZEND_API void convert_scalar_to_number(z
5587 Z_LVAL(holder) = zend_dval_to_lval(Z_DVAL_P(op)); \
5588 break; \
5589 case IS_STRING: \
5590+ Z_STRLEN(holder) = 0; \
5591 Z_LVAL(holder) = strtol(Z_STRVAL_P(op), NULL, 10); \
5592 break; \
5593 case IS_ARRAY: \
5594@@ -271,6 +278,7 @@ ZEND_API void convert_scalar_to_number(z
5595 Z_LVAL(holder) = (Z_DVAL_P(op) ? 1 : 0); \
5596 break; \
5597 case IS_STRING: \
5598+ Z_STRLEN(holder) = 0; \
5599 if (Z_STRLEN_P(op) == 0 \
5600 || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { \
5601 Z_LVAL(holder) = 0; \
5602@@ -356,6 +364,9 @@ ZEND_API void convert_to_long_base(zval
5603 {
5604 char *strval = Z_STRVAL_P(op);
65be62f2 5605
65be62f2 5606+#if SUHOSIN_PATCH
3f3163a9 5607+ Z_STRLEN_P(op) = 0;
65be62f2 5608+#endif
3f3163a9
AM
5609 Z_LVAL_P(op) = strtol(strval, NULL, base);
5610 STR_FREE(strval);
5611 }
5612@@ -416,6 +427,9 @@ ZEND_API void convert_to_double(zval *op
5613 {
5614 char *strval = Z_STRVAL_P(op);
5615
65be62f2 5616+#if SUHOSIN_PATCH
3f3163a9 5617+ Z_STRLEN_P(op) = 0;
65be62f2 5618+#endif
3f3163a9
AM
5619 Z_DVAL_P(op) = zend_strtod(strval, NULL);
5620 STR_FREE(strval);
5621 }
5622@@ -502,8 +516,14 @@ ZEND_API void convert_to_boolean(zval *o
5623
5624 if (Z_STRLEN_P(op) == 0
5625 || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
5626+#if SUHOSIN_PATCH
5627+ Z_STRLEN_P(op) = 0;
65be62f2 5628+#endif
3f3163a9
AM
5629 Z_LVAL_P(op) = 0;
5630 } else {
5631+#if SUHOSIN_PATCH
5632+ Z_STRLEN_P(op) = 0;
5633+#endif
5634 Z_LVAL_P(op) = 1;
65be62f2 5635 }
3f3163a9
AM
5636 STR_FREE(strval);
5637@@ -617,6 +637,9 @@ static void convert_scalar_to_array(zval
5638 *entry = *op;
5639 INIT_PZVAL(entry);
65be62f2 5640
65be62f2 5641+#if SUHOSIN_PATCH
3f3163a9 5642+ Z_STRLEN_P(op) = 0;
65be62f2 5643+#endif
3f3163a9
AM
5644 switch (type) {
5645 case IS_ARRAY:
5646 ALLOC_HASHTABLE(Z_ARRVAL_P(op));
5647diff -Naurp php-5.3.6RC1/Zend/zend_variables.c php-5.3.6RC1.oden/Zend/zend_variables.c
5648--- php-5.3.6RC1/Zend/zend_variables.c 2011-01-01 03:19:59.000000000 +0100
5649+++ php-5.3.6RC1.oden/Zend/zend_variables.c 2011-02-20 11:50:19.331840524 +0100
5650@@ -34,6 +34,9 @@ ZEND_API void _zval_dtor_func(zval *zval
5651 case IS_CONSTANT:
5652 CHECK_ZVAL_STRING_REL(zvalue);
5653 STR_FREE_REL(zvalue->value.str.val);
65be62f2 5654+#if SUHOSIN_PATCH
3f3163a9 5655+ zvalue->value.str.len = 0;
65be62f2 5656+#endif
3f3163a9
AM
5657 break;
5658 case IS_ARRAY:
5659 case IS_CONSTANT_ARRAY: {
5660@@ -78,6 +81,9 @@ ZEND_API void _zval_internal_dtor(zval *
5661 case IS_CONSTANT:
5662 CHECK_ZVAL_STRING_REL(zvalue);
5663 free(zvalue->value.str.val);
65be62f2 5664+#if SUHOSIN_PATCH
3f3163a9
AM
5665+ zvalue->value.str.len = 0;
5666+#endif
5667 break;
5668 case IS_ARRAY:
5669 case IS_CONSTANT_ARRAY:
This page took 1.011448 seconds and 4 git commands to generate.