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