xref: /PHP-7.3/ext/fileinfo/libmagic.patch (revision f15ab32a)
1diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
2--- libmagic.orig/apprentice.c	2018-03-11 01:46:42.000000000 +0100
3+++ libmagic/apprentice.c	2020-02-26 09:55:13.842042400 +0100
4@@ -2,7 +2,7 @@
5  * Copyright (c) Ian F. Darwin 1986-1995.
6  * Software written by Ian F. Darwin and others;
7  * maintained 1995-present by Christos Zoulas and others.
8- *
9+ *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13@@ -12,7 +12,7 @@
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17- *
18+ *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22@@ -29,6 +29,8 @@
23  * apprentice - make one pass through /etc/magic, learning its secrets.
24  */
25
26+#include "php.h"
27+
28 #include "file.h"
29
30 #ifndef	lint
31@@ -36,24 +38,27 @@
32 #endif	/* lint */
33
34 #include "magic.h"
35+#include "patchlevel.h"
36 #include <stdlib.h>
37-#ifdef HAVE_UNISTD_H
38-#include <unistd.h>
39+
40+#if defined(__hpux) && !defined(HAVE_STRTOULL)
41+#if SIZEOF_LONG == 8
42+# define strtoull strtoul
43+#else
44+# define strtoull __strtoull
45 #endif
46-#ifdef HAVE_STDDEF_H
47-#include <stddef.h>
48+#endif
49+
50+#ifdef PHP_WIN32
51+#include "win32/unistd.h"
52+#define strtoull _strtoui64
53+#else
54+#include <unistd.h>
55 #endif
56 #include <string.h>
57 #include <assert.h>
58 #include <ctype.h>
59 #include <fcntl.h>
60-#ifdef QUICK
61-#include <sys/mman.h>
62-#endif
63-#include <dirent.h>
64-#if defined(HAVE_LIMITS_H)
65-#include <limits.h>
66-#endif
67
68 #ifndef SSIZE_MAX
69 #define MAXMAGIC_SIZE        ((ssize_t)0x7fffffff)
70@@ -75,6 +80,10 @@
71 #endif
72 #endif
73
74+#ifndef offsetof
75+#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
76+#endif
77+
78 #ifndef MAP_FAILED
79 #define MAP_FAILED (void *) -1
80 #endif
81@@ -91,7 +100,7 @@
82 #define MAP_TYPE_MMAP	2
83
84 struct magic_entry {
85-	struct magic *mp;
86+	struct magic *mp;
87 	uint32_t cont_count;
88 	uint32_t max_count;
89 };
90@@ -126,7 +135,7 @@
91 private size_t apprentice_magic_strength(const struct magic *);
92 private int apprentice_sort(const void *, const void *);
93 private void apprentice_list(struct mlist *, int );
94-private struct magic_map *apprentice_load(struct magic_set *,
95+private struct magic_map *apprentice_load(struct magic_set *,
96     const char *, int);
97 private struct mlist *mlist_alloc(void);
98 private void mlist_free(struct mlist *);
99@@ -170,38 +179,7 @@
100 	{ NULL, 0, NULL }
101 };
102
103-#ifdef COMPILE_ONLY
104-
105-int main(int, char *[]);
106-
107-int
108-main(int argc, char *argv[])
109-{
110-	int ret;
111-	struct magic_set *ms;
112-	char *progname;
113-
114-	if ((progname = strrchr(argv[0], '/')) != NULL)
115-		progname++;
116-	else
117-		progname = argv[0];
118-
119-	if (argc != 2) {
120-		(void)fprintf(stderr, "Usage: %s file\n", progname);
121-		return 1;
122-	}
123-
124-	if ((ms = magic_open(MAGIC_CHECK)) == NULL) {
125-		(void)fprintf(stderr, "%s: %s\n", progname, strerror(errno));
126-		return 1;
127-	}
128-	ret = magic_compile(ms, argv[1]) == -1 ? 1 : 0;
129-	if (ret == 1)
130-		(void)fprintf(stderr, "%s: %s\n", progname, magic_error(ms));
131-	magic_close(ms);
132-	return ret;
133-}
134-#endif /* COMPILE_ONLY */
135+#include "../data_file.c"
136
137 struct type_tbl_s {
138 	const char name[16];
139@@ -409,7 +387,7 @@
140 	struct mlist *ml;
141
142 	mlp->map = NULL;
143-	if ((ml = CAST(struct mlist *, malloc(sizeof(*ml)))) == NULL)
144+	if ((ml = CAST(struct mlist *, emalloc(sizeof(*ml)))) == NULL)
145 		return -1;
146
147 	ml->map = idx == 0 ? map : NULL;
148@@ -430,10 +408,8 @@
149 apprentice_1(struct magic_set *ms, const char *fn, int action)
150 {
151 	struct magic_map *map;
152-#ifndef COMPILE_ONLY
153 	struct mlist *ml;
154 	size_t i;
155-#endif
156
157 	if (magicsize != FILE_MAGICSIZE) {
158 		file_error(ms, 0, "magic element size %lu != %lu",
159@@ -449,14 +425,15 @@
160 		return apprentice_compile(ms, map, fn);
161 	}
162
163-#ifndef COMPILE_ONLY
164 	map = apprentice_map(ms, fn);
165 	if (map == (struct magic_map *)-1)
166 		return -1;
167 	if (map == NULL) {
168-		if (ms->flags & MAGIC_CHECK)
169-			file_magwarn(ms, "using regular magic file `%s'", fn);
170-		map = apprentice_load(ms, fn, action);
171+		if (fn) {
172+			if (ms->flags & MAGIC_CHECK)
173+				file_magwarn(ms, "using regular magic file `%s'", fn);
174+			map = apprentice_load(ms, fn, action);
175+		}
176 		if (map == NULL)
177 			return -1;
178 	}
179@@ -478,9 +455,6 @@
180 		}
181 	}
182 	return 0;
183-#else
184-	return 0;
185-#endif /* COMPILE_ONLY */
186 }
187
188 protected void
189@@ -491,10 +465,16 @@
190 		return;
191 	for (i = 0; i < MAGIC_SETS; i++)
192 		mlist_free(ms->mlist[i]);
193-	free(ms->o.pbuf);
194-	free(ms->o.buf);
195-	free(ms->c.li);
196-	free(ms);
197+	if (ms->o.pbuf) {
198+		efree(ms->o.pbuf);
199+	}
200+	if (ms->o.buf) {
201+		efree(ms->o.buf);
202+	}
203+	if (ms->c.li) {
204+		efree(ms->c.li);
205+	}
206+	efree(ms);
207 }
208
209 protected struct magic_set *
210@@ -503,7 +483,7 @@
211 	struct magic_set *ms;
212 	size_t i, len;
213
214-	if ((ms = CAST(struct magic_set *, calloc((size_t)1,
215+	if ((ms = CAST(struct magic_set *, ecalloc((size_t)1,
216 	    sizeof(struct magic_set)))) == NULL)
217 		return NULL;
218
219@@ -515,7 +495,7 @@
220 	ms->o.buf = ms->o.pbuf = NULL;
221 	len = (ms->c.len = 10) * sizeof(*ms->c.li);
222
223-	if ((ms->c.li = CAST(struct level_info *, malloc(len))) == NULL)
224+	if ((ms->c.li = CAST(struct level_info *, emalloc(len))) == NULL)
225 		goto free;
226
227 	ms->event_flags = 0;
228@@ -533,48 +513,35 @@
229 	ms->bytes_max = FILE_BYTES_MAX;
230 	return ms;
231 free:
232-	free(ms);
233+	efree(ms);
234 	return NULL;
235 }
236
237 private void
238 apprentice_unmap(struct magic_map *map)
239 {
240-	size_t i;
241 	if (map == NULL)
242 		return;
243-
244-	switch (map->type) {
245-	case MAP_TYPE_USER:
246-		break;
247-	case MAP_TYPE_MALLOC:
248-		for (i = 0; i < MAGIC_SETS; i++) {
249-			void *b = map->magic[i];
250-			void *p = map->p;
251-			if (CAST(char *, b) >= CAST(char *, p) &&
252-			    CAST(char *, b) <= CAST(char *, p) + map->len)
253-				continue;
254-			free(map->magic[i]);
255+	if (map->p != php_magic_database) {
256+		if (map->p == NULL) {
257+			int j;
258+			for (j = 0; j < MAGIC_SETS; j++) {
259+				if (map->magic[j]) {
260+					efree(map->magic[j]);
261+				}
262+			}
263+		} else {
264+			efree(map->p);
265 		}
266-		free(map->p);
267-		break;
268-#ifdef QUICK
269-	case MAP_TYPE_MMAP:
270-		if (map->p && map->p != MAP_FAILED)
271-			(void)munmap(map->p, map->len);
272-		break;
273-#endif
274-	default:
275-		abort();
276 	}
277-	free(map);
278+	efree(map);
279 }
280
281 private struct mlist *
282 mlist_alloc(void)
283 {
284 	struct mlist *mlist;
285-	if ((mlist = CAST(struct mlist *, calloc(1, sizeof(*mlist)))) == NULL) {
286+	if ((mlist = CAST(struct mlist *, ecalloc(1, sizeof(*mlist)))) == NULL) {
287 		return NULL;
288 	}
289 	mlist->next = mlist->prev = mlist;
290@@ -593,60 +560,12 @@
291 	for (ml = mlist->next; (next = ml->next) != NULL; ml = next) {
292 		if (ml->map)
293 			apprentice_unmap(CAST(struct magic_map *, ml->map));
294-		free(ml);
295+		efree(ml);
296 		if (ml == mlist)
297 			break;
298 	}
299 }
300
301-#ifndef COMPILE_ONLY
302-/* void **bufs: an array of compiled magic files */
303-protected int
304-buffer_apprentice(struct magic_set *ms, struct magic **bufs,
305-    size_t *sizes, size_t nbufs)
306-{
307-	size_t i, j;
308-	struct mlist *ml;
309-	struct magic_map *map;
310-
311-	if (nbufs == 0)
312-		return -1;
313-
314-	(void)file_reset(ms, 0);
315-
316-	init_file_tables();
317-
318-	for (i = 0; i < MAGIC_SETS; i++) {
319-		mlist_free(ms->mlist[i]);
320-		if ((ms->mlist[i] = mlist_alloc()) == NULL) {
321-			file_oomem(ms, sizeof(*ms->mlist[i]));
322-			goto fail;
323-		}
324-	}
325-
326-	for (i = 0; i < nbufs; i++) {
327-		map = apprentice_buf(ms, bufs[i], sizes[i]);
328-		if (map == NULL)
329-			goto fail;
330-
331-		for (j = 0; j < MAGIC_SETS; j++) {
332-			if (add_mlist(ms->mlist[j], map, j) == -1) {
333-				file_oomem(ms, sizeof(*ml));
334-				goto fail;
335-			}
336-		}
337-	}
338-
339-	return 0;
340-fail:
341-	for (i = 0; i < MAGIC_SETS; i++) {
342-		mlist_free(ms->mlist[i]);
343-		ms->mlist[i] = NULL;
344-	}
345-	return -1;
346-}
347-#endif
348-
349 /* const char *fn: list of magic files and directories */
350 protected int
351 file_apprentice(struct magic_set *ms, const char *fn, int action)
352@@ -655,14 +574,31 @@
353 	int fileerr, errs = -1;
354 	size_t i;
355
356-	(void)file_reset(ms, 0);
357+	if (ms->mlist[0] != NULL)
358+		(void)file_reset(ms, 0);
359
360+/* XXX disabling default magic loading so the compiled in data is used */
361+#if 0
362 	if ((fn = magic_getpath(fn, action)) == NULL)
363 		return -1;
364+#endif
365
366 	init_file_tables();
367
368-	if ((mfn = strdup(fn)) == NULL) {
369+	if (fn == NULL)
370+		fn = getenv("MAGIC");
371+	if (fn == NULL) {
372+		for (i = 0; i < MAGIC_SETS; i++) {
373+			mlist_free(ms->mlist[i]);
374+			if ((ms->mlist[i] = mlist_alloc()) == NULL) {
375+				file_oomem(ms, sizeof(*ms->mlist[i]));
376+				return -1;
377+			}
378+		}
379+		return apprentice_1(ms, fn, action);
380+	}
381+
382+	if ((mfn = estrdup(fn)) == NULL) {
383 		file_oomem(ms, strlen(fn));
384 		return -1;
385 	}
386@@ -675,7 +611,7 @@
387 				mlist_free(ms->mlist[i]);
388 				ms->mlist[i] = NULL;
389 			}
390-			free(mfn);
391+			efree(mfn);
392 			return -1;
393 		}
394 	}
395@@ -692,7 +628,7 @@
396 		fn = p;
397 	}
398
399-	free(mfn);
400+	efree(mfn);
401
402 	if (errs == -1) {
403 		for (i = 0; i < MAGIC_SETS; i++) {
404@@ -974,7 +910,7 @@
405 	return val;
406 }
407
408-/*
409+/*
410  * Sort callback for sorting entries by "strength" (basically length)
411  */
412 private int
413@@ -992,7 +928,7 @@
414 		return 1;
415 }
416
417-/*
418+/*
419  * Shows sorted patterns list in the order which is used for the matching
420  */
421 private void
422@@ -1088,7 +1024,7 @@
423 			mstart->flag |= BINTEST;
424 		if (mstart->str_flags & STRING_TEXTTEST)
425 			mstart->flag |= TEXTTEST;
426-
427+
428 		if (mstart->flag & (TEXTTEST|BINTEST))
429 			break;
430
431@@ -1120,7 +1056,7 @@
432
433 		mset[i].max += ALLOC_INCR;
434 		if ((mp = CAST(struct magic_entry *,
435-		    realloc(mset[i].me, sizeof(*mp) * mset[i].max))) ==
436+		    erealloc(mset[i].me, sizeof(*mp) * mset[i].max))) ==
437 		    NULL) {
438 			file_oomem(ms, sizeof(*mp) * mset[i].max);
439 			return -1;
440@@ -1141,13 +1077,19 @@
441 load_1(struct magic_set *ms, int action, const char *fn, int *errs,
442    struct magic_entry_set *mset)
443 {
444-	size_t lineno = 0, llen = 0;
445+	char buffer[BUFSIZ + 1];
446 	char *line = NULL;
447-	ssize_t len;
448+	size_t len;
449+	size_t lineno = 0;
450 	struct magic_entry me;
451
452-	FILE *f = fopen(ms->file = fn, "r");
453-	if (f == NULL) {
454+	php_stream *stream;
455+
456+
457+	ms->file = fn;
458+	stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS, NULL);
459+
460+	if (stream == NULL) {
461 		if (errno != ENOENT)
462 			file_error(ms, errno, "cannot read magic file `%s'",
463 				   fn);
464@@ -1157,8 +1099,7 @@
465
466 	memset(&me, 0, sizeof(me));
467 	/* read and parse this file */
468-	for (ms->line = 1; (len = getline(&line, &llen, f)) != -1;
469-	    ms->line++) {
470+	for (ms->line = 1; (line = php_stream_get_line(stream, buffer , BUFSIZ, &len)) != NULL; ms->line++) {
471 		if (len == 0) /* null line, garbage, etc */
472 			continue;
473 		if (line[len - 1] == '\n') {
474@@ -1216,8 +1157,8 @@
475 	}
476 	if (me.mp)
477 		(void)addentry(ms, &me, mset);
478-	free(line);
479-	(void)fclose(f);
480+    efree(line);
481+	php_stream_close(stream);
482 }
483
484 /*
485@@ -1280,7 +1221,7 @@
486 				file_magwarn(ms,
487 				    "level 0 \"default\" did not sort last");
488 			}
489-			return;
490+			return;
491 		}
492 	}
493 }
494@@ -1296,7 +1237,7 @@
495 		mentrycount += me[i].cont_count;
496
497 	slen = sizeof(**ma) * mentrycount;
498-	if ((*ma = CAST(struct magic *, malloc(slen))) == NULL) {
499+	if ((*ma = CAST(struct magic *, emalloc(slen))) == NULL) {
500 		file_oomem(ms, slen);
501 		return -1;
502 	}
503@@ -1318,8 +1259,8 @@
504 	if (me == NULL)
505 		return;
506 	for (i = 0; i < nme; i++)
507-		free(me[i].mp);
508-	free(me);
509+		efree(me[i].mp);
510+	efree(me);
511 }
512
513 private struct magic_map *
514@@ -1328,18 +1269,19 @@
515 	int errs = 0;
516 	uint32_t i, j;
517 	size_t files = 0, maxfiles = 0;
518-	char **filearr = NULL, *mfn;
519-	struct stat st;
520+	char **filearr = NULL;
521+	zend_stat_t st;
522 	struct magic_map *map;
523 	struct magic_entry_set mset[MAGIC_SETS];
524-	DIR *dir;
525-	struct dirent *d;
526+	php_stream *dir;
527+	php_stream_dirent d;
528+
529
530 	memset(mset, 0, sizeof(mset));
531 	ms->flags |= MAGIC_CHECK;	/* Enable checks for parsed files */
532
533
534-	if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL)
535+	if ((map = CAST(struct magic_map *, ecalloc(1, sizeof(*map)))) == NULL)
536 	{
537 		file_oomem(ms, sizeof(*map));
538 		return NULL;
539@@ -1351,24 +1293,26 @@
540 		(void)fprintf(stderr, "%s\n", usg_hdr);
541
542 	/* load directory or file */
543-	if (stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
544-		dir = opendir(fn);
545+	/* FIXME: Read file names and sort them to prevent
546+	   non-determinism. See Debian bug #488562. */
547+	if (php_sys_stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
548+		int mflen;
549+		char mfn[MAXPATHLEN];
550+
551+		dir = php_stream_opendir((char *)fn, REPORT_ERRORS, NULL);
552 		if (!dir) {
553 			errs++;
554 			goto out;
555 		}
556-		while ((d = readdir(dir)) != NULL) {
557-			if (d->d_name[0] == '.')
558-				continue;
559-			if (asprintf(&mfn, "%s/%s", fn, d->d_name) < 0) {
560+		while (php_stream_readdir(dir, &d)) {
561+			if ((mflen = snprintf(mfn, sizeof(mfn), "%s/%s", fn, d.d_name)) < 0) {
562 				file_oomem(ms,
563-				    strlen(fn) + strlen(d->d_name) + 2);
564+				strlen(fn) + strlen(d.d_name) + 2);
565 				errs++;
566-				closedir(dir);
567+				php_stream_closedir(dir);
568 				goto out;
569 			}
570-			if (stat(mfn, &st) == -1 || !S_ISREG(st.st_mode)) {
571-				free(mfn);
572+			if (zend_stat(mfn, &st) == -1 || !S_ISREG(st.st_mode)) {
573 				continue;
574 			}
575 			if (files >= maxfiles) {
576@@ -1376,23 +1320,22 @@
577 				maxfiles = (maxfiles + 1) * 2;
578 				mlen = maxfiles * sizeof(*filearr);
579 				if ((filearr = CAST(char **,
580-				    realloc(filearr, mlen))) == NULL) {
581+				    erealloc(filearr, mlen))) == NULL) {
582 					file_oomem(ms, mlen);
583-					free(mfn);
584-					closedir(dir);
585+					php_stream_closedir(dir);
586 					errs++;
587 					goto out;
588 				}
589 			}
590-			filearr[files++] = mfn;
591+			filearr[files++] = estrndup(mfn, (mflen > sizeof(mfn) - 1)? sizeof(mfn) - 1: mflen);
592 		}
593-		closedir(dir);
594+		php_stream_closedir(dir);
595 		qsort(filearr, files, sizeof(*filearr), cmpstrp);
596 		for (i = 0; i < files; i++) {
597 			load_1(ms, action, filearr[i], &errs, mset);
598-			free(filearr[i]);
599+			efree(filearr[i]);
600 		}
601-		free(filearr);
602+		efree(filearr);
603 	} else
604 		load_1(ms, action, fn, &errs, mset);
605 	if (errs)
606@@ -1833,7 +1776,7 @@
607 	 */
608 	while (*l == '>') {
609 		++l;		/* step over */
610-		cont_level++;
611+		cont_level++;
612 	}
613 #ifdef ENABLE_CONDITIONALS
614 	if (cont_level == 0 || cont_level > last_cont_level)
615@@ -1859,7 +1802,7 @@
616 		if (me->cont_count == me->max_count) {
617 			struct magic *nm;
618 			size_t cnt = me->max_count + ALLOC_CHUNK;
619-			if ((nm = CAST(struct magic *, realloc(me->mp,
620+			if ((nm = CAST(struct magic *, erealloc(me->mp,
621 			    sizeof(*nm) * cnt))) == NULL) {
622 				file_oomem(ms, sizeof(*nm) * cnt);
623 				return -1;
624@@ -1874,7 +1817,7 @@
625 		static const size_t len = sizeof(*m) * ALLOC_CHUNK;
626 		if (me->mp != NULL)
627 			return 1;
628-		if ((m = CAST(struct magic *, malloc(len))) == NULL) {
629+		if ((m = CAST(struct magic *, emalloc(len))) == NULL) {
630 			file_oomem(ms, len);
631 			return -1;
632 		}
633@@ -1916,17 +1859,6 @@
634 			file_magwarn(ms, "offset `%s' invalid", l);
635 		return -1;
636 	}
637-#if 0
638-        if (m->offset < 0 && cont_level != 0 &&
639-	    (m->flag & (OFFADD | INDIROFFADD)) == 0) {
640-		if (ms->flags & MAGIC_CHECK) {
641-			file_magwarn(ms,
642-			    "negative direct offset `%s' at level %u",
643-			    l, cont_level);
644-		}
645-		return -1;
646-	}
647-#endif
648         l = t;
649
650 	if (m->flag & INDIR) {
651@@ -2012,7 +1944,7 @@
652 			}
653 			l = t;
654 		}
655-		if (*l++ != ')' ||
656+		if (*l++ != ')' ||
657 		    ((m->in_op & FILE_OPINDIRECT) && *l++ != ')')) {
658 			if (ms->flags & MAGIC_CHECK)
659 				file_magwarn(ms,
660@@ -2037,7 +1969,7 @@
661 		/*
662 		 * Try it as a keyword type prefixed by "u"; match what
663 		 * follows the "u".  If that fails, try it as an SUS
664-		 * integer type.
665+		 * integer type.
666 		 */
667 		m->type = get_type(type_tbl, l + 1, &l);
668 		if (m->type == FILE_INVALID) {
669@@ -2077,7 +2009,7 @@
670 		/* Not found - try it as a special keyword. */
671 		m->type = get_type(special_tbl, l, &l);
672 	}
673-
674+
675 	if (m->type == FILE_INVALID) {
676 		if (ms->flags & MAGIC_CHECK)
677 			file_magwarn(ms, "type `%s' invalid", l);
678@@ -2089,7 +2021,7 @@
679
680 	m->mask_op = 0;
681 	if (*l == '~') {
682-		if (!IS_STRING(m->type))
683+		if (!IS_LIBMAGIC_STRING(m->type))
684 			m->mask_op |= FILE_OPINVERSE;
685 		else if (ms->flags & MAGIC_CHECK)
686 			file_magwarn(ms, "'~' invalid for string types");
687@@ -2098,7 +2030,7 @@
688 	m->str_range = 0;
689 	m->str_flags = m->type == FILE_PSTRING ? PSTRING_1_LE : 0;
690 	if ((op = get_op(*l)) != -1) {
691-		if (IS_STRING(m->type)) {
692+		if (IS_LIBMAGIC_STRING(m->type)) {
693 			int r;
694
695 			if (op != FILE_OPDIVIDE) {
696@@ -2124,7 +2056,7 @@
697 	 * anything if mask = 0 (unless you have a better idea)
698 	 */
699 	EATAB;
700-
701+
702 	switch (*l) {
703 	case '>':
704 	case '<':
705@@ -2156,7 +2088,7 @@
706 		break;
707 	default:
708   		m->reln = '=';	/* the default relation */
709-		if (*l == 'x' && ((isascii((unsigned char)l[1]) &&
710+		if (*l == 'x' && ((isascii((unsigned char)l[1]) &&
711 		    isspace((unsigned char)l[1])) || !l[1])) {
712 			m->reln = *l;
713 			++l;
714@@ -2171,7 +2103,7 @@
715
716 	/*
717 	 * TODO finish this macro and start using it!
718-	 * #define offsetcheck {if (offset > ms->bytes_max -1)
719+	 * #define offsetcheck {if (offset > ms->bytes_max -1)
720 	 *	magwarn("offset too big"); }
721 	 */
722
723@@ -2203,11 +2135,6 @@
724 		if (check_format(ms, m) == -1)
725 			return -1;
726 	}
727-#ifndef COMPILE_ONLY
728-	if (action == FILE_CHECK) {
729-		file_mdump(m);
730-	}
731-#endif
732 	m->mimetype[0] = '\0';		/* initialise MIME type to none */
733 	return 0;
734 }
735@@ -2279,7 +2206,7 @@
736
737 private int
738 parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line,
739-    off_t off, size_t len, const char *name, const char *extra, int nt)
740+    zend_off_t off, size_t len, const char *name, const char *extra, int nt)
741 {
742 	size_t i;
743 	const char *l = line;
744@@ -2291,7 +2218,7 @@
745 		file_magwarn(ms, "Current entry already has a %s type "
746 		    "`%.*s', new type `%s'", name, (int)len, buf, l);
747 		return -1;
748-	}
749+	}
750
751 	if (*m->desc == '\0') {
752 		file_magwarn(ms, "Current entry does not yet have a "
753@@ -2361,7 +2288,7 @@
754 	struct magic *m = &me->mp[0];
755
756 	return parse_extra(ms, me, line,
757-	    CAST(off_t, offsetof(struct magic, mimetype)),
758+	    CAST(zend_off_t, offsetof(struct magic, mimetype)),
759 	    sizeof(m->mimetype), "MIME", "+-/.$?:{}", 1);
760 }
761
762@@ -2428,7 +2355,7 @@
763 			if (*ptr++ != 'l')
764 				goto invalid;
765 		}
766-
767+
768 		switch (*ptr++) {
769 #ifdef STRICT_FORMAT 	/* "long" formats are int formats for us */
770 		/* so don't accept the 'l' modifier */
771@@ -2446,7 +2373,7 @@
772 			default:
773 				goto invalid;
774 			}
775-
776+
777 		/*
778 		 * Don't accept h and hh modifiers. They make writing
779 		 * magic entries more complicated, for very little benefit
780@@ -2502,7 +2429,7 @@
781 		default:
782 			goto invalid;
783 		}
784-
785+
786 	case FILE_FMT_FLOAT:
787 	case FILE_FMT_DOUBLE:
788 		if (*ptr == '-')
789@@ -2521,11 +2448,11 @@
790 		case 'g':
791 		case 'G':
792 			return 0;
793-
794+
795 		default:
796 			goto invalid;
797 		}
798-
799+
800
801 	case FILE_FMT_STR:
802 		if (*ptr == '-')
803@@ -2537,14 +2464,14 @@
804 			while (isdigit((unsigned char )*ptr))
805 				ptr++;
806 		}
807-
808+
809 		switch (*ptr++) {
810 		case 's':
811 			return 0;
812 		default:
813 			goto invalid;
814 		}
815-
816+
817 	default:
818 		/* internal error */
819 		abort();
820@@ -2555,7 +2482,7 @@
821 	*estr = "too long";
822 	return -1;
823 }
824-
825+
826 /*
827  * Check that the optional printf format in description matches
828  * the type of the magic.
829@@ -2578,7 +2505,7 @@
830
831 	if (m->type >= file_nformats) {
832 		file_magwarn(ms, "Internal error inconsistency between "
833-		    "m->type and format strings");
834+		    "m->type and format strings");
835 		return -1;
836 	}
837 	if (file_formats[m->type] == FILE_FMT_NONE) {
838@@ -2598,7 +2525,7 @@
839 		    file_names[m->type], m->desc);
840 		return -1;
841 	}
842-
843+
844 	for (; *ptr; ptr++) {
845 		if (*ptr == '%') {
846 			file_magwarn(ms,
847@@ -2611,9 +2538,9 @@
848 	return 0;
849 }
850
851-/*
852- * Read a numeric value from a pointer, into the value union of a magic
853- * pointer, according to the magic type.  Update the string pointer to point
854+/*
855+ * Read a numeric value from a pointer, into the value union of a magic
856+ * pointer, according to the magic type.  Update the string pointer to point
857  * just after the number read.  Return 0 for success, non-zero for failure.
858  */
859 private int
860@@ -2640,14 +2567,19 @@
861 			return -1;
862 		}
863 		if (m->type == FILE_REGEX) {
864-			file_regex_t rx;
865-			int rc = file_regcomp(&rx, m->value.s, REG_EXTENDED);
866-			if (rc) {
867-				if (ms->flags & MAGIC_CHECK)
868-					file_regerror(&rx, rc, ms);
869+			zval pattern;
870+			int options = 0;
871+			pcre_cache_entry *pce;
872+
873+			convert_libmagic_pattern(&pattern, m->value.s, strlen(m->value.s), options);
874+
875+			if ((pce = pcre_get_compiled_regex_cache(Z_STR(pattern))) == NULL) {
876+				zval_dtor(&pattern);
877+				return -1;
878 			}
879-			file_regfree(&rx);
880-			return rc ? -1 : 0;
881+			zval_dtor(&pattern);
882+
883+			return 0;
884 		}
885 		return 0;
886 	default:
887@@ -2770,7 +2702,7 @@
888 			default:
889 				if (warn) {
890 					if (isprint((unsigned char)c)) {
891-						/* Allow escaping of
892+						/* Allow escaping of
893 						 * ``relations'' */
894 						if (strchr("<>&^=!", c) == NULL
895 						    && (m->type != FILE_REGEX ||
896@@ -2975,7 +2907,7 @@
897 {
898 	const char *l = *p;
899
900-	if (LOWCASE(*l) == 'u')
901+	if (LOWCASE(*l) == 'u')
902 		l++;
903
904 	switch (LOWCASE(*l)) {
905@@ -3001,7 +2933,7 @@
906 {
907 	struct magic_map *map;
908
909-	if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) {
910+	if ((map = CAST(struct magic_map *, ecalloc(1, sizeof(*map)))) == NULL) {
911 		file_oomem(ms, sizeof(*map));
912 		return NULL;
913 	}
914@@ -3022,79 +2954,145 @@
915 private struct magic_map *
916 apprentice_map(struct magic_set *ms, const char *fn)
917 {
918-	int fd;
919-	struct stat st;
920+	uint32_t *ptr;
921+	uint32_t version, entries, nentries;
922+	int needsbyteswap;
923 	char *dbname = NULL;
924 	struct magic_map *map;
925-	struct magic_map *rv = NULL;
926+	size_t i;
927+	php_stream *stream = NULL;
928+	php_stream_statbuf st;
929+
930+
931
932-	fd = -1;
933-	if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) {
934+	if ((map = CAST(struct magic_map *, ecalloc(1, sizeof(*map)))) == NULL) {
935 		file_oomem(ms, sizeof(*map));
936-		goto error;
937+		return NULL;
938+	}
939+
940+	if (fn == NULL) {
941+		map->p = (void *)&php_magic_database;
942+		goto internal_loaded;
943 	}
944-	map->type = MAP_TYPE_USER;	/* unspecified */
945+
946+#ifdef PHP_WIN32
947+	/* Don't bother on windows with php_stream_open_wrapper,
948+	return to give apprentice_load() a chance. */
949+	if (php_stream_stat_path_ex((char *)fn, 0, &st, NULL) == SUCCESS) {
950+               if (st.sb.st_mode & S_IFDIR) {
951+                       return NULL;
952+               }
953+       }
954+#endif
955
956 	dbname = mkdbname(ms, fn, 0);
957 	if (dbname == NULL)
958 		goto error;
959
960-	if ((fd = open(dbname, O_RDONLY|O_BINARY)) == -1)
961+	stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS, NULL);
962+
963+	if (!stream) {
964 		goto error;
965+	}
966
967-	if (fstat(fd, &st) == -1) {
968+	if (php_stream_stat(stream, &st) < 0) {
969 		file_error(ms, errno, "cannot stat `%s'", dbname);
970 		goto error;
971 	}
972-	if (st.st_size < 8 || st.st_size > MAXMAGIC_SIZE) {
973+	if (st.sb.st_size < 8 || st.sb.st_size > MAXMAGIC_SIZE) {
974 		file_error(ms, 0, "file `%s' is too %s", dbname,
975-		    st.st_size < 8 ? "small" : "large");
976+		    st.sb.st_size < 8 ? "small" : "large");
977 		goto error;
978 	}
979
980-	map->len = (size_t)st.st_size;
981-#ifdef QUICK
982-	map->type = MAP_TYPE_MMAP;
983-	if ((map->p = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE,
984-	    MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) {
985-		file_error(ms, errno, "cannot map `%s'", dbname);
986-		goto error;
987-	}
988-#else
989-	map->type = MAP_TYPE_MALLOC;
990-	if ((map->p = CAST(void *, malloc(map->len))) == NULL) {
991+	map->len = (size_t)st.sb.st_size;
992+	if ((map->p = CAST(void *, emalloc(map->len))) == NULL) {
993 		file_oomem(ms, map->len);
994 		goto error;
995 	}
996-	if (read(fd, map->p, map->len) != (ssize_t)map->len) {
997+	if (php_stream_read(stream, map->p, (size_t)st.sb.st_size) != (size_t)st.sb.st_size) {
998 		file_badread(ms);
999 		goto error;
1000 	}
1001+	map->len = 0;
1002 #define RET	1
1003-#endif
1004-	(void)close(fd);
1005-	fd = -1;
1006
1007-	if (check_buffer(ms, map, dbname) != 0) {
1008-		rv = (struct magic_map *)-1;
1009+	php_stream_close(stream);
1010+	stream = NULL;
1011+
1012+internal_loaded:
1013+	ptr = (uint32_t *)(void *)map->p;
1014+	if (*ptr != MAGICNO) {
1015+		if (swap4(*ptr) != MAGICNO) {
1016+			file_error(ms, 0, "bad magic in `%s'", dbname);
1017+			goto error;
1018+		}
1019+		needsbyteswap = 1;
1020+	} else
1021+		needsbyteswap = 0;
1022+	if (needsbyteswap)
1023+		version = swap4(ptr[1]);
1024+	else
1025+		version = ptr[1];
1026+	if (version != VERSIONNO) {
1027+		file_error(ms, 0, "File %d.%d supports only version %d magic "
1028+		    "files. `%s' is version %d", FILE_VERSION_MAJOR, patchlevel,
1029+		    VERSIONNO, dbname, version);
1030 		goto error;
1031 	}
1032-#ifdef QUICK
1033-	if (mprotect(map->p, (size_t)st.st_size, PROT_READ) == -1) {
1034-		file_error(ms, errno, "cannot mprotect `%s'", dbname);
1035+
1036+	/* php_magic_database is a const, performing writes will segfault. This is for big-endian
1037+	machines only, PPC and Sparc specifically. Consider static variable or MINIT in
1038+	future. */
1039+	if (needsbyteswap && fn == NULL) {
1040+		map->p = emalloc(sizeof(php_magic_database));
1041+		map->p = memcpy(map->p, php_magic_database, sizeof(php_magic_database));
1042+	}
1043+
1044+	if (NULL != fn) {
1045+		nentries = (uint32_t)(st.sb.st_size / sizeof(struct magic));
1046+		entries = (uint32_t)(st.sb.st_size / sizeof(struct magic));
1047+		if ((zend_off_t)(entries * sizeof(struct magic)) != st.sb.st_size) {
1048+			file_error(ms, 0, "Size of `%s' %llu is not a multiple of %zu",
1049+				dbname, (unsigned long long)st.sb.st_size,
1050+				sizeof(struct magic));
1051+			goto error;
1052+		}
1053+	}
1054+	map->magic[0] = CAST(struct magic *, map->p) + 1;
1055+	nentries = 0;
1056+	for (i = 0; i < MAGIC_SETS; i++) {
1057+		if (needsbyteswap)
1058+			map->nmagic[i] = swap4(ptr[i + 2]);
1059+		else
1060+			map->nmagic[i] = ptr[i + 2];
1061+		if (i != MAGIC_SETS - 1)
1062+			map->magic[i + 1] = map->magic[i] + map->nmagic[i];
1063+		nentries += map->nmagic[i];
1064+	}
1065+	if (NULL != fn && entries != nentries + 1) {
1066+		file_error(ms, 0, "Inconsistent entries in `%s' %u != %u",
1067+		    dbname, entries, nentries + 1);
1068 		goto error;
1069 	}
1070-#endif
1071+	if (needsbyteswap)
1072+		for (i = 0; i < MAGIC_SETS; i++)
1073+			byteswap(map->magic[i], map->nmagic[i]);
1074
1075-	free(dbname);
1076+	if (dbname) {
1077+		efree(dbname);
1078+	}
1079 	return map;
1080
1081 error:
1082-	if (fd != -1)
1083-		(void)close(fd);
1084+	if (stream) {
1085+		php_stream_close(stream);
1086+	}
1087 	apprentice_unmap(map);
1088-	free(dbname);
1089-	return rv;
1090+	if (dbname) {
1091+		efree(dbname);
1092+	}
1093+	return NULL;
1094 }
1095
1096 private int
1097@@ -3120,7 +3118,7 @@
1098 		version = ptr[1];
1099 	if (version != VERSIONNO) {
1100 		file_error(ms, 0, "File %s supports only version %d magic "
1101-		    "files. `%s' is version %d", VERSION,
1102+		    "files. `%s' is version %d", FILE_VERSION_MAJOR,
1103 		    VERSIONNO, dbname, version);
1104 		return -1;
1105 	}
1106@@ -3161,7 +3159,6 @@
1107 {
1108 	static const size_t nm = sizeof(*map->nmagic) * MAGIC_SETS;
1109 	static const size_t m = sizeof(**map->magic);
1110-	int fd = -1;
1111 	size_t len;
1112 	char *dbname;
1113 	int rv = -1;
1114@@ -3170,14 +3167,17 @@
1115 		struct magic m;
1116 		uint32_t h[2 + MAGIC_SETS];
1117 	} hdr;
1118+	php_stream *stream;
1119
1120 	dbname = mkdbname(ms, fn, 1);
1121
1122-	if (dbname == NULL)
1123+	if (dbname == NULL)
1124 		goto out;
1125
1126-	if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1)
1127-	{
1128+	/* wb+ == O_WRONLY|O_CREAT|O_TRUNC|O_BINARY */
1129+	stream = php_stream_open_wrapper((char *)fn, "wb+", REPORT_ERRORS, NULL);
1130+
1131+	if (!stream) {
1132 		file_error(ms, errno, "cannot open `%s'", dbname);
1133 		goto out;
1134 	}
1135@@ -3186,26 +3186,25 @@
1136 	hdr.h[1] = VERSIONNO;
1137 	memcpy(hdr.h + 2, map->nmagic, nm);
1138
1139-	if (write(fd, &hdr, sizeof(hdr)) != (ssize_t)sizeof(hdr)) {
1140+	if (php_stream_write(stream,(const char *)&hdr, sizeof(hdr)) != (ssize_t)sizeof(hdr)) {
1141 		file_error(ms, errno, "error writing `%s'", dbname);
1142-		goto out2;
1143+		goto out;
1144 	}
1145
1146 	for (i = 0; i < MAGIC_SETS; i++) {
1147 		len = m * map->nmagic[i];
1148-		if (write(fd, map->magic[i], len) != (ssize_t)len) {
1149+		if (php_stream_write(stream, (const char *)map->magic[i], len) != (ssize_t)len) {
1150 			file_error(ms, errno, "error writing `%s'", dbname);
1151-			goto out2;
1152+			goto out;
1153 		}
1154 	}
1155
1156+	if (stream) {
1157+		php_stream_close(stream);
1158+	}
1159 	rv = 0;
1160-out2:
1161-	if (fd != -1)
1162-		(void)close(fd);
1163 out:
1164-	apprentice_unmap(map);
1165-	free(dbname);
1166+	efree(dbname);
1167 	return rv;
1168 }
1169
1170@@ -3239,16 +3238,18 @@
1171 	q++;
1172 	/* Compatibility with old code that looked in .mime */
1173 	if (ms->flags & MAGIC_MIME) {
1174-		if (asprintf(&buf, "%.*s.mime%s", (int)(q - fn), fn, ext) < 0)
1175-			return NULL;
1176-		if (access(buf, R_OK) != -1) {
1177+		spprintf(&buf, MAXPATHLEN, "%.*s.mime%s", (int)(q - fn), fn, ext);
1178+#ifdef PHP_WIN32
1179+		if (VCWD_ACCESS(buf, R_OK) == 0) {
1180+#else
1181+		if (VCWD_ACCESS(buf, R_OK) != -1) {
1182+#endif
1183 			ms->flags &= MAGIC_MIME_TYPE;
1184 			return buf;
1185 		}
1186-		free(buf);
1187+		efree(buf);
1188 	}
1189-	if (asprintf(&buf, "%.*s%s", (int)(q - fn), fn, ext) < 0)
1190-		return NULL;
1191+	spprintf(&buf, MAXPATHLEN, "%.*s%s", (int)(q - fn), fn, ext);
1192
1193 	/* Compatibility with old code that looked in .mime */
1194 	if (strstr(fn, ".mime") != NULL)
1195@@ -3274,8 +3275,8 @@
1196 swap2(uint16_t sv)
1197 {
1198 	uint16_t rv;
1199-	uint8_t *s = (uint8_t *)(void *)&sv;
1200-	uint8_t *d = (uint8_t *)(void *)&rv;
1201+	uint8_t *s = (uint8_t *)(void *)&sv;
1202+	uint8_t *d = (uint8_t *)(void *)&rv;
1203 	d[0] = s[1];
1204 	d[1] = s[0];
1205 	return rv;
1206@@ -3288,8 +3289,8 @@
1207 swap4(uint32_t sv)
1208 {
1209 	uint32_t rv;
1210-	uint8_t *s = (uint8_t *)(void *)&sv;
1211-	uint8_t *d = (uint8_t *)(void *)&rv;
1212+	uint8_t *s = (uint8_t *)(void *)&sv;
1213+	uint8_t *d = (uint8_t *)(void *)&rv;
1214 	d[0] = s[3];
1215 	d[1] = s[2];
1216 	d[2] = s[1];
1217@@ -3304,8 +3305,8 @@
1218 swap8(uint64_t sv)
1219 {
1220 	uint64_t rv;
1221-	uint8_t *s = (uint8_t *)(void *)&sv;
1222-	uint8_t *d = (uint8_t *)(void *)&rv;
1223+	uint8_t *s = (uint8_t *)(void *)&sv;
1224+	uint8_t *d = (uint8_t *)(void *)&rv;
1225 #if 0
1226 	d[0] = s[3];
1227 	d[1] = s[2];
1228@@ -3338,7 +3339,7 @@
1229 	m->offset = swap4((int32_t)m->offset);
1230 	m->in_offset = swap4((uint32_t)m->in_offset);
1231 	m->lineno = swap4((uint32_t)m->lineno);
1232-	if (IS_STRING(m->type)) {
1233+	if (IS_LIBMAGIC_STRING(m->type)) {
1234 		m->str_range = swap4(m->str_range);
1235 		m->str_flags = swap4(m->str_flags);
1236 	}
1237@@ -3348,7 +3349,7 @@
1238 	}
1239 }
1240
1241-protected size_t
1242+protected size_t
1243 file_pstring_length_size(const struct magic *m)
1244 {
1245 	switch (m->str_flags & PSTRING_LEN) {
1246diff -u libmagic.orig/apptype.c libmagic/apptype.c
1247--- libmagic.orig/apptype.c	2011-09-07 23:57:15.000000000 +0200
1248+++ libmagic/apptype.c	2020-02-26 09:55:13.843047200 +0100
1249@@ -1,15 +1,15 @@
1250 /*
1251  * Adapted from: apptype.c, Written by Eberhard Mattes and put into the
1252  * public domain
1253- *
1254+ *
1255  * Notes: 1. Qualify the filename so that DosQueryAppType does not do extraneous
1256  * searches.
1257- *
1258+ *
1259  * 2. DosQueryAppType will return FAPPTYP_DOS on a file ending with ".com"
1260  * (other than an OS/2 exe or Win exe with this name). Eberhard Mattes
1261  * remarks Tue, 6 Apr 93: Moreover, it reports the type of the (new and very
1262  * bug ridden) Win Emacs as "OS/2 executable".
1263- *
1264+ *
1265  * 3. apptype() uses the filename if given, otherwise a tmp file is created with
1266  * the contents of buf. If buf is not the complete file, apptype can
1267  * incorrectly identify the exe type. The "-z" option of "file" is the reason
1268@@ -18,10 +18,10 @@
1269
1270 /*
1271  * amai: Darrel Hankerson did the changes described here.
1272- *
1273+ *
1274  * It remains to check the validity of comments (2.) since it's referred to an
1275  * "old" OS/2 version.
1276- *
1277+ *
1278  */
1279
1280 #include "file.h"
1281diff -u libmagic.orig/ascmagic.c libmagic/ascmagic.c
1282--- libmagic.orig/ascmagic.c	2017-11-02 21:25:39.000000000 +0100
1283+++ libmagic/ascmagic.c	2020-02-26 09:55:13.845043300 +0100
1284@@ -90,7 +90,7 @@
1285 		rv = file_ascmagic_with_encoding(ms, &bb,
1286 		    ubuf, ulen, code, type, text);
1287
1288-	free(ubuf);
1289+	efree(ubuf);
1290
1291 	return rv;
1292 }
1293@@ -137,7 +137,7 @@
1294 		/* malloc size is a conservative overestimate; could be
1295 		   improved, or at least realloced after conversion. */
1296 		mlen = ulen * 6;
1297-		if ((utf8_buf = CAST(unsigned char *, malloc(mlen))) == NULL) {
1298+		if ((utf8_buf = CAST(unsigned char *, emalloc(mlen))) == NULL) {
1299 			file_oomem(ms, mlen);
1300 			goto done;
1301 		}
1302@@ -305,7 +305,8 @@
1303 	}
1304 	rv = 1;
1305 done:
1306-	free(utf8_buf);
1307+	if (utf8_buf)
1308+		efree(utf8_buf);
1309
1310 	return rv;
1311 }
1312diff -u libmagic.orig/buffer.c libmagic/buffer.c
1313--- libmagic.orig/buffer.c	2018-03-11 01:46:42.000000000 +0100
1314+++ libmagic/buffer.c	2020-02-26 09:55:13.846042600 +0100
1315@@ -31,7 +31,11 @@
1316 #endif	/* lint */
1317
1318 #include "magic.h"
1319+#ifdef PHP_WIN32
1320+#include "win32/unistd.h"
1321+#else
1322 #include <unistd.h>
1323+#endif
1324 #include <string.h>
1325 #include <stdlib.h>
1326 #include <sys/stat.h>
1327@@ -40,7 +44,7 @@
1328 buffer_init(struct buffer *b, int fd, const void *data, size_t len)
1329 {
1330 	b->fd = fd;
1331-	if (b->fd == -1 || fstat(b->fd, &b->st) == -1)
1332+	if (b->fd == -1 || zend_fstat(b->fd, &b->st) == -1)
1333 		memset(&b->st, 0, sizeof(b->st));
1334 	b->fbuf = data;
1335 	b->flen = len;
1336@@ -52,7 +56,7 @@
1337 void
1338 buffer_fini(struct buffer *b)
1339 {
1340-	free(b->ebuf);
1341+	efree(b->ebuf);
1342 }
1343
1344 int
1345@@ -68,12 +72,14 @@
1346
1347 	b->elen =  (size_t)b->st.st_size < b->flen ?
1348 	    (size_t)b->st.st_size : b->flen;
1349-	if ((b->ebuf = malloc(b->elen)) == NULL)
1350+	if ((b->ebuf = emalloc(b->elen)) == NULL)
1351 		goto out;
1352
1353 	b->eoff = b->st.st_size - b->elen;
1354-	if (pread(b->fd, b->ebuf, b->elen, b->eoff) == -1) {
1355-		free(b->ebuf);
1356+	if (FINFO_LSEEK_FUNC(b->fd, b->eoff, SEEK_SET) == (zend_off_t)-1 ||
1357+		FINFO_READ_FUNC(b->fd, b->ebuf, b->elen) != (ssize_t)b->elen)
1358+	{
1359+		efree(b->ebuf);
1360 		goto out;
1361 	}
1362
1363diff -u libmagic.orig/cdf.c libmagic/cdf.c
1364--- libmagic.orig/cdf.c	2018-03-11 01:46:42.000000000 +0100
1365+++ libmagic/cdf.c	2020-02-26 09:55:13.847043900 +0100
1366@@ -43,7 +43,17 @@
1367 #include <err.h>
1368 #endif
1369 #include <stdlib.h>
1370+
1371+#ifdef PHP_WIN32
1372+#include "win32/unistd.h"
1373+#else
1374 #include <unistd.h>
1375+#endif
1376+
1377+#ifndef UINT32_MAX
1378+# define UINT32_MAX (0xffffffff)
1379+#endif
1380+
1381 #include <string.h>
1382 #include <time.h>
1383 #include <ctype.h>
1384@@ -80,37 +90,9 @@
1385 			    CDF_TOLE8(CAST(uint64_t, x))))
1386 #define CDF_GETUINT32(x, y)	cdf_getuint32(x, y)
1387
1388-#define CDF_MALLOC(n) cdf_malloc(__FILE__, __LINE__, (n))
1389-#define CDF_REALLOC(p, n) cdf_realloc(__FILE__, __LINE__, (p), (n))
1390-#define CDF_CALLOC(n, u) cdf_calloc(__FILE__, __LINE__, (n), (u))
1391-
1392-
1393-/*ARGSUSED*/
1394-static void *
1395-cdf_malloc(const char *file __attribute__((__unused__)),
1396-    size_t line __attribute__((__unused__)), size_t n)
1397-{
1398-	DPRINTF(("%s,%zu: %s %zu\n", file, line, __func__, n));
1399-	return malloc(n);
1400-}
1401-
1402-/*ARGSUSED*/
1403-static void *
1404-cdf_realloc(const char *file __attribute__((__unused__)),
1405-    size_t line __attribute__((__unused__)), void *p, size_t n)
1406-{
1407-	DPRINTF(("%s,%zu: %s %zu\n", file, line, __func__, n));
1408-	return realloc(p, n);
1409-}
1410-
1411-/*ARGSUSED*/
1412-static void *
1413-cdf_calloc(const char *file __attribute__((__unused__)),
1414-    size_t line __attribute__((__unused__)), size_t n, size_t u)
1415-{
1416-	DPRINTF(("%s,%zu: %s %zu %zu\n", file, line, __func__, n, u));
1417-	return calloc(n, u);
1418-}
1419+#define CDF_MALLOC(n) emalloc(n)
1420+#define CDF_REALLOC(p, n) erealloc(p, n)
1421+#define CDF_CALLOC(n, u) ecalloc(n, u)
1422
1423 /*
1424  * swap a short
1425@@ -303,7 +285,7 @@
1426 	scn->sst_len = 0;
1427 	scn->sst_dirlen = 0;
1428 	scn->sst_ss = 0;
1429-	free(scn->sst_tab);
1430+	efree(scn->sst_tab);
1431 	scn->sst_tab = NULL;
1432 	return -1;
1433 }
1434@@ -336,12 +318,13 @@
1435 }
1436
1437 static ssize_t
1438-cdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len)
1439+cdf_read(const cdf_info_t *info, zend_off_t off, void *buf, size_t len)
1440 {
1441 	size_t siz = (size_t)off + len;
1442
1443-	if ((off_t)(off + len) != (off_t)siz)
1444+	if ((zend_off_t)(off + len) != (zend_off_t)siz) {
1445 		goto out;
1446+	}
1447
1448 	if (info->i_buf != NULL && info->i_len >= siz) {
1449 		(void)memcpy(buf, &info->i_buf[off], len);
1450@@ -351,7 +334,10 @@
1451 	if (info->i_fd == -1)
1452 		goto out;
1453
1454-	if (pread(info->i_fd, buf, len, off) != (ssize_t)len)
1455+	if (FINFO_LSEEK_FUNC(info->i_fd, off, SEEK_SET) == (zend_off_t)-1)
1456+		return -1;
1457+
1458+	if (FINFO_READ_FUNC(info->i_fd, buf, len) != (ssize_t)len)
1459 		return -1;
1460
1461 	return (ssize_t)len;
1462@@ -366,7 +352,7 @@
1463 	char buf[512];
1464
1465 	(void)memcpy(cdf_bo.s, "\01\02\03\04", 4);
1466-	if (cdf_read(info, (off_t)0, buf, sizeof(buf)) == -1)
1467+	if (cdf_read(info, (zend_off_t)0, buf, sizeof(buf)) == -1)
1468 		return -1;
1469 	cdf_unpack_header(h, buf);
1470 	cdf_swap_header(h);
1471@@ -400,7 +386,7 @@
1472 	size_t ss = CDF_SEC_SIZE(h);
1473 	size_t pos = CDF_SEC_POS(h, id);
1474 	assert(ss == len);
1475-	return cdf_read(info, (off_t)pos, ((char *)buf) + offs, len);
1476+	return cdf_read(info, (zend_off_t)pos, ((char *)buf) + offs, len);
1477 }
1478
1479 ssize_t
1480@@ -501,14 +487,14 @@
1481 	}
1482 out:
1483 	sat->sat_len = i;
1484-	free(msa);
1485+	efree(msa);
1486 	return 0;
1487 out3:
1488 	errno = EFTYPE;
1489 out2:
1490-	free(msa);
1491+	efree(msa);
1492 out1:
1493-	free(sat->sat_tab);
1494+	efree(sat->sat_tab);
1495 	return -1;
1496 }
1497
1498@@ -676,7 +662,7 @@
1499 		return -1;
1500
1501 	if ((buf = CAST(char *, CDF_MALLOC(ss))) == NULL) {
1502-		free(dir->dir_tab);
1503+		efree(dir->dir_tab);
1504 		return -1;
1505 	}
1506
1507@@ -698,11 +684,11 @@
1508 	if (NEED_SWAP)
1509 		for (i = 0; i < dir->dir_len; i++)
1510 			cdf_swap_dir(&dir->dir_tab[i]);
1511-	free(buf);
1512+	efree(buf);
1513 	return 0;
1514 out:
1515-	free(dir->dir_tab);
1516-	free(buf);
1517+	efree(dir->dir_tab);
1518+	efree(buf);
1519 	errno = EFTYPE;
1520 	return -1;
1521 }
1522@@ -747,7 +733,7 @@
1523 out:
1524 	errno = EFTYPE;
1525 out1:
1526-	free(ssat->sat_tab);
1527+	efree(ssat->sat_tab);
1528 	return -1;
1529 }
1530
1531@@ -859,7 +845,7 @@
1532 }
1533
1534 static const uint8_t *
1535-cdf_get_property_info_pos(const cdf_stream_t *sst, const cdf_header_t *h,
1536+cdf_get_property_info_pos(const cdf_stream_t *sst, const cdf_header_t *h,
1537     const uint8_t *p, const uint8_t *e, size_t i)
1538 {
1539 	size_t tail = (i << 1) + 1;
1540@@ -874,7 +860,7 @@
1541 	    __LINE__) == -1)
1542 		return NULL;
1543 	ofs = CDF_GETUINT32(p, tail);
1544-	q = CAST(const uint8_t *, cdf_offset(CAST(const void *, p),
1545+	q = CAST(const uint8_t *, cdf_offset(CAST(const void *, p),
1546 	    ofs - 2 * sizeof(uint32_t)));
1547
1548 	if (q < p) {
1549@@ -896,7 +882,7 @@
1550 	size_t newcount = *maxcount + incr;
1551
1552 	if (newcount > CDF_PROP_LIMIT) {
1553-		DPRINTF(("exceeded property limit %zu > %zu\n",
1554+		DPRINTF(("exceeded property limit %zu > %zu\n",
1555 		    newcount, CDF_PROP_LIMIT));
1556 		goto out;
1557 	}
1558@@ -909,7 +895,7 @@
1559 	*maxcount = newcount;
1560 	return inp;
1561 out:
1562-	free(*info);
1563+	efree(*info);
1564 	*maxcount = 0;
1565 	*info = NULL;
1566 	return NULL;
1567@@ -1003,8 +989,9 @@
1568 				goto out;
1569 			}
1570 			nelements = CDF_GETUINT32(q, 1);
1571-			if (nelements == 0) {
1572-				DPRINTF(("CDF_VECTOR with nelements == 0\n"));
1573+			if (nelements > CDF_ELEMENT_LIMIT || nelements == 0) {
1574+				DPRINTF(("CDF_VECTOR with nelements == %"
1575+				    SIZE_T_FORMAT "u\n", nelements));
1576 				goto out;
1577 			}
1578 			slen = 2;
1579@@ -1046,8 +1033,6 @@
1580 					goto out;
1581 				inp += nelem;
1582 			}
1583-			DPRINTF(("nelements = %" SIZE_T_FORMAT "u\n",
1584-			    nelements));
1585 			for (j = 0; j < nelements && i < sh.sh_properties;
1586 			    j++, i++)
1587 			{
1588@@ -1092,7 +1077,7 @@
1589 	}
1590 	return 0;
1591 out:
1592-	free(*info);
1593+	efree(*info);
1594 	*info = NULL;
1595 	*count = 0;
1596 	*maxcount = 0;
1597@@ -1383,7 +1368,7 @@
1598 	cdf_directory_t *d;
1599 	char name[__arraycount(d->d_name)];
1600 	cdf_stream_t scn;
1601-	struct timespec ts;
1602+	struct timeval ts;
1603
1604 	static const char *types[] = { "empty", "user storage",
1605 	    "user stream", "lockbytes", "property", "root storage" };
1606@@ -1425,7 +1410,7 @@
1607 				break;
1608 			}
1609 			cdf_dump_stream(&scn);
1610-			free(scn.sst_tab);
1611+			efree(scn.sst_tab);
1612 			break;
1613 		default:
1614 			break;
1615@@ -1438,7 +1423,7 @@
1616 cdf_dump_property_info(const cdf_property_info_t *info, size_t count)
1617 {
1618 	cdf_timestamp_t tp;
1619-	struct timespec ts;
1620+	struct timeval ts;
1621 	char buf[64];
1622 	size_t i, j;
1623
1624@@ -1523,7 +1508,7 @@
1625 	(void)fprintf(stderr, "Class %s\n", buf);
1626 	(void)fprintf(stderr, "Count %d\n", ssi.si_count);
1627 	cdf_dump_property_info(info, count);
1628-	free(info);
1629+	efree(info);
1630 }
1631
1632
1633@@ -1544,7 +1529,7 @@
1634 		    cdf_u16tos8(sbuf, ce[i].ce_namlen, ce[i].ce_name),
1635 		    cdf_ctime(&ts.tv_sec, tbuf));
1636 	}
1637-	free(cat);
1638+	efree(cat);
1639 }
1640
1641 #endif
1642diff -u libmagic.orig/cdf.h libmagic/cdf.h
1643--- libmagic.orig/cdf.h	2017-03-09 17:57:17.000000000 +0100
1644+++ libmagic/cdf.h	2020-02-26 09:55:13.848043100 +0100
1645@@ -35,10 +35,10 @@
1646 #ifndef _H_CDF_
1647 #define _H_CDF_
1648
1649-#ifdef WIN32
1650+#ifdef PHP_WIN32
1651 #include <winsock2.h>
1652-#define timespec timeval
1653-#define tv_nsec tv_usec
1654+#define asctime_r php_asctime_r
1655+#define ctime_r php_ctime_r
1656 #endif
1657 #ifdef __DJGPP__
1658 #define timespec timeval
1659@@ -48,6 +48,7 @@
1660 typedef int32_t cdf_secid_t;
1661
1662 #define CDF_LOOP_LIMIT					10000
1663+#define CDF_ELEMENT_LIMIT				100000
1664
1665 #define CDF_SECID_NULL					0
1666 #define CDF_SECID_FREE					-1
1667@@ -272,7 +273,7 @@
1668 typedef struct {
1669 	uint16_t ce_namlen;
1670 	uint32_t ce_num;
1671-	uint64_t ce_timestamp;
1672+	uint64_t ce_timestamp;
1673 	uint16_t ce_name[256];
1674 } cdf_catalog_entry_t;
1675
1676diff -u libmagic.orig/cdf_time.c libmagic/cdf_time.c
1677--- libmagic.orig/cdf_time.c	2017-03-29 17:57:48.000000000 +0200
1678+++ libmagic/cdf_time.c	2020-02-26 09:55:13.849044200 +0100
1679@@ -23,6 +23,7 @@
1680  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1681  * POSSIBILITY OF SUCH DAMAGE.
1682  */
1683+#include "php.h"
1684
1685 #include "file.h"
1686
1687@@ -56,7 +57,7 @@
1688
1689 	for (y = CDF_BASE_YEAR; y < year; y++)
1690 		days += isleap(y) + 365;
1691-
1692+
1693 	return days;
1694 }
1695
1696@@ -77,7 +78,7 @@
1697 	return days;
1698 }
1699
1700-/*
1701+/*
1702  * Return the 0...11 month number.
1703  */
1704 static int
1705@@ -152,7 +153,7 @@
1706 #endif
1707 #ifdef notyet
1708 	struct tm tm;
1709-	if (gmtime_r(&ts->ts_sec, &tm) == NULL) {
1710+	if (php_gmtime_r(&ts->ts_sec, &tm) == NULL) {
1711 		errno = EINVAL;
1712 		return -1;
1713 	}
1714@@ -168,7 +169,7 @@
1715 char *
1716 cdf_ctime(const time_t *sec, char *buf)
1717 {
1718-	char *ptr = ctime_r(sec, buf);
1719+	char *ptr = php_ctime_r(sec, buf);
1720 	if (ptr != NULL)
1721 		return buf;
1722 	(void)snprintf(buf, 26, "*Bad* %#16.16" INT64_T_FORMAT "x\n",
1723diff -u libmagic.orig/compress.c libmagic/compress.c
1724--- libmagic.orig/compress.c	2017-11-02 21:25:39.000000000 +0100
1725+++ libmagic/compress.c	2020-02-26 09:55:13.850043300 +0100
1726@@ -2,7 +2,7 @@
1727  * Copyright (c) Ian F. Darwin 1986-1995.
1728  * Software written by Ian F. Darwin and others;
1729  * maintained 1995-present by Christos Zoulas and others.
1730- *
1731+ *
1732  * Redistribution and use in source and binary forms, with or without
1733  * modification, are permitted provided that the following conditions
1734  * are met:
1735@@ -12,7 +12,7 @@
1736  * 2. Redistributions in binary form must reproduce the above copyright
1737  *    notice, this list of conditions and the following disclaimer in the
1738  *    documentation and/or other materials provided with the distribution.
1739- *
1740+ *
1741  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1742  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1743  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1744@@ -29,13 +29,13 @@
1745  * compress routines:
1746  *	zmagic() - returns 0 if not recognized, uncompresses and prints
1747  *		   information if recognized
1748- *	uncompress(method, old, n, newch) - uncompress old into new,
1749+ *	uncompress(method, old, n, newch) - uncompress old into new,
1750  *					    using method, return sizeof new
1751  */
1752 #include "file.h"
1753
1754 #ifndef lint
1755-FILE_RCSID("@(#)$File: compress.c,v 1.106 2017/11/02 20:25:39 christos Exp $")
1756+FILE_RCSID("@(#)$File: compress.c,v 1.104 2017/03/29 15:57:48 christos Exp $")
1757 #endif
1758
1759 #include "magic.h"
1760@@ -45,15 +45,13 @@
1761 #endif
1762 #include <string.h>
1763 #include <errno.h>
1764-#include <ctype.h>
1765-#include <stdarg.h>
1766 #ifdef HAVE_SIGNAL_H
1767 #include <signal.h>
1768 # ifndef HAVE_SIG_T
1769 typedef void (*sig_t)(int);
1770 # endif /* HAVE_SIG_T */
1771-#endif
1772-#if !defined(__MINGW32__) && !defined(WIN32)
1773+#endif
1774+#ifndef PHP_WIN32
1775 #include <sys/ioctl.h>
1776 #endif
1777 #ifdef HAVE_SYS_WAIT_H
1778@@ -62,51 +60,12 @@
1779 #if defined(HAVE_SYS_TIME_H)
1780 #include <sys/time.h>
1781 #endif
1782-#if defined(HAVE_ZLIB_H) && defined(ZLIBSUPPORT)
1783+#if defined(HAVE_ZLIB_H) && defined(PHP_FILEINFO_UNCOMPRESS)
1784 #define BUILTIN_DECOMPRESS
1785 #include <zlib.h>
1786 #endif
1787-#ifdef DEBUG
1788-int tty = -1;
1789-#define DPRINTF(...)	do { \
1790-	if (tty == -1) \
1791-		tty = open("/dev/tty", O_RDWR); \
1792-	if (tty == -1) \
1793-		abort(); \
1794-	dprintf(tty, __VA_ARGS__); \
1795-} while (/*CONSTCOND*/0)
1796-#else
1797-#define DPRINTF(...)
1798-#endif
1799-
1800-#ifdef ZLIBSUPPORT
1801-/*
1802- * The following python code is not really used because ZLIBSUPPORT is only
1803- * defined if we have a built-in zlib, and the built-in zlib handles that.
1804- * That is not true for android where we have zlib.h and not -lz.
1805- */
1806-static const char zlibcode[] =
1807-    "import sys, zlib; sys.stdout.write(zlib.decompress(sys.stdin.read()))";
1808-
1809-static const char *zlib_args[] = { "python", "-c", zlibcode, NULL };
1810
1811-static int
1812-zlibcmp(const unsigned char *buf)
1813-{
1814-	unsigned short x = 1;
1815-	unsigned char *s = CAST(unsigned char *, CAST(void *, &x));
1816-
1817-	if ((buf[0] & 0xf) != 8 || (buf[0] & 0x80) != 0)
1818-		return 0;
1819-	if (s[0] != 1)	/* endianness test */
1820-		x = buf[0] | (buf[1] << 8);
1821-	else
1822-		x = buf[1] | (buf[0] << 8);
1823-	if (x % 31)
1824-		return 0;
1825-	return 1;
1826-}
1827-#endif
1828+#undef FIONREAD
1829
1830 #define gzip_flags "-cd"
1831 #define lrzip_flags "-do"
1832@@ -169,7 +128,7 @@
1833 #define ERRDATA	2
1834
1835 private ssize_t swrite(int, const void *, size_t);
1836-#if HAVE_FORK
1837+#ifdef PHP_FILEINFO_UNCOMPRESS
1838 private size_t ncompr = sizeof(compr) / sizeof(compr[0]);
1839 private int uncompressbuf(int, size_t, size_t, const unsigned char *,
1840     unsigned char **, size_t *);
1841@@ -179,12 +138,12 @@
1842 private int uncompressgzipped(const unsigned char *, unsigned char **, size_t,
1843     size_t *);
1844 #endif
1845-static int makeerror(unsigned char **, size_t *, const char *, ...)
1846-    __attribute__((__format__(__printf__, 3, 4)));
1847+static int makeerror(unsigned char **, size_t *, const char *, ...);
1848 private const char *methodname(size_t);
1849
1850 protected int
1851-file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name)
1852+file_zmagic(struct magic_set *ms, int fd, const char *name,
1853+    const unsigned char *buf, size_t nbytes)
1854 {
1855 	unsigned char *newbuf = NULL;
1856 	size_t i, nsz;
1857@@ -192,9 +151,6 @@
1858 	file_pushbuf_t *pb;
1859 	int urv, prv, rv = 0;
1860 	int mime = ms->flags & MAGIC_MIME;
1861-	int fd = b->fd;
1862-	const unsigned char *buf = b->fbuf;
1863-	size_t nbytes = b->flen;
1864 #ifdef HAVE_SIGNAL_H
1865 	sig_t osigpipe;
1866 #endif
1867@@ -226,7 +182,7 @@
1868 		switch (urv) {
1869 		case OKDATA:
1870 		case ERRDATA:
1871-
1872+
1873 			ms->flags &= ~MAGIC_COMPRESS;
1874 			if (urv == ERRDATA)
1875 				prv = file_printf(ms, "%s ERROR: %s",
1876@@ -253,10 +209,10 @@
1877 				goto error;
1878 			if ((rbuf = file_pop_buffer(ms, pb)) != NULL) {
1879 				if (file_printf(ms, "%s", rbuf) == -1) {
1880-					free(rbuf);
1881+					efree(rbuf);
1882 					goto error;
1883 				}
1884-				free(rbuf);
1885+				efree(rbuf);
1886 			}
1887 			if (!mime && file_printf(ms, ")") == -1)
1888 				goto error;
1889@@ -277,7 +233,8 @@
1890 #ifdef HAVE_SIGNAL_H
1891 	(void)signal(SIGPIPE, osigpipe);
1892 #endif
1893-	free(newbuf);
1894+	if (newbuf)
1895+		efree(newbuf);
1896 	ms->flags |= MAGIC_COMPRESS;
1897 	DPRINTF("Zmagic returns %d\n", rv);
1898 	return rv;
1899@@ -312,7 +269,7 @@
1900  * `safe' read for sockets and pipes.
1901  */
1902 protected ssize_t
1903-sread(int fd, void *buf, size_t n, int canbepipe __attribute__((__unused__)))
1904+sread(int fd, void *buf, size_t n, int canbepipe)
1905 {
1906 	ssize_t rv;
1907 #ifdef FIONREAD
1908@@ -360,7 +317,7 @@
1909
1910 nocheck:
1911 	do
1912-		switch ((rv = read(fd, buf, n))) {
1913+		switch ((rv = FINFO_READ_FUNC(fd, buf, n))) {
1914 		case -1:
1915 			if (errno == EINTR)
1916 				continue;
1917@@ -437,13 +394,14 @@
1918 		return -1;
1919 	}
1920 	(void)close(tfd);
1921-	if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
1922+	if (FINFO_LSEEK_FUNC(fd, (zend_off_t)0, SEEK_SET) == (zend_off_t)-1) {
1923 		file_badseek(ms);
1924 		return -1;
1925 	}
1926 	return fd;
1927 }
1928-#if HAVE_FORK
1929+
1930+#ifdef PHP_FILEINFO_UNCOMPRESS
1931 #ifdef BUILTIN_DECOMPRESS
1932
1933 #define FHCRC		(1 << 1)
1934@@ -494,7 +452,7 @@
1935 	int rc;
1936 	z_stream z;
1937
1938-	if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL)
1939+	if ((*newch = CAST(unsigned char *, emalloc(bytes_max + 1))) == NULL)
1940 		return makeerror(newch, n, "No buffer, %s", strerror(errno));
1941
1942 	z.next_in = CCAST(Bytef *, old);
1943@@ -518,7 +476,7 @@
1944 	rc = inflateEnd(&z);
1945 	if (rc != Z_OK)
1946 		goto err;
1947-
1948+
1949 	/* let's keep the nul-terminate tradition */
1950 	(*newch)[*n] = '\0';
1951
1952@@ -586,7 +544,7 @@
1953 	int status;
1954
1955 	closefd(fdp[STDIN_FILENO], 0);
1956-	/*
1957+	/*
1958 	 * fork again, to avoid blocking because both
1959 	 * pipes filled
1960 	 */
1961@@ -689,13 +647,13 @@
1962 			fdp[STDIN_FILENO][0] = fd;
1963 			(void) lseek(fd, (off_t)0, SEEK_SET);
1964 		}
1965-
1966+
1967 		for (i = 0; i < __arraycount(fdp); i++)
1968 			copydesc(CAST(int, i), fdp[i]);
1969
1970 		(void)execvp(compr[method].argv[0],
1971 		    (char *const *)(intptr_t)compr[method].argv);
1972-		dprintf(STDERR_FILENO, "exec `%s' failed, %s",
1973+		dprintf(STDERR_FILENO, "exec `%s' failed, %s",
1974 		    compr[method].argv[0], strerror(errno));
1975 		exit(1);
1976 		/*NOTREACHED*/
1977@@ -711,7 +669,7 @@
1978 		if (fd == -1)
1979 			writechild(fdp, old, *n);
1980
1981-		*newch = CAST(unsigned char *, malloc(bytes_max + 1));
1982+		*newch = CAST(unsigned char *, emalloc(bytes_max + 1));
1983 		if (*newch == NULL) {
1984 			rv = makeerror(newch, n, "No buffer, %s",
1985 			    strerror(errno));
1986@@ -730,7 +688,7 @@
1987 			r = filter_error(*newch, r);
1988 			break;
1989 		}
1990-		free(*newch);
1991+		efree(*newch);
1992 		if  (r == 0)
1993 			rv = makeerror(newch, n, "Read failed, %s",
1994 			    strerror(errno));
1995@@ -738,27 +696,5 @@
1996 			rv = makeerror(newch, n, "No data");
1997 		goto err;
1998 	}
1999-
2000-	*n = r;
2001-	/* NUL terminate, as every buffer is handled here. */
2002-	(*newch)[*n] = '\0';
2003-err:
2004-	closefd(fdp[STDIN_FILENO], 1);
2005-	closefd(fdp[STDOUT_FILENO], 0);
2006-	closefd(fdp[STDERR_FILENO], 0);
2007-	if (wait(&status) == -1) {
2008-		free(*newch);
2009-		rv = makeerror(newch, n, "Wait failed, %s", strerror(errno));
2010-		DPRINTF("Child wait return %#x\n", status);
2011-	} else if (!WIFEXITED(status)) {
2012-		DPRINTF("Child not exited (%#x)\n", status);
2013-	} else if (WEXITSTATUS(status) != 0) {
2014-		DPRINTF("Child exited (%#x)\n", WEXITSTATUS(status));
2015-	}
2016-
2017-	closefd(fdp[STDIN_FILENO], 0);
2018-	DPRINTF("Returning %p n=%zu rv=%d\n", *newch, *n, rv);
2019-
2020-	return rv;
2021 }
2022-#endif
2023+#endif /* if PHP_FILEINFO_UNCOMPRESS */
2024diff -u libmagic.orig/der.c libmagic/der.c
2025--- libmagic.orig/der.c	2017-02-10 19:14:01.000000000 +0100
2026+++ libmagic/der.c	2020-02-26 09:55:13.851044000 +0100
2027@@ -51,7 +51,9 @@
2028 #include "magic.h"
2029 #include "der.h"
2030 #else
2031+#ifndef PHP_WIN32
2032 #include <sys/mman.h>
2033+#endif
2034 #include <sys/stat.h>
2035 #include <err.h>
2036 #endif
2037@@ -207,7 +209,7 @@
2038 static const char *
2039 der_tag(char *buf, size_t len, uint32_t tag)
2040 {
2041-	if (tag < DER_TAG_LONG)
2042+	if (tag < DER_TAG_LONG)
2043 		strlcpy(buf, der__tag[tag], len);
2044 	else
2045 		snprintf(buf, len, "%#x", tag);
2046@@ -218,6 +220,7 @@
2047 static int
2048 der_data(char *buf, size_t blen, uint32_t tag, const void *q, uint32_t len)
2049 {
2050+	uint32_t i = 0;
2051 	const uint8_t *d = CAST(const uint8_t *, q);
2052 	switch (tag) {
2053 	case DER_TAG_PRINTABLE_STRING:
2054@@ -229,7 +232,7 @@
2055 		break;
2056 	}
2057
2058-	for (uint32_t i = 0; i < len; i++) {
2059+	for (; i < len; i++) {
2060 		uint32_t z = i << 1;
2061 		if (z < blen - 2)
2062 			snprintf(buf + z, blen - z, "%.2x", d[i]);
2063@@ -343,7 +346,7 @@
2064 	default:
2065 		break;
2066 	}
2067-
2068+
2069 	for (uint32_t i = 0; i < len; i++)
2070 		printf("%.2x", d[i]);
2071 	printf("\n");
2072@@ -367,7 +370,7 @@
2073 		if (p + x >= ep)
2074 			break;
2075 		uint32_t len = getlength(p, &x, ep - p + x);
2076-
2077+
2078 		printf("%zu %zu-%zu %c,%c,%s,%u:", level, ox, x,
2079 		    der_class[c], der_type[t],
2080 		    der_tag(buf, sizeof(buf), tag), len);
2081diff -u libmagic.orig/elfclass.h libmagic/elfclass.h
2082--- libmagic.orig/elfclass.h	2014-12-17 00:18:40.000000000 +0100
2083+++ libmagic/elfclass.h	2020-02-26 09:55:13.852043400 +0100
2084@@ -1,7 +1,7 @@
2085 /*
2086  * Copyright (c) Christos Zoulas 2008.
2087  * All Rights Reserved.
2088- *
2089+ *
2090  * Redistribution and use in source and binary forms, with or without
2091  * modification, are permitted provided that the following conditions
2092  * are met:
2093@@ -11,7 +11,7 @@
2094  * 2. Redistributions in binary form must reproduce the above copyright
2095  *    notice, this list of conditions and the following disclaimer in the
2096  *    documentation and/or other materials provided with the distribution.
2097- *
2098+ *
2099  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2100  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2101  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2102@@ -41,7 +41,7 @@
2103 			return toomany(ms, "program headers", phnum);
2104 		flags |= FLAGS_IS_CORE;
2105 		if (dophn_core(ms, clazz, swap, fd,
2106-		    (off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
2107+		    (zend_off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
2108 		    (size_t)elf_getu16(swap, elfhdr.e_phentsize),
2109 		    fsize, &flags, &notecount) == -1)
2110 			return -1;
2111@@ -56,7 +56,7 @@
2112 		if (shnum > ms->elf_shnum_max)
2113 			return toomany(ms, "section", shnum);
2114 		if (dophn_exec(ms, clazz, swap, fd,
2115-		    (off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
2116+		    (zend_off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
2117 		    (size_t)elf_getu16(swap, elfhdr.e_phentsize),
2118 		    fsize, shnum, &flags, &notecount) == -1)
2119 			return -1;
2120@@ -66,7 +66,7 @@
2121 		if (shnum > ms->elf_shnum_max)
2122 			return toomany(ms, "section headers", shnum);
2123 		if (doshn(ms, clazz, swap, fd,
2124-		    (off_t)elf_getu(swap, elfhdr.e_shoff), shnum,
2125+		    (zend_off_t)elf_getu(swap, elfhdr.e_shoff), shnum,
2126 		    (size_t)elf_getu16(swap, elfhdr.e_shentsize),
2127 		    fsize, elf_getu16(swap, elfhdr.e_machine),
2128 		    (int)elf_getu16(swap, elfhdr.e_shstrndx),
2129diff -u libmagic.orig/encoding.c libmagic/encoding.c
2130--- libmagic.orig/encoding.c	2017-11-02 21:25:39.000000000 +0100
2131+++ libmagic/encoding.c	2020-02-26 09:55:13.854045100 +0100
2132@@ -88,12 +88,12 @@
2133 	*code_mime = "binary";
2134
2135 	mlen = (nbytes + 1) * sizeof((*ubuf)[0]);
2136-	if ((*ubuf = CAST(unichar *, calloc((size_t)1, mlen))) == NULL) {
2137+	if ((*ubuf = CAST(unichar *, ecalloc((size_t)1, mlen))) == NULL) {
2138 		file_oomem(ms, mlen);
2139 		goto done;
2140 	}
2141 	mlen = (nbytes + 1) * sizeof(nbuf[0]);
2142-	if ((nbuf = CAST(unsigned char *, calloc((size_t)1, mlen))) == NULL) {
2143+	if ((nbuf = CAST(unsigned char *, ecalloc((size_t)1, mlen))) == NULL) {
2144 		file_oomem(ms, mlen);
2145 		goto done;
2146 	}
2147@@ -153,9 +153,9 @@
2148 	}
2149
2150  done:
2151-	free(nbuf);
2152+	efree(nbuf);
2153 	if (ubuf == &udefbuf)
2154-		free(udefbuf);
2155+		efree(udefbuf);
2156
2157 	return rv;
2158 }
2159diff -u libmagic.orig/file.h libmagic/file.h
2160--- libmagic.orig/file.h	2018-03-11 01:46:42.000000000 +0100
2161+++ libmagic/file.h	2020-02-26 09:55:13.856043400 +0100
2162@@ -27,21 +27,15 @@
2163  */
2164 /*
2165  * file.h - definitions for file(1) program
2166- * @(#)$File: file.h,v 1.191 2018/02/21 21:26:00 christos Exp $
2167+ * @(#)$File: file.h,v 1.182 2017/04/07 19:46:44 christos Exp $
2168  */
2169
2170 #ifndef __file_h__
2171 #define __file_h__
2172
2173-#ifdef HAVE_CONFIG_H
2174-#include <config.h>
2175-#endif
2176-#ifdef HAVE_STDINT_H
2177-#ifndef __STDC_LIMIT_MACROS
2178-#define __STDC_LIMIT_MACROS
2179-#endif
2180+#include "config.h"
2181
2182-#ifdef WIN32
2183+#ifdef PHP_WIN32
2184   #ifdef _WIN64
2185     #define SIZE_T_FORMAT "I64"
2186   #else
2187@@ -54,19 +48,31 @@
2188   #define INT64_T_FORMAT "ll"
2189   #define INTMAX_T_FORMAT "j"
2190 #endif
2191-#include <stdint.h>
2192-#endif
2193
2194 #include <stdio.h>	/* Include that here, to make sure __P gets defined */
2195 #include <errno.h>
2196 #include <fcntl.h>	/* For open and flags */
2197+#ifdef HAVE_STDINT_H
2198+#ifndef __STDC_LIMIT_MACROS
2199+#define __STDC_LIMIT_MACROS
2200+#endif
2201+#include <stdint.h>
2202+#endif
2203 #ifdef HAVE_INTTYPES_H
2204 #include <inttypes.h>
2205 #endif
2206-#include <regex.h>
2207-#include <time.h>
2208+#ifdef PHP_WIN32
2209+#include "win32/php_stdint.h"
2210+#endif
2211+
2212+#include "php.h"
2213+#include "ext/standard/php_string.h"
2214+#include "ext/pcre/php_pcre.h"
2215+
2216 #include <sys/types.h>
2217-#ifndef WIN32
2218+#ifdef PHP_WIN32
2219+#include "win32/param.h"
2220+#else
2221 #include <sys/param.h>
2222 #endif
2223 /* Do this here and now, because struct stat gets re-defined on solaris */
2224@@ -79,7 +85,7 @@
2225 #define MAGIC "/etc/magic"
2226 #endif
2227
2228-#if defined(__EMX__) || defined (WIN32)
2229+#if defined(__EMX__) || defined(PHP_WIN32)
2230 #define PATHSEP	';'
2231 #else
2232 #define PATHSEP	':'
2233@@ -113,12 +119,6 @@
2234 #endif
2235 #endif
2236
2237-#ifndef __GNUC__
2238-#ifndef __attribute__
2239-#define __attribute__(a)
2240-#endif
2241-#endif
2242-
2243 #ifndef MIN
2244 #define	MIN(a,b)	(((a) < (b)) ? (a) : (b))
2245 #endif
2246@@ -147,10 +147,10 @@
2247
2248 struct buffer {
2249 	int fd;
2250-	struct stat st;
2251+	zend_stat_t st;
2252 	const void *fbuf;
2253 	size_t flen;
2254-	off_t eoff;
2255+	zend_off_t eoff;
2256 	void *ebuf;
2257 	size_t elen;
2258 };
2259@@ -240,7 +240,7 @@
2260 #define				FILE_DER	48
2261 #define				FILE_NAMES_SIZE	49 /* size of array to contain all names */
2262
2263-#define IS_STRING(t) \
2264+#define IS_LIBMAGIC_STRING(t) \
2265 	((t) == FILE_STRING || \
2266 	 (t) == FILE_PSTRING || \
2267 	 (t) == FILE_BESTRING16 || \
2268@@ -443,26 +443,22 @@
2269 /* Type for Unicode characters */
2270 typedef unsigned long unichar;
2271
2272-struct stat;
2273 #define FILE_T_LOCAL	1
2274 #define FILE_T_WINDOWS	2
2275 protected const char *file_fmttime(uint64_t, int, char *);
2276 protected struct magic_set *file_ms_alloc(int);
2277 protected void file_ms_free(struct magic_set *);
2278-protected int file_buffer(struct magic_set *, int, const char *, const void *,
2279+protected int file_buffer(struct magic_set *, php_stream *, const char *, const void *,
2280     size_t);
2281-protected int file_fsmagic(struct magic_set *, const char *, struct stat *);
2282+protected int file_fsmagic(struct magic_set *, const char *, zend_stat_t *, php_stream *);
2283 protected int file_pipe2file(struct magic_set *, int, const void *, size_t);
2284-protected int file_vprintf(struct magic_set *, const char *, va_list)
2285-    __attribute__((__format__(__printf__, 2, 0)));
2286 protected size_t file_printedlen(const struct magic_set *);
2287 protected int file_replace(struct magic_set *, const char *, const char *);
2288-protected int file_printf(struct magic_set *, const char *, ...)
2289-    __attribute__((__format__(__printf__, 2, 3)));
2290+protected int file_printf(struct magic_set *, const char *, ...);
2291 protected int file_reset(struct magic_set *, int);
2292 protected int file_tryelf(struct magic_set *, const struct buffer *);
2293 protected int file_trycdf(struct magic_set *, const struct buffer *);
2294-#if HAVE_FORK
2295+#ifdef PHP_FILEINFO_UNCOMPRESS
2296 protected int file_zmagic(struct magic_set *, const struct buffer *,
2297     const char *);
2298 #endif
2299@@ -484,13 +480,9 @@
2300 protected void file_badread(struct magic_set *);
2301 protected void file_badseek(struct magic_set *);
2302 protected void file_oomem(struct magic_set *, size_t);
2303-protected void file_error(struct magic_set *, int, const char *, ...)
2304-    __attribute__((__format__(__printf__, 3, 4)));
2305-protected void file_magerror(struct magic_set *, const char *, ...)
2306-    __attribute__((__format__(__printf__, 2, 3)));
2307-protected void file_magwarn(struct magic_set *, const char *, ...)
2308-    __attribute__((__format__(__printf__, 2, 3)));
2309-protected void file_mdump(struct magic *);
2310+protected void file_error(struct magic_set *, int, const char *, ...);
2311+protected void file_magerror(struct magic_set *, const char *, ...);
2312+protected void file_magwarn(struct magic_set *, const char *, ...);
2313 protected void file_showstr(FILE *, const char *, size_t);
2314 protected size_t file_mbswidth(const char *);
2315 protected const char *file_getbuffer(struct magic_set *);
2316@@ -510,31 +502,8 @@
2317 protected void buffer_fini(struct buffer *);
2318 protected int buffer_fill(const struct buffer *);
2319
2320-#if defined(HAVE_LOCALE_H)
2321-#include <locale.h>
2322-#endif
2323-#if defined(HAVE_XLOCALE_H)
2324-#include <xlocale.h>
2325-#endif
2326-
2327-typedef struct {
2328-	const char *pat;
2329-#if defined(HAVE_NEWLOCALE) && defined(HAVE_USELOCALE) && defined(HAVE_FREELOCALE)
2330-#define USE_C_LOCALE
2331-	locale_t old_lc_ctype;
2332-	locale_t c_lc_ctype;
2333-#else
2334-	char *old_lc_ctype;
2335-#endif
2336-	int rc;
2337-	regex_t rx;
2338-} file_regex_t;
2339-
2340-protected int file_regcomp(file_regex_t *, const char *, int);
2341-protected int file_regexec(file_regex_t *, const char *, size_t, regmatch_t *,
2342-    int);
2343-protected void file_regfree(file_regex_t *);
2344-protected void file_regerror(file_regex_t *, int, struct magic_set *);
2345+public void
2346+convert_libmagic_pattern(zval *pattern, char *val, size_t len, uint32_t options);
2347
2348 typedef struct {
2349 	char *buf;
2350@@ -544,10 +513,8 @@
2351 protected file_pushbuf_t *file_push_buffer(struct magic_set *);
2352 protected char  *file_pop_buffer(struct magic_set *, file_pushbuf_t *);
2353
2354-#ifndef COMPILE_ONLY
2355 extern const char *file_names[];
2356 extern const size_t file_nnames;
2357-#endif
2358
2359 #ifndef HAVE_STRERROR
2360 extern int sys_nerr;
2361@@ -560,23 +527,10 @@
2362 #define strtoul(a, b, c)	strtol(a, b, c)
2363 #endif
2364
2365-#ifndef HAVE_PREAD
2366-ssize_t pread(int, void *, size_t, off_t);
2367-#endif
2368-#ifndef HAVE_VASPRINTF
2369-int vasprintf(char **, const char *, va_list);
2370-#endif
2371-#ifndef HAVE_ASPRINTF
2372-int asprintf(char **, const char *, ...);
2373-#endif
2374-#ifndef HAVE_DPRINTF
2375-int dprintf(int, const char *, ...);
2376-#endif
2377-
2378-#ifndef HAVE_STRLCPY
2379+#ifndef strlcpy
2380 size_t strlcpy(char *, const char *, size_t);
2381 #endif
2382-#ifndef HAVE_STRLCAT
2383+#ifndef strlcat
2384 size_t strlcat(char *, const char *, size_t);
2385 #endif
2386 #ifndef HAVE_STRCASESTR
2387@@ -592,39 +546,6 @@
2388 #ifndef HAVE_ASCTIME_R
2389 char   *asctime_r(const struct tm *, char *);
2390 #endif
2391-#ifndef HAVE_GMTIME_R
2392-struct tm *gmtime_r(const time_t *, struct tm *);
2393-#endif
2394-#ifndef HAVE_LOCALTIME_R
2395-struct tm *localtime_r(const time_t *, struct tm *);
2396-#endif
2397-#ifndef HAVE_FMTCHECK
2398-const char *fmtcheck(const char *, const char *)
2399-     __attribute__((__format_arg__(2)));
2400-#endif
2401-
2402-#ifdef HAVE_LIBSECCOMP
2403-// basic filter
2404-// this mode should not interfere with normal operations
2405-// only some dangerous syscalls are blacklisted
2406-int enable_sandbox_basic(void);
2407-
2408-// enhanced filter
2409-// this mode allows only the necessary syscalls used during normal operation
2410-// extensive testing required !!!
2411-int enable_sandbox_full(void);
2412-#endif
2413-
2414-protected const char *file_getprogname(void);
2415-protected void file_setprogname(const char *);
2416-protected void file_err(int, const char *, ...)
2417-    __attribute__((__format__(__printf__, 2, 3)));
2418-protected void file_errx(int, const char *, ...)
2419-    __attribute__((__format__(__printf__, 2, 3)));
2420-protected void file_warn(const char *, ...)
2421-    __attribute__((__format__(__printf__, 1, 2)));
2422-protected void file_warnx(const char *, ...)
2423-    __attribute__((__format__(__printf__, 1, 2)));
2424
2425 #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H) && !defined(QUICK)
2426 #define QUICK
2427@@ -647,6 +568,18 @@
2428 #else
2429 #define FILE_RCSID(id)
2430 #endif
2431+
2432+#ifdef PHP_WIN32
2433+#ifdef _WIN64
2434+#define FINFO_LSEEK_FUNC _lseeki64
2435+#else
2436+#define FINFO_LSEEK_FUNC _lseek
2437+#endif
2438+#define FINFO_READ_FUNC _read
2439+#else
2440+#define FINFO_LSEEK_FUNC lseek
2441+#define FINFO_READ_FUNC read
2442+#endif
2443 #ifndef __RCSID
2444 #define __RCSID(a)
2445 #endif
2446diff -u libmagic.orig/fsmagic.c libmagic/fsmagic.c
2447--- libmagic.orig/fsmagic.c	2017-05-24 21:17:50.000000000 +0200
2448+++ libmagic/fsmagic.c	2020-02-26 09:55:13.857043000 +0100
2449@@ -2,7 +2,7 @@
2450  * Copyright (c) Ian F. Darwin 1986-1995.
2451  * Software written by Ian F. Darwin and others;
2452  * maintained 1995-present by Christos Zoulas and others.
2453- *
2454+ *
2455  * Redistribution and use in source and binary forms, with or without
2456  * modification, are permitted provided that the following conditions
2457  * are met:
2458@@ -12,7 +12,7 @@
2459  * 2. Redistributions in binary form must reproduce the above copyright
2460  *    notice, this list of conditions and the following disclaimer in the
2461  *    documentation and/or other materials provided with the distribution.
2462- *
2463+ *
2464  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2465  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2466  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2467@@ -63,26 +63,10 @@
2468 # define minor(dev)  ((dev) & 0xff)
2469 #endif
2470 #undef HAVE_MAJOR
2471-#ifdef	S_IFLNK
2472-private int
2473-bad_link(struct magic_set *ms, int err, char *buf)
2474-{
2475-	int mime = ms->flags & MAGIC_MIME;
2476-	if ((mime & MAGIC_MIME_TYPE) &&
2477-	    file_printf(ms, "inode/symlink")
2478-	    == -1)
2479-		return -1;
2480-	else if (!mime) {
2481-		if (ms->flags & MAGIC_ERROR) {
2482-			file_error(ms, err,
2483-				   "broken symbolic link to %s", buf);
2484-			return -1;
2485-		}
2486-		if (file_printf(ms, "broken symbolic link to %s", buf) == -1)
2487-			return -1;
2488-	}
2489-	return 1;
2490-}
2491+
2492+#ifdef PHP_WIN32
2493+
2494+# undef S_IFIFO
2495 #endif
2496 private int
2497 handle_mime(struct magic_set *ms, int mime, const char *str)
2498@@ -100,70 +84,39 @@
2499 }
2500
2501 protected int
2502-file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
2503+file_fsmagic(struct magic_set *ms, const char *fn, zend_stat_t *sb, php_stream *stream)
2504 {
2505 	int ret, did = 0;
2506 	int mime = ms->flags & MAGIC_MIME;
2507 	int silent = ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION);
2508-#ifdef	S_IFLNK
2509-	char buf[BUFSIZ+4];
2510-	ssize_t nch;
2511-	struct stat tstatbuf;
2512-#endif
2513
2514-	if (fn == NULL)
2515+	if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))
2516+		return 0;
2517+
2518+	if (fn == NULL && !stream) {
2519 		return 0;
2520+	}
2521
2522 #define COMMA	(did++ ? ", " : "")
2523-	/*
2524-	 * Fstat is cheaper but fails for files you don't have read perms on.
2525-	 * On 4.2BSD and similar systems, use lstat() to identify symlinks.
2526-	 */
2527-#ifdef	S_IFLNK
2528-	if ((ms->flags & MAGIC_SYMLINK) == 0)
2529-		ret = lstat(fn, sb);
2530-	else
2531-#endif
2532-	ret = stat(fn, sb);	/* don't merge into if; see "ret =" above */
2533
2534-#ifdef WIN32
2535-	{
2536-		HANDLE hFile = CreateFile((LPCSTR)fn, 0, FILE_SHARE_DELETE |
2537-		    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0,
2538-		    NULL);
2539-		if (hFile != INVALID_HANDLE_VALUE) {
2540-			/*
2541-			 * Stat failed, but we can still open it - assume it's
2542-			 * a block device, if nothing else.
2543-			 */
2544-			if (ret) {
2545-				sb->st_mode = S_IFBLK;
2546-				ret = 0;
2547-			}
2548-			switch (GetFileType(hFile)) {
2549-			case FILE_TYPE_CHAR:
2550-				sb->st_mode |= S_IFCHR;
2551-				sb->st_mode &= ~S_IFREG;
2552-				break;
2553-			case FILE_TYPE_PIPE:
2554-				sb->st_mode |= S_IFIFO;
2555-				sb->st_mode &= ~S_IFREG;
2556-				break;
2557+	if (stream) {
2558+		php_stream_statbuf ssb;
2559+		if (php_stream_stat(stream, &ssb) < 0) {
2560+			if (ms->flags & MAGIC_ERROR) {
2561+				file_error(ms, errno, "cannot stat `%s'", fn);
2562+				return -1;
2563 			}
2564-			CloseHandle(hFile);
2565+			return 0;
2566 		}
2567-	}
2568-#endif
2569-
2570-	if (ret) {
2571-		if (ms->flags & MAGIC_ERROR) {
2572-			file_error(ms, errno, "cannot stat `%s'", fn);
2573-			return -1;
2574+		memcpy(sb, &ssb.sb, sizeof(struct stat));
2575+	} else {
2576+		if (php_sys_stat(fn, sb) != 0) {
2577+			if (ms->flags & MAGIC_ERROR) {
2578+				file_error(ms, errno, "cannot stat `%s'", fn);
2579+				return -1;
2580+			}
2581+			return 0;
2582 		}
2583-		if (file_printf(ms, "cannot open `%s' (%s)",
2584-		    fn, strerror(errno)) == -1)
2585-			return -1;
2586-		return 0;
2587 	}
2588
2589 	ret = 1;
2590@@ -174,44 +127,36 @@
2591 				return -1;
2592 #endif
2593 #ifdef S_ISGID
2594-		if (sb->st_mode & S_ISGID)
2595+		if (sb->st_mode & S_ISGID)
2596 			if (file_printf(ms, "%ssetgid", COMMA) == -1)
2597 				return -1;
2598 #endif
2599 #ifdef S_ISVTX
2600-		if (sb->st_mode & S_ISVTX)
2601+		if (sb->st_mode & S_ISVTX)
2602 			if (file_printf(ms, "%ssticky", COMMA) == -1)
2603 				return -1;
2604 #endif
2605 	}
2606-
2607+
2608 	switch (sb->st_mode & S_IFMT) {
2609-	case S_IFDIR:
2610-		if (mime) {
2611-			if (handle_mime(ms, mime, "directory") == -1)
2612-				return -1;
2613-		} else if (silent) {
2614-		} else if (file_printf(ms, "%sdirectory", COMMA) == -1)
2615-			return -1;
2616-		break;
2617-#ifdef S_IFCHR
2618-	case S_IFCHR:
2619-		/*
2620-		 * If -s has been specified, treat character special files
2621-		 * like ordinary files.  Otherwise, just report that they
2622-		 * are block special files and go on to the next file.
2623-		 */
2624-		if ((ms->flags & MAGIC_DEVICES) != 0) {
2625-			ret = 0;
2626-			break;
2627-		}
2628-		if (mime) {
2629-			if (handle_mime(ms, mime, "chardevice") == -1)
2630-				return -1;
2631-		} else if (silent) {
2632-		} else {
2633-#ifdef HAVE_STRUCT_STAT_ST_RDEV
2634-# ifdef dv_unit
2635+#ifndef PHP_WIN32
2636+# ifdef S_IFCHR
2637+		case S_IFCHR:
2638+			/*
2639+			 * If -s has been specified, treat character special files
2640+			 * like ordinary files.  Otherwise, just report that they
2641+			 * are block special files and go on to the next file.
2642+			 */
2643+			if ((ms->flags & MAGIC_DEVICES) != 0) {
2644+				ret = 0;
2645+				break;
2646+			}
2647+			if (mime) {
2648+				if (handle_mime(ms, mime, "chardevice") == -1)
2649+					return -1;
2650+			} else {
2651+#  ifdef HAVE_STAT_ST_RDEV
2652+#   ifdef dv_unit
2653 			if (file_printf(ms, "%scharacter special (%d/%d/%d)",
2654 			    COMMA, major(sb->st_rdev), dv_unit(sb->st_rdev),
2655 					dv_subunit(sb->st_rdev)) == -1)
2656@@ -226,45 +171,11 @@
2657 			if (file_printf(ms, "%scharacter special", COMMA) == -1)
2658 				return -1;
2659 #endif
2660-		}
2661-		break;
2662-#endif
2663-#ifdef S_IFBLK
2664-	case S_IFBLK:
2665-		/*
2666-		 * If -s has been specified, treat block special files
2667-		 * like ordinary files.  Otherwise, just report that they
2668-		 * are block special files and go on to the next file.
2669-		 */
2670-		if ((ms->flags & MAGIC_DEVICES) != 0) {
2671-			ret = 0;
2672-			break;
2673-		}
2674-		if (mime) {
2675-			if (handle_mime(ms, mime, "blockdevice") == -1)
2676-				return -1;
2677-		} else if (silent) {
2678-		} else {
2679-#ifdef HAVE_STRUCT_STAT_ST_RDEV
2680-# ifdef dv_unit
2681-			if (file_printf(ms, "%sblock special (%d/%d/%d)",
2682-			    COMMA, major(sb->st_rdev), dv_unit(sb->st_rdev),
2683-			    dv_subunit(sb->st_rdev)) == -1)
2684-				return -1;
2685-# else
2686-			if (file_printf(ms, "%sblock special (%ld/%ld)",
2687-			    COMMA, (long)major(sb->st_rdev),
2688-			    (long)minor(sb->st_rdev)) == -1)
2689-				return -1;
2690+	}
2691+			return 1;
2692 # endif
2693-#else
2694-			if (file_printf(ms, "%sblock special", COMMA) == -1)
2695-				return -1;
2696 #endif
2697-		}
2698-		break;
2699-#endif
2700-	/* TODO add code to handle V7 MUX and Blit MUX files */
2701+
2702 #ifdef	S_IFIFO
2703 	case S_IFIFO:
2704 		if((ms->flags & MAGIC_DEVICES) != 0)
2705@@ -272,7 +183,6 @@
2706 		if (mime) {
2707 			if (handle_mime(ms, mime, "fifo") == -1)
2708 				return -1;
2709-		} else if (silent) {
2710 		} else if (file_printf(ms, "%sfifo (named pipe)", COMMA) == -1)
2711 			return -1;
2712 		break;
2713@@ -282,89 +192,20 @@
2714 		if (mime) {
2715 			if (handle_mime(ms, mime, "door") == -1)
2716 				return -1;
2717-		} else if (silent) {
2718 		} else if (file_printf(ms, "%sdoor", COMMA) == -1)
2719 			return -1;
2720 		break;
2721 #endif
2722 #ifdef	S_IFLNK
2723 	case S_IFLNK:
2724-		if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
2725+		/* stat is used, if it made here then the link is broken */
2726 			if (ms->flags & MAGIC_ERROR) {
2727-			    file_error(ms, errno, "unreadable symlink `%s'",
2728-				fn);
2729+			    file_error(ms, errno, "unreadable symlink `%s'", fn);
2730 			    return -1;
2731 			}
2732-			if (mime) {
2733-				if (handle_mime(ms, mime, "symlink") == -1)
2734-					return -1;
2735-			} else if (silent) {
2736-			} else if (file_printf(ms,
2737-			    "%sunreadable symlink `%s' (%s)", COMMA, fn,
2738-			    strerror(errno)) == -1)
2739-				return -1;
2740-			break;
2741-		}
2742-		buf[nch] = '\0';	/* readlink(2) does not do this */
2743-
2744-		/* If broken symlink, say so and quit early. */
2745-		if (*buf == '/') {
2746-			if (stat(buf, &tstatbuf) < 0)
2747-				return bad_link(ms, errno, buf);
2748-		} else {
2749-			char *tmp;
2750-			char buf2[BUFSIZ+BUFSIZ+4];
2751-
2752-			if ((tmp = strrchr(fn,  '/')) == NULL) {
2753-				tmp = buf; /* in current directory anyway */
2754-			} else {
2755-				if (tmp - fn + 1 > BUFSIZ) {
2756-					if (ms->flags & MAGIC_ERROR) {
2757-						file_error(ms, 0,
2758-						    "path too long: `%s'", buf);
2759-						return -1;
2760-					}
2761-					if (mime) {
2762-						if (handle_mime(ms, mime,
2763-						    "x-path-too-long") == -1)
2764-							return -1;
2765-					} else if (silent) {
2766-					} else if (file_printf(ms,
2767-					    "%spath too long: `%s'", COMMA,
2768-					    fn) == -1)
2769-						return -1;
2770-					break;
2771-				}
2772-				/* take dir part */
2773-				(void)strlcpy(buf2, fn, sizeof buf2);
2774-				buf2[tmp - fn + 1] = '\0';
2775-				/* plus (rel) link */
2776-				(void)strlcat(buf2, buf, sizeof buf2);
2777-				tmp = buf2;
2778-			}
2779-			if (stat(tmp, &tstatbuf) < 0)
2780-				return bad_link(ms, errno, buf);
2781-		}
2782-
2783-		/* Otherwise, handle it. */
2784-		if ((ms->flags & MAGIC_SYMLINK) != 0) {
2785-			const char *p;
2786-			ms->flags &= MAGIC_SYMLINK;
2787-			p = magic_file(ms, buf);
2788-			ms->flags |= MAGIC_SYMLINK;
2789-			if (p == NULL)
2790-				return -1;
2791-		} else { /* just print what it points to */
2792-			if (mime) {
2793-				if (handle_mime(ms, mime, "symlink") == -1)
2794-					return -1;
2795-			} else if (silent) {
2796-			} else if (file_printf(ms, "%ssymbolic link to %s",
2797-			    COMMA, buf) == -1)
2798-				return -1;
2799-		}
2800-		break;
2801+	return 1;
2802 #endif
2803+
2804 #ifdef	S_IFSOCK
2805 #ifndef __COHERENT__
2806 	case S_IFSOCK:
2807diff -u libmagic.orig/funcs.c libmagic/funcs.c
2808--- libmagic.orig/funcs.c	2017-11-02 21:25:39.000000000 +0100
2809+++ libmagic/funcs.c	2020-02-26 09:55:13.859042500 +0100
2810@@ -31,7 +31,6 @@
2811 #endif	/* lint */
2812
2813 #include "magic.h"
2814-#include <assert.h>
2815 #include <stdarg.h>
2816 #include <stdlib.h>
2817 #include <string.h>
2818@@ -42,78 +41,77 @@
2819 #if defined(HAVE_WCTYPE_H)
2820 #include <wctype.h>
2821 #endif
2822-#if defined(HAVE_LIMITS_H)
2823-#include <limits.h>
2824+#if defined(HAVE_LOCALE_H)
2825+#include <locale.h>
2826 #endif
2827
2828 #ifndef SIZE_MAX
2829 #define SIZE_MAX	((size_t)~0)
2830 #endif
2831
2832-/*
2833- * Like printf, only we append to a buffer.
2834- */
2835-protected int
2836-file_vprintf(struct magic_set *ms, const char *fmt, va_list ap)
2837-{
2838-	int len;
2839-	char *buf, *newstr;
2840+#include "php.h"
2841+#include "main/php_network.h"
2842
2843-	if (ms->event_flags & EVENT_HAD_ERR)
2844-		return 0;
2845-	len = vasprintf(&buf, fmt, ap);
2846-	if (len < 0)
2847-		goto out;
2848-
2849-	if (ms->o.buf != NULL) {
2850-		len = asprintf(&newstr, "%s%s", ms->o.buf, buf);
2851-		free(buf);
2852-		if (len < 0)
2853-			goto out;
2854-		free(ms->o.buf);
2855-		buf = newstr;
2856-	}
2857-	ms->o.buf = buf;
2858-	return 0;
2859-out:
2860-	fprintf(stderr, "vasprintf failed (%s)", strerror(errno));
2861-	return -1;
2862-}
2863+#ifndef PREG_OFFSET_CAPTURE
2864+# define PREG_OFFSET_CAPTURE                 (1<<8)
2865+#endif
2866
2867 protected int
2868 file_printf(struct magic_set *ms, const char *fmt, ...)
2869 {
2870-	int rv;
2871 	va_list ap;
2872+	size_t len;
2873+	char *buf = NULL, *newstr;
2874
2875 	va_start(ap, fmt);
2876-	rv = file_vprintf(ms, fmt, ap);
2877+	len = vspprintf(&buf, 0, fmt, ap);
2878 	va_end(ap);
2879-	return rv;
2880+
2881+	if (ms->o.buf != NULL) {
2882+		len = spprintf(&newstr, 0, "%s%s", ms->o.buf, (buf ? buf : ""));
2883+		if (buf) {
2884+			efree(buf);
2885+		}
2886+		efree(ms->o.buf);
2887+		ms->o.buf = newstr;
2888+	} else {
2889+		ms->o.buf = buf;
2890+	}
2891+	return 0;
2892 }
2893
2894 /*
2895  * error - print best error message possible
2896  */
2897 /*VARARGS*/
2898-__attribute__((__format__(__printf__, 3, 0)))
2899 private void
2900 file_error_core(struct magic_set *ms, int error, const char *f, va_list va,
2901     size_t lineno)
2902 {
2903+	char *buf = NULL;
2904+
2905 	/* Only the first error is ok */
2906 	if (ms->event_flags & EVENT_HAD_ERR)
2907 		return;
2908 	if (lineno != 0) {
2909-		free(ms->o.buf);
2910+		efree(ms->o.buf);
2911 		ms->o.buf = NULL;
2912 		file_printf(ms, "line %" SIZE_T_FORMAT "u:", lineno);
2913 	}
2914-	if (ms->o.buf && *ms->o.buf)
2915-		file_printf(ms, " ");
2916-	file_vprintf(ms, f, va);
2917-	if (error > 0)
2918-		file_printf(ms, " (%s)", strerror(error));
2919+
2920+	vspprintf(&buf, 0, f, va);
2921+	va_end(va);
2922+
2923+	if (error > 0) {
2924+		file_printf(ms, "%s (%s)", (*buf ? buf : ""), strerror(error));
2925+	} else if (*buf) {
2926+		file_printf(ms, "%s", buf);
2927+	}
2928+
2929+	if (buf) {
2930+		efree(buf);
2931+	}
2932+
2933 	ms->event_flags |= EVENT_HAD_ERR;
2934 	ms->error = error;
2935 }
2936@@ -160,7 +158,6 @@
2937 	file_error(ms, errno, "error reading");
2938 }
2939
2940-#ifndef COMPILE_ONLY
2941
2942 static int
2943 checkdone(struct magic_set *ms, int *rv)
2944@@ -174,8 +171,8 @@
2945
2946 /*ARGSUSED*/
2947 protected int
2948-file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__unused__)),
2949-    const void *buf, size_t nb)
2950+file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const void *buf,
2951+    size_t nb)
2952 {
2953 	int m = 0, rv = 0, looks_text = 0;
2954 	const char *code = NULL;
2955@@ -184,7 +181,8 @@
2956 	const char *def = "data";
2957 	const char *ftype = NULL;
2958 	struct buffer b;
2959-
2960+	int fd = -1;
2961+
2962 	buffer_init(&b, fd, buf, nb);
2963
2964 	if (nb == 0) {
2965@@ -216,8 +214,8 @@
2966 		}
2967 	}
2968 #endif
2969-#if HAVE_FORK
2970-	/* try compression stuff */
2971+
2972+#if PHP_FILEINFO_UNCOMPRESS
2973 	if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) == 0) {
2974 		m = file_zmagic(ms, &b, inname);
2975 		if ((ms->flags & MAGIC_DEBUG) != 0)
2976@@ -239,13 +237,22 @@
2977 	}
2978
2979 	/* Check if we have a CDF file */
2980-	if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) {
2981-		m = file_trycdf(ms, &b);
2982-		if ((ms->flags & MAGIC_DEBUG) != 0)
2983-			(void)fprintf(stderr, "[try cdf %d]\n", m);
2984-		if (m) {
2985-			if (checkdone(ms, &rv))
2986-				goto done;
2987+	if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0 && stream) {
2988+#ifdef _WIN64
2989+		php_socket_t _fd = fd;
2990+		int _ret = php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&_fd, 0);
2991+		fd = (int)_fd;
2992+#else
2993+		int _ret = php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&fd, 0);
2994+#endif
2995+		if (SUCCESS == _ret) {
2996+			m = file_trycdf(ms, &b);
2997+			if ((ms->flags & MAGIC_DEBUG) != 0)
2998+				(void)fprintf(stderr, "[try cdf %d]\n", m);
2999+			if (m) {
3000+				if (checkdone(ms, &rv))
3001+					goto done;
3002+			}
3003 		}
3004 	}
3005
3006@@ -315,7 +322,7 @@
3007 		if (file_printf(ms, "%s", code_mime) == -1)
3008 			rv = -1;
3009 	}
3010-#if HAVE_FORK
3011+#if PHP_FILEINFO_UNCOMPRESS
3012  done_encoding:
3013 #endif
3014 	buffer_fini(&b);
3015@@ -324,7 +331,6 @@
3016
3017 	return m;
3018 }
3019-#endif
3020
3021 protected int
3022 file_reset(struct magic_set *ms, int checkloaded)
3023@@ -334,11 +340,11 @@
3024 		return -1;
3025 	}
3026 	if (ms->o.buf) {
3027-		free(ms->o.buf);
3028+		efree(ms->o.buf);
3029 		ms->o.buf = NULL;
3030 	}
3031 	if (ms->o.pbuf) {
3032-		free(ms->o.pbuf);
3033+		efree(ms->o.pbuf);
3034 		ms->o.pbuf = NULL;
3035 	}
3036 	ms->event_flags &= ~EVENT_HAD_ERR;
3037@@ -376,7 +382,7 @@
3038 		return NULL;
3039 	}
3040 	psize = len * 4 + 1;
3041-	if ((pbuf = CAST(char *, realloc(ms->o.pbuf, psize))) == NULL) {
3042+	if ((pbuf = CAST(char *, erealloc(ms->o.pbuf, psize))) == NULL) {
3043 		file_oomem(ms, psize);
3044 		return NULL;
3045 	}
3046@@ -440,8 +446,8 @@
3047 	if (level >= ms->c.len) {
3048 		len = (ms->c.len = 20 + level) * sizeof(*ms->c.li);
3049 		ms->c.li = CAST(struct level_info *, (ms->c.li == NULL) ?
3050-		    malloc(len) :
3051-		    realloc(ms->c.li, len));
3052+		    emalloc(len) :
3053+		    erealloc(ms->c.li, len));
3054 		if (ms->c.li == NULL) {
3055 			file_oomem(ms, len);
3056 			return -1;
3057@@ -464,76 +470,38 @@
3058 protected int
3059 file_replace(struct magic_set *ms, const char *pat, const char *rep)
3060 {
3061-	file_regex_t rx;
3062-	int rc, rv = -1;
3063-
3064-	rc = file_regcomp(&rx, pat, REG_EXTENDED);
3065-	if (rc) {
3066-		file_regerror(&rx, rc, ms);
3067-	} else {
3068-		regmatch_t rm;
3069-		int nm = 0;
3070-		while (file_regexec(&rx, ms->o.buf, 1, &rm, 0) == 0) {
3071-			ms->o.buf[rm.rm_so] = '\0';
3072-			if (file_printf(ms, "%s%s", rep,
3073-			    rm.rm_eo != 0 ? ms->o.buf + rm.rm_eo : "") == -1)
3074-				goto out;
3075-			nm++;
3076-		}
3077-		rv = nm;
3078+	zval patt;
3079+	uint32_t opts = 0;
3080+	pcre_cache_entry *pce;
3081+	zend_string *res;
3082+	zend_string *repl;
3083+	size_t rep_cnt = 0;
3084+
3085+	opts |= PCRE2_MULTILINE;
3086+	convert_libmagic_pattern(&patt, (char*)pat, strlen(pat), opts);
3087+	if ((pce = pcre_get_compiled_regex_cache_ex(Z_STR(patt), 0)) == NULL) {
3088+		zval_ptr_dtor(&patt);
3089+		rep_cnt = -1;
3090+		goto out;
3091 	}
3092-out:
3093-	file_regfree(&rx);
3094-	return rv;
3095-}
3096+	zval_ptr_dtor(&patt);
3097
3098-protected int
3099-file_regcomp(file_regex_t *rx, const char *pat, int flags)
3100-{
3101-#ifdef USE_C_LOCALE
3102-	rx->c_lc_ctype = newlocale(LC_CTYPE_MASK, "C", 0);
3103-	assert(rx->c_lc_ctype != NULL);
3104-	rx->old_lc_ctype = uselocale(rx->c_lc_ctype);
3105-	assert(rx->old_lc_ctype != NULL);
3106-#else
3107-	rx->old_lc_ctype = setlocale(LC_CTYPE, "C");
3108-#endif
3109-	rx->pat = pat;
3110+	repl = zend_string_init(rep, strlen(rep), 0);
3111+	res = php_pcre_replace_impl(pce, NULL, ms->o.buf, strlen(ms->o.buf), repl, -1, &rep_cnt);
3112
3113-	return rx->rc = regcomp(&rx->rx, pat, flags);
3114-}
3115+	zend_string_release_ex(repl, 0);
3116+	if (NULL == res) {
3117+		rep_cnt = -1;
3118+		goto out;
3119+	}
3120
3121-protected int
3122-file_regexec(file_regex_t *rx, const char *str, size_t nmatch,
3123-    regmatch_t* pmatch, int eflags)
3124-{
3125-	assert(rx->rc == 0);
3126-	/* XXX: force initialization because glibc does not always do this */
3127-	memset(pmatch, 0, nmatch * sizeof(*pmatch));
3128-	return regexec(&rx->rx, str, nmatch, pmatch, eflags);
3129-}
3130+	strncpy(ms->o.buf, ZSTR_VAL(res), ZSTR_LEN(res));
3131+	ms->o.buf[ZSTR_LEN(res)] = '\0';
3132
3133-protected void
3134-file_regfree(file_regex_t *rx)
3135-{
3136-	if (rx->rc == 0)
3137-		regfree(&rx->rx);
3138-#ifdef USE_C_LOCALE
3139-	(void)uselocale(rx->old_lc_ctype);
3140-	freelocale(rx->c_lc_ctype);
3141-#else
3142-	(void)setlocale(LC_CTYPE, rx->old_lc_ctype);
3143-#endif
3144-}
3145+	zend_string_release_ex(res, 0);
3146
3147-protected void
3148-file_regerror(file_regex_t *rx, int rc, struct magic_set *ms)
3149-{
3150-	char errmsg[512];
3151-
3152-	(void)regerror(rc, &rx->rx, errmsg, sizeof(errmsg));
3153-	file_magerror(ms, "regex error %d for `%s', (%s)", rc, rx->pat,
3154-	    errmsg);
3155+out:
3156+	return rep_cnt;
3157 }
3158
3159 protected file_pushbuf_t *
3160@@ -544,7 +512,7 @@
3161 	if (ms->event_flags & EVENT_HAD_ERR)
3162 		return NULL;
3163
3164-	if ((pb = (CAST(file_pushbuf_t *, malloc(sizeof(*pb))))) == NULL)
3165+	if ((pb = (CAST(file_pushbuf_t *, emalloc(sizeof(*pb))))) == NULL)
3166 		return NULL;
3167
3168 	pb->buf = ms->o.buf;
3169@@ -562,8 +530,8 @@
3170 	char *rbuf;
3171
3172 	if (ms->event_flags & EVENT_HAD_ERR) {
3173-		free(pb->buf);
3174-		free(pb);
3175+		efree(pb->buf);
3176+		efree(pb);
3177 		return NULL;
3178 	}
3179
3180@@ -572,7 +540,7 @@
3181 	ms->o.buf = pb->buf;
3182 	ms->offset = pb->offset;
3183
3184-	free(pb);
3185+	efree(pb);
3186 	return rbuf;
3187 }
3188
3189diff -u libmagic.orig/magic.c libmagic/magic.c
3190--- libmagic.orig/magic.c	2017-08-28 15:39:18.000000000 +0200
3191+++ libmagic/magic.c	2020-02-26 09:55:13.861044300 +0100
3192@@ -25,11 +25,6 @@
3193  * SUCH DAMAGE.
3194  */
3195
3196-#ifdef WIN32
3197-#include <windows.h>
3198-#include <shlwapi.h>
3199-#endif
3200-
3201 #include "file.h"
3202
3203 #ifndef	lint
3204@@ -39,14 +34,19 @@
3205 #include "magic.h"
3206
3207 #include <stdlib.h>
3208+#ifdef PHP_WIN32
3209+#include "win32/unistd.h"
3210+#else
3211 #include <unistd.h>
3212+#endif
3213 #include <string.h>
3214-#ifdef QUICK
3215-#include <sys/mman.h>
3216+#include "config.h"
3217+
3218+#ifdef PHP_WIN32
3219+#include <shlwapi.h>
3220 #endif
3221-#ifdef HAVE_LIMITS_H
3222+
3223 #include <limits.h>	/* for PIPE_BUF */
3224-#endif
3225
3226 #if defined(HAVE_UTIMES)
3227 # include <sys/time.h>
3228@@ -71,194 +71,23 @@
3229 #endif
3230 #endif
3231
3232+#ifdef PHP_WIN32
3233+# undef S_IFLNK
3234+# undef S_IFIFO
3235+#endif
3236+
3237 private void close_and_restore(const struct magic_set *, const char *, int,
3238-    const struct stat *);
3239+    const zend_stat_t *);
3240 private int unreadable_info(struct magic_set *, mode_t, const char *);
3241+#if 0
3242 private const char* get_default_magic(void);
3243-#ifndef COMPILE_ONLY
3244-private const char *file_or_fd(struct magic_set *, const char *, int);
3245 #endif
3246+private const char *file_or_stream(struct magic_set *, const char *, php_stream *);
3247
3248 #ifndef	STDIN_FILENO
3249 #define	STDIN_FILENO	0
3250 #endif
3251
3252-#ifdef WIN32
3253-/* HINSTANCE of this shared library. Needed for get_default_magic() */
3254-static HINSTANCE _w32_dll_instance = NULL;
3255-
3256-static void
3257-_w32_append_path(char **hmagicpath, const char *fmt, ...)
3258-{
3259-	char *tmppath;
3260-        char *newpath;
3261-	va_list ap;
3262-
3263-	va_start(ap, fmt);
3264-	if (vasprintf(&tmppath, fmt, ap) < 0) {
3265-		va_end(ap);
3266-		return;
3267-	}
3268-	va_end(ap);
3269-
3270-	if (access(tmppath, R_OK) == -1)
3271-		goto out;
3272-
3273-	if (*hmagicpath == NULL) {
3274-		*hmagicpath = tmppath;
3275-		return;
3276-	}
3277-
3278-	if (asprintf(&newpath, "%s%c%s", *hmagicpath, PATHSEP, tmppath) < 0)
3279-		goto out;
3280-
3281-	free(*hmagicpath);
3282-	free(tmppath);
3283-	*hmagicpath = newpath;
3284-	return;
3285-out:
3286-	free(tmppath);
3287-}
3288-
3289-static void
3290-_w32_get_magic_relative_to(char **hmagicpath, HINSTANCE module)
3291-{
3292-	static const char *trypaths[] = {
3293-		"%s/share/misc/magic.mgc",
3294-		"%s/magic.mgc",
3295-	};
3296-	LPSTR dllpath;
3297-	size_t sp;
3298-
3299-	dllpath = calloc(MAX_PATH + 1, sizeof(*dllpath));
3300-
3301-	if (!GetModuleFileNameA(module, dllpath, MAX_PATH))
3302-		goto out;
3303-
3304-	PathRemoveFileSpecA(dllpath);
3305-
3306-	if (module) {
3307-		char exepath[MAX_PATH];
3308-		GetModuleFileNameA(NULL, exepath, MAX_PATH);
3309-		PathRemoveFileSpecA(exepath);
3310-		if (stricmp(exepath, dllpath) == 0)
3311-			goto out;
3312-	}
3313-
3314-	sp = strlen(dllpath);
3315-	if (sp > 3 && stricmp(&dllpath[sp - 3], "bin") == 0) {
3316-		_w32_append_path(hmagicpath,
3317-		    "%s/../share/misc/magic.mgc", dllpath);
3318-		goto out;
3319-	}
3320-
3321-	for (sp = 0; sp < __arraycount(trypaths); sp++)
3322-		_w32_append_path(hmagicpath, trypaths[sp], dllpath);
3323-out:
3324-	free(dllpath);
3325-}
3326-
3327-/* Placate GCC by offering a sacrificial previous prototype */
3328-BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID);
3329-
3330-BOOL WINAPI
3331-DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
3332-    LPVOID lpvReserved __attribute__((__unused__)))
3333-{
3334-	if (fdwReason == DLL_PROCESS_ATTACH)
3335-		_w32_dll_instance = hinstDLL;
3336-	return 1;
3337-}
3338-#endif
3339-
3340-private const char *
3341-get_default_magic(void)
3342-{
3343-	static const char hmagic[] = "/.magic/magic.mgc";
3344-	static char *default_magic;
3345-	char *home, *hmagicpath;
3346-
3347-#ifndef WIN32
3348-	struct stat st;
3349-
3350-	if (default_magic) {
3351-		free(default_magic);
3352-		default_magic = NULL;
3353-	}
3354-	if ((home = getenv("HOME")) == NULL)
3355-		return MAGIC;
3356-
3357-	if (asprintf(&hmagicpath, "%s/.magic.mgc", home) < 0)
3358-		return MAGIC;
3359-	if (stat(hmagicpath, &st) == -1) {
3360-		free(hmagicpath);
3361-		if (asprintf(&hmagicpath, "%s/.magic", home) < 0)
3362-			return MAGIC;
3363-		if (stat(hmagicpath, &st) == -1)
3364-			goto out;
3365-		if (S_ISDIR(st.st_mode)) {
3366-			free(hmagicpath);
3367-			if (asprintf(&hmagicpath, "%s/%s", home, hmagic) < 0)
3368-				return MAGIC;
3369-			if (access(hmagicpath, R_OK) == -1)
3370-				goto out;
3371-		}
3372-	}
3373-
3374-	if (asprintf(&default_magic, "%s:%s", hmagicpath, MAGIC) < 0)
3375-		goto out;
3376-	free(hmagicpath);
3377-	return default_magic;
3378-out:
3379-	default_magic = NULL;
3380-	free(hmagicpath);
3381-	return MAGIC;
3382-#else
3383-	hmagicpath = NULL;
3384-
3385-	if (default_magic) {
3386-		free(default_magic);
3387-		default_magic = NULL;
3388-	}
3389-
3390-	/* First, try to get a magic file from user-application data */
3391-	if ((home = getenv("LOCALAPPDATA")) != NULL)
3392-		_w32_append_path(&hmagicpath, "%s%s", home, hmagic);
3393-
3394-	/* Second, try to get a magic file from the user profile data */
3395-	if ((home = getenv("USERPROFILE")) != NULL)
3396-		_w32_append_path(&hmagicpath,
3397-		    "%s/Local Settings/Application Data%s", home, hmagic);
3398-
3399-	/* Third, try to get a magic file from Common Files */
3400-	if ((home = getenv("COMMONPROGRAMFILES")) != NULL)
3401-		_w32_append_path(&hmagicpath, "%s%s", home, hmagic);
3402-
3403-	/* Fourth, try to get magic file relative to exe location */
3404-        _w32_get_magic_relative_to(&hmagicpath, NULL);
3405-
3406-	/* Fifth, try to get magic file relative to dll location */
3407-        _w32_get_magic_relative_to(&hmagicpath, _w32_dll_instance);
3408-
3409-	/* Avoid MAGIC constant - it likely points to a file within MSys tree */
3410-	default_magic = hmagicpath;
3411-	return default_magic;
3412-#endif
3413-}
3414-
3415-public const char *
3416-magic_getpath(const char *magicfile, int action)
3417-{
3418-	if (magicfile != NULL)
3419-		return magicfile;
3420-
3421-	magicfile = getenv("MAGIC");
3422-	if (magicfile != NULL)
3423-		return magicfile;
3424-
3425-	return action == FILE_LOAD ? get_default_magic() : MAGIC;
3426-}
3427-
3428 public struct magic_set *
3429 magic_open(int flags)
3430 {
3431@@ -304,20 +133,6 @@
3432 	return file_apprentice(ms, magicfile, FILE_LOAD);
3433 }
3434
3435-#ifndef COMPILE_ONLY
3436-/*
3437- * Install a set of compiled magic buffers.
3438- */
3439-public int
3440-magic_load_buffers(struct magic_set *ms, void **bufs, size_t *sizes,
3441-    size_t nbufs)
3442-{
3443-	if (ms == NULL)
3444-		return -1;
3445-	return buffer_apprentice(ms, (struct magic **)bufs, sizes, nbufs);
3446-}
3447-#endif
3448-
3449 public int
3450 magic_compile(struct magic_set *ms, const char *magicfile)
3451 {
3452@@ -344,7 +159,7 @@
3453
3454 private void
3455 close_and_restore(const struct magic_set *ms, const char *name, int fd,
3456-    const struct stat *sb)
3457+    const zend_stat_t *sb)
3458 {
3459 	if (fd == STDIN_FILENO || name == NULL)
3460 		return;
3461@@ -375,7 +190,6 @@
3462 	}
3463 }
3464
3465-#ifndef COMPILE_ONLY
3466
3467 /*
3468  * find type of descriptor
3469@@ -385,7 +199,7 @@
3470 {
3471 	if (ms == NULL)
3472 		return NULL;
3473-	return file_or_fd(ms, NULL, fd);
3474+	return file_or_stream(ms, NULL, NULL);
3475 }
3476
3477 /*
3478@@ -396,31 +210,42 @@
3479 {
3480 	if (ms == NULL)
3481 		return NULL;
3482-	return file_or_fd(ms, inname, STDIN_FILENO);
3483+	return file_or_stream(ms, inname, NULL);
3484+}
3485+
3486+public const char *
3487+magic_stream(struct magic_set *ms, php_stream *stream)
3488+{
3489+	if (ms == NULL)
3490+		return NULL;
3491+	return file_or_stream(ms, NULL, stream);
3492 }
3493
3494 private const char *
3495-file_or_fd(struct magic_set *ms, const char *inname, int fd)
3496+file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
3497 {
3498 	int	rv = -1;
3499 	unsigned char *buf;
3500-	struct stat	sb;
3501+	zend_stat_t   sb;
3502 	ssize_t nbytes = 0;	/* number of bytes read from a datafile */
3503-	int	ispipe = 0;
3504-	off_t	pos = (off_t)-1;
3505+	int no_in_stream = 0;
3506
3507 	if (file_reset(ms, 1) == -1)
3508 		goto out;
3509
3510+	if (!inname && !stream) {
3511+		return NULL;
3512+	}
3513+
3514 	/*
3515 	 * one extra for terminating '\0', and
3516 	 * some overlapping space for matches near EOF
3517 	 */
3518 #define SLOP (1 + sizeof(union VALUETYPE))
3519-	if ((buf = CAST(unsigned char *, malloc(ms->bytes_max + SLOP))) == NULL)
3520+	if ((buf = CAST(unsigned char *, emalloc(ms->bytes_max + SLOP))) == NULL)
3521 		return NULL;
3522
3523-	switch (file_fsmagic(ms, inname, &sb)) {
3524+	switch (file_fsmagic(ms, inname, &sb, stream)) {
3525 	case -1:		/* error */
3526 		goto done;
3527 	case 0:			/* nothing found */
3528@@ -430,103 +255,41 @@
3529 		goto done;
3530 	}
3531
3532-#ifdef WIN32
3533-	/* Place stdin in binary mode, so EOF (Ctrl+Z) doesn't stop early. */
3534-	if (fd == STDIN_FILENO)
3535-		_setmode(STDIN_FILENO, O_BINARY);
3536-#endif
3537-
3538-	if (inname == NULL) {
3539-		if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode))
3540-			ispipe = 1;
3541-		else
3542-			pos = lseek(fd, (off_t)0, SEEK_CUR);
3543-	} else {
3544-		int flags = O_RDONLY|O_BINARY;
3545-		int okstat = stat(inname, &sb) == 0;
3546+	errno = 0;
3547
3548-		if (okstat && S_ISFIFO(sb.st_mode)) {
3549-#ifdef O_NONBLOCK
3550-			flags |= O_NONBLOCK;
3551-#endif
3552-			ispipe = 1;
3553-		}
3554+	if (!stream && inname) {
3555+		no_in_stream = 1;
3556+		stream = php_stream_open_wrapper((char *)inname, "rb", REPORT_ERRORS, NULL);
3557+	}
3558
3559-		errno = 0;
3560-		if ((fd = open(inname, flags)) < 0) {
3561-#ifdef WIN32
3562-			/*
3563-			 * Can't stat, can't open.  It may have been opened in
3564-			 * fsmagic, so if the user doesn't have read permission,
3565-			 * allow it to say so; otherwise an error was probably
3566-			 * displayed in fsmagic.
3567-			 */
3568-			if (!okstat && errno == EACCES) {
3569-				sb.st_mode = S_IFBLK;
3570-				okstat = 1;
3571-			}
3572-#endif
3573-			if (okstat &&
3574-			    unreadable_info(ms, sb.st_mode, inname) == -1)
3575-				goto done;
3576-			rv = 0;
3577+	if (!stream) {
3578+		if (unreadable_info(ms, sb.st_mode, inname) == -1)
3579 			goto done;
3580-		}
3581+		rv = 0;
3582+		goto done;
3583+	}
3584+
3585 #ifdef O_NONBLOCK
3586-		if ((flags = fcntl(fd, F_GETFL)) != -1) {
3587-			flags &= ~O_NONBLOCK;
3588-			(void)fcntl(fd, F_SETFL, flags);
3589-		}
3590+/* we should be already be in non blocking mode for network socket */
3591 #endif
3592-	}
3593
3594 	/*
3595 	 * try looking at the first ms->bytes_max bytes
3596 	 */
3597-	if (ispipe) {
3598-		ssize_t r = 0;
3599-
3600-		while ((r = sread(fd, (void *)&buf[nbytes],
3601-		    (size_t)(ms->bytes_max - nbytes), 1)) > 0) {
3602-			nbytes += r;
3603-			if (r < PIPE_BUF) break;
3604-		}
3605-
3606-		if (nbytes == 0 && inname) {
3607-			/* We can not read it, but we were able to stat it. */
3608-			if (unreadable_info(ms, sb.st_mode, inname) == -1)
3609-				goto done;
3610-			rv = 0;
3611-			goto done;
3612-		}
3613-
3614-	} else {
3615-		/* Windows refuses to read from a big console buffer. */
3616-		size_t howmany =
3617-#if defined(WIN32)
3618-				_isatty(fd) ? 8 * 1024 :
3619-#endif
3620-				ms->bytes_max;
3621-		if ((nbytes = read(fd, (char *)buf, howmany)) == -1) {
3622-			if (inname == NULL && fd != STDIN_FILENO)
3623-				file_error(ms, errno, "cannot read fd %d", fd);
3624-			else
3625-				file_error(ms, errno, "cannot read `%s'",
3626-				    inname == NULL ? "/dev/stdin" : inname);
3627-			goto done;
3628-		}
3629+	if ((nbytes = php_stream_read(stream, (char *)buf, ms->bytes_max - nbytes)) < 0) {
3630+		file_error(ms, errno, "cannot read `%s'", inname);
3631+		goto done;
3632 	}
3633
3634 	(void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */
3635-	if (file_buffer(ms, fd, inname, buf, (size_t)nbytes) == -1)
3636+	if (file_buffer(ms, stream, inname, buf, (size_t)nbytes) == -1)
3637 		goto done;
3638 	rv = 0;
3639 done:
3640-	free(buf);
3641-	if (fd != -1) {
3642-		if (pos != (off_t)-1)
3643-			(void)lseek(fd, pos, SEEK_SET);
3644-		close_and_restore(ms, inname, fd, &sb);
3645+	efree(buf);
3646+
3647+	if (no_in_stream && stream) {
3648+		php_stream_close(stream);
3649 	}
3650 out:
3651 	return rv == 0 ? file_getbuffer(ms) : NULL;
3652@@ -544,12 +307,11 @@
3653 	 * The main work is done here!
3654 	 * We have the file name and/or the data buffer to be identified.
3655 	 */
3656-	if (file_buffer(ms, -1, NULL, buf, nb) == -1) {
3657+	if (file_buffer(ms, NULL, NULL, buf, nb) == -1) {
3658 		return NULL;
3659 	}
3660 	return file_getbuffer(ms);
3661 }
3662-#endif
3663
3664 public const char *
3665 magic_error(struct magic_set *ms)
3666diff -u libmagic.orig/magic.h libmagic/magic.h
3667--- libmagic.orig/magic.h	2020-02-26 09:56:58.945274100 +0100
3668+++ libmagic/magic.h	2020-02-26 09:55:13.862044300 +0100
3669@@ -122,6 +122,7 @@
3670
3671 const char *magic_getpath(const char *, int);
3672 const char *magic_file(magic_t, const char *);
3673+const char *magic_stream(magic_t, php_stream *);
3674 const char *magic_descriptor(magic_t, int);
3675 const char *magic_buffer(magic_t, const void *, size_t);
3676
3677diff -u libmagic.orig/print.c libmagic/print.c
3678--- libmagic.orig/print.c	2017-02-10 19:14:01.000000000 +0100
3679+++ libmagic/print.c	2020-02-26 09:55:13.864043900 +0100
3680@@ -2,7 +2,7 @@
3681  * Copyright (c) Ian F. Darwin 1986-1995.
3682  * Software written by Ian F. Darwin and others;
3683  * maintained 1995-present by Christos Zoulas and others.
3684- *
3685+ *
3686  * Redistribution and use in source and binary forms, with or without
3687  * modification, are permitted provided that the following conditions
3688  * are met:
3689@@ -12,7 +12,7 @@
3690  * 2. Redistributions in binary form must reproduce the above copyright
3691  *    notice, this list of conditions and the following disclaimer in the
3692  *    documentation and/or other materials provided with the distribution.
3693- *
3694+ *
3695  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
3696  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3697  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3698@@ -28,6 +28,7 @@
3699 /*
3700  * print.c - debugging printout routines
3701  */
3702+#include "php.h"
3703
3704 #include "file.h"
3705
3706@@ -75,7 +76,7 @@
3707 	if (m->mask_op & FILE_OPINVERSE)
3708 		(void) fputc('~', stderr);
3709
3710-	if (IS_STRING(m->type)) {
3711+	if (IS_LIBMAGIC_STRING(m->type)) {
3712 		if (m->str_flags) {
3713 			(void) fputc('/', stderr);
3714 			if (m->str_flags & STRING_COMPACT_WHITESPACE)
3715@@ -215,18 +216,18 @@
3716 file_magwarn(struct magic_set *ms, const char *f, ...)
3717 {
3718 	va_list va;
3719+	char *expanded_format = NULL;
3720+	int expanded_len;
3721
3722-	/* cuz we use stdout for most, stderr here */
3723-	(void) fflush(stdout);
3724-
3725-	if (ms->file)
3726-		(void) fprintf(stderr, "%s, %lu: ", ms->file,
3727-		    (unsigned long)ms->line);
3728-	(void) fprintf(stderr, "Warning: ");
3729 	va_start(va, f);
3730-	(void) vfprintf(stderr, f, va);
3731+	expanded_len = vasprintf(&expanded_format, f, va);
3732 	va_end(va);
3733-	(void) fputc('\n', stderr);
3734+
3735+	if (expanded_len >= 0 && expanded_format) {
3736+		php_error_docref(NULL, E_NOTICE, "Warning: %s", expanded_format);
3737+
3738+		free(expanded_format);
3739+	}
3740 }
3741
3742 protected const char *
3743@@ -247,13 +248,13 @@
3744 	}
3745
3746 	if (flags & FILE_T_LOCAL) {
3747-		tm = localtime_r(&t, &tmz);
3748+		tm = php_localtime_r(&t, &tmz);
3749 	} else {
3750-		tm = gmtime_r(&t, &tmz);
3751+		tm = php_gmtime_r(&t, &tmz);
3752 	}
3753 	if (tm == NULL)
3754 		goto out;
3755-	pp = asctime_r(tm, buf);
3756+	pp = php_asctime_r(tm, buf);
3757
3758 	if (pp == NULL)
3759 		goto out;
3760diff -u libmagic.orig/readcdf.c libmagic/readcdf.c
3761--- libmagic.orig/readcdf.c	2017-11-02 21:25:39.000000000 +0100
3762+++ libmagic/readcdf.c	2020-02-26 09:55:13.865044100 +0100
3763@@ -31,7 +31,11 @@
3764
3765 #include <assert.h>
3766 #include <stdlib.h>
3767+#ifdef PHP_WIN32
3768+#include "win32/unistd.h"
3769+#else
3770 #include <unistd.h>
3771+#endif
3772 #include <string.h>
3773 #include <time.h>
3774 #include <ctype.h>
3775@@ -104,10 +108,6 @@
3776 		if (clsid[0] == cv[i].clsid[0] && clsid[1] == cv[i].clsid[1])
3777 			return cv[i].mime;
3778 	}
3779-#ifdef CDF_DEBUG
3780-	fprintf(stderr, "unknown mime %" PRIx64 ", %" PRIx64 "\n", clsid[0],
3781-	    clsid[1]);
3782-#endif
3783 	return NULL;
3784 }
3785
3786@@ -116,30 +116,24 @@
3787 {
3788 	size_t i;
3789 	const char *rv = NULL;
3790-#ifdef USE_C_LOCALE
3791-	locale_t old_lc_ctype, c_lc_ctype;
3792+	char *vbuf_lower;
3793
3794-	c_lc_ctype = newlocale(LC_CTYPE_MASK, "C", 0);
3795-	assert(c_lc_ctype != NULL);
3796-	old_lc_ctype = uselocale(c_lc_ctype);
3797-	assert(old_lc_ctype != NULL);
3798-#else
3799-	char *old_lc_ctype = setlocale(LC_CTYPE, "C");
3800-#endif
3801-	for (i = 0; nv[i].pattern != NULL; i++)
3802-		if (strcasestr(vbuf, nv[i].pattern) != NULL) {
3803+	vbuf_lower = zend_str_tolower_dup(vbuf, strlen(vbuf));
3804+	for (i = 0; nv[i].pattern != NULL; i++) {
3805+		char *pattern_lower;
3806+		int found;
3807+
3808+		pattern_lower = zend_str_tolower_dup(nv[i].pattern, strlen(nv[i].pattern));
3809+		found = (strstr(vbuf_lower, pattern_lower) != NULL);
3810+		efree(pattern_lower);
3811+
3812+		if (found) {
3813 			rv = nv[i].mime;
3814 			break;
3815 		}
3816-#ifdef CDF_DEBUG
3817-	fprintf(stderr, "unknown app %s\n", vbuf);
3818-#endif
3819-#ifdef USE_C_LOCALE
3820-	(void)uselocale(old_lc_ctype);
3821-	freelocale(c_lc_ctype);
3822-#else
3823-	setlocale(LC_CTYPE, old_lc_ctype);
3824-#endif
3825+	}
3826+
3827+	efree(vbuf_lower);
3828 	return rv;
3829 }
3830
3831@@ -155,6 +149,8 @@
3832         const char *s, *e;
3833         int len;
3834
3835+	memset(&ts, 0, sizeof(ts));
3836+
3837         if (!NOTMIME(ms) && root_storage)
3838 		str = cdf_clsid_to_mime(root_storage->d_storage_uuid,
3839 		    clsid2mime);
3840@@ -281,10 +277,10 @@
3841 			if (file_printf(ms, "%s%s",
3842 			    cdf_u16tos8(buf, ce[i].ce_namlen, ce[i].ce_name),
3843 			    i == cat->cat_num - 1 ? "]" : ", ") == -1) {
3844-				free(cat);
3845+				efree(cat);
3846 				return -1;
3847 			}
3848-		free(cat);
3849+		efree(cat);
3850 	} else {
3851 		if (file_printf(ms, "application/CDFV2") == -1)
3852 			return -1;
3853@@ -345,7 +341,7 @@
3854 	}
3855
3856         m = cdf_file_property_info(ms, info, count, root_storage);
3857-        free(info);
3858+        efree(info);
3859
3860         return m == -1 ? -2 : m;
3861 }
3862@@ -353,11 +349,11 @@
3863 #ifdef notdef
3864 private char *
3865 format_clsid(char *buf, size_t len, const uint64_t uuid[2]) {
3866-	snprintf(buf, len, "%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4"
3867+	snprintf(buf, len, "%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4"
3868 	    PRIx64 "-%.12" PRIx64,
3869 	    (uuid[0] >> 32) & (uint64_t)0x000000000ffffffffULL,
3870 	    (uuid[0] >> 16) & (uint64_t)0x0000000000000ffffULL,
3871-	    (uuid[0] >>  0) & (uint64_t)0x0000000000000ffffULL,
3872+	    (uuid[0] >>  0) & (uint64_t)0x0000000000000ffffULL,
3873 	    (uuid[1] >> 48) & (uint64_t)0x0000000000000ffffULL,
3874 	    (uuid[1] >>  0) & (uint64_t)0x0000fffffffffffffULL);
3875 	return buf;
3876@@ -436,7 +432,7 @@
3877 	const char *sections[5];
3878 	const int  types[5];
3879 } sectioninfo[] = {
3880-	{ "Encrypted", "encrypted",
3881+	{ "Encrypted", "encrypted",
3882 		{
3883 			"EncryptedPackage", "EncryptedSummary",
3884 			NULL, NULL, NULL,
3885@@ -448,7 +444,7 @@
3886
3887 		},
3888 	},
3889-	{ "QuickBooks", "quickbooks",
3890+	{ "QuickBooks", "quickbooks",
3891 		{
3892 #if 0
3893 			"TaxForms", "PDFTaxForms", "modulesInBackup",
3894@@ -655,11 +651,11 @@
3895 	cdf_zero_stream(&scn);
3896 	cdf_zero_stream(&sst);
3897 out3:
3898-        free(dir.dir_tab);
3899+        efree(dir.dir_tab);
3900 out2:
3901-        free(ssat.sat_tab);
3902+        efree(ssat.sat_tab);
3903 out1:
3904-        free(sat.sat_tab);
3905+        efree(sat.sat_tab);
3906 out0:
3907 	if (i == -1) {
3908 	    if (NOTMIME(ms)) {
3909diff -u libmagic.orig/softmagic.c libmagic/softmagic.c
3910--- libmagic.orig/softmagic.c	2018-04-15 20:49:15.000000000 +0200
3911+++ libmagic/softmagic.c	2020-02-26 09:55:13.866043500 +0100
3912@@ -43,6 +43,10 @@
3913 #include <time.h>
3914 #include "der.h"
3915
3916+#ifndef PREG_OFFSET_CAPTURE
3917+# define PREG_OFFSET_CAPTURE                 (1<<8)
3918+#endif
3919+
3920 private int match(struct magic_set *, struct magic *, uint32_t,
3921     const struct buffer *, size_t, int, int, int, uint16_t *,
3922     uint16_t *, int *, int *, int *);
3923@@ -119,8 +123,8 @@
3924 	return 0;
3925 }
3926
3927-#define FILE_FMTDEBUG
3928-#ifdef FILE_FMTDEBUG
3929+
3930+#if defined(FILE_FMTDEBUG) && defined(HAVE_FMTCHECK)
3931 #define F(a, b, c) file_fmtcheck((a), (b), (c), __FILE__, __LINE__)
3932
3933 private const char * __attribute__((__format_arg__(3)))
3934@@ -134,8 +138,10 @@
3935 		    " with `%s'", file, line, desc, def);
3936 	return ptr;
3937 }
3938-#else
3939+#elif defined(HAVE_FMTCHECK)
3940 #define F(a, b, c) fmtcheck((b), (c))
3941+#else
3942+#define F(a, b, c) ((b))
3943 #endif
3944
3945 /*
3946@@ -189,7 +195,7 @@
3947 		struct magic *m = &magic[magindex];
3948
3949 		if (m->type != FILE_NAME)
3950-		if ((IS_STRING(m->type) &&
3951+		if ((IS_LIBMAGIC_STRING(m->type) &&
3952 #define FLT (STRING_BINTEST | STRING_TEXTTEST)
3953 		     ((text && (m->str_flags & FLT) == STRING_BINTEST) ||
3954 		      (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) ||
3955@@ -416,42 +422,28 @@
3956 private int
3957 check_fmt(struct magic_set *ms, const char *fmt)
3958 {
3959-	file_regex_t rx;
3960-	int rc, rv = -1;
3961+	pcre_cache_entry *pce;
3962+	int rv = -1;
3963+	zend_string *pattern;
3964
3965 	if (strchr(fmt, '%') == NULL)
3966 		return 0;
3967
3968-	rc = file_regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB);
3969-	if (rc) {
3970-		file_regerror(&rx, rc, ms);
3971+	pattern = zend_string_init("~%[-0-9\\.]*s~", sizeof("~%[-0-9\\.]*s~") - 1, 0);
3972+	if ((pce = pcre_get_compiled_regex_cache_ex(pattern, 0)) == NULL) {
3973+		rv = -1;
3974 	} else {
3975-		rc = file_regexec(&rx, fmt, 0, 0, 0);
3976-		rv = !rc;
3977+		pcre2_code *re = php_pcre_pce_re(pce);
3978+		pcre2_match_data *match_data = php_pcre_create_match_data(0, re);
3979+		if (match_data) {
3980+			rv = pcre2_match(re, (PCRE2_SPTR)fmt, strlen(fmt), 0, 0, match_data, php_pcre_mctx()) > 0;
3981+			php_pcre_free_match_data(match_data);
3982+		}
3983 	}
3984-	file_regfree(&rx);
3985+	zend_string_release(pattern);
3986 	return rv;
3987 }
3988
3989-#ifndef HAVE_STRNDUP
3990-char * strndup(const char *, size_t);
3991-
3992-char *
3993-strndup(const char *str, size_t n)
3994-{
3995-	size_t len;
3996-	char *copy;
3997-
3998-	for (len = 0; len < n && str[len]; len++)
3999-		continue;
4000-	if ((copy = malloc(len + 1)) == NULL)
4001-		return NULL;
4002-	(void)memcpy(copy, str, len);
4003-	copy[len] = '\0';
4004-	return copy;
4005-}
4006-#endif /* HAVE_STRNDUP */
4007-
4008 static int
4009 varexpand(char *buf, size_t len, const struct buffer *b, const char *str)
4010 {
4011@@ -743,14 +735,10 @@
4012 		char *cp;
4013 		int rval;
4014
4015-		cp = strndup((const char *)ms->search.s, ms->search.rm_len);
4016-		if (cp == NULL) {
4017-			file_oomem(ms, ms->search.rm_len);
4018-			return -1;
4019-		}
4020+		cp = estrndup((const char *)ms->search.s, ms->search.rm_len);
4021 		rval = file_printf(ms, F(ms, desc, "%s"),
4022 		    file_printable(sbuf, sizeof(sbuf), cp));
4023-		free(cp);
4024+		efree(cp);
4025
4026 		if (rval == -1)
4027 			return -1;
4028@@ -1135,7 +1123,7 @@
4029 			 * string by p->s, so we need to deduct sz.
4030 			 * Because we can use one of the bytes of the length
4031 			 * after we shifted as NUL termination.
4032-			 */
4033+			 */
4034 			len = sz;
4035 		}
4036 		while (len--)
4037@@ -1209,7 +1197,7 @@
4038 			goto out;
4039 		return 1;
4040 	case FILE_BEDOUBLE:
4041-		p->q = BE64(p);
4042+		p->q = BE64(p);
4043 		if (cvt_double(p, m) == -1)
4044 			goto out;
4045 		return 1;
4046@@ -1481,8 +1469,6 @@
4047 		return -1;
4048 	}
4049
4050-
4051-
4052 	if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o),
4053 	    (uint32_t)nbytes, m) == -1)
4054 		return -1;
4055@@ -1494,9 +1480,6 @@
4056 		    m->type, m->flag, offset, o, nbytes,
4057 		    *indir_count, *name_count);
4058 		mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
4059-#ifndef COMPILE_ONLY
4060-		file_mdump(m);
4061-#endif
4062 	}
4063
4064 	if (m->flag & INDIR) {
4065@@ -1609,9 +1592,6 @@
4066 		if ((ms->flags & MAGIC_DEBUG) != 0) {
4067 			mdebug(offset, (char *)(void *)p,
4068 			    sizeof(union VALUETYPE));
4069-#ifndef COMPILE_ONLY
4070-			file_mdump(m);
4071-#endif
4072 		}
4073 	}
4074
4075@@ -1696,15 +1676,15 @@
4076 		if (rv == 1) {
4077 			if ((ms->flags & MAGIC_NODESC) == 0 &&
4078 			    file_printf(ms, F(ms, m->desc, "%u"), offset) == -1) {
4079-				free(rbuf);
4080+				if (rbuf) efree(rbuf);
4081 				return -1;
4082 			}
4083 			if (file_printf(ms, "%s", rbuf) == -1) {
4084-				free(rbuf);
4085+				if (rbuf) efree(rbuf);
4086 				return -1;
4087 			}
4088 		}
4089-		free(rbuf);
4090+		if (rbuf) efree(rbuf);
4091 		return rv;
4092
4093 	case FILE_USE:
4094@@ -1827,6 +1807,41 @@
4095 	return file_strncmp(a, b, len, flags);
4096 }
4097
4098+public void
4099+convert_libmagic_pattern(zval *pattern, char *val, size_t len, uint32_t options)
4100+{
4101+	int i, j=0;
4102+	zend_string *t;
4103+
4104+	t = zend_string_alloc(len * 2 + 4, 0);
4105+
4106+	ZSTR_VAL(t)[j++] = '~';
4107+
4108+	for (i = 0; i < len; i++, j++) {
4109+		switch (val[i]) {
4110+			case '~':
4111+				ZSTR_VAL(t)[j++] = '\\';
4112+				ZSTR_VAL(t)[j] = '~';
4113+				break;
4114+			default:
4115+				ZSTR_VAL(t)[j] = val[i];
4116+				break;
4117+		}
4118+	}
4119+	ZSTR_VAL(t)[j++] = '~';
4120+
4121+	if (options & PCRE2_CASELESS)
4122+		ZSTR_VAL(t)[j++] = 'i';
4123+
4124+	if (options & PCRE2_MULTILINE)
4125+		ZSTR_VAL(t)[j++] = 'm';
4126+
4127+	ZSTR_VAL(t)[j]='\0';
4128+	ZSTR_LEN(t) = j;
4129+
4130+	ZVAL_NEW_STR(pattern, t);
4131+}
4132+
4133 private int
4134 magiccheck(struct magic_set *ms, struct magic *m)
4135 {
4136@@ -1987,65 +2002,77 @@
4137 		break;
4138 	}
4139 	case FILE_REGEX: {
4140-		int rc;
4141-		file_regex_t rx;
4142-		const char *search;
4143+		zval pattern;
4144+		uint32_t options = 0;
4145+		pcre_cache_entry *pce;
4146
4147-		if (ms->search.s == NULL)
4148-			return 0;
4149+		options |= PCRE2_MULTILINE;
4150
4151-		l = 0;
4152-		rc = file_regcomp(&rx, m->value.s,
4153-		    REG_EXTENDED|REG_NEWLINE|
4154-		    ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
4155-		if (rc) {
4156-			file_regerror(&rx, rc, ms);
4157-			v = (uint64_t)-1;
4158+		if (m->str_flags & STRING_IGNORE_CASE) {
4159+			options |= PCRE2_CASELESS;
4160+		}
4161+
4162+		convert_libmagic_pattern(&pattern, (char *)m->value.s, m->vallen, options);
4163+
4164+		l = v = 0;
4165+		if ((pce = pcre_get_compiled_regex_cache(Z_STR(pattern))) == NULL) {
4166+			zval_ptr_dtor(&pattern);
4167+			return -1;
4168 		} else {
4169-			regmatch_t pmatch;
4170-			size_t slen = ms->search.s_len;
4171-			char *copy;
4172-			if (slen != 0) {
4173-			    copy = CAST(char *, malloc(slen));
4174-			    if (copy == NULL)  {
4175-				file_regfree(&rx);
4176-				file_error(ms, errno,
4177-				    "can't allocate %" SIZE_T_FORMAT "u bytes",
4178-				    slen);
4179-				return -1;
4180-			    }
4181-			    memcpy(copy, ms->search.s, slen);
4182-			    copy[--slen] = '\0';
4183-			    search = copy;
4184+			/* pce now contains the compiled regex */
4185+			zval retval;
4186+			zval subpats;
4187+			char *haystack;
4188+
4189+			ZVAL_NULL(&retval);
4190+			ZVAL_NULL(&subpats);
4191+
4192+			/* Cut the search len from haystack, equals to REG_STARTEND */
4193+			haystack = estrndup(ms->search.s, ms->search.s_len);
4194+
4195+			/* match v = 0, no match v = 1 */
4196+			php_pcre_match_impl(pce, haystack, ms->search.s_len, &retval, &subpats, 0, 1, PREG_OFFSET_CAPTURE, 0);
4197+			/* Free haystack */
4198+			efree(haystack);
4199+
4200+			if (Z_LVAL(retval) < 0) {
4201+				zval_ptr_dtor(&subpats);
4202+				zval_ptr_dtor(&pattern);
4203+				return -1;
4204+			} else if ((Z_LVAL(retval) > 0) && (Z_TYPE(subpats) == IS_ARRAY)) {
4205+				/* Need to fetch global match which equals pmatch[0] */
4206+				zval *pzval;
4207+				HashTable *ht = Z_ARRVAL(subpats);
4208+				if ((pzval = zend_hash_index_find(ht, 0)) != NULL && Z_TYPE_P(pzval) == IS_ARRAY) {
4209+					/* If everything goes according to the master plan
4210+					   tmpcopy now contains two elements:
4211+					   0 = the match
4212+					   1 = starting position of the match */
4213+					zval *match, *offset;
4214+					if ((match = zend_hash_index_find(Z_ARRVAL_P(pzval), 0)) &&
4215+							(offset = zend_hash_index_find(Z_ARRVAL_P(pzval), 1))) {
4216+						if (Z_TYPE_P(match) != IS_STRING && Z_TYPE_P(offset) != IS_LONG) {
4217+							goto error_out;
4218+						}
4219+						ms->search.s += Z_LVAL_P(offset); /* this is where the match starts */
4220+						ms->search.offset += Z_LVAL_P(offset); /* this is where the match starts as size_t */
4221+						ms->search.rm_len = Z_STRLEN_P(match) /* This is the length of the matched pattern */;
4222+						v = 0;
4223+					} else {
4224+						goto error_out;
4225+					}
4226+				} else {
4227+error_out:
4228+					zval_ptr_dtor(&subpats);
4229+					zval_ptr_dtor(&pattern);
4230+					return -1;
4231+				}
4232 			} else {
4233-			    search = CCAST(char *, "");
4234-			    copy = NULL;
4235-			}
4236-			rc = file_regexec(&rx, (const char *)search,
4237-			    1, &pmatch, 0);
4238-			free(copy);
4239-			switch (rc) {
4240-			case 0:
4241-				ms->search.s += (int)pmatch.rm_so;
4242-				ms->search.offset += (size_t)pmatch.rm_so;
4243-				ms->search.rm_len =
4244-				    (size_t)(pmatch.rm_eo - pmatch.rm_so);
4245-				v = 0;
4246-				break;
4247-
4248-			case REG_NOMATCH:
4249 				v = 1;
4250-				break;
4251-
4252-			default:
4253-				file_regerror(&rx, rc, ms);
4254-				v = (uint64_t)-1;
4255-				break;
4256 			}
4257+			zval_ptr_dtor(&subpats);
4258+			zval_ptr_dtor(&pattern);
4259 		}
4260-		file_regfree(&rx);
4261-		if (v == (uint64_t)-1)
4262-			return -1;
4263 		break;
4264 	}
4265 	case FILE_INDIRECT:
4266diff -u libmagic.orig/strcasestr.c libmagic/strcasestr.c
4267--- libmagic.orig/strcasestr.c	2014-05-13 18:48:12.000000000 +0200
4268+++ libmagic/strcasestr.c	2019-04-02 11:56:06.853152400 +0200
4269@@ -39,6 +39,8 @@
4270
4271 #include "file.h"
4272
4273+#include "php_stdint.h"
4274+
4275 #include <assert.h>
4276 #include <ctype.h>
4277 #include <string.h>
4278