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