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