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