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