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