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