File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / fileinfo / libmagic.patch
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:48 2014 UTC (10 years, 6 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>