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