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