xref: /PHP-5.5/ext/fileinfo/libmagic.patch (revision 4ed26187)
1diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
2--- libmagic.orig/apprentice.c	Thu Mar 21 18:45:14 2013
3+++ libmagic/apprentice.c	Sun Jan  4 17:02:29 2015
4@@ -29,6 +29,8 @@
5  * apprentice - make one pass through /etc/magic, learning its secrets.
6  */
7
8+#include "php.h"
9+
10 #include "file.h"
11
12 #ifndef	lint
13@@ -36,18 +38,30 @@
14 #endif	/* lint */
15
16 #include "magic.h"
17+#include "patchlevel.h"
18 #include <stdlib.h>
19-#ifdef HAVE_UNISTD_H
20+
21+#if defined(__hpux) && !defined(HAVE_STRTOULL)
22+#if SIZEOF_LONG == 8
23+# define strtoull strtoul
24+#else
25+# define strtoull __strtoull
26+#endif
27+#endif
28+
29+#ifdef PHP_WIN32
30+#include "win32/unistd.h"
31+#if _MSC_VER <= 1300
32+# include "win32/php_strtoi64.h"
33+#endif
34+#define strtoull _strtoui64
35+#else
36 #include <unistd.h>
37 #endif
38 #include <string.h>
39 #include <assert.h>
40 #include <ctype.h>
41 #include <fcntl.h>
42-#ifdef QUICK
43-#include <sys/mman.h>
44-#endif
45-#include <dirent.h>
46
47 #define	EATAB {while (isascii((unsigned char) *l) && \
48 		      isspace((unsigned char) *l))  ++l;}
49@@ -143,38 +157,7 @@
50 	{ NULL, 0, NULL }
51 };
52
53-#ifdef COMPILE_ONLY
54-
55-int main(int, char *[]);
56-
57-int
58-main(int argc, char *argv[])
59-{
60-	int ret;
61-	struct magic_set *ms;
62-	char *progname;
63-
64-	if ((progname = strrchr(argv[0], '/')) != NULL)
65-		progname++;
66-	else
67-		progname = argv[0];
68-
69-	if (argc != 2) {
70-		(void)fprintf(stderr, "Usage: %s file\n", progname);
71-		return 1;
72-	}
73-
74-	if ((ms = magic_open(MAGIC_CHECK)) == NULL) {
75-		(void)fprintf(stderr, "%s: %s\n", progname, strerror(errno));
76-		return 1;
77-	}
78-	ret = magic_compile(ms, argv[1]) == -1 ? 1 : 0;
79-	if (ret == 1)
80-		(void)fprintf(stderr, "%s: %s\n", progname, magic_error(ms));
81-	magic_close(ms);
82-	return ret;
83-}
84-#endif /* COMPILE_ONLY */
85+#include "../data_file.c"
86
87 struct type_tbl_s {
88 	const char name[16];
89@@ -255,6 +238,10 @@
90 # undef XX
91 # undef XX_NULL
92
93+#ifndef S_ISDIR
94+#define S_ISDIR(mode) ((mode) & _S_IFDIR)
95+#endif
96+
97 private int
98 get_type(const struct type_tbl_s *tbl, const char *l, const char **t)
99 {
100@@ -378,7 +365,7 @@
101 {
102 	struct mlist *ml;
103
104-	if ((ml = CAST(struct mlist *, malloc(sizeof(*ml)))) == NULL)
105+	if ((ml = CAST(struct mlist *, emalloc(sizeof(*ml)))) == NULL)
106 		return -1;
107
108 	ml->map = idx == 0 ? map : NULL;
109@@ -416,12 +403,13 @@
110 		return apprentice_compile(ms, map, fn);
111 	}
112
113-#ifndef COMPILE_ONLY
114 	map = apprentice_map(ms, fn);
115 	if (map == NULL) {
116-		if (ms->flags & MAGIC_CHECK)
117-			file_magwarn(ms, "using regular magic file `%s'", fn);
118-		map = apprentice_load(ms, fn, action);
119+		if (fn) {
120+			if (ms->flags & MAGIC_CHECK)
121+				file_magwarn(ms, "using regular magic file `%s'", fn);
122+			map = apprentice_load(ms, fn, action);
123+		}
124 		if (map == NULL)
125 			return -1;
126 	}
127@@ -444,7 +432,6 @@
128 	}
129
130 	return 0;
131-#endif /* COMPILE_ONLY */
132 }
133
134 protected void
135@@ -455,10 +442,16 @@
136 		return;
137 	for (i = 0; i < MAGIC_SETS; i++)
138 		mlist_free(ms->mlist[i]);
139-	free(ms->o.pbuf);
140-	free(ms->o.buf);
141-	free(ms->c.li);
142-	free(ms);
143+	if (ms->o.pbuf) {
144+		efree(ms->o.pbuf);
145+	}
146+	if (ms->o.buf) {
147+		efree(ms->o.buf);
148+	}
149+	if (ms->c.li) {
150+		efree(ms->c.li);
151+	}
152+	efree(ms);
153 }
154
155 protected struct magic_set *
156@@ -467,7 +460,7 @@
157 	struct magic_set *ms;
158 	size_t i, len;
159
160-	if ((ms = CAST(struct magic_set *, calloc((size_t)1,
161+	if ((ms = CAST(struct magic_set *, ecalloc((size_t)1,
162 	    sizeof(struct magic_set)))) == NULL)
163 		return NULL;
164
165@@ -479,7 +472,7 @@
166 	ms->o.buf = ms->o.pbuf = NULL;
167 	len = (ms->c.len = 10) * sizeof(*ms->c.li);
168
169-	if ((ms->c.li = CAST(struct level_info *, malloc(len))) == NULL)
170+	if ((ms->c.li = CAST(struct level_info *, emalloc(len))) == NULL)
171 		goto free;
172
173 	ms->event_flags = 0;
174@@ -490,7 +483,7 @@
175 	ms->line = 0;
176 	return ms;
177 free:
178-	free(ms);
179+	efree(ms);
180 	return NULL;
181 }
182
183@@ -499,22 +492,26 @@
184 {
185 	if (map == NULL)
186 		return;
187-	if (map->p == NULL)
188-		return;
189-#ifdef QUICK
190-	if (map->len)
191-		(void)munmap(map->p, map->len);
192-	else
193-#endif
194-		free(map->p);
195-	free(map);
196+	if (map->p != php_magic_database) {
197+		if (map->p == NULL) {
198+			int j;
199+			for (j = 0; j < MAGIC_SETS; j++) {
200+				if (map->magic[j]) {
201+					efree(map->magic[j]);
202+				}
203+			}
204+		} else {
205+			efree(map->p);
206+		}
207+	}
208+	efree(map);
209 }
210
211 private struct mlist *
212 mlist_alloc(void)
213 {
214 	struct mlist *mlist;
215-	if ((mlist = CAST(struct mlist *, calloc(1, sizeof(*mlist)))) == NULL) {
216+	if ((mlist = CAST(struct mlist *, ecalloc(1, sizeof(*mlist)))) == NULL) {
217 		return NULL;
218 	}
219 	mlist->next = mlist->prev = mlist;
220@@ -533,10 +530,10 @@
221 		struct mlist *next = ml->next;
222 		if (ml->map)
223 			apprentice_unmap(ml->map);
224-		free(ml);
225+		efree(ml);
226 		ml = next;
227 	}
228-	free(ml);
229+	efree(ml);
230 }
231
232 /* const char *fn: list of magic files and directories */
233@@ -546,13 +543,28 @@
234 	char *p, *mfn;
235 	int file_err, errs = -1;
236 	size_t i;
237-
238+/* XXX disabling default magic loading so the compiled in data is used */
239+#if 0
240 	if ((fn = magic_getpath(fn, action)) == NULL)
241 		return -1;
242+#endif
243
244 	init_file_tables();
245
246-	if ((mfn = strdup(fn)) == NULL) {
247+	if (fn == NULL)
248+		fn = getenv("MAGIC");
249+	if (fn == NULL) {
250+		for (i = 0; i < MAGIC_SETS; i++) {
251+			mlist_free(ms->mlist[i]);
252+			if ((ms->mlist[i] = mlist_alloc()) == NULL) {
253+				file_oomem(ms, sizeof(*ms->mlist[i]));
254+				return -1;
255+			}
256+		}
257+		return apprentice_1(ms, fn, action);
258+	}
259+
260+	if ((mfn = estrdup(fn)) == NULL) {
261 		file_oomem(ms, strlen(fn));
262 		return -1;
263 	}
264@@ -567,7 +579,7 @@
265 					mlist_free(ms->mlist[i]);
266 				while (i != 0);
267 			}
268-			free(mfn);
269+			efree(mfn);
270 			return -1;
271 		}
272 	}
273@@ -584,7 +596,7 @@
274 		fn = p;
275 	}
276
277-	free(mfn);
278+	efree(mfn);
279
280 	if (errs == -1) {
281 		for (i = 0; i < MAGIC_SETS; i++) {
282@@ -904,7 +916,7 @@
283
284 		maxmagic[i] += ALLOC_INCR;
285 		if ((mp = CAST(struct magic_entry *,
286-		    realloc(mentry[i], sizeof(*mp) * maxmagic[i]))) ==
287+		    erealloc(mentry[i], sizeof(*mp) * maxmagic[i]))) ==
288 		    NULL) {
289 			file_oomem(ms, sizeof(*mp) * maxmagic[i]);
290 			return -1;
291@@ -925,13 +937,24 @@
292 load_1(struct magic_set *ms, int action, const char *fn, int *errs,
293    struct magic_entry **mentry, uint32_t *mentrycount)
294 {
295-	size_t lineno = 0, llen = 0;
296+	char buffer[BUFSIZ + 1];
297 	char *line = NULL;
298-	ssize_t len;
299+	size_t len;
300+	size_t lineno = 0;
301 	struct magic_entry me;
302
303-	FILE *f = fopen(ms->file = fn, "r");
304-	if (f == NULL) {
305+	php_stream *stream;
306+
307+	TSRMLS_FETCH();
308+
309+	ms->file = fn;
310+#if PHP_API_VERSION < 20100412
311+	stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
312+#else
313+	stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS, NULL);
314+#endif
315+
316+	if (stream == NULL) {
317 		if (errno != ENOENT)
318 			file_error(ms, errno, "cannot read magic file `%s'",
319 				   fn);
320@@ -941,8 +964,7 @@
321
322 	memset(&me, 0, sizeof(me));
323 	/* read and parse this file */
324-	for (ms->line = 1; (len = getline(&line, &llen, f)) != -1;
325-	    ms->line++) {
326+	for (ms->line = 1; (line = php_stream_get_line(stream, buffer , BUFSIZ, &len)) != NULL; ms->line++) {
327 		if (len == 0) /* null line, garbage, etc */
328 			continue;
329 		if (line[len - 1] == '\n') {
330@@ -994,14 +1016,13 @@
331 				goto again;
332 			default:
333 				(*errs)++;
334-				break;
335-			}
336+			break;
337 		}
338 	}
339+	}
340 	if (me.mp)
341 		(void)addentry(ms, &me, mentry, mentrycount);
342-	free(line);
343-	(void)fclose(f);
344+	php_stream_close(stream);
345 }
346
347 /*
348@@ -1080,7 +1101,7 @@
349 		mentrycount += me[i].cont_count;
350
351 	slen = sizeof(**ma) * mentrycount;
352-	if ((*ma = CAST(struct magic *, malloc(slen))) == NULL) {
353+	if ((*ma = CAST(struct magic *, emalloc(slen))) == NULL) {
354 		file_oomem(ms, slen);
355 		return -1;
356 	}
357@@ -1102,27 +1123,29 @@
358 	if (me == NULL)
359 		return;
360 	for (i = 0; i < nme; i++)
361-		free(me[i].mp);
362-	free(me);
363+		efree(me[i].mp);
364+	efree(me);
365 }
366
367 private struct magic_map *
368 apprentice_load(struct magic_set *ms, const char *fn, int action)
369 {
370-	int errs = 0;
371+	int errs = 0;
372 	struct magic_entry *mentry[MAGIC_SETS] = { NULL };
373 	uint32_t mentrycount[MAGIC_SETS] = { 0 };
374 	uint32_t i, j;
375 	size_t files = 0, maxfiles = 0;
376-	char **filearr = NULL, *mfn;
377+	char **filearr = NULL;
378 	struct stat st;
379 	struct magic_map *map;
380-	DIR *dir;
381-	struct dirent *d;
382+	php_stream *dir;
383+	php_stream_dirent d;
384+
385+	TSRMLS_FETCH();
386
387 	ms->flags |= MAGIC_CHECK;	/* Enable checks for parsed files */
388
389-	if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) {
390+	if ((map = CAST(struct magic_map *, ecalloc(1, sizeof(*map)))) == NULL) {
391 		file_oomem(ms, sizeof(*map));
392 		return NULL;
393 	}
394@@ -1131,23 +1154,37 @@
395 	if (action == FILE_CHECK)
396 		(void)fprintf(stderr, "%s\n", usg_hdr);
397
398+	{
399+		/* XXX the maxmagic has to be reset each time we load some new magic file.
400+		Where file commando is used it's not essential as the CLI process
401+		ends, multiple loading within the same process wouldn't work. */
402+		int k;
403+		for (k = 0; k < MAGIC_SETS; k++) {
404+			maxmagic[k] = 0;
405+		}
406+	}
407+
408 	/* load directory or file */
409-	if (stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
410-		dir = opendir(fn);
411+	/* FIXME: Read file names and sort them to prevent
412+	   non-determinism. See Debian bug #488562. */
413+	if (php_sys_stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
414+		int mflen;
415+		char mfn[MAXPATHLEN];
416+
417+		dir = php_stream_opendir((char *)fn, REPORT_ERRORS, NULL);
418 		if (!dir) {
419 			errs++;
420 			goto out;
421 		}
422-		while ((d = readdir(dir)) != NULL) {
423-			if (asprintf(&mfn, "%s/%s", fn, d->d_name) < 0) {
424+		while (php_stream_readdir(dir, &d)) {
425+			if ((mflen = snprintf(mfn, sizeof(mfn), "%s/%s", fn, d.d_name)) < 0) {
426 				file_oomem(ms,
427-				    strlen(fn) + strlen(d->d_name) + 2);
428+				strlen(fn) + strlen(d.d_name) + 2);
429 				errs++;
430-				closedir(dir);
431+				php_stream_closedir(dir);
432 				goto out;
433 			}
434 			if (stat(mfn, &st) == -1 || !S_ISREG(st.st_mode)) {
435-				free(mfn);
436 				continue;
437 			}
438 			if (files >= maxfiles) {
439@@ -1155,24 +1192,23 @@
440 				maxfiles = (maxfiles + 1) * 2;
441 				mlen = maxfiles * sizeof(*filearr);
442 				if ((filearr = CAST(char **,
443-				    realloc(filearr, mlen))) == NULL) {
444+				    erealloc(filearr, mlen))) == NULL) {
445 					file_oomem(ms, mlen);
446-					free(mfn);
447-					closedir(dir);
448+					php_stream_closedir(dir);
449 					errs++;
450 					goto out;
451 				}
452 			}
453-			filearr[files++] = mfn;
454+			filearr[files++] = estrndup(mfn, (mflen > sizeof(mfn) - 1)? sizeof(mfn) - 1: mflen);
455 		}
456-		closedir(dir);
457+		php_stream_closedir(dir);
458 		qsort(filearr, files, sizeof(*filearr), cmpstrp);
459 		for (i = 0; i < files; i++) {
460 			load_1(ms, action, filearr[i], &errs, mentry,
461 			    mentrycount);
462-			free(filearr[i]);
463+			efree(filearr[i]);
464 		}
465-		free(filearr);
466+		efree(filearr);
467 	} else
468 		load_1(ms, action, fn, &errs, mentry, mentrycount);
469 	if (errs)
470@@ -1211,9 +1247,9 @@
471 	if (errs) {
472 		for (j = 0; j < MAGIC_SETS; j++) {
473 			if (map->magic[j])
474-				free(map->magic[j]);
475+				efree(map->magic[j]);
476 		}
477-		free(map);
478+		efree(map);
479 		return NULL;
480 	}
481 	return map;
482@@ -1233,7 +1269,7 @@
483 		 * the sign extension must have happened.
484 		 */
485 		case FILE_BYTE:
486-			v = (char) v;
487+			v = (signed char) v;
488 			break;
489 		case FILE_SHORT:
490 		case FILE_BESHORT:
491@@ -1500,7 +1536,7 @@
492 		if (me->cont_count == me->max_count) {
493 			struct magic *nm;
494 			size_t cnt = me->max_count + ALLOC_CHUNK;
495-			if ((nm = CAST(struct magic *, realloc(me->mp,
496+			if ((nm = CAST(struct magic *, erealloc(me->mp,
497 			    sizeof(*nm) * cnt))) == NULL) {
498 				file_oomem(ms, sizeof(*nm) * cnt);
499 				return -1;
500@@ -1515,7 +1551,7 @@
501 		static const size_t len = sizeof(*m) * ALLOC_CHUNK;
502 		if (me->mp != NULL)
503 			return 1;
504-		if ((m = CAST(struct magic *, malloc(len))) == NULL) {
505+		if ((m = CAST(struct magic *, emalloc(len))) == NULL) {
506 			file_oomem(ms, len);
507 			return -1;
508 		}
509@@ -1688,7 +1724,7 @@
510 				m->type = get_standard_integer_type(l, &l);
511 			else if (*l == 's' && !isalpha((unsigned char)l[1])) {
512 				m->type = FILE_STRING;
513-				++l;
514+		++l;
515 			}
516 		}
517 	}
518@@ -1701,6 +1737,10 @@
519 	if (m->type == FILE_INVALID) {
520 		if (ms->flags & MAGIC_CHECK)
521 			file_magwarn(ms, "type `%s' invalid", l);
522+		if (me->mp) {
523+			efree(me->mp);
524+			me->mp = NULL;
525+		}
526 		return -1;
527 	}
528
529@@ -1709,7 +1749,7 @@
530
531 	m->mask_op = 0;
532 	if (*l == '~') {
533-		if (!IS_STRING(m->type))
534+		if (!IS_LIBMAGIC_STRING(m->type))
535 			m->mask_op |= FILE_OPINVERSE;
536 		else if (ms->flags & MAGIC_CHECK)
537 			file_magwarn(ms, "'~' invalid for string types");
538@@ -1718,7 +1758,7 @@
539 	m->str_range = 0;
540 	m->str_flags = m->type == FILE_PSTRING ? PSTRING_1_LE : 0;
541 	if ((op = get_op(*l)) != -1) {
542-		if (!IS_STRING(m->type)) {
543+		if (!IS_LIBMAGIC_STRING(m->type)) {
544 			uint64_t val;
545 			++l;
546 			m->mask_op |= op;
547@@ -1909,11 +1949,6 @@
548 		if (check_format(ms, m) == -1)
549 			return -1;
550 	}
551-#ifndef COMPILE_ONLY
552-	if (action == FILE_CHECK) {
553-		file_mdump(m);
554-	}
555-#endif
556 	m->mimetype[0] = '\0';		/* initialise MIME type to none */
557 	return 0;
558 }
559@@ -2554,59 +2589,80 @@
560 private struct magic_map *
561 apprentice_map(struct magic_set *ms, const char *fn)
562 {
563-	int fd;
564-	struct stat st;
565 	uint32_t *ptr;
566 	uint32_t version, entries, nentries;
567 	int needsbyteswap;
568 	char *dbname = NULL;
569 	struct magic_map *map;
570 	size_t i;
571+	php_stream *stream = NULL;
572+	php_stream_statbuf st;
573
574-	fd = -1;
575-	if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) {
576+
577+	TSRMLS_FETCH();
578+
579+	if ((map = CAST(struct magic_map *, ecalloc(1, sizeof(*map)))) == NULL) {
580 		file_oomem(ms, sizeof(*map));
581+		efree(map);
582 		goto error;
583 	}
584
585+	if (fn == NULL) {
586+		map->p = (void *)&php_magic_database;
587+		goto internal_loaded;
588+	}
589+
590+#ifdef PHP_WIN32
591+	/* Don't bother on windows with php_stream_open_wrapper,
592+	return to give apprentice_load() a chance. */
593+	if (php_stream_stat_path_ex((char *)fn, 0, &st, NULL) == SUCCESS) {
594+               if (st.sb.st_mode & S_IFDIR) {
595+                       goto error;
596+               }
597+       }
598+#endif
599+
600 	dbname = mkdbname(ms, fn, 0);
601 	if (dbname == NULL)
602 		goto error;
603
604-	if ((fd = open(dbname, O_RDONLY|O_BINARY)) == -1)
605+#if PHP_API_VERSION < 20100412
606+		stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
607+#else
608+		stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS, NULL);
609+#endif
610+
611+	if (!stream) {
612 		goto error;
613+	}
614
615-	if (fstat(fd, &st) == -1) {
616+	if (php_stream_stat(stream, &st) < 0) {
617 		file_error(ms, errno, "cannot stat `%s'", dbname);
618 		goto error;
619 	}
620-	if (st.st_size < 8) {
621+
622+	if (st.sb.st_size < 8) {
623 		file_error(ms, 0, "file `%s' is too small", dbname);
624 		goto error;
625 	}
626
627-	map->len = (size_t)st.st_size;
628-#ifdef QUICK
629-	if ((map->p = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE,
630-	    MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) {
631-		file_error(ms, errno, "cannot map `%s'", dbname);
632-		goto error;
633-	}
634-#else
635-	if ((map->p = CAST(void *, malloc(map->len))) == NULL) {
636+	map->len = (size_t)st.sb.st_size;
637+	if ((map->p = CAST(void *, emalloc(map->len))) == NULL) {
638 		file_oomem(ms, map->len);
639 		goto error;
640 	}
641-	if (read(fd, map->p, map->len) != (ssize_t)map->len) {
642+	if (php_stream_read(stream, map->p, (size_t)st.sb.st_size) != (size_t)st.sb.st_size) {
643 		file_badread(ms);
644 		goto error;
645 	}
646 	map->len = 0;
647 #define RET	1
648-#endif
649-	(void)close(fd);
650-	fd = -1;
651-	ptr = CAST(uint32_t *, map->p);
652+
653+	php_stream_close(stream);
654+	stream = NULL;
655+
656+internal_loaded:
657+	ptr = (uint32_t *)(void *)map->p;
658 	if (*ptr != MAGICNO) {
659 		if (swap4(*ptr) != MAGICNO) {
660 			file_error(ms, 0, "bad magic in `%s'", dbname);
661@@ -2620,17 +2676,29 @@
662 	else
663 		version = ptr[1];
664 	if (version != VERSIONNO) {
665-		file_error(ms, 0, "File %s supports only version %d magic "
666-		    "files. `%s' is version %d", VERSION,
667+		file_error(ms, 0, "File %d.%d supports only version %d magic "
668+		    "files. `%s' is version %d", FILE_VERSION_MAJOR, patchlevel,
669 		    VERSIONNO, dbname, version);
670 		goto error;
671 	}
672-	entries = (uint32_t)(st.st_size / sizeof(struct magic));
673-	if ((off_t)(entries * sizeof(struct magic)) != st.st_size) {
674-		file_error(ms, 0, "Size of `%s' %llu is not a multiple of %zu",
675-		    dbname, (unsigned long long)st.st_size,
676-		    sizeof(struct magic));
677-		goto error;
678+
679+	/* php_magic_database is a const, performing writes will segfault. This is for big-endian
680+	machines only, PPC and Sparc specifically. Consider static variable or MINIT in
681+	future. */
682+	if (needsbyteswap && fn == NULL) {
683+		map->p = emalloc(sizeof(php_magic_database));
684+		map->p = memcpy(map->p, php_magic_database, sizeof(php_magic_database));
685+	}
686+
687+	if (NULL != fn) {
688+		nentries = (uint32_t)(st.sb.st_size / sizeof(struct magic));
689+		entries = (uint32_t)(st.sb.st_size / sizeof(struct magic));
690+		if ((off_t)(entries * sizeof(struct magic)) != st.sb.st_size) {
691+			file_error(ms, 0, "Size of `%s' %llu is not a multiple of %zu",
692+				dbname, (unsigned long long)st.sb.st_size,
693+				sizeof(struct magic));
694+			goto error;
695+		}
696 	}
697 	map->magic[0] = CAST(struct magic *, map->p) + 1;
698 	nentries = 0;
699@@ -2643,22 +2711,29 @@
700 			map->magic[i + 1] = map->magic[i] + map->nmagic[i];
701 		nentries += map->nmagic[i];
702 	}
703-	if (entries != nentries + 1) {
704+	if (NULL != fn && entries != nentries + 1) {
705 		file_error(ms, 0, "Inconsistent entries in `%s' %u != %u",
706 		    dbname, entries, nentries + 1);
707 		goto error;
708 	}
709+
710 	if (needsbyteswap)
711 		for (i = 0; i < MAGIC_SETS; i++)
712 			byteswap(map->magic[i], map->nmagic[i]);
713-	free(dbname);
714+
715+	if (dbname) {
716+		efree(dbname);
717+	}
718 	return map;
719
720 error:
721-	if (fd != -1)
722-		(void)close(fd);
723+	if (stream) {
724+		php_stream_close(stream);
725+	}
726 	apprentice_unmap(map);
727-	free(dbname);
728+	if (dbname) {
729+		efree(dbname);
730+	}
731 	return NULL;
732 }
733
734@@ -2679,14 +2754,23 @@
735 	char *dbname;
736 	int rv = -1;
737 	uint32_t i;
738+	php_stream *stream;
739+
740+	TSRMLS_FETCH();
741
742-	dbname = mkdbname(ms, fn, 1);
743+	dbname = mkdbname(ms, fn, 0);
744
745 	if (dbname == NULL)
746 		goto out;
747
748-	if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1)
749-	{
750+/* wb+ == O_WRONLY|O_CREAT|O_TRUNC|O_BINARY */
751+#if PHP_API_VERSION < 20100412
752+	stream = php_stream_open_wrapper((char *)fn, "wb+", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
753+#else
754+	stream = php_stream_open_wrapper((char *)fn, "wb+", REPORT_ERRORS, NULL);
755+#endif
756+
757+	if (!stream) {
758 		file_error(ms, errno, "cannot open `%s'", dbname);
759 		goto out;
760 	}
761@@ -2696,31 +2780,33 @@
762 		goto out;
763 	}
764
765-	if (write(fd, map->nmagic, nm) != (ssize_t)nm) {
766+	if (php_stream_write(stream, (const char *)map->nmagic, nm) != (ssize_t)nm) {
767 		file_error(ms, errno, "error writing `%s'", dbname);
768 		goto out;
769 	}
770
771 	assert(nm + sizeof(ar) < m);
772
773-	if (lseek(fd, (off_t)m, SEEK_SET) != (off_t)m) {
774+	if (php_stream_seek(stream,(off_t)sizeof(struct magic), SEEK_SET) != sizeof(struct magic)) {
775 		file_error(ms, errno, "error seeking `%s'", dbname);
776 		goto out;
777 	}
778
779 	for (i = 0; i < MAGIC_SETS; i++) {
780 		len = m * map->nmagic[i];
781-		if (write(fd, map->magic[i], len) != (ssize_t)len) {
782+		if (php_stream_write(stream, (const char *)map->magic[i], len) != (ssize_t)len) {
783 			file_error(ms, errno, "error writing `%s'", dbname);
784 			goto out;
785 		}
786 	}
787
788-	if (fd != -1)
789-		(void)close(fd);
790+	if (stream) {
791+		php_stream_close(stream);
792+	}
793+
794 	rv = 0;
795 out:
796-	free(dbname);
797+	efree(dbname);
798 	return rv;
799 }
800
801@@ -2733,6 +2819,7 @@
802 {
803 	const char *p, *q;
804 	char *buf;
805+	TSRMLS_FETCH();
806
807 	if (strip) {
808 		if ((p = strrchr(fn, '/')) != NULL)
809@@ -2754,16 +2841,18 @@
810 	q++;
811 	/* Compatibility with old code that looked in .mime */
812 	if (ms->flags & MAGIC_MIME) {
813-		if (asprintf(&buf, "%.*s.mime%s", (int)(q - fn), fn, ext) < 0)
814-			return NULL;
815-		if (access(buf, R_OK) != -1) {
816+		spprintf(&buf, MAXPATHLEN, "%.*s.mime%s", (int)(q - fn), fn, ext);
817+#ifdef PHP_WIN32
818+		if (VCWD_ACCESS(buf, R_OK) == 0) {
819+#else
820+		if (VCWD_ACCESS(buf, R_OK) != -1) {
821+#endif
822 			ms->flags &= MAGIC_MIME_TYPE;
823 			return buf;
824 		}
825-		free(buf);
826+		efree(buf);
827 	}
828-	if (asprintf(&buf, "%.*s%s", (int)(q - fn), fn, ext) < 0)
829-		return NULL;
830+	spprintf(&buf, MAXPATHLEN, "%.*s%s", (int)(q - fn), fn, ext);
831
832 	/* Compatibility with old code that looked in .mime */
833 	if (strstr(p, ".mime") != NULL)
834@@ -2853,7 +2942,7 @@
835 	m->offset = swap4((uint32_t)m->offset);
836 	m->in_offset = swap4((uint32_t)m->in_offset);
837 	m->lineno = swap4((uint32_t)m->lineno);
838-	if (IS_STRING(m->type)) {
839+	if (IS_LIBMAGIC_STRING(m->type)) {
840 		m->str_range = swap4(m->str_range);
841 		m->str_flags = swap4(m->str_flags);
842 	}
843diff -u libmagic.orig/ascmagic.c libmagic/ascmagic.c
844--- libmagic.orig/ascmagic.c	Wed Oct 31 18:03:01 2012
845+++ libmagic/ascmagic.c	Sun Jan  4 17:02:29 2015
846@@ -139,7 +139,7 @@
847 		/* malloc size is a conservative overestimate; could be
848 		   improved, or at least realloced after conversion. */
849 		mlen = ulen * 6;
850-		if ((utf8_buf = CAST(unsigned char *, malloc(mlen))) == NULL) {
851+		if ((utf8_buf = CAST(unsigned char *, emalloc(mlen))) == NULL) {
852 			file_oomem(ms, mlen);
853 			goto done;
854 		}
855@@ -147,7 +147,7 @@
856 		    == NULL)
857 			goto done;
858 		if ((rv = file_softmagic(ms, utf8_buf,
859-		    (size_t)(utf8_end - utf8_buf), TEXTTEST, text)) == 0)
860+		    (size_t)(utf8_end - utf8_buf), 0, TEXTTEST, text)) == 0)
861 			rv = -1;
862 	}
863
864@@ -211,6 +211,7 @@
865 				case 0:
866 					if (file_printf(ms, ", ") == -1)
867 						goto done;
868+					break;
869 				case -1:
870 					goto done;
871 				default:
872@@ -296,7 +297,8 @@
873 	}
874 	rv = 1;
875 done:
876-	free(utf8_buf);
877+	if (utf8_buf)
878+		efree(utf8_buf);
879
880 	return rv;
881 }
882diff -u libmagic.orig/cdf.c libmagic/cdf.c
883--- libmagic.orig/cdf.c	Thu Mar 21 18:45:14 2013
884+++ libmagic/cdf.c	Sun Jan  4 17:02:29 2015
885@@ -43,7 +43,17 @@
886 #include <err.h>
887 #endif
888 #include <stdlib.h>
889+
890+#ifdef PHP_WIN32
891+#include "win32/unistd.h"
892+#else
893 #include <unistd.h>
894+#endif
895+
896+#ifndef UINT32_MAX
897+# define UINT32_MAX (0xffffffff)
898+#endif
899+
900 #include <string.h>
901 #include <time.h>
902 #include <ctype.h>
903@@ -267,13 +277,15 @@
904 {
905 	const char *b = (const char *)sst->sst_tab;
906 	const char *e = ((const char *)p) + tail;
907+	size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ?
908+	    CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h);
909 	(void)&line;
910-	if (e >= b && (size_t)(e - b) <= CDF_SEC_SIZE(h) * sst->sst_len)
911+	if (e >= b && (size_t)(e - b) <= ss * sst->sst_len)
912 		return 0;
913 	DPRINTF(("%d: offset begin %p < end %p || %" SIZE_T_FORMAT "u"
914 	    " > %" SIZE_T_FORMAT "u [%" SIZE_T_FORMAT "u %"
915 	    SIZE_T_FORMAT "u]\n", line, b, e, (size_t)(e - b),
916-	    CDF_SEC_SIZE(h) * sst->sst_len, CDF_SEC_SIZE(h), sst->sst_len));
917+	    ss * sst->sst_len, ss, sst->sst_len));
918 	errno = EFTYPE;
919 	return -1;
920 }
921@@ -296,7 +308,10 @@
922 	if (info->i_fd == -1)
923 		return -1;
924
925-	if (pread(info->i_fd, buf, len, off) != (ssize_t)len)
926+	if (FINFO_LSEEK_FUNC(info->i_fd, off, SEEK_SET) == (off_t)-1)
927+		return -1;
928+
929+	if (FINFO_READ_FUNC(info->i_fd, buf, len) != (ssize_t)len)
930 		return -1;
931
932 	return (ssize_t)len;
933@@ -352,10 +367,10 @@
934 	size_t ss = CDF_SHORT_SEC_SIZE(h);
935 	size_t pos = CDF_SHORT_SEC_POS(h, id);
936 	assert(ss == len);
937-	if (pos > CDF_SEC_SIZE(h) * sst->sst_len) {
938+	if (pos + len > CDF_SEC_SIZE(h) * sst->sst_len) {
939 		DPRINTF(("Out of bounds read %" SIZE_T_FORMAT "u > %"
940 		    SIZE_T_FORMAT "u\n",
941-		    pos, CDF_SEC_SIZE(h) * sst->sst_len));
942+		    pos + len, CDF_SEC_SIZE(h) * sst->sst_len));
943 		return -1;
944 	}
945 	(void)memcpy(((char *)buf) + offs,
946@@ -455,7 +470,8 @@
947 cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size)
948 {
949 	size_t i, j;
950-	cdf_secid_t maxsector = (cdf_secid_t)(sat->sat_len * size);
951+	cdf_secid_t maxsector = (cdf_secid_t)((sat->sat_len * size)
952+	    / sizeof(maxsector));
953
954 	DPRINTF(("Chain:"));
955 	for (j = i = 0; sid >= 0; i++, j++) {
956@@ -465,8 +481,8 @@
957 			errno = EFTYPE;
958 			return (size_t)-1;
959 		}
960-		if (sid > maxsector) {
961-			DPRINTF(("Sector %d > %d\n", sid, maxsector));
962+		if (sid >= maxsector) {
963+			DPRINTF(("Sector %d >= %d\n", sid, maxsector));
964 			errno = EFTYPE;
965 			return (size_t)-1;
966 		}
967@@ -796,11 +812,15 @@
968 	if (cdf_check_stream_offset(sst, h, e, 0, __LINE__) == -1)
969 		goto out;
970 	for (i = 0; i < sh.sh_properties; i++) {
971-		size_t ofs = CDF_GETUINT32(p, (i << 1) + 1);
972+		size_t ofs, tail = (i << 1) + 1;
973+		if (cdf_check_stream_offset(sst, h, p, tail * sizeof(uint32_t),
974+		    __LINE__) == -1)
975+			goto out;
976+		ofs = CDF_GETUINT32(p, tail);
977 		q = (const uint8_t *)(const void *)
978 		    ((const char *)(const void *)p + ofs
979 		    - 2 * sizeof(uint32_t));
980-		if (q > e) {
981+		if (q < p || q > e) {
982 			DPRINTF(("Ran of the end %p > %p\n", q, e));
983 			goto out;
984 		}
985@@ -810,6 +830,10 @@
986 		    i, inp[i].pi_id, inp[i].pi_type, q - p, offs));
987 		if (inp[i].pi_type & CDF_VECTOR) {
988 			nelements = CDF_GETUINT32(q, 1);
989+			if (nelements == 0) {
990+				DPRINTF(("CDF_VECTOR with nelements == 0\n"));
991+				goto out;
992+			}
993 			o = 2;
994 		} else {
995 			nelements = 1;
996@@ -884,7 +908,9 @@
997 			}
998 			DPRINTF(("nelements = %" SIZE_T_FORMAT "u\n",
999 			    nelements));
1000-			for (j = 0; j < nelements; j++, i++) {
1001+			for (j = 0; j < nelements && i < sh.sh_properties;
1002+			    j++, i++)
1003+			{
1004 				uint32_t l = CDF_GETUINT32(q, o);
1005 				inp[i].pi_str.s_len = l;
1006 				inp[i].pi_str.s_buf = (const char *)
1007@@ -929,7 +955,7 @@
1008 cdf_unpack_summary_info(const cdf_stream_t *sst, const cdf_header_t *h,
1009     cdf_summary_info_header_t *ssi, cdf_property_info_t **info, size_t *count)
1010 {
1011-	size_t i, maxcount;
1012+	size_t maxcount;
1013 	const cdf_summary_info_header_t *si =
1014 	    CAST(const cdf_summary_info_header_t *, sst->sst_tab);
1015 	const cdf_section_declaration_t *sd =
1016@@ -944,21 +970,13 @@
1017 	ssi->si_os = CDF_TOLE2(si->si_os);
1018 	ssi->si_class = si->si_class;
1019 	cdf_swap_class(&ssi->si_class);
1020-	ssi->si_count = CDF_TOLE2(si->si_count);
1021+	ssi->si_count = CDF_TOLE4(si->si_count);
1022 	*count = 0;
1023 	maxcount = 0;
1024 	*info = NULL;
1025-	for (i = 0; i < CDF_TOLE4(si->si_count); i++) {
1026-		if (i >= CDF_LOOP_LIMIT) {
1027-			DPRINTF(("Unpack summary info loop limit"));
1028-			errno = EFTYPE;
1029-			return -1;
1030-		}
1031-		if (cdf_read_property_info(sst, h, CDF_TOLE4(sd->sd_offset),
1032-		    info, count, &maxcount) == -1) {
1033+	if (cdf_read_property_info(sst, h, CDF_TOLE4(sd->sd_offset), info,
1034+		count, &maxcount) == -1)
1035 			return -1;
1036-		}
1037-	}
1038 	return 0;
1039 }
1040
1041@@ -1132,7 +1150,7 @@
1042 	cdf_directory_t *d;
1043 	char name[__arraycount(d->d_name)];
1044 	cdf_stream_t scn;
1045-	struct timespec ts;
1046+	struct timeval ts;
1047
1048 	static const char *types[] = { "empty", "user storage",
1049 	    "user stream", "lockbytes", "property", "root storage" };
1050@@ -1185,7 +1203,7 @@
1051 cdf_dump_property_info(const cdf_property_info_t *info, size_t count)
1052 {
1053 	cdf_timestamp_t tp;
1054-	struct timespec ts;
1055+	struct timeval ts;
1056 	char buf[64];
1057 	size_t i, j;
1058
1059@@ -1229,7 +1247,11 @@
1060 			break;
1061 		case CDF_FILETIME:
1062 			tp = info[i].pi_tp;
1063+#if defined(PHP_WIN32) && _MSC_VER <= 1500
1064+		if (tp < 1000000000000000i64) {
1065+#else
1066 			if (tp < 1000000000000000LL) {
1067+#endif
1068 				cdf_print_elapsed_time(buf, sizeof(buf), tp);
1069 				(void)fprintf(stderr, "timestamp %s\n", buf);
1070 			} else {
1071diff -u libmagic.orig/cdf.h libmagic/cdf.h
1072--- libmagic.orig/cdf.h	Wed Oct 31 18:03:01 2012
1073+++ libmagic/cdf.h	Sun Jan  4 17:02:29 2015
1074@@ -35,10 +35,12 @@
1075 #ifndef _H_CDF_
1076 #define _H_CDF_
1077
1078-#ifdef WIN32
1079+#ifdef PHP_WIN32
1080 #include <winsock2.h>
1081 #define timespec timeval
1082 #define tv_nsec tv_usec
1083+#define asctime_r php_asctime_r
1084+#define ctime_r php_ctime_r
1085 #endif
1086 #ifdef __DJGPP__
1087 #define timespec timeval
1088@@ -57,7 +59,11 @@
1089
1090 typedef struct {
1091 	uint64_t	h_magic;
1092-#define CDF_MAGIC	0xE11AB1A1E011CFD0LL
1093+#if defined(PHP_WIN32) && _MSC_VER <= 1500
1094+# define CDF_MAGIC	0xE11AB1A1E011CFD0i64
1095+#else
1096+# define CDF_MAGIC	0xE11AB1A1E011CFD0LL
1097+#endif
1098 	uint64_t	h_uuid[2];
1099 	uint16_t	h_revision;
1100 	uint16_t	h_version;
1101@@ -267,9 +273,9 @@
1102 	size_t i_len;
1103 } cdf_info_t;
1104
1105-struct timespec;
1106-int cdf_timestamp_to_timespec(struct timespec *, cdf_timestamp_t);
1107-int cdf_timespec_to_timestamp(cdf_timestamp_t *, const struct timespec *);
1108+struct timeval;
1109+int cdf_timestamp_to_timespec(struct timeval *, cdf_timestamp_t);
1110+int cdf_timespec_to_timestamp(cdf_timestamp_t *, const struct timeval *);
1111 int cdf_read_header(const cdf_info_t *, cdf_header_t *);
1112 void cdf_swap_header(cdf_header_t *);
1113 void cdf_unpack_header(cdf_header_t *, char *);
1114diff -u libmagic.orig/cdf_time.c libmagic/cdf_time.c
1115--- libmagic.orig/cdf_time.c	Wed Oct 31 18:03:01 2012
1116+++ libmagic/cdf_time.c	Sun Nov  9 19:16:18 2014
1117@@ -96,7 +96,7 @@
1118 }
1119
1120 int
1121-cdf_timestamp_to_timespec(struct timespec *ts, cdf_timestamp_t t)
1122+cdf_timestamp_to_timespec(struct timeval *ts, cdf_timestamp_t t)
1123 {
1124 	struct tm tm;
1125 #ifdef HAVE_STRUCT_TM_TM_ZONE
1126@@ -104,8 +104,9 @@
1127 #endif
1128 	int rdays;
1129
1130-	/* Unit is 100's of nanoseconds */
1131-	ts->tv_nsec = (t % CDF_TIME_PREC) * 100;
1132+	/* XXX 5.14 at least introdced 100 ns intervals, this is to do */
1133+	/* Time interval, in microseconds */
1134+	ts->tv_usec = (t % CDF_TIME_PREC) * CDF_TIME_PREC;
1135
1136 	t /= CDF_TIME_PREC;
1137 	tm.tm_sec = (int)(t % 60);
1138@@ -117,7 +118,7 @@
1139 	tm.tm_hour = (int)(t % 24);
1140 	t /= 24;
1141
1142-	// XXX: Approx
1143+	/* XXX: Approx */
1144 	tm.tm_year = (int)(CDF_BASE_YEAR + (t / 365));
1145
1146 	rdays = cdf_getdays(tm.tm_year);
1147@@ -144,7 +145,7 @@
1148
1149 int
1150 /*ARGSUSED*/
1151-cdf_timespec_to_timestamp(cdf_timestamp_t *t, const struct timespec *ts)
1152+cdf_timespec_to_timestamp(cdf_timestamp_t *t, const struct timeval *ts)
1153 {
1154 #ifndef __lint__
1155 	(void)&t;
1156@@ -156,7 +157,7 @@
1157 		errno = EINVAL;
1158 		return -1;
1159 	}
1160-	*t = (ts->ts_nsec / 100) * CDF_TIME_PREC;
1161+	*t = (ts->ts_usec / CDF_TIME_PREC) * CDF_TIME_PREC;
1162 	*t = tm.tm_sec;
1163 	*t += tm.tm_min * 60;
1164 	*t += tm.tm_hour * 60 * 60;
1165@@ -180,7 +181,7 @@
1166 int
1167 main(int argc, char *argv[])
1168 {
1169-	struct timespec ts;
1170+	struct timeval ts;
1171 	char buf[25];
1172 	static const cdf_timestamp_t tst = 0x01A5E403C2D59C00ULL;
1173 	static const char *ref = "Sat Apr 23 01:30:00 1977";
1174diff -u libmagic.orig/compress.c libmagic/compress.c
1175--- libmagic.orig/compress.c	Sun Jan  6 21:35:43 2013
1176+++ libmagic/compress.c	Sun Jan  4 17:02:29 2015
1177@@ -32,6 +32,7 @@
1178  *	uncompress(method, old, n, newch) - uncompress old into new,
1179  *					    using method, return sizeof new
1180  */
1181+#include "config.h"
1182 #include "file.h"
1183
1184 #ifndef lint
1185@@ -45,7 +46,8 @@
1186 #endif
1187 #include <string.h>
1188 #include <errno.h>
1189-#ifndef __MINGW32__
1190+#include <sys/types.h>
1191+#ifndef PHP_WIN32
1192 #include <sys/ioctl.h>
1193 #endif
1194 #ifdef HAVE_SYS_WAIT_H
1195@@ -59,6 +61,9 @@
1196 #include <zlib.h>
1197 #endif
1198
1199+#undef FIONREAD
1200+
1201+
1202 private const struct {
1203 	const char magic[8];
1204 	size_t maglen;
1205@@ -85,8 +90,7 @@
1206 #define NODATA ((size_t)~0)
1207
1208 private ssize_t swrite(int, const void *, size_t);
1209-#if HAVE_FORK
1210-private size_t ncompr = sizeof(compr) / sizeof(compr[0]);
1211+#ifdef PHP_FILEINFO_UNCOMPRESS
1212 private size_t uncompressbuf(struct magic_set *, int, size_t,
1213     const unsigned char *, unsigned char **, size_t);
1214 #ifdef BUILTIN_DECOMPRESS
1215@@ -102,10 +106,13 @@
1216 	size_t i, nsz;
1217 	int rv = 0;
1218 	int mime = ms->flags & MAGIC_MIME;
1219+	size_t ncompr;
1220
1221 	if ((ms->flags & MAGIC_COMPRESS) == 0)
1222 		return 0;
1223
1224+	ncompr = sizeof(compr) / sizeof(compr[0]);
1225+
1226 	for (i = 0; i < ncompr; i++) {
1227 		if (nbytes < compr[i].maglen)
1228 			continue;
1229@@ -134,7 +141,8 @@
1230 		}
1231 	}
1232 error:
1233-	free(newbuf);
1234+	if (newbuf)
1235+		efree(newbuf);
1236 	ms->flags |= MAGIC_COMPRESS;
1237 	return rv;
1238 }
1239@@ -168,7 +176,7 @@
1240  * `safe' read for sockets and pipes.
1241  */
1242 protected ssize_t
1243-sread(int fd, void *buf, size_t n, int canbepipe __attribute__((__unused__)))
1244+sread(int fd, void *buf, size_t n, int canbepipe)
1245 {
1246 	ssize_t rv;
1247 #ifdef FIONREAD
1248@@ -216,7 +224,7 @@
1249
1250 nocheck:
1251 	do
1252-		switch ((rv = read(fd, buf, n))) {
1253+		switch ((rv = FINFO_READ_FUNC(fd, buf, n))) {
1254 		case -1:
1255 			if (errno == EINTR)
1256 				continue;
1257@@ -293,13 +301,14 @@
1258 		return -1;
1259 	}
1260 	(void)close(tfd);
1261-	if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
1262+	if (FINFO_LSEEK_FUNC(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
1263 		file_badseek(ms);
1264 		return -1;
1265 	}
1266 	return fd;
1267 }
1268-#if HAVE_FORK
1269+
1270+#ifdef PHP_FILEINFO_UNCOMPRESS
1271 #ifdef BUILTIN_DECOMPRESS
1272
1273 #define FHCRC		(1 << 1)
1274@@ -336,7 +345,7 @@
1275
1276 	if (data_start >= n)
1277 		return 0;
1278-	if ((*newch = CAST(unsigned char *, malloc(HOWMANY + 1))) == NULL) {
1279+	if ((*newch = CAST(unsigned char *, emalloc(HOWMANY + 1))) == NULL) {
1280 		return 0;
1281 	}
1282
1283@@ -397,19 +406,16 @@
1284 	case 0:	/* child */
1285 		(void) close(0);
1286 		if (fd != -1) {
1287-		    if (dup(fd) == -1)
1288-			_exit(1);
1289-		    (void) lseek(0, (off_t)0, SEEK_SET);
1290+		    (void) dup(fd);
1291+		    (void) FINFO_LSEEK_FUNC(0, (off_t)0, SEEK_SET);
1292 		} else {
1293-		    if (dup(fdin[0]) == -1)
1294-			_exit(1);
1295+		    (void) dup(fdin[0]);
1296 		    (void) close(fdin[0]);
1297 		    (void) close(fdin[1]);
1298 		}
1299
1300 		(void) close(1);
1301-		if (dup(fdout[1]) == -1)
1302-			_exit(1);
1303+		(void) dup(fdout[1]);
1304 		(void) close(fdout[0]);
1305 		(void) close(fdout[1]);
1306 #ifndef DEBUG
1307@@ -466,20 +472,14 @@
1308 			fdin[1] = -1;
1309 		}
1310
1311-		if ((*newch = (unsigned char *) malloc(HOWMANY + 1)) == NULL) {
1312-#ifdef DEBUG
1313-			(void)fprintf(stderr, "Malloc failed (%s)\n",
1314-			    strerror(errno));
1315-#endif
1316-			n = 0;
1317-			goto err;
1318-		}
1319+		*newch = (unsigned char *) emalloc(HOWMANY + 1);
1320+
1321 		if ((r = sread(fdout[0], *newch, HOWMANY, 0)) <= 0) {
1322 #ifdef DEBUG
1323 			(void)fprintf(stderr, "Read failed (%s)\n",
1324 			    strerror(errno));
1325 #endif
1326-			free(*newch);
1327+			efree(*newch);
1328 			n = 0;
1329 			newch[0] = '\0';
1330 			goto err;
1331@@ -503,4 +503,4 @@
1332 		return n;
1333 	}
1334 }
1335-#endif
1336+#endif /* if PHP_FILEINFO_UNCOMPRESS */
1337diff -u libmagic.orig/file.h libmagic/file.h
1338--- libmagic.orig/file.h	Mon Feb 18 16:40:59 2013
1339+++ libmagic/file.h	Sun Jan  4 17:02:29 2015
1340@@ -33,11 +33,9 @@
1341 #ifndef __file_h__
1342 #define __file_h__
1343
1344-#ifdef HAVE_CONFIG_H
1345-#include <config.h>
1346-#endif
1347+#include "config.h"
1348
1349-#ifdef WIN32
1350+#ifdef PHP_WIN32
1351   #ifdef _WIN64
1352     #define SIZE_T_FORMAT "I64"
1353   #else
1354@@ -61,10 +59,20 @@
1355 #ifdef HAVE_INTTYPES_H
1356 #include <inttypes.h>
1357 #endif
1358-#include <regex.h>
1359-#include <time.h>
1360+#ifdef PHP_WIN32
1361+#include "win32/php_stdint.h"
1362+#endif
1363+
1364+#include "php.h"
1365+#include "ext/standard/php_string.h"
1366+#include "ext/pcre/php_pcre.h"
1367+
1368 #include <sys/types.h>
1369+#ifdef PHP_WIN32
1370+#include "win32/param.h"
1371+#else
1372 #include <sys/param.h>
1373+#endif
1374 /* Do this here and now, because struct stat gets re-defined on solaris */
1375 #include <sys/stat.h>
1376 #include <stdarg.h>
1377@@ -75,7 +83,7 @@
1378 #define MAGIC "/etc/magic"
1379 #endif
1380
1381-#if defined(__EMX__) || defined (WIN32)
1382+#if defined(__EMX__) || defined(PHP_WIN32)
1383 #define PATHSEP	';'
1384 #else
1385 #define PATHSEP	':'
1386@@ -109,12 +117,6 @@
1387 #endif
1388 #endif
1389
1390-#ifndef __GNUC__
1391-#ifndef __attribute__
1392-#define __attribute__(a)
1393-#endif
1394-#endif
1395-
1396 #ifndef MIN
1397 #define	MIN(a,b)	(((a) < (b)) ? (a) : (b))
1398 #endif
1399@@ -224,7 +226,7 @@
1400 #define				FILE_USE	46
1401 #define				FILE_NAMES_SIZE	47 /* size of array to contain all names */
1402
1403-#define IS_STRING(t) \
1404+#define IS_LIBMAGIC_STRING(t) \
1405 	((t) == FILE_STRING || \
1406 	 (t) == FILE_PSTRING || \
1407 	 (t) == FILE_BESTRING16 || \
1408@@ -248,7 +250,7 @@
1409 #ifdef ENABLE_CONDITIONALS
1410 	uint8_t cond;		/* conditional type */
1411 #else
1412-	uint8_t dummy;
1413+	uint8_t dummy;
1414 #endif
1415 	uint8_t factor_op;
1416 #define		FILE_FACTOR_OP_PLUS	'+'
1417@@ -347,7 +349,7 @@
1418 /* list of magic entries */
1419 struct mlist {
1420 	struct magic *magic;		/* array of magic entries */
1421-	uint32_t nmagic;		/* number of entries in array */
1422+	uint32_t nmagic;			/* number of entries in array */
1423 	void *map;			/* internal resources used by entry */
1424 	struct mlist *next, *prev;
1425 };
1426@@ -411,21 +413,16 @@
1427 protected const char *file_fmttime(uint64_t, int, char *);
1428 protected struct magic_set *file_ms_alloc(int);
1429 protected void file_ms_free(struct magic_set *);
1430-protected int file_buffer(struct magic_set *, int, const char *, const void *,
1431+protected int file_buffer(struct magic_set *, php_stream *, const char *, const void *,
1432     size_t);
1433-protected int file_fsmagic(struct magic_set *, const char *, struct stat *);
1434+protected int file_fsmagic(struct magic_set *, const char *, struct stat *, php_stream *);
1435 protected int file_pipe2file(struct magic_set *, int, const void *, size_t);
1436-protected int file_vprintf(struct magic_set *, const char *, va_list);
1437-protected size_t file_printedlen(const struct magic_set *);
1438 protected int file_replace(struct magic_set *, const char *, const char *);
1439-protected int file_printf(struct magic_set *, const char *, ...)
1440-    __attribute__((__format__(__printf__, 2, 3)));
1441+protected int file_printf(struct magic_set *, const char *, ...);
1442 protected int file_reset(struct magic_set *);
1443-protected int file_tryelf(struct magic_set *, int, const unsigned char *,
1444-    size_t);
1445 protected int file_trycdf(struct magic_set *, int, const unsigned char *,
1446     size_t);
1447-#if HAVE_FORK
1448+#ifdef PHP_FILEINFO_UNCOMPRESS
1449 protected int file_zmagic(struct magic_set *, int, const char *,
1450     const unsigned char *, size_t);
1451 #endif
1452@@ -438,21 +435,18 @@
1453     unichar **, size_t *, const char **, const char **, const char **);
1454 protected int file_is_tar(struct magic_set *, const unsigned char *, size_t);
1455 protected int file_softmagic(struct magic_set *, const unsigned char *, size_t,
1456-    int, int);
1457+    size_t, int, int);
1458 protected int file_apprentice(struct magic_set *, const char *, int);
1459 protected int file_magicfind(struct magic_set *, const char *, struct mlist *);
1460 protected uint64_t file_signextend(struct magic_set *, struct magic *,
1461     uint64_t);
1462+protected void file_delmagic(struct magic *, int type, size_t entries);
1463 protected void file_badread(struct magic_set *);
1464 protected void file_badseek(struct magic_set *);
1465 protected void file_oomem(struct magic_set *, size_t);
1466-protected void file_error(struct magic_set *, int, const char *, ...)
1467-    __attribute__((__format__(__printf__, 3, 4)));
1468-protected void file_magerror(struct magic_set *, const char *, ...)
1469-    __attribute__((__format__(__printf__, 2, 3)));
1470-protected void file_magwarn(struct magic_set *, const char *, ...)
1471-    __attribute__((__format__(__printf__, 2, 3)));
1472-protected void file_mdump(struct magic *);
1473+protected void file_error(struct magic_set *, int, const char *, ...);
1474+protected void file_magerror(struct magic_set *, const char *, ...);
1475+protected void file_magwarn(struct magic_set *, const char *, ...);
1476 protected void file_showstr(FILE *, const char *, size_t);
1477 protected size_t file_mbswidth(const char *);
1478 protected const char *file_getbuffer(struct magic_set *);
1479@@ -462,16 +456,14 @@
1480     size_t *);
1481 protected size_t file_pstring_length_size(const struct magic *);
1482 protected size_t file_pstring_get_length(const struct magic *, const char *);
1483+protected size_t file_printedlen(const struct magic_set *ms);
1484 #ifdef __EMX__
1485 protected int file_os2_apptype(struct magic_set *, const char *, const void *,
1486     size_t);
1487 #endif /* __EMX__ */
1488
1489-
1490-#ifndef COMPILE_ONLY
1491 extern const char *file_names[];
1492 extern const size_t file_nnames;
1493-#endif
1494
1495 #ifndef HAVE_STRERROR
1496 extern int sys_nerr;
1497@@ -484,32 +476,16 @@
1498 #define strtoul(a, b, c)	strtol(a, b, c)
1499 #endif
1500
1501-#ifndef HAVE_PREAD
1502-ssize_t pread(int, void *, size_t, off_t);
1503-#endif
1504-#ifndef HAVE_VASPRINTF
1505-int vasprintf(char **, const char *, va_list);
1506-#endif
1507-#ifndef HAVE_ASPRINTF
1508-int asprintf(char **ptr, const char *format_string, ...);
1509-#endif
1510-
1511-#ifndef HAVE_STRLCPY
1512+#ifndef strlcpy
1513 size_t strlcpy(char *dst, const char *src, size_t siz);
1514 #endif
1515-#ifndef HAVE_STRLCAT
1516+#ifndef strlcat
1517 size_t strlcat(char *dst, const char *src, size_t siz);
1518 #endif
1519 #ifndef HAVE_GETLINE
1520 ssize_t getline(char **dst, size_t *len, FILE *fp);
1521 ssize_t getdelim(char **dst, size_t *len, int delimiter, FILE *fp);
1522 #endif
1523-#ifndef HAVE_CTIME_R
1524-char   *ctime_r(const time_t *, char *);
1525-#endif
1526-#ifndef HAVE_ASCTIME_R
1527-char   *asctime_r(const struct tm *, char *);
1528-#endif
1529
1530 #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H) && !defined(QUICK)
1531 #define QUICK
1532@@ -531,6 +507,14 @@
1533 #endif
1534 #else
1535 #define FILE_RCSID(id)
1536+#endif
1537+
1538+#ifdef PHP_WIN32
1539+#define FINFO_LSEEK_FUNC _lseek
1540+#define FINFO_READ_FUNC _read
1541+#else
1542+#define FINFO_LSEEK_FUNC lseek
1543+#define FINFO_READ_FUNC read
1544 #endif
1545
1546 #endif /* __file_h__ */
1547diff -u libmagic.orig/fsmagic.c libmagic/fsmagic.c
1548--- libmagic.orig/fsmagic.c	Thu Mar 21 18:45:14 2013
1549+++ libmagic/fsmagic.c	Sun Jan  4 17:02:29 2015
1550@@ -59,27 +59,21 @@
1551 # define minor(dev)  ((dev) & 0xff)
1552 #endif
1553 #undef HAVE_MAJOR
1554-#ifdef	S_IFLNK
1555-private int
1556-bad_link(struct magic_set *ms, int err, char *buf)
1557-{
1558-	int mime = ms->flags & MAGIC_MIME;
1559-	if ((mime & MAGIC_MIME_TYPE) &&
1560-	    file_printf(ms, "inode/symlink")
1561-	    == -1)
1562-		return -1;
1563-	else if (!mime) {
1564-		if (ms->flags & MAGIC_ERROR) {
1565-			file_error(ms, err,
1566-				   "broken symbolic link to `%s'", buf);
1567-			return -1;
1568-		}
1569-		if (file_printf(ms, "broken symbolic link to `%s'", buf) == -1)
1570-			return -1;
1571-	}
1572-	return 1;
1573-}
1574+
1575+#ifdef PHP_WIN32
1576+
1577+# undef S_IFIFO
1578+#endif
1579+
1580+
1581+#ifndef S_ISDIR
1582+#define S_ISDIR(mode) ((mode) & _S_IFDIR)
1583+#endif
1584+
1585+#ifndef S_ISREG
1586+#define S_ISREG(mode) ((mode) & _S_IFREG)
1587 #endif
1588+
1589 private int
1590 handle_mime(struct magic_set *ms, int mime, const char *str)
1591 {
1592@@ -96,49 +90,45 @@
1593 }
1594
1595 protected int
1596-file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
1597+file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *stream)
1598 {
1599 	int ret, did = 0;
1600 	int mime = ms->flags & MAGIC_MIME;
1601-#ifdef	S_IFLNK
1602-	char buf[BUFSIZ+4];
1603-	ssize_t nch;
1604-	struct stat tstatbuf;
1605-#endif
1606+	TSRMLS_FETCH();
1607
1608 	if (ms->flags & MAGIC_APPLE)
1609 		return 0;
1610-	if (fn == NULL)
1611+
1612+	if (fn == NULL && !stream) {
1613 		return 0;
1614+	}
1615
1616 #define COMMA	(did++ ? ", " : "")
1617-	/*
1618-	 * Fstat is cheaper but fails for files you don't have read perms on.
1619-	 * On 4.2BSD and similar systems, use lstat() to identify symlinks.
1620-	 */
1621-#ifdef	S_IFLNK
1622-	if ((ms->flags & MAGIC_SYMLINK) == 0)
1623-		ret = lstat(fn, sb);
1624-	else
1625-#endif
1626-	ret = stat(fn, sb);	/* don't merge into if; see "ret =" above */
1627-
1628-	if (ret) {
1629-		if (ms->flags & MAGIC_ERROR) {
1630-			file_error(ms, errno, "cannot stat `%s'", fn);
1631-			return -1;
1632+
1633+	if (stream) {
1634+		php_stream_statbuf ssb;
1635+		if (php_stream_stat(stream, &ssb) < 0) {
1636+			if (ms->flags & MAGIC_ERROR) {
1637+				file_error(ms, errno, "cannot stat `%s'", fn);
1638+				return -1;
1639+			}
1640+			return 1;
1641+		}
1642+		memcpy(sb, &ssb.sb, sizeof(struct stat));
1643+	} else {
1644+		if (php_sys_stat(fn, sb) != 0) {
1645+			if (ms->flags & MAGIC_ERROR) {
1646+				file_error(ms, errno, "cannot stat `%s'", fn);
1647+				return -1;
1648+			}
1649+			return 1;
1650 		}
1651-		if (file_printf(ms, "cannot open `%s' (%s)",
1652-		    fn, strerror(errno)) == -1)
1653-			return -1;
1654-		ms->event_flags |= EVENT_HAD_ERR;
1655-		return -1;
1656 	}
1657
1658 	ret = 1;
1659 	if (!mime) {
1660 #ifdef S_ISUID
1661-		if (sb->st_mode & S_ISUID)
1662+		if (sb->st_mode & S_ISUID)
1663 			if (file_printf(ms, "%ssetuid", COMMA) == -1)
1664 				return -1;
1665 #endif
1666@@ -155,82 +145,43 @@
1667 	}
1668
1669 	switch (sb->st_mode & S_IFMT) {
1670-	case S_IFDIR:
1671-		if (mime) {
1672-			if (handle_mime(ms, mime, "directory") == -1)
1673-				return -1;
1674-		} else if (file_printf(ms, "%sdirectory", COMMA) == -1)
1675-			return -1;
1676-		break;
1677-#ifdef S_IFCHR
1678-	case S_IFCHR:
1679-		/*
1680-		 * If -s has been specified, treat character special files
1681-		 * like ordinary files.  Otherwise, just report that they
1682-		 * are block special files and go on to the next file.
1683-		 */
1684-		if ((ms->flags & MAGIC_DEVICES) != 0) {
1685-			ret = 0;
1686-			break;
1687-		}
1688-		if (mime) {
1689-			if (handle_mime(ms, mime, "chardevice") == -1)
1690-				return -1;
1691-		} else {
1692-#ifdef HAVE_STAT_ST_RDEV
1693-# ifdef dv_unit
1694+#ifndef PHP_WIN32
1695+# ifdef S_IFCHR
1696+		case S_IFCHR:
1697+			/*
1698+			 * If -s has been specified, treat character special files
1699+			 * like ordinary files.  Otherwise, just report that they
1700+			 * are block special files and go on to the next file.
1701+			 */
1702+			if ((ms->flags & MAGIC_DEVICES) != 0) {
1703+				ret = 0;
1704+				break;
1705+			}
1706+			if (mime) {
1707+				if (handle_mime(ms, mime, "x-character-device") == -1)
1708+					return -1;
1709+			} else {
1710+#  ifdef HAVE_STAT_ST_RDEV
1711+#   ifdef dv_unit
1712 			if (file_printf(ms, "%scharacter special (%d/%d/%d)",
1713 			    COMMA, major(sb->st_rdev), dv_unit(sb->st_rdev),
1714-					dv_subunit(sb->st_rdev)) == -1)
1715-				return -1;
1716-# else
1717+						dv_subunit(sb->st_rdev)) == -1)
1718+					return -1;
1719+#   else
1720 			if (file_printf(ms, "%scharacter special (%ld/%ld)",
1721 			    COMMA, (long)major(sb->st_rdev),
1722 			    (long)minor(sb->st_rdev)) == -1)
1723-				return -1;
1724-# endif
1725-#else
1726+					return -1;
1727+#   endif
1728+#  else
1729 			if (file_printf(ms, "%scharacter special", COMMA) == -1)
1730-				return -1;
1731-#endif
1732-		}
1733-		break;
1734-#endif
1735-#ifdef S_IFBLK
1736-	case S_IFBLK:
1737-		/*
1738-		 * If -s has been specified, treat block special files
1739-		 * like ordinary files.  Otherwise, just report that they
1740-		 * are block special files and go on to the next file.
1741-		 */
1742-		if ((ms->flags & MAGIC_DEVICES) != 0) {
1743-			ret = 0;
1744-			break;
1745-		}
1746-		if (mime) {
1747-			if (handle_mime(ms, mime, "blockdevice") == -1)
1748-				return -1;
1749-		} else {
1750-#ifdef HAVE_STAT_ST_RDEV
1751-# ifdef dv_unit
1752-			if (file_printf(ms, "%sblock special (%d/%d/%d)",
1753-			    COMMA, major(sb->st_rdev), dv_unit(sb->st_rdev),
1754-			    dv_subunit(sb->st_rdev)) == -1)
1755-				return -1;
1756-# else
1757-			if (file_printf(ms, "%sblock special (%ld/%ld)",
1758-			    COMMA, (long)major(sb->st_rdev),
1759-			    (long)minor(sb->st_rdev)) == -1)
1760-				return -1;
1761+					return -1;
1762+#  endif
1763+			}
1764+			return 1;
1765 # endif
1766-#else
1767-			if (file_printf(ms, "%sblock special", COMMA) == -1)
1768-				return -1;
1769 #endif
1770-		}
1771-		break;
1772-#endif
1773-	/* TODO add code to handle V7 MUX and Blit MUX files */
1774+
1775 #ifdef	S_IFIFO
1776 	case S_IFIFO:
1777 		if((ms->flags & MAGIC_DEVICES) != 0)
1778@@ -253,79 +204,14 @@
1779 #endif
1780 #ifdef	S_IFLNK
1781 	case S_IFLNK:
1782-		if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
1783+		/* stat is used, if it made here then the link is broken */
1784 			if (ms->flags & MAGIC_ERROR) {
1785-			    file_error(ms, errno, "unreadable symlink `%s'",
1786-				fn);
1787+			    file_error(ms, errno, "unreadable symlink `%s'", fn);
1788 			    return -1;
1789 			}
1790-			if (mime) {
1791-				if (handle_mime(ms, mime, "symlink") == -1)
1792-					return -1;
1793-			} else if (file_printf(ms,
1794-			    "%sunreadable symlink `%s' (%s)", COMMA, fn,
1795-			    strerror(errno)) == -1)
1796-				return -1;
1797-			break;
1798-		}
1799-		buf[nch] = '\0';	/* readlink(2) does not do this */
1800-
1801-		/* If broken symlink, say so and quit early. */
1802-		if (*buf == '/') {
1803-			if (stat(buf, &tstatbuf) < 0)
1804-				return bad_link(ms, errno, buf);
1805-		} else {
1806-			char *tmp;
1807-			char buf2[BUFSIZ+BUFSIZ+4];
1808-
1809-			if ((tmp = strrchr(fn,  '/')) == NULL) {
1810-				tmp = buf; /* in current directory anyway */
1811-			} else {
1812-				if (tmp - fn + 1 > BUFSIZ) {
1813-					if (ms->flags & MAGIC_ERROR) {
1814-						file_error(ms, 0,
1815-						    "path too long: `%s'", buf);
1816-						return -1;
1817-					}
1818-					if (mime) {
1819-						if (handle_mime(ms, mime,
1820-						    "x-path-too-long") == -1)
1821-							return -1;
1822-					} else if (file_printf(ms,
1823-					    "%spath too long: `%s'", COMMA,
1824-					    fn) == -1)
1825-						return -1;
1826-					break;
1827-				}
1828-				/* take dir part */
1829-				(void)strlcpy(buf2, fn, sizeof buf2);
1830-				buf2[tmp - fn + 1] = '\0';
1831-				/* plus (rel) link */
1832-				(void)strlcat(buf2, buf, sizeof buf2);
1833-				tmp = buf2;
1834-			}
1835-			if (stat(tmp, &tstatbuf) < 0)
1836-				return bad_link(ms, errno, buf);
1837-		}
1838-
1839-		/* Otherwise, handle it. */
1840-		if ((ms->flags & MAGIC_SYMLINK) != 0) {
1841-			const char *p;
1842-			ms->flags &= MAGIC_SYMLINK;
1843-			p = magic_file(ms, buf);
1844-			ms->flags |= MAGIC_SYMLINK;
1845-			if (p == NULL)
1846-				return -1;
1847-		} else { /* just print what it points to */
1848-			if (mime) {
1849-				if (handle_mime(ms, mime, "symlink") == -1)
1850-					return -1;
1851-			} else if (file_printf(ms, "%ssymbolic link to `%s'",
1852-			    COMMA, buf) == -1)
1853-				return -1;
1854-		}
1855-		break;
1856+	return 1;
1857 #endif
1858+
1859 #ifdef	S_IFSOCK
1860 #ifndef __COHERENT__
1861 	case S_IFSOCK:
1862@@ -337,27 +223,27 @@
1863 		break;
1864 #endif
1865 #endif
1866-	case S_IFREG:
1867-		/*
1868-		 * regular file, check next possibility
1869-		 *
1870-		 * If stat() tells us the file has zero length, report here that
1871-		 * the file is empty, so we can skip all the work of opening and
1872-		 * reading the file.
1873+		case S_IFREG:
1874+	/*
1875+	 * regular file, check next possibility
1876+	 *
1877+	 * If stat() tells us the file has zero length, report here that
1878+	 * the file is empty, so we can skip all the work of opening and
1879+	 * reading the file.
1880 		 * But if the -s option has been given, we skip this
1881 		 * optimization, since on some systems, stat() reports zero
1882 		 * size for raw disk partitions. (If the block special device
1883 		 * really has zero length, the fact that it is empty will be
1884 		 * detected and reported correctly when we read the file.)
1885-		 */
1886-		if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
1887-			if (mime) {
1888-				if (handle_mime(ms, mime, "x-empty") == -1)
1889-					return -1;
1890-			} else if (file_printf(ms, "%sempty", COMMA) == -1)
1891+	 */
1892+	if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
1893+		if (mime) {
1894+			if (handle_mime(ms, mime, "x-empty") == -1)
1895 				return -1;
1896+			} else if (file_printf(ms, "%sempty", COMMA) == -1)
1897+			return -1;
1898 			break;
1899-		}
1900+	}
1901 		ret = 0;
1902 		break;
1903
1904@@ -367,9 +253,5 @@
1905 		/*NOTREACHED*/
1906 	}
1907
1908-	if (!mime && did) {
1909-	    if (file_printf(ms, " ") == -1)
1910-		    return -1;
1911-	}
1912 	return ret;
1913 }
1914diff -u libmagic.orig/funcs.c libmagic/funcs.c
1915--- libmagic.orig/funcs.c	Wed Oct 31 18:03:01 2012
1916+++ libmagic/funcs.c	Sun Jan  4 17:02:29 2015
1917@@ -41,52 +41,42 @@
1918 #if defined(HAVE_WCTYPE_H)
1919 #include <wctype.h>
1920 #endif
1921-#if defined(HAVE_LIMITS_H)
1922-#include <limits.h>
1923+
1924+#ifndef SIZE_MAX
1925+# define SIZE_MAX ((size_t) -1)
1926 #endif
1927
1928-#ifndef SIZE_MAX
1929-#define SIZE_MAX	((size_t)~0)
1930+#ifndef PREG_OFFSET_CAPTURE
1931+# define PREG_OFFSET_CAPTURE                 (1<<8)
1932 #endif
1933
1934+extern public void convert_libmagic_pattern(zval *pattern, int options);
1935+
1936 /*
1937  * Like printf, only we append to a buffer.
1938  */
1939 protected int
1940-file_vprintf(struct magic_set *ms, const char *fmt, va_list ap)
1941+file_printf(struct magic_set *ms, const char *fmt, ...)
1942 {
1943+	va_list ap;
1944 	int len;
1945-	char *buf, *newstr;
1946+	char *buf = NULL, *newstr;
1947
1948-	len = vasprintf(&buf, fmt, ap);
1949-	if (len < 0)
1950-		goto out;
1951+	va_start(ap, fmt);
1952+	len = vspprintf(&buf, 0, fmt, ap);
1953+	va_end(ap);
1954
1955 	if (ms->o.buf != NULL) {
1956-		len = asprintf(&newstr, "%s%s", ms->o.buf, buf);
1957-		free(buf);
1958-		if (len < 0)
1959-			goto out;
1960-		free(ms->o.buf);
1961-		buf = newstr;
1962+		len = spprintf(&newstr, 0, "%s%s", ms->o.buf, (buf ? buf : ""));
1963+		if (buf) {
1964+			efree(buf);
1965+		}
1966+		efree(ms->o.buf);
1967+		ms->o.buf = newstr;
1968+	} else {
1969+		ms->o.buf = buf;
1970 	}
1971-	ms->o.buf = buf;
1972 	return 0;
1973-out:
1974-	file_error(ms, errno, "vasprintf failed");
1975-	return -1;
1976-}
1977-
1978-protected int
1979-file_printf(struct magic_set *ms, const char *fmt, ...)
1980-{
1981-	int rv;
1982-	va_list ap;
1983-
1984-	va_start(ap, fmt);
1985-	rv = file_vprintf(ms, fmt, ap);
1986-	va_end(ap);
1987-	return rv;
1988 }
1989
1990 /*
1991@@ -97,17 +87,30 @@
1992 file_error_core(struct magic_set *ms, int error, const char *f, va_list va,
1993     size_t lineno)
1994 {
1995+	char *buf = NULL;
1996+
1997 	/* Only the first error is ok */
1998 	if (ms->event_flags & EVENT_HAD_ERR)
1999 		return;
2000 	if (lineno != 0) {
2001-		free(ms->o.buf);
2002+		efree(ms->o.buf);
2003 		ms->o.buf = NULL;
2004 		file_printf(ms, "line %" SIZE_T_FORMAT "u: ", lineno);
2005 	}
2006-	file_vprintf(ms, f, va);
2007-	if (error > 0)
2008-		file_printf(ms, " (%s)", strerror(error));
2009+
2010+	vspprintf(&buf, 0, f, va);
2011+	va_end(va);
2012+
2013+	if (error > 0) {
2014+		file_printf(ms, "%s (%s)", (*buf ? buf : ""), strerror(error));
2015+	} else if (*buf) {
2016+		file_printf(ms, "%s", buf);
2017+	}
2018+
2019+	if (buf) {
2020+		efree(buf);
2021+	}
2022+
2023 	ms->event_flags |= EVENT_HAD_ERR;
2024 	ms->error = error;
2025 }
2026@@ -154,10 +157,9 @@
2027 	file_error(ms, errno, "error reading");
2028 }
2029
2030-#ifndef COMPILE_ONLY
2031 protected int
2032-file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((unused)),
2033-    const void *buf, size_t nb)
2034+file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const void *buf,
2035+    size_t nb)
2036 {
2037 	int m = 0, rv = 0, looks_text = 0;
2038 	int mime = ms->flags & MAGIC_MIME;
2039@@ -201,10 +203,10 @@
2040 		}
2041 	}
2042 #endif
2043-#if HAVE_FORK
2044-	/* try compression stuff */
2045+
2046+#if PHP_FILEINFO_UNCOMPRESS
2047 	if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) == 0)
2048-		if ((m = file_zmagic(ms, fd, inname, ubuf, nb)) != 0) {
2049+		if ((m = file_zmagic(ms, stream, inname, ubuf, nb)) != 0) {
2050 			if ((ms->flags & MAGIC_DEBUG) != 0)
2051 				(void)fprintf(stderr, "zmagic %d\n", m);
2052 			goto done;
2053@@ -219,16 +221,21 @@
2054 		}
2055
2056 	/* Check if we have a CDF file */
2057-	if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0)
2058-		if ((m = file_trycdf(ms, fd, ubuf, nb)) != 0) {
2059-			if ((ms->flags & MAGIC_DEBUG) != 0)
2060-				(void)fprintf(stderr, "cdf %d\n", m);
2061-			goto done;
2062+	if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) {
2063+		int fd;
2064+		TSRMLS_FETCH();
2065+		if (stream && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&fd, 0)) {
2066+			if ((m = file_trycdf(ms, fd, ubuf, nb)) != 0) {
2067+				if ((ms->flags & MAGIC_DEBUG) != 0)
2068+					(void)fprintf(stderr, "cdf %d\n", m);
2069+				goto done;
2070+			}
2071 		}
2072+	}
2073
2074 	/* try soft magic tests */
2075 	if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0)
2076-		if ((m = file_softmagic(ms, ubuf, nb, BINTEST,
2077+		if ((m = file_softmagic(ms, ubuf, nb, 0, BINTEST,
2078 		    looks_text)) != 0) {
2079 			if ((ms->flags & MAGIC_DEBUG) != 0)
2080 				(void)fprintf(stderr, "softmagic %d\n", m);
2081@@ -296,7 +303,6 @@
2082
2083 	return m;
2084 }
2085-#endif
2086
2087 protected int
2088 file_reset(struct magic_set *ms)
2089@@ -306,11 +312,11 @@
2090 		return -1;
2091 	}
2092 	if (ms->o.buf) {
2093-		free(ms->o.buf);
2094+		efree(ms->o.buf);
2095 		ms->o.buf = NULL;
2096 	}
2097 	if (ms->o.pbuf) {
2098-		free(ms->o.pbuf);
2099+		efree(ms->o.pbuf);
2100 		ms->o.pbuf = NULL;
2101 	}
2102 	ms->event_flags &= ~EVENT_HAD_ERR;
2103@@ -329,7 +335,7 @@
2104 protected const char *
2105 file_getbuffer(struct magic_set *ms)
2106 {
2107-	char *pbuf, *op, *np;
2108+	char *op, *np;
2109 	size_t psize, len;
2110
2111 	if (ms->event_flags & EVENT_HAD_ERR)
2112@@ -344,15 +350,13 @@
2113 	/* * 4 is for octal representation, + 1 is for NUL */
2114 	len = strlen(ms->o.buf);
2115 	if (len > (SIZE_MAX - 1) / 4) {
2116-		file_oomem(ms, len);
2117 		return NULL;
2118 	}
2119 	psize = len * 4 + 1;
2120-	if ((pbuf = CAST(char *, realloc(ms->o.pbuf, psize))) == NULL) {
2121+	if ((ms->o.pbuf = CAST(char *, erealloc(ms->o.pbuf, psize))) == NULL) {
2122 		file_oomem(ms, psize);
2123 		return NULL;
2124 	}
2125-	ms->o.pbuf = pbuf;
2126
2127 #if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
2128 	{
2129@@ -412,8 +416,8 @@
2130 	if (level >= ms->c.len) {
2131 		len = (ms->c.len += 20) * sizeof(*ms->c.li);
2132 		ms->c.li = CAST(struct level_info *, (ms->c.li == NULL) ?
2133-		    malloc(len) :
2134-		    realloc(ms->c.li, len));
2135+		    emalloc(len) :
2136+		    erealloc(ms->c.li, len));
2137 		if (ms->c.li == NULL) {
2138 			file_oomem(ms, len);
2139 			return -1;
2140@@ -433,29 +437,47 @@
2141 	return ms->o.buf == NULL ? 0 : strlen(ms->o.buf);
2142 }
2143
2144-protected int
2145+
2146+protected int
2147 file_replace(struct magic_set *ms, const char *pat, const char *rep)
2148 {
2149-	regex_t rx;
2150-	int rc;
2151+	zval *patt;
2152+	int opts = 0;
2153+	pcre_cache_entry *pce;
2154+	char *res;
2155+	zval *repl;
2156+	int res_len, rep_cnt = 0;
2157+	TSRMLS_FETCH();
2158+
2159+	MAKE_STD_ZVAL(patt);
2160+	ZVAL_STRINGL(patt, pat, strlen(pat), 0);
2161+	opts |= PCRE_MULTILINE;
2162+	convert_libmagic_pattern(patt, opts);
2163+	if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(patt), Z_STRLEN_P(patt) TSRMLS_CC)) == NULL) {
2164+		zval_dtor(patt);
2165+		FREE_ZVAL(patt);
2166+		return -1;
2167+	}
2168+
2169+	MAKE_STD_ZVAL(repl);
2170+	ZVAL_STRINGL(repl, rep, strlen(rep), 0);
2171+
2172+	res = php_pcre_replace_impl(pce, ms->o.buf, strlen(ms->o.buf), repl,
2173+			0, &res_len, -1, &rep_cnt TSRMLS_CC);
2174
2175-	rc = regcomp(&rx, pat, REG_EXTENDED);
2176-	if (rc) {
2177-		char errmsg[512];
2178-		(void)regerror(rc, &rx, errmsg, sizeof(errmsg));
2179-		file_magerror(ms, "regex error %d, (%s)", rc, errmsg);
2180+	FREE_ZVAL(repl);
2181+	zval_dtor(patt);
2182+	FREE_ZVAL(patt);
2183+
2184+	if (NULL == res) {
2185 		return -1;
2186-	} else {
2187-		regmatch_t rm;
2188-		int nm = 0;
2189-		while (regexec(&rx, ms->o.buf, 1, &rm, 0) == 0) {
2190-			ms->o.buf[rm.rm_so] = '\0';
2191-			if (file_printf(ms, "%s%s", rep,
2192-			    rm.rm_eo != 0 ? ms->o.buf + rm.rm_eo : "") == -1)
2193-				return -1;
2194-			nm++;
2195-		}
2196-		regfree(&rx);
2197-		return nm;
2198 	}
2199+
2200+	strncpy(ms->o.buf, res, res_len);
2201+	ms->o.buf[res_len] = '\0';
2202+
2203+	efree(res);
2204+
2205+	return rep_cnt;
2206 }
2207+
2208diff -u libmagic.orig/magic.c libmagic/magic.c
2209--- libmagic.orig/magic.c	Fri Jan 11 17:43:09 2013
2210+++ libmagic/magic.c	Sun Jan  4 17:02:29 2015
2211@@ -25,11 +25,6 @@
2212  * SUCH DAMAGE.
2213  */
2214
2215-#ifdef WIN32
2216-#include <windows.h>
2217-#include <shlwapi.h>
2218-#endif
2219-
2220 #include "file.h"
2221
2222 #ifndef	lint
2223@@ -39,15 +34,24 @@
2224 #include "magic.h"
2225
2226 #include <stdlib.h>
2227+#ifdef PHP_WIN32
2228+#include "win32/unistd.h"
2229+#else
2230 #include <unistd.h>
2231+#endif
2232 #include <string.h>
2233-#ifdef QUICK
2234-#include <sys/mman.h>
2235+#ifdef PHP_WIN32
2236+# include "config.w32.h"
2237+#else
2238+# include "php_config.h"
2239 #endif
2240-#ifdef HAVE_LIMITS_H
2241-#include <limits.h>	/* for PIPE_BUF */
2242+
2243+#ifdef PHP_WIN32
2244+#include <shlwapi.h>
2245 #endif
2246
2247+#include <limits.h>	/* for PIPE_BUF */
2248+
2249 #if defined(HAVE_UTIMES)
2250 # include <sys/time.h>
2251 #elif defined(HAVE_UTIME)
2252@@ -71,18 +75,25 @@
2253 #endif
2254 #endif
2255
2256+#ifdef PHP_WIN32
2257+# undef S_IFLNK
2258+# undef S_IFIFO
2259+#endif
2260+
2261 private void close_and_restore(const struct magic_set *, const char *, int,
2262     const struct stat *);
2263 private int unreadable_info(struct magic_set *, mode_t, const char *);
2264+#if 0
2265 private const char* get_default_magic(void);
2266-#ifndef COMPILE_ONLY
2267-private const char *file_or_fd(struct magic_set *, const char *, int);
2268 #endif
2269+private const char *file_or_stream(struct magic_set *, const char *, php_stream *);
2270
2271 #ifndef	STDIN_FILENO
2272 #define	STDIN_FILENO	0
2273 #endif
2274
2275+/* XXX this functionality is excluded in php, enable it in apprentice.c:340 */
2276+#if 0
2277 private const char *
2278 get_default_magic(void)
2279 {
2280@@ -90,7 +101,7 @@
2281 	static char *default_magic;
2282 	char *home, *hmagicpath;
2283
2284-#ifndef WIN32
2285+#ifndef PHP_WIN32
2286 	struct stat st;
2287
2288 	if (default_magic) {
2289@@ -104,17 +115,17 @@
2290 		return MAGIC;
2291 	if (stat(hmagicpath, &st) == -1) {
2292 		free(hmagicpath);
2293-		if (asprintf(&hmagicpath, "%s/.magic", home) < 0)
2294+	if (asprintf(&hmagicpath, "%s/.magic", home) < 0)
2295+		return MAGIC;
2296+	if (stat(hmagicpath, &st) == -1)
2297+		goto out;
2298+	if (S_ISDIR(st.st_mode)) {
2299+		free(hmagicpath);
2300+		if (asprintf(&hmagicpath, "%s/%s", home, hmagic) < 0)
2301 			return MAGIC;
2302-		if (stat(hmagicpath, &st) == -1)
2303+		if (access(hmagicpath, R_OK) == -1)
2304 			goto out;
2305-		if (S_ISDIR(st.st_mode)) {
2306-			free(hmagicpath);
2307-			if (asprintf(&hmagicpath, "%s/%s", home, hmagic) < 0)
2308-				return MAGIC;
2309-			if (access(hmagicpath, R_OK) == -1)
2310-				goto out;
2311-		}
2312+	}
2313 	}
2314
2315 	if (asprintf(&default_magic, "%s:%s", hmagicpath, MAGIC) < 0)
2316@@ -128,6 +139,7 @@
2317 #else
2318 	char *hmagicp = hmagicpath;
2319 	char *tmppath = NULL;
2320+	LPTSTR dllpath;
2321
2322 #define APPENDPATH() \
2323 	do { \
2324@@ -172,7 +184,7 @@
2325 	}
2326
2327 	/* Third, try to get magic file relative to dll location */
2328-	LPTSTR dllpath = malloc(sizeof(*dllpath) * (MAX_PATH + 1));
2329+	dllpath = malloc(sizeof(*dllpath) * (MAX_PATH + 1));
2330 	dllpath[MAX_PATH] = 0;	/* just in case long path gets truncated and not null terminated */
2331 	if (GetModuleFileNameA(NULL, dllpath, MAX_PATH)){
2332 		PathRemoveFileSpecA(dllpath);
2333@@ -210,6 +222,7 @@
2334
2335 	return action == FILE_LOAD ? get_default_magic() : MAGIC;
2336 }
2337+#endif
2338
2339 public struct magic_set *
2340 magic_open(int flags)
2341@@ -250,7 +263,7 @@
2342 magic_load(struct magic_set *ms, const char *magicfile)
2343 {
2344 	if (ms == NULL)
2345-		return -1;
2346+	return -1;
2347 	return file_apprentice(ms, magicfile, FILE_LOAD);
2348 }
2349
2350@@ -262,13 +275,6 @@
2351 	return file_apprentice(ms, magicfile, FILE_COMPILE);
2352 }
2353
2354-public int
2355-magic_check(struct magic_set *ms, const char *magicfile)
2356-{
2357-	if (ms == NULL)
2358-		return -1;
2359-	return file_apprentice(ms, magicfile, FILE_CHECK);
2360-}
2361
2362 public int
2363 magic_list(struct magic_set *ms, const char *magicfile)
2364@@ -282,9 +288,6 @@
2365 close_and_restore(const struct magic_set *ms, const char *name, int fd,
2366     const struct stat *sb)
2367 {
2368-	if (fd == STDIN_FILENO)
2369-		return;
2370-	(void) close(fd);
2371
2372 	if ((ms->flags & MAGIC_PRESERVE_ATIME) != 0) {
2373 		/*
2374@@ -311,7 +314,6 @@
2375 	}
2376 }
2377
2378-#ifndef COMPILE_ONLY
2379
2380 /*
2381  * find type of descriptor
2382@@ -321,7 +323,7 @@
2383 {
2384 	if (ms == NULL)
2385 		return NULL;
2386-	return file_or_fd(ms, NULL, fd);
2387+	return file_or_stream(ms, NULL, NULL);
2388 }
2389
2390 /*
2391@@ -332,30 +334,42 @@
2392 {
2393 	if (ms == NULL)
2394 		return NULL;
2395-	return file_or_fd(ms, inname, STDIN_FILENO);
2396+	return file_or_stream(ms, inname, NULL);
2397+}
2398+
2399+public const char *
2400+magic_stream(struct magic_set *ms, php_stream *stream)
2401+{
2402+	if (ms == NULL)
2403+		return NULL;
2404+	return file_or_stream(ms, NULL, stream);
2405 }
2406
2407 private const char *
2408-file_or_fd(struct magic_set *ms, const char *inname, int fd)
2409+file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
2410 {
2411 	int	rv = -1;
2412 	unsigned char *buf;
2413 	struct stat	sb;
2414 	ssize_t nbytes = 0;	/* number of bytes read from a datafile */
2415-	int	ispipe = 0;
2416+	int no_in_stream = 0;
2417+	TSRMLS_FETCH();
2418+
2419+	if (!inname && !stream) {
2420+		return NULL;
2421+	}
2422
2423 	/*
2424 	 * one extra for terminating '\0', and
2425 	 * some overlapping space for matches near EOF
2426 	 */
2427 #define SLOP (1 + sizeof(union VALUETYPE))
2428-	if ((buf = CAST(unsigned char *, malloc(HOWMANY + SLOP))) == NULL)
2429-		return NULL;
2430+	buf = emalloc(HOWMANY + SLOP);
2431
2432 	if (file_reset(ms) == -1)
2433 		goto done;
2434
2435-	switch (file_fsmagic(ms, inname, &sb)) {
2436+	switch (file_fsmagic(ms, inname, &sb, stream)) {
2437 	case -1:		/* error */
2438 		goto done;
2439 	case 0:			/* nothing found */
2440@@ -365,68 +379,48 @@
2441 		goto done;
2442 	}
2443
2444-	if (inname == NULL) {
2445-		if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode))
2446-			ispipe = 1;
2447-	} else {
2448-		int flags = O_RDONLY|O_BINARY;
2449+	errno = 0;
2450
2451-		if (stat(inname, &sb) == 0 && S_ISFIFO(sb.st_mode)) {
2452-#ifdef O_NONBLOCK
2453-			flags |= O_NONBLOCK;
2454+	if (!stream && inname) {
2455+		no_in_stream = 1;
2456+#if PHP_API_VERSION < 20100412
2457+		stream = php_stream_open_wrapper((char *)inname, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
2458+#else
2459+		stream = php_stream_open_wrapper((char *)inname, "rb", REPORT_ERRORS, NULL);
2460 #endif
2461-			ispipe = 1;
2462-		}
2463+	}
2464
2465-		errno = 0;
2466-		if ((fd = open(inname, flags)) < 0) {
2467-			if (unreadable_info(ms, sb.st_mode, inname) == -1)
2468-				goto done;
2469-			rv = 0;
2470+	if (!stream) {
2471+		if (unreadable_info(ms, sb.st_mode, inname) == -1)
2472 			goto done;
2473-		}
2474+		rv = 0;
2475+		goto done;
2476+	}
2477+
2478 #ifdef O_NONBLOCK
2479-		if ((flags = fcntl(fd, F_GETFL)) != -1) {
2480-			flags &= ~O_NONBLOCK;
2481-			(void)fcntl(fd, F_SETFL, flags);
2482-		}
2483+/* we should be already be in non blocking mode for network socket */
2484 #endif
2485-	}
2486
2487 	/*
2488 	 * try looking at the first HOWMANY bytes
2489 	 */
2490-	if (ispipe) {
2491-		ssize_t r = 0;
2492-
2493-		while ((r = sread(fd, (void *)&buf[nbytes],
2494-		    (size_t)(HOWMANY - nbytes), 1)) > 0) {
2495-			nbytes += r;
2496-			if (r < PIPE_BUF) break;
2497-		}
2498-
2499-		if (nbytes == 0) {
2500-			/* We can not read it, but we were able to stat it. */
2501-			if (unreadable_info(ms, sb.st_mode, inname) == -1)
2502-				goto done;
2503-			rv = 0;
2504-			goto done;
2505-		}
2506-
2507-	} else {
2508-		if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
2509-			file_error(ms, errno, "cannot read `%s'", inname);
2510-			goto done;
2511-		}
2512+	if ((nbytes = php_stream_read(stream, (char *)buf, HOWMANY)) < 0) {
2513+		file_error(ms, errno, "cannot read `%s'", inname);
2514+		goto done;
2515 	}
2516
2517 	(void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */
2518-	if (file_buffer(ms, fd, inname, buf, (size_t)nbytes) == -1)
2519+	if (file_buffer(ms, stream, inname, buf, (size_t)nbytes) == -1)
2520 		goto done;
2521 	rv = 0;
2522 done:
2523-	free(buf);
2524-	close_and_restore(ms, inname, fd, &sb);
2525+	efree(buf);
2526+
2527+	if (no_in_stream && stream) {
2528+		php_stream_close(stream);
2529+	}
2530+
2531+	close_and_restore(ms, inname, 0, &sb);
2532 	return rv == 0 ? file_getbuffer(ms) : NULL;
2533 }
2534
2535@@ -440,14 +434,13 @@
2536 		return NULL;
2537 	/*
2538 	 * The main work is done here!
2539-	 * We have the file name and/or the data buffer to be identified.
2540+	 * We have the file name and/or the data buffer to be identified.
2541 	 */
2542-	if (file_buffer(ms, -1, NULL, buf, nb) == -1) {
2543+	if (file_buffer(ms, NULL, NULL, buf, nb) == -1) {
2544 		return NULL;
2545 	}
2546 	return file_getbuffer(ms);
2547 }
2548-#endif
2549
2550 public const char *
2551 magic_error(struct magic_set *ms)
2552diff -u libmagic.orig/magic.h libmagic/magic.h
2553--- libmagic.orig/magic.h	Thu Mar 21 18:52:42 2013
2554+++ libmagic/magic.h	Sun Jan  4 17:02:29 2015
2555@@ -87,6 +87,7 @@
2556
2557 const char *magic_getpath(const char *, int);
2558 const char *magic_file(magic_t, const char *);
2559+const char *magic_stream(magic_t, php_stream *);
2560 const char *magic_descriptor(magic_t, int);
2561 const char *magic_buffer(magic_t, const void *, size_t);
2562
2563@@ -96,7 +97,6 @@
2564 int magic_version(void);
2565 int magic_load(magic_t, const char *);
2566 int magic_compile(magic_t, const char *);
2567-int magic_check(magic_t, const char *);
2568 int magic_list(magic_t, const char *);
2569 int magic_errno(magic_t);
2570
2571diff -u libmagic.orig/print.c libmagic/print.c
2572--- libmagic.orig/print.c	Thu Mar 21 18:45:14 2013
2573+++ libmagic/print.c	Sun Jan  4 17:04:32 2015
2574@@ -28,13 +28,17 @@
2575 /*
2576  * print.c - debugging printout routines
2577  */
2578+#define _GNU_SOURCE
2579+#include "php.h"
2580
2581 #include "file.h"
2582+#include "cdf.h"
2583
2584 #ifndef lint
2585 FILE_RCSID("@(#)$File: print.c,v 1.76 2013/02/26 18:25:00 christos Exp $")
2586 #endif  /* lint */
2587
2588+#include <stdio.h>
2589 #include <string.h>
2590 #include <stdarg.h>
2591 #include <stdlib.h>
2592@@ -43,188 +47,31 @@
2593 #endif
2594 #include <time.h>
2595
2596-#define SZOF(a)	(sizeof(a) / sizeof(a[0]))
2597-
2598-#include "cdf.h"
2599-
2600-#ifndef COMPILE_ONLY
2601-protected void
2602-file_mdump(struct magic *m)
2603-{
2604-	static const char optyp[] = { FILE_OPS };
2605-	char tbuf[26];
2606-
2607-	(void) fprintf(stderr, "%u: %.*s %u", m->lineno,
2608-	    (m->cont_level & 7) + 1, ">>>>>>>>", m->offset);
2609-
2610-	if (m->flag & INDIR) {
2611-		(void) fprintf(stderr, "(%s,",
2612-		    /* Note: type is unsigned */
2613-		    (m->in_type < file_nnames) ? file_names[m->in_type] :
2614-		    "*bad in_type*");
2615-		if (m->in_op & FILE_OPINVERSE)
2616-			(void) fputc('~', stderr);
2617-		(void) fprintf(stderr, "%c%u),",
2618-		    ((size_t)(m->in_op & FILE_OPS_MASK) <
2619-		    SZOF(optyp)) ? optyp[m->in_op & FILE_OPS_MASK] : '?',
2620-		    m->in_offset);
2621-	}
2622-	(void) fprintf(stderr, " %s%s", (m->flag & UNSIGNED) ? "u" : "",
2623-	    /* Note: type is unsigned */
2624-	    (m->type < file_nnames) ? file_names[m->type] : "*bad type");
2625-	if (m->mask_op & FILE_OPINVERSE)
2626-		(void) fputc('~', stderr);
2627-
2628-	if (IS_STRING(m->type)) {
2629-		if (m->str_flags) {
2630-			(void) fputc('/', stderr);
2631-			if (m->str_flags & STRING_COMPACT_WHITESPACE)
2632-				(void) fputc(CHAR_COMPACT_WHITESPACE, stderr);
2633-			if (m->str_flags & STRING_COMPACT_OPTIONAL_WHITESPACE)
2634-				(void) fputc(CHAR_COMPACT_OPTIONAL_WHITESPACE,
2635-				    stderr);
2636-			if (m->str_flags & STRING_IGNORE_LOWERCASE)
2637-				(void) fputc(CHAR_IGNORE_LOWERCASE, stderr);
2638-			if (m->str_flags & STRING_IGNORE_UPPERCASE)
2639-				(void) fputc(CHAR_IGNORE_UPPERCASE, stderr);
2640-			if (m->str_flags & REGEX_OFFSET_START)
2641-				(void) fputc(CHAR_REGEX_OFFSET_START, stderr);
2642-			if (m->str_flags & STRING_TEXTTEST)
2643-				(void) fputc(CHAR_TEXTTEST, stderr);
2644-			if (m->str_flags & STRING_BINTEST)
2645-				(void) fputc(CHAR_BINTEST, stderr);
2646-			if (m->str_flags & PSTRING_1_BE)
2647-				(void) fputc(CHAR_PSTRING_1_BE, stderr);
2648-			if (m->str_flags & PSTRING_2_BE)
2649-				(void) fputc(CHAR_PSTRING_2_BE, stderr);
2650-			if (m->str_flags & PSTRING_2_LE)
2651-				(void) fputc(CHAR_PSTRING_2_LE, stderr);
2652-			if (m->str_flags & PSTRING_4_BE)
2653-				(void) fputc(CHAR_PSTRING_4_BE, stderr);
2654-			if (m->str_flags & PSTRING_4_LE)
2655-				(void) fputc(CHAR_PSTRING_4_LE, stderr);
2656-			if (m->str_flags & PSTRING_LENGTH_INCLUDES_ITSELF)
2657-				(void) fputc(
2658-				    CHAR_PSTRING_LENGTH_INCLUDES_ITSELF,
2659-				    stderr);
2660-		}
2661-		if (m->str_range)
2662-			(void) fprintf(stderr, "/%u", m->str_range);
2663-	}
2664-	else {
2665-		if ((size_t)(m->mask_op & FILE_OPS_MASK) < SZOF(optyp))
2666-			(void) fputc(optyp[m->mask_op & FILE_OPS_MASK], stderr);
2667-		else
2668-			(void) fputc('?', stderr);
2669-
2670-		if (m->num_mask) {
2671-			(void) fprintf(stderr, "%.8llx",
2672-			    (unsigned long long)m->num_mask);
2673-		}
2674-	}
2675-	(void) fprintf(stderr, ",%c", m->reln);
2676-
2677-	if (m->reln != 'x') {
2678-		switch (m->type) {
2679-		case FILE_BYTE:
2680-		case FILE_SHORT:
2681-		case FILE_LONG:
2682-		case FILE_LESHORT:
2683-		case FILE_LELONG:
2684-		case FILE_MELONG:
2685-		case FILE_BESHORT:
2686-		case FILE_BELONG:
2687-		case FILE_INDIRECT:
2688-			(void) fprintf(stderr, "%d", m->value.l);
2689-			break;
2690-		case FILE_BEQUAD:
2691-		case FILE_LEQUAD:
2692-		case FILE_QUAD:
2693-			(void) fprintf(stderr, "%" INT64_T_FORMAT "d",
2694-			    (unsigned long long)m->value.q);
2695-			break;
2696-		case FILE_PSTRING:
2697-		case FILE_STRING:
2698-		case FILE_REGEX:
2699-		case FILE_BESTRING16:
2700-		case FILE_LESTRING16:
2701-		case FILE_SEARCH:
2702-			file_showstr(stderr, m->value.s, (size_t)m->vallen);
2703-			break;
2704-		case FILE_DATE:
2705-		case FILE_LEDATE:
2706-		case FILE_BEDATE:
2707-		case FILE_MEDATE:
2708-			(void)fprintf(stderr, "%s,",
2709-			    file_fmttime(m->value.l, FILE_T_LOCAL, tbuf));
2710-			break;
2711-		case FILE_LDATE:
2712-		case FILE_LELDATE:
2713-		case FILE_BELDATE:
2714-		case FILE_MELDATE:
2715-			(void)fprintf(stderr, "%s,",
2716-			    file_fmttime(m->value.l, 0, tbuf));
2717-		case FILE_QDATE:
2718-		case FILE_LEQDATE:
2719-		case FILE_BEQDATE:
2720-			(void)fprintf(stderr, "%s,",
2721-			    file_fmttime(m->value.q, FILE_T_LOCAL, tbuf));
2722-			break;
2723-		case FILE_QLDATE:
2724-		case FILE_LEQLDATE:
2725-		case FILE_BEQLDATE:
2726-			(void)fprintf(stderr, "%s,",
2727-			    file_fmttime(m->value.q, 0, tbuf));
2728-			break;
2729-		case FILE_QWDATE:
2730-		case FILE_LEQWDATE:
2731-		case FILE_BEQWDATE:
2732-			(void)fprintf(stderr, "%s,",
2733-			    file_fmttime(m->value.q, FILE_T_WINDOWS, tbuf));
2734-			break;
2735-		case FILE_FLOAT:
2736-		case FILE_BEFLOAT:
2737-		case FILE_LEFLOAT:
2738-			(void) fprintf(stderr, "%G", m->value.f);
2739-			break;
2740-		case FILE_DOUBLE:
2741-		case FILE_BEDOUBLE:
2742-		case FILE_LEDOUBLE:
2743-			(void) fprintf(stderr, "%G", m->value.d);
2744-			break;
2745-		case FILE_DEFAULT:
2746-			/* XXX - do anything here? */
2747-			break;
2748-		case FILE_USE:
2749-		case FILE_NAME:
2750-			(void) fprintf(stderr, "'%s'", m->value.s);
2751-			break;
2752-		default:
2753-			(void) fprintf(stderr, "*bad type %d*", m->type);
2754-			break;
2755-		}
2756-	}
2757-	(void) fprintf(stderr, ",\"%s\"]\n", m->desc);
2758-}
2759+#ifdef PHP_WIN32
2760+# define asctime_r php_asctime_r
2761+# define ctime_r php_ctime_r
2762 #endif
2763
2764+#define SZOF(a)	(sizeof(a) / sizeof(a[0]))
2765+
2766 /*VARARGS*/
2767 protected void
2768 file_magwarn(struct magic_set *ms, const char *f, ...)
2769 {
2770 	va_list va;
2771+	char *expanded_format = NULL;
2772+	int expanded_len;
2773+	TSRMLS_FETCH();
2774
2775-	/* cuz we use stdout for most, stderr here */
2776-	(void) fflush(stdout);
2777-
2778-	if (ms->file)
2779-		(void) fprintf(stderr, "%s, %lu: ", ms->file,
2780-		    (unsigned long)ms->line);
2781-	(void) fprintf(stderr, "Warning: ");
2782 	va_start(va, f);
2783-	(void) vfprintf(stderr, f, va);
2784+	expanded_len = vasprintf(&expanded_format, f, va);
2785 	va_end(va);
2786-	(void) fputc('\n', stderr);
2787+
2788+	if (expanded_len >= 0 && expanded_format) {
2789+		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Warning: %s", expanded_format);
2790+
2791+		free(expanded_format);
2792+	}
2793 }
2794
2795 protected const char *
2796@@ -235,7 +82,7 @@
2797 	struct tm *tm;
2798
2799 	if (flags & FILE_T_WINDOWS) {
2800-		struct timespec ts;
2801+		struct timeval ts;
2802 		cdf_timestamp_to_timespec(&ts, t);
2803 		t = ts.tv_sec;
2804 	}
2805diff -u libmagic.orig/readcdf.c libmagic/readcdf.c
2806--- libmagic.orig/readcdf.c	Wed Oct 31 18:03:01 2012
2807+++ libmagic/readcdf.c	Sun Jan  4 17:02:29 2015
2808@@ -30,7 +30,11 @@
2809 #endif
2810
2811 #include <stdlib.h>
2812+#ifdef PHP_WIN32
2813+#include "win32/unistd.h"
2814+#else
2815 #include <unistd.h>
2816+#endif
2817 #include <string.h>
2818 #include <time.h>
2819 #include <ctype.h>
2820@@ -46,12 +50,14 @@
2821 {
2822         size_t i;
2823         cdf_timestamp_t tp;
2824-        struct timespec ts;
2825+        struct timeval ts;
2826         char buf[64];
2827         const char *str = NULL;
2828         const char *s;
2829         int len;
2830
2831+	memset(&ts, 0, sizeof(ts));
2832+
2833         for (i = 0; i < count; i++) {
2834                 cdf_print_property_name(buf, sizeof(buf), info[i].pi_id);
2835                 switch (info[i].pi_type) {
2836@@ -125,8 +131,12 @@
2837                 case CDF_FILETIME:
2838                         tp = info[i].pi_tp;
2839                         if (tp != 0) {
2840-				char tbuf[64];
2841-                                if (tp < 1000000000000000LL) {
2842+							char tbuf[64];
2843+#if defined(PHP_WIN32) && _MSC_VER <= 1500
2844+							if (tp < 1000000000000000i64) {
2845+#else
2846+							if (tp < 1000000000000000LL) {
2847+#endif
2848                                         cdf_print_elapsed_time(tbuf,
2849                                             sizeof(tbuf), tp);
2850                                         if (NOTMIME(ms) && file_printf(ms,
2851@@ -134,9 +144,13 @@
2852                                                 return -1;
2853                                 } else {
2854                                         char *c, *ec;
2855-                                        cdf_timestamp_to_timespec(&ts, tp);
2856-                                        c = cdf_ctime(&ts.tv_sec, tbuf);
2857-                                        if ((ec = strchr(c, '\n')) != NULL)
2858+					const time_t sec = ts.tv_sec;
2859+                                        if (cdf_timestamp_to_timespec(&ts, tp) == -1) {
2860+											return -1;
2861+										}
2862+                                        c = cdf_ctime(&sec, tbuf);
2863+                                        if (c != NULL &&
2864+					    (ec = strchr(c, '\n')) != NULL)
2865                                                 *ec = '\0';
2866
2867                                         if (NOTMIME(ms) && file_printf(ms,
2868@@ -314,9 +328,9 @@
2869 			if (file_printf(ms,
2870 			    "Composite Document File V2 Document") == -1)
2871 			    return -1;
2872-			if (*expn)
2873-			    if (file_printf(ms, ", %s%s", corrupt, expn) == -1)
2874-				return -1;
2875+                if (*expn)
2876+                        if (file_printf(ms, ", %s%s", corrupt, expn) == -1)
2877+                                return -1;
2878 		    } else {
2879 			if (file_printf(ms, "application/CDFV2-corrupt") == -1)
2880 			    return -1;
2881diff -u libmagic.orig/softmagic.c libmagic/softmagic.c
2882--- libmagic.orig/softmagic.c	Thu Mar 21 18:45:14 2013
2883+++ libmagic/softmagic.c	Sun Jan  4 17:02:29 2015
2884@@ -41,6 +41,11 @@
2885 #include <stdlib.h>
2886 #include <time.h>
2887
2888+#ifndef PREG_OFFSET_CAPTURE
2889+# define PREG_OFFSET_CAPTURE                 (1<<8)
2890+#endif
2891+
2892+
2893
2894 private int match(struct magic_set *, struct magic *, uint32_t,
2895     const unsigned char *, size_t, size_t, int, int, int, int, int *, int *,
2896@@ -53,7 +58,7 @@
2897 private int32_t moffset(struct magic_set *, struct magic *);
2898 private void mdebug(uint32_t, const char *, size_t);
2899 private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
2900-    const unsigned char *, uint32_t, size_t, size_t);
2901+    const unsigned char *, uint32_t, size_t, struct magic *);
2902 private int mconvert(struct magic_set *, struct magic *, int);
2903 private int print_sep(struct magic_set *, int);
2904 private int handle_annotation(struct magic_set *, struct magic *);
2905@@ -62,6 +67,8 @@
2906 private void cvt_32(union VALUETYPE *, const struct magic *);
2907 private void cvt_64(union VALUETYPE *, const struct magic *);
2908
2909+#define OFFSET_OOB(n, o, i)	((n) < (o) || (i) > ((n) - (o)))
2910+
2911 /*
2912  * softmagic - lookup one file in parsed, in-memory copy of database
2913  * Passed the name and FILE * of one file to be typed.
2914@@ -69,13 +76,13 @@
2915 /*ARGSUSED1*/		/* nbytes passed for regularity, maybe need later */
2916 protected int
2917 file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
2918-    int mode, int text)
2919+    size_t level, int mode, int text)
2920 {
2921 	struct mlist *ml;
2922 	int rv, printed_something = 0, need_separator = 0;
2923 	for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next)
2924 		if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode,
2925-		    text, 0, 0, &printed_something, &need_separator,
2926+		    text, 0, level, &printed_something, &need_separator,
2927 		    NULL)) != 0)
2928 			return rv;
2929
2930@@ -132,7 +139,7 @@
2931 		struct magic *m = &magic[magindex];
2932
2933 		if (m->type != FILE_NAME)
2934-		if ((IS_STRING(m->type) &&
2935+		if ((IS_LIBMAGIC_STRING(m->type) &&
2936 #define FLT (STRING_BINTEST | STRING_TEXTTEST)
2937 		     ((text && (m->str_flags & FLT) == STRING_BINTEST) ||
2938 		      (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) ||
2939@@ -209,8 +216,8 @@
2940 		if (file_check_mem(ms, ++cont_level) == -1)
2941 			return -1;
2942
2943-		while (magic[magindex+1].cont_level != 0 &&
2944-		    ++magindex < nmagic) {
2945+		while (magindex + 1 < nmagic && magic[magindex+1].cont_level != 0 &&
2946+		    ++magindex) {
2947 			m = &magic[magindex];
2948 			ms->line = m->lineno; /* for messages */
2949
2950@@ -335,44 +342,22 @@
2951 private int
2952 check_fmt(struct magic_set *ms, struct magic *m)
2953 {
2954-	regex_t rx;
2955-	int rc;
2956-
2957-	if (strchr(m->desc, '%') == NULL)
2958+	pcre *pce;
2959+	int re_options;
2960+	pcre_extra *re_extra;
2961+	TSRMLS_FETCH();
2962+
2963+	if (strchr(m->desc, '%') == NULL) {
2964 		return 0;
2965-
2966-	rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB);
2967-	if (rc) {
2968-		char errmsg[512];
2969-		(void)regerror(rc, &rx, errmsg, sizeof(errmsg));
2970-		file_magerror(ms, "regex error %d, (%s)", rc, errmsg);
2971+	}
2972+
2973+	if ((pce = pcre_get_compiled_regex("~%[-0-9.]*s~", &re_extra, &re_options TSRMLS_CC)) == NULL) {
2974 		return -1;
2975 	} else {
2976-		rc = regexec(&rx, m->desc, 0, 0, 0);
2977-		regfree(&rx);
2978-		return !rc;
2979+	 	return !pcre_exec(pce, re_extra, m->desc, strlen(m->desc), 0, re_options, NULL, 0);
2980 	}
2981 }
2982
2983-#ifndef HAVE_STRNDUP
2984-char * strndup(const char *, size_t);
2985-
2986-char *
2987-strndup(const char *str, size_t n)
2988-{
2989-	size_t len;
2990-	char *copy;
2991-
2992-	for (len = 0; len < n && str[len]; len++)
2993-		continue;
2994-	if ((copy = malloc(len + 1)) == NULL)
2995-		return NULL;
2996-	(void)memcpy(copy, str, len);
2997-	copy[len] = '\0';
2998-	return copy;
2999-}
3000-#endif /* HAVE_STRNDUP */
3001-
3002 private int32_t
3003 mprint(struct magic_set *ms, struct magic *m)
3004 {
3005@@ -583,13 +568,13 @@
3006 		char *cp;
3007 		int rval;
3008
3009-		cp = strndup((const char *)ms->search.s, ms->search.rm_len);
3010+		cp = estrndup((const char *)ms->search.s, ms->search.rm_len);
3011 		if (cp == NULL) {
3012 			file_oomem(ms, ms->search.rm_len);
3013 			return -1;
3014 		}
3015 		rval = file_printf(ms, m->desc, cp);
3016-		free(cp);
3017+		efree(cp);
3018
3019 		if (rval == -1)
3020 			return -1;
3021@@ -835,16 +820,16 @@
3022 	if (m->num_mask) \
3023 		switch (m->mask_op & FILE_OPS_MASK) { \
3024 		case FILE_OPADD: \
3025-			p->fld += cast m->num_mask; \
3026+			p->fld += cast (int64_t)m->num_mask; \
3027 			break; \
3028 		case FILE_OPMINUS: \
3029-			p->fld -= cast m->num_mask; \
3030+			p->fld -= cast (int64_t)m->num_mask; \
3031 			break; \
3032 		case FILE_OPMULTIPLY: \
3033-			p->fld *= cast m->num_mask; \
3034+			p->fld *= cast (int64_t)m->num_mask; \
3035 			break; \
3036 		case FILE_OPDIVIDE: \
3037-			p->fld /= cast m->num_mask; \
3038+			p->fld /= cast (int64_t)m->num_mask; \
3039 			break; \
3040 		} \
3041
3042@@ -896,10 +881,21 @@
3043 		return 1;
3044 	}
3045 	case FILE_PSTRING: {
3046-		char *ptr1 = p->s, *ptr2 = ptr1 + file_pstring_length_size(m);
3047+		size_t sz = file_pstring_length_size(m);
3048+		char *ptr1 = p->s, *ptr2 = ptr1 + sz;
3049 		size_t len = file_pstring_get_length(m, ptr1);
3050-		if (len >= sizeof(p->s))
3051-			len = sizeof(p->s) - 1;
3052+		sz = sizeof(p->s) - sz; /* maximum length of string */
3053+		if (len >= sz) {
3054+			/*
3055+			 * The size of the pascal string length (sz)
3056+			 * is 1, 2, or 4. We need at least 1 byte for NUL
3057+			 * termination, but we've already truncated the
3058+			 * string by p->s, so we need to deduct sz.
3059+			 * Because we can use one of the bytes of the length
3060+			 * after we shifted as NUL termination.
3061+			 */
3062+			len = sz;
3063+		}
3064 		while (len--)
3065 			*ptr1++ = *ptr2++;
3066 		*ptr1 = '\0';
3067@@ -1010,7 +1006,7 @@
3068
3069 private int
3070 mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
3071-    const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
3072+    const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m)
3073 {
3074 	/*
3075 	 * Note: FILE_SEARCH and FILE_REGEX do not actually copy
3076@@ -1030,15 +1026,24 @@
3077 			const char *last;	/* end of search region */
3078 			const char *buf;	/* start of search region */
3079 			const char *end;
3080-			size_t lines;
3081+			size_t lines, linecnt, bytecnt;
3082+
3083+			linecnt = m->str_range;
3084+			bytecnt = linecnt * 80;
3085
3086+			if (bytecnt == 0) {
3087+				bytecnt = 8192;
3088+			}
3089+			if (bytecnt > nbytes) {
3090+				bytecnt = nbytes;
3091+			}
3092 			if (s == NULL) {
3093 				ms->search.s_len = 0;
3094 				ms->search.s = NULL;
3095 				return 0;
3096 			}
3097 			buf = RCAST(const char *, s) + offset;
3098-			end = last = RCAST(const char *, s) + nbytes;
3099+			end = last = RCAST(const char *, s) + bytecnt;
3100 			/* mget() guarantees buf <= last */
3101 			for (lines = linecnt, b = buf; lines && b < end &&
3102 			     ((b = CAST(const char *,
3103@@ -1051,7 +1056,7 @@
3104 					b++;
3105 			}
3106 			if (lines)
3107-				last = RCAST(const char *, s) + nbytes;
3108+				last = RCAST(const char *, s) + bytecnt;
3109
3110 			ms->search.s = buf;
3111 			ms->search.s_len = last - buf;
3112@@ -1125,7 +1130,6 @@
3113     int *need_separator, int *returnval)
3114 {
3115 	uint32_t soffset, offset = ms->offset;
3116-	uint32_t count = m->str_range;
3117 	int rv, oneed_separator;
3118 	char *sbuf, *rbuf;
3119 	union VALUETYPE *p = &ms->ms_value;
3120@@ -1137,17 +1141,13 @@
3121 	}
3122
3123 	if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o),
3124-	    (uint32_t)nbytes, count) == -1)
3125+	    (uint32_t)nbytes, m) == -1)
3126 		return -1;
3127
3128 	if ((ms->flags & MAGIC_DEBUG) != 0) {
3129 		fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%zu, "
3130-		    "nbytes=%zu, count=%u)\n", m->type, m->flag, offset, o,
3131-		    nbytes, count);
3132+		    "nbytes=%zu)\n", m->type, m->flag, offset, o, nbytes);
3133 		mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
3134-#ifndef COMPILE_ONLY
3135-		file_mdump(m);
3136-#endif
3137 	}
3138
3139 	if (m->flag & INDIR) {
3140@@ -1191,7 +1191,7 @@
3141 		}
3142 		switch (cvt_flip(m->in_type, flip)) {
3143 		case FILE_BYTE:
3144-			if (nbytes < (offset + 1))
3145+			if (OFFSET_OOB(nbytes, offset, 1))
3146 				return 0;
3147 			if (off) {
3148 				switch (m->in_op & FILE_OPS_MASK) {
3149@@ -1226,7 +1226,7 @@
3150 				offset = ~offset;
3151 			break;
3152 		case FILE_BESHORT:
3153-			if (nbytes < (offset + 2))
3154+			if (OFFSET_OOB(nbytes, offset, 2))
3155 				return 0;
3156 			if (off) {
3157 				switch (m->in_op & FILE_OPS_MASK) {
3158@@ -1278,7 +1278,7 @@
3159 				offset = ~offset;
3160 			break;
3161 		case FILE_LESHORT:
3162-			if (nbytes < (offset + 2))
3163+			if (OFFSET_OOB(nbytes, offset, 2))
3164 				return 0;
3165 			if (off) {
3166 				switch (m->in_op & FILE_OPS_MASK) {
3167@@ -1330,7 +1330,7 @@
3168 				offset = ~offset;
3169 			break;
3170 		case FILE_SHORT:
3171-			if (nbytes < (offset + 2))
3172+			if (OFFSET_OOB(nbytes, offset, 2))
3173 				return 0;
3174 			if (off) {
3175 				switch (m->in_op & FILE_OPS_MASK) {
3176@@ -1367,7 +1367,7 @@
3177 			break;
3178 		case FILE_BELONG:
3179 		case FILE_BEID3:
3180-			if (nbytes < (offset + 4))
3181+			if (OFFSET_OOB(nbytes, offset, 4))
3182 				return 0;
3183 			if (off) {
3184 				switch (m->in_op & FILE_OPS_MASK) {
3185@@ -1438,7 +1438,7 @@
3186 			break;
3187 		case FILE_LELONG:
3188 		case FILE_LEID3:
3189-			if (nbytes < (offset + 4))
3190+			if (OFFSET_OOB(nbytes, offset, 4))
3191 				return 0;
3192 			if (off) {
3193 				switch (m->in_op & FILE_OPS_MASK) {
3194@@ -1508,7 +1508,7 @@
3195 				offset = ~offset;
3196 			break;
3197 		case FILE_MELONG:
3198-			if (nbytes < (offset + 4))
3199+			if (OFFSET_OOB(nbytes, offset, 4))
3200 				return 0;
3201 			if (off) {
3202 				switch (m->in_op & FILE_OPS_MASK) {
3203@@ -1578,7 +1578,7 @@
3204 				offset = ~offset;
3205 			break;
3206 		case FILE_LONG:
3207-			if (nbytes < (offset + 4))
3208+			if (OFFSET_OOB(nbytes, offset, 4))
3209 				return 0;
3210 			if (off) {
3211 				switch (m->in_op & FILE_OPS_MASK) {
3212@@ -1637,30 +1637,27 @@
3213 			if ((ms->flags & MAGIC_DEBUG) != 0)
3214 				fprintf(stderr, "indirect +offs=%u\n", offset);
3215 		}
3216-		if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
3217+		if (mcopy(ms, p, m->type, 0, s, offset, nbytes, m) == -1)
3218 			return -1;
3219 		ms->offset = offset;
3220
3221 		if ((ms->flags & MAGIC_DEBUG) != 0) {
3222 			mdebug(offset, (char *)(void *)p,
3223 			    sizeof(union VALUETYPE));
3224-#ifndef COMPILE_ONLY
3225-			file_mdump(m);
3226-#endif
3227 		}
3228 	}
3229
3230 	/* Verify we have enough data to match magic type */
3231 	switch (m->type) {
3232 	case FILE_BYTE:
3233-		if (nbytes < (offset + 1)) /* should alway be true */
3234+		if (OFFSET_OOB(nbytes, offset, 1))
3235 			return 0;
3236 		break;
3237
3238 	case FILE_SHORT:
3239 	case FILE_BESHORT:
3240 	case FILE_LESHORT:
3241-		if (nbytes < (offset + 2))
3242+		if (OFFSET_OOB(nbytes, offset, 2))
3243 			return 0;
3244 		break;
3245
3246@@ -1679,38 +1676,40 @@
3247 	case FILE_FLOAT:
3248 	case FILE_BEFLOAT:
3249 	case FILE_LEFLOAT:
3250-		if (nbytes < (offset + 4))
3251+		if (OFFSET_OOB(nbytes, offset, 4))
3252 			return 0;
3253 		break;
3254
3255 	case FILE_DOUBLE:
3256 	case FILE_BEDOUBLE:
3257 	case FILE_LEDOUBLE:
3258-		if (nbytes < (offset + 8))
3259+		if (OFFSET_OOB(nbytes, offset, 8))
3260 			return 0;
3261 		break;
3262
3263 	case FILE_STRING:
3264 	case FILE_PSTRING:
3265 	case FILE_SEARCH:
3266-		if (nbytes < (offset + m->vallen))
3267+		if (OFFSET_OOB(nbytes, offset, m->vallen))
3268 			return 0;
3269 		break;
3270
3271 	case FILE_REGEX:
3272-		if (nbytes < offset)
3273+		if (OFFSET_OOB(nbytes, offset, 0))
3274 			return 0;
3275 		break;
3276
3277 	case FILE_INDIRECT:
3278-		if (nbytes < offset)
3279+		if (offset == 0)
3280+			return 0;
3281+		if (OFFSET_OOB(nbytes, offset, 0))
3282 			return 0;
3283 		sbuf = ms->o.buf;
3284 		soffset = ms->offset;
3285 		ms->o.buf = NULL;
3286 		ms->offset = 0;
3287 		rv = file_softmagic(ms, s + offset, nbytes - offset,
3288-		    BINTEST, text);
3289+		    recursion_level, BINTEST, text);
3290 		if ((ms->flags & MAGIC_DEBUG) != 0)
3291 			fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv);
3292 		rbuf = ms->o.buf;
3293@@ -1718,16 +1717,26 @@
3294 		ms->offset = soffset;
3295 		if (rv == 1) {
3296 			if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 &&
3297-			    file_printf(ms, m->desc, offset) == -1)
3298+			    file_printf(ms, m->desc, offset) == -1) {
3299+				if (rbuf) {
3300+					efree(rbuf);
3301+				}
3302 				return -1;
3303-			if (file_printf(ms, "%s", rbuf) == -1)
3304+			}
3305+			if (file_printf(ms, "%s", rbuf) == -1) {
3306+				if (rbuf) {
3307+					efree(rbuf);
3308+				}
3309 				return -1;
3310-			free(rbuf);
3311+			}
3312+		}
3313+		if (rbuf) {
3314+			efree(rbuf);
3315 		}
3316 		return rv;
3317
3318 	case FILE_USE:
3319-		if (nbytes < offset)
3320+		if (OFFSET_OOB(nbytes, offset, 0))
3321 			return 0;
3322 		sbuf = m->value.s;
3323 		if (*sbuf == '^') {
3324@@ -1837,6 +1846,42 @@
3325 	return file_strncmp(a, b, len, flags);
3326 }
3327
3328+public void
3329+convert_libmagic_pattern(zval *pattern, int options)
3330+{
3331+		int i, j=0;
3332+		char *t;
3333+
3334+		t = (char *) safe_emalloc(Z_STRLEN_P(pattern), 2, 5);
3335+
3336+		t[j++] = '~';
3337+
3338+		for (i=0; i<Z_STRLEN_P(pattern); i++, j++) {
3339+			switch (Z_STRVAL_P(pattern)[i]) {
3340+				case '~':
3341+					t[j++] = '\\';
3342+					t[j] = '~';
3343+					break;
3344+				default:
3345+					t[j] = Z_STRVAL_P(pattern)[i];
3346+					break;
3347+			}
3348+		}
3349+		t[j++] = '~';
3350+
3351+		if (options & PCRE_CASELESS)
3352+			t[j++] = 'i';
3353+
3354+		if (options & PCRE_MULTILINE)
3355+			t[j++] = 'm';
3356+
3357+		t[j]='\0';
3358+
3359+		Z_STRVAL_P(pattern) = t;
3360+		Z_STRLEN_P(pattern) = j;
3361+
3362+}
3363+
3364 private int
3365 magiccheck(struct magic_set *ms, struct magic *m)
3366 {
3367@@ -1996,69 +2041,157 @@
3368 		break;
3369 	}
3370 	case FILE_REGEX: {
3371-		int rc;
3372-		regex_t rx;
3373-		char errmsg[512];
3374-
3375-		if (ms->search.s == NULL)
3376-			return 0;
3377-
3378-		l = 0;
3379-		rc = regcomp(&rx, m->value.s,
3380-		    REG_EXTENDED|REG_NEWLINE|
3381-		    ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
3382-		if (rc) {
3383-			(void)regerror(rc, &rx, errmsg, sizeof(errmsg));
3384-			file_magerror(ms, "regex error %d, (%s)",
3385-			    rc, errmsg);
3386-			v = (uint64_t)-1;
3387-		}
3388-		else {
3389-			regmatch_t pmatch[1];
3390-#ifndef REG_STARTEND
3391-#define	REG_STARTEND	0
3392-			size_t l = ms->search.s_len - 1;
3393-			char c = ms->search.s[l];
3394-			((char *)(intptr_t)ms->search.s)[l] = '\0';
3395-#else
3396-			pmatch[0].rm_so = 0;
3397-			pmatch[0].rm_eo = ms->search.s_len;
3398-#endif
3399-			rc = regexec(&rx, (const char *)ms->search.s,
3400-			    1, pmatch, REG_STARTEND);
3401-#if REG_STARTEND == 0
3402-			((char *)(intptr_t)ms->search.s)[l] = c;
3403-#endif
3404-			switch (rc) {
3405-			case 0:
3406-				ms->search.s += (int)pmatch[0].rm_so;
3407-				ms->search.offset += (size_t)pmatch[0].rm_so;
3408-				ms->search.rm_len =
3409-				    (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so);
3410-				v = 0;
3411-				break;
3412+		zval *pattern;
3413+		int options = 0;
3414+		pcre_cache_entry *pce;
3415+		TSRMLS_FETCH();
3416+
3417+		MAKE_STD_ZVAL(pattern);
3418+		ZVAL_STRINGL(pattern, (char *)m->value.s, m->vallen, 0);
3419+
3420+		options |= PCRE_MULTILINE;
3421+
3422+		if (m->str_flags & STRING_IGNORE_CASE) {
3423+			options |= PCRE_CASELESS;
3424+		}
3425+
3426+		convert_libmagic_pattern(pattern, options);
3427+
3428+		l = v = 0;
3429+		if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(pattern), Z_STRLEN_P(pattern) TSRMLS_CC)) == NULL) {
3430+			zval_dtor(pattern);
3431+			FREE_ZVAL(pattern);
3432+			return -1;
3433+		} else {
3434+			/* pce now contains the compiled regex */
3435+			zval *retval;
3436+			zval *subpats;
3437+			char *haystack;
3438+
3439+			MAKE_STD_ZVAL(retval);
3440+			ALLOC_INIT_ZVAL(subpats);
3441+
3442+			/* Cut the search len from haystack, equals to REG_STARTEND */
3443+			haystack = estrndup(ms->search.s, ms->search.s_len);
3444+
3445+			/* match v = 0, no match v = 1 */
3446+			php_pcre_match_impl(pce, haystack, ms->search.s_len, retval, subpats, 1, 1, PREG_OFFSET_CAPTURE, 0 TSRMLS_CC);
3447+			/* Free haystack */
3448+			efree(haystack);
3449+
3450+			if (Z_LVAL_P(retval) < 0) {
3451+				zval_ptr_dtor(&subpats);
3452+				FREE_ZVAL(retval);
3453+				zval_dtor(pattern);
3454+				FREE_ZVAL(pattern);
3455+				return -1;
3456+			} else if ((Z_LVAL_P(retval) > 0) && (Z_TYPE_P(subpats) == IS_ARRAY)) {
3457+
3458+				/* Need to fetch global match which equals pmatch[0] */
3459+				HashTable *ht = Z_ARRVAL_P(subpats);
3460+				HashPosition outer_pos;
3461+				zval *pattern_match = NULL, *pattern_offset = NULL;
3462+
3463+				zend_hash_internal_pointer_reset_ex(ht, &outer_pos);
3464+
3465+				if (zend_hash_has_more_elements_ex(ht, &outer_pos) == SUCCESS &&
3466+					zend_hash_move_forward_ex(ht, &outer_pos)) {
3467+
3468+					zval **ppzval;
3469+
3470+					/* The first element (should be) is the global match
3471+					   Need to move to the inner array to get the global match */
3472+
3473+					if (zend_hash_get_current_data_ex(ht, (void**)&ppzval, &outer_pos) != FAILURE) {
3474+
3475+						HashTable *inner_ht;
3476+						HashPosition inner_pos;
3477+						zval **match, **offset;
3478+						zval tmpcopy = **ppzval, matchcopy, offsetcopy;
3479+
3480+						zval_copy_ctor(&tmpcopy);
3481+						INIT_PZVAL(&tmpcopy);
3482+
3483+						inner_ht = Z_ARRVAL(tmpcopy);
3484+
3485+						/* If everything goes according to the master plan
3486+						   tmpcopy now contains two elements:
3487+						   0 = the match
3488+						   1 = starting position of the match */
3489+						zend_hash_internal_pointer_reset_ex(inner_ht, &inner_pos);
3490+
3491+						if (zend_hash_has_more_elements_ex(inner_ht, &inner_pos) == SUCCESS &&
3492+							zend_hash_move_forward_ex(inner_ht, &inner_pos)) {
3493+
3494+							if (zend_hash_get_current_data_ex(inner_ht, (void**)&match, &inner_pos) != FAILURE) {
3495+
3496+								matchcopy = **match;
3497+								zval_copy_ctor(&matchcopy);
3498+								INIT_PZVAL(&matchcopy);
3499+								convert_to_string(&matchcopy);
3500+
3501+								MAKE_STD_ZVAL(pattern_match);
3502+								Z_STRVAL_P(pattern_match) = (char *)Z_STRVAL(matchcopy);
3503+								Z_STRLEN_P(pattern_match) = Z_STRLEN(matchcopy);
3504+								Z_TYPE_P(pattern_match) = IS_STRING;
3505+
3506+								zval_dtor(&matchcopy);
3507+							}
3508+						}
3509+
3510+						if (zend_hash_has_more_elements_ex(inner_ht, &inner_pos) == SUCCESS &&
3511+							zend_hash_move_forward_ex(inner_ht, &inner_pos)) {
3512+
3513+							if (zend_hash_get_current_data_ex(inner_ht, (void**)&offset, &inner_pos) != FAILURE) {
3514+
3515+								offsetcopy = **offset;
3516+								zval_copy_ctor(&offsetcopy);
3517+								INIT_PZVAL(&offsetcopy);
3518+								convert_to_long(&offsetcopy);
3519+
3520+								MAKE_STD_ZVAL(pattern_offset);
3521+								Z_LVAL_P(pattern_offset) = Z_LVAL(offsetcopy);
3522+								Z_TYPE_P(pattern_offset) = IS_LONG;
3523+
3524+								zval_dtor(&offsetcopy);
3525+							}
3526+						}
3527+						zval_dtor(&tmpcopy);
3528+					}
3529+
3530+					if ((pattern_match != NULL) && (pattern_offset != NULL)) {
3531+						ms->search.s += (int)Z_LVAL_P(pattern_offset); /* this is where the match starts */
3532+						ms->search.offset += (size_t)Z_LVAL_P(pattern_offset); /* this is where the match starts as size_t */
3533+						ms->search.rm_len = Z_STRLEN_P(pattern_match) /* This is the length of the matched pattern */;
3534+						v = 0;
3535+
3536+						efree(pattern_match);
3537+						efree(pattern_offset);
3538+
3539+					} else {
3540+						zval_ptr_dtor(&subpats);
3541+						FREE_ZVAL(retval);
3542+						zval_dtor(pattern);
3543+						FREE_ZVAL(pattern);
3544+						return -1;
3545+					}
3546+				}
3547
3548-			case REG_NOMATCH:
3549+
3550+			} else {
3551 				v = 1;
3552-				break;
3553-
3554-			default:
3555-				(void)regerror(rc, &rx, errmsg, sizeof(errmsg));
3556-				file_magerror(ms, "regexec error %d, (%s)",
3557-				    rc, errmsg);
3558-				v = (uint64_t)-1;
3559-				break;
3560 			}
3561-			regfree(&rx);
3562+			zval_ptr_dtor(&subpats);
3563+			FREE_ZVAL(retval);
3564 		}
3565-		if (v == (uint64_t)-1)
3566-			return -1;
3567-		break;
3568+		zval_dtor(pattern);
3569+		FREE_ZVAL(pattern);
3570+		break;
3571 	}
3572 	case FILE_INDIRECT:
3573 	case FILE_USE:
3574 	case FILE_NAME:
3575-		return 1;
3576+		return 1;
3577 	default:
3578 		file_magerror(ms, "invalid type %d in magiccheck()", m->type);
3579 		return -1;
3580