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