summaryrefslogtreecommitdiff
path: root/ext/fileinfo/libmagic
diff options
context:
space:
mode:
authorAnatol Belski <ab@php.net>2013-04-07 22:15:56 +0200
committerAnatol Belski <ab@php.net>2013-04-07 22:15:56 +0200
commit10367fa7c6a4a2cf9bee02d8905e284185428f09 (patch)
tree380b04df159e9f46f91283d5b26171b5a4a8394c /ext/fileinfo/libmagic
parent39bc1bd25f765726e6cdf15fd663b2c1430d2c8a (diff)
downloadphp-git-10367fa7c6a4a2cf9bee02d8905e284185428f09.tar.gz
upgraded libmagic to 5.14
Diffstat (limited to 'ext/fileinfo/libmagic')
-rw-r--r--ext/fileinfo/libmagic/apprentice.c993
-rw-r--r--ext/fileinfo/libmagic/ascmagic.c11
-rw-r--r--ext/fileinfo/libmagic/cdf.c8
-rw-r--r--ext/fileinfo/libmagic/cdf.h4
-rw-r--r--ext/fileinfo/libmagic/cdf_time.c18
-rw-r--r--ext/fileinfo/libmagic/compress.c24
-rw-r--r--ext/fileinfo/libmagic/elfclass.h3
-rw-r--r--ext/fileinfo/libmagic/file.h58
-rw-r--r--ext/fileinfo/libmagic/fsmagic.c73
-rw-r--r--ext/fileinfo/libmagic/funcs.c26
-rw-r--r--ext/fileinfo/libmagic/magic.c104
-rw-r--r--ext/fileinfo/libmagic/magic.h3
-rw-r--r--ext/fileinfo/libmagic/patchlevel.h6
-rw-r--r--ext/fileinfo/libmagic/print.c23
-rw-r--r--ext/fileinfo/libmagic/readcdf.c24
-rw-r--r--ext/fileinfo/libmagic/readelf.c36
-rw-r--r--ext/fileinfo/libmagic/softmagic.c333
17 files changed, 1210 insertions, 537 deletions
diff --git a/ext/fileinfo/libmagic/apprentice.c b/ext/fileinfo/libmagic/apprentice.c
index 09e1812156..ef65a7ecc0 100644
--- a/ext/fileinfo/libmagic/apprentice.c
+++ b/ext/fileinfo/libmagic/apprentice.c
@@ -34,7 +34,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: apprentice.c,v 1.173 2011/12/08 12:38:24 rrt Exp $")
+FILE_RCSID("@(#)$File: apprentice.c,v 1.191 2013/02/26 21:02:48 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -58,7 +58,6 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.173 2011/12/08 12:38:24 rrt Exp $")
#else
#include <unistd.h>
#endif
-
#include <string.h>
#include <assert.h>
#include <ctype.h>
@@ -86,12 +85,22 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.173 2011/12/08 12:38:24 rrt Exp $")
#define MAP_FILE 0
#endif
+#define ALLOC_CHUNK (size_t)10
+#define ALLOC_INCR (size_t)200
+
struct magic_entry {
struct magic *mp;
uint32_t cont_count;
uint32_t max_count;
};
+struct magic_map {
+ void *p;
+ size_t len;
+ struct magic *magic[MAGIC_SETS];
+ uint32_t nmagic[MAGIC_SETS];
+};
+
int file_formats[FILE_NAMES_SIZE];
const size_t file_nformats = FILE_NAMES_SIZE;
const char *file_names[FILE_NAMES_SIZE];
@@ -101,24 +110,26 @@ private int getvalue(struct magic_set *ms, struct magic *, const char **, int);
private int hextoint(int);
private const char *getstr(struct magic_set *, struct magic *, const char *,
int);
-private int parse(struct magic_set *, struct magic_entry **, uint32_t *,
- const char *, size_t, int);
+private int parse(struct magic_set *, struct magic_entry *, const char *,
+ size_t, int);
private void eatsize(const char **);
-private int apprentice_1(struct magic_set *, const char *, int, struct mlist *);
+private int apprentice_1(struct magic_set *, const char *, int);
private size_t apprentice_magic_strength(const struct magic *);
private int apprentice_sort(const void *, const void *);
private void apprentice_list(struct mlist *, int );
-private int apprentice_load(struct magic_set *, struct magic **, uint32_t *,
+private struct magic_map *apprentice_load(struct magic_set *,
const char *, int);
+private struct mlist *mlist_alloc(void);
+private void mlist_free(struct mlist *);
private void byteswap(struct magic *, uint32_t);
private void bs1(struct magic *);
private uint16_t swap2(uint16_t);
private uint32_t swap4(uint32_t);
private uint64_t swap8(uint64_t);
private char *mkdbname(struct magic_set *, const char *, int);
-private int apprentice_map(struct magic_set *, struct magic **, uint32_t *,
- const char *);
-private int apprentice_compile(struct magic_set *, struct magic **, uint32_t *,
+private struct magic_map *apprentice_map(struct magic_set *, const char *);
+private void apprentice_unmap(struct magic_map *);
+private int apprentice_compile(struct magic_set *, struct magic_map *,
const char *);
private int check_format_type(const char *, int);
private int check_format(struct magic_set *, struct magic *);
@@ -127,10 +138,12 @@ private int parse_mime(struct magic_set *, struct magic_entry *, const char *);
private int parse_strength(struct magic_set *, struct magic_entry *, const char *);
private int parse_apple(struct magic_set *, struct magic_entry *, const char *);
-private size_t maxmagic = 0;
+
+private size_t maxmagic[MAGIC_SETS] = { 0 };
private size_t magicsize = sizeof(struct magic);
private const char usg_hdr[] = "cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
+
private struct {
const char *name;
size_t len;
@@ -146,14 +159,24 @@ private struct {
#include "../data_file.c"
-static const struct type_tbl_s {
+struct type_tbl_s {
const char name[16];
const size_t len;
const int type;
const int format;
-} type_tbl[] = {
+};
+
+/*
+ * XXX - the actual Single UNIX Specification says that "long" means "long",
+ * as in the C data type, but we treat it as meaning "4-byte integer".
+ * Given that the OS X version of file 5.04 did the same, I guess that passes
+ * the actual test; having "long" be dependent on how big a "long" is on
+ * the machine running "file" is silly.
+ */
+static const struct type_tbl_s type_tbl[] = {
# define XX(s) s, (sizeof(s) - 1)
# define XX_NULL "", 0
+ { XX("invalid"), FILE_INVALID, FILE_FMT_NONE },
{ XX("byte"), FILE_BYTE, FILE_FMT_NUM },
{ XX("short"), FILE_SHORT, FILE_FMT_NUM },
{ XX("default"), FILE_DEFAULT, FILE_FMT_STR },
@@ -194,22 +217,37 @@ static const struct type_tbl_s {
{ XX("ledouble"), FILE_LEDOUBLE, FILE_FMT_DOUBLE },
{ XX("leid3"), FILE_LEID3, FILE_FMT_NUM },
{ XX("beid3"), FILE_BEID3, FILE_FMT_NUM },
- { XX("indirect"), FILE_INDIRECT, FILE_FMT_NONE },
+ { XX("indirect"), FILE_INDIRECT, FILE_FMT_NUM },
+ { XX("qwdate"), FILE_QWDATE, FILE_FMT_STR },
+ { XX("leqwdate"), FILE_LEQWDATE, FILE_FMT_STR },
+ { XX("beqwdate"), FILE_BEQWDATE, FILE_FMT_STR },
+ { XX("name"), FILE_NAME, FILE_FMT_NONE },
+ { XX("use"), FILE_USE, FILE_FMT_NONE },
+ { XX_NULL, FILE_INVALID, FILE_FMT_NONE },
+};
+
+/*
+ * These are not types, and cannot be preceded by "u" to make them
+ * unsigned.
+ */
+static const struct type_tbl_s special_tbl[] = {
+ { XX("name"), FILE_NAME, FILE_FMT_STR },
+ { XX("use"), FILE_USE, FILE_FMT_STR },
{ XX_NULL, FILE_INVALID, FILE_FMT_NONE },
+};
# undef XX
# undef XX_NULL
-};
#ifndef S_ISDIR
#define S_ISDIR(mode) ((mode) & _S_IFDIR)
#endif
private int
-get_type(const char *l, const char **t)
+get_type(const struct type_tbl_s *tbl, const char *l, const char **t)
{
const struct type_tbl_s *p;
- for (p = type_tbl; p->len; p++) {
+ for (p = tbl; p->len; p++) {
if (strncmp(l, p->name, p->len) == 0) {
if (t)
*t = l + p->len;
@@ -219,6 +257,91 @@ get_type(const char *l, const char **t)
return p->type;
}
+private int
+get_standard_integer_type(const char *l, const char **t)
+{
+ int type;
+
+ if (isalpha((unsigned char)l[1])) {
+ switch (l[1]) {
+ case 'C':
+ /* "dC" and "uC" */
+ type = FILE_BYTE;
+ break;
+ case 'S':
+ /* "dS" and "uS" */
+ type = FILE_SHORT;
+ break;
+ case 'I':
+ case 'L':
+ /*
+ * "dI", "dL", "uI", and "uL".
+ *
+ * XXX - the actual Single UNIX Specification says
+ * that "L" means "long", as in the C data type,
+ * but we treat it as meaning "4-byte integer".
+ * Given that the OS X version of file 5.04 did
+ * the same, I guess that passes the actual SUS
+ * validation suite; having "dL" be dependent on
+ * how big a "long" is on the machine running
+ * "file" is silly.
+ */
+ type = FILE_LONG;
+ break;
+ case 'Q':
+ /* "dQ" and "uQ" */
+ type = FILE_QUAD;
+ break;
+ default:
+ /* "d{anything else}", "u{anything else}" */
+ return FILE_INVALID;
+ }
+ l += 2;
+ } else if (isdigit((unsigned char)l[1])) {
+ /*
+ * "d{num}" and "u{num}"; we only support {num} values
+ * of 1, 2, 4, and 8 - the Single UNIX Specification
+ * doesn't say anything about whether arbitrary
+ * values should be supported, but both the Solaris 10
+ * and OS X Mountain Lion versions of file passed the
+ * Single UNIX Specification validation suite, and
+ * neither of them support values bigger than 8 or
+ * non-power-of-2 values.
+ */
+ if (isdigit((unsigned char)l[2])) {
+ /* Multi-digit, so > 9 */
+ return FILE_INVALID;
+ }
+ switch (l[1]) {
+ case '1':
+ type = FILE_BYTE;
+ break;
+ case '2':
+ type = FILE_SHORT;
+ break;
+ case '4':
+ type = FILE_LONG;
+ break;
+ case '8':
+ type = FILE_QUAD;
+ break;
+ default:
+ /* XXX - what about 3, 5, 6, or 7? */
+ return FILE_INVALID;
+ }
+ l += 2;
+ } else {
+ /*
+ * "d" or "u" by itself.
+ */
+ type = FILE_LONG;
+ ++l;
+ }
+ if (t)
+ *t = l;
+ return type;
+}
+
private void
init_file_tables(void)
{
@@ -234,110 +357,187 @@ init_file_tables(void)
file_names[p->type] = p->name;
file_formats[p->type] = p->format;
}
+ assert(p - type_tbl == FILE_NAMES_SIZE);
+}
+
+private int
+add_mlist(struct mlist *mlp, struct magic_map *map, size_t idx)
+{
+ struct mlist *ml;
+
+ if ((ml = CAST(struct mlist *, emalloc(sizeof(*ml)))) == NULL)
+ return -1;
+
+ ml->map = idx == 0 ? map : NULL;
+ ml->magic = map->magic[idx];
+ ml->nmagic = map->nmagic[idx];
+
+ mlp->prev->next = ml;
+ ml->prev = mlp->prev;
+ ml->next = mlp;
+ mlp->prev = ml;
+ return 0;
}
/*
* Handle one file or directory.
*/
private int
-apprentice_1(struct magic_set *ms, const char *fn, int action,
- struct mlist *mlist)
+apprentice_1(struct magic_set *ms, const char *fn, int action)
{
- struct magic *magic = NULL;
- uint32_t nmagic = 0;
struct mlist *ml;
- int rv = -1;
- int mapped;
+ struct magic_map *map;
+ size_t i;
if (magicsize != FILE_MAGICSIZE) {
file_error(ms, 0, "magic element size %lu != %lu",
- (unsigned long)sizeof(*magic),
+ (unsigned long)sizeof(*map->magic[0]),
(unsigned long)FILE_MAGICSIZE);
return -1;
}
if (action == FILE_COMPILE) {
- rv = apprentice_load(ms, &magic, &nmagic, fn, action);
- if (rv != 0)
+ map = apprentice_load(ms, fn, action);
+ if (map == NULL)
return -1;
- rv = apprentice_compile(ms, &magic, &nmagic, fn);
- efree(magic);
- return rv;
+ return apprentice_compile(ms, map, fn);
}
- if ((rv = apprentice_map(ms, &magic, &nmagic, fn)) == -1) {
+ map = apprentice_map(ms, fn);
+ if (map == NULL) {
if (fn) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "using regular magic file `%s'", fn);
- rv = apprentice_load(ms, &magic, &nmagic, fn, action);
+ map = apprentice_load(ms, fn, action);
}
-
- if (rv != 0)
+ if (map == NULL)
return -1;
}
- mapped = rv;
-
- if (magic == NULL) {
- file_delmagic(magic, mapped, nmagic);
- return -1;
+ for (i = 0; i < MAGIC_SETS; i++) {
+ if (add_mlist(ms->mlist[i], map, i) == -1) {
+ file_oomem(ms, sizeof(*ml));
+ apprentice_unmap(map);
+ return -1;
+ }
}
- ml = emalloc(sizeof(*ml));
-
- ml->magic = magic;
- ml->nmagic = nmagic;
- ml->mapped = mapped;
-
- mlist->prev->next = ml;
- ml->prev = mlist->prev;
- ml->next = mlist;
- mlist->prev = ml;
-
if (action == FILE_LIST) {
- printf("Binary patterns:\n");
- apprentice_list(mlist, BINTEST);
- printf("Text patterns:\n");
- apprentice_list(mlist, TEXTTEST);
+ for (i = 0; i < MAGIC_SETS; i++) {
+ printf("Set %zu:\nBinary patterns:\n", i);
+ apprentice_list(ms->mlist[i], BINTEST);
+ printf("Text patterns:\n");
+ apprentice_list(ms->mlist[i], TEXTTEST);
+ }
}
return 0;
}
protected void
-file_delmagic(struct magic *p, int type, size_t entries)
+file_ms_free(struct magic_set *ms)
{
- if (p == NULL)
+ size_t i;
+ if (ms == NULL)
return;
- switch (type) {
- case 3:
- /* Do nothing, it's part of the code segment */
- break;
+ for (i = 0; i < MAGIC_SETS; i++)
+ mlist_free(ms->mlist[i]);
+ if (ms->o.pbuf) {
+ efree(ms->o.pbuf);
+ }
+ if (ms->o.buf) {
+ efree(ms->o.buf);
+ }
+ if (ms->c.li) {
+ efree(ms->c.li);
+ }
+ efree(ms);
+}
- case 1:
- p--;
- /*FALLTHROUGH*/
+protected struct magic_set *
+file_ms_alloc(int flags)
+{
+ struct magic_set *ms;
+ size_t i, len;
- case 0:
- efree(p);
- break;
+ if ((ms = CAST(struct magic_set *, ecalloc((size_t)1,
+ sizeof(struct magic_set)))) == NULL)
+ return NULL;
- default:
- abort();
+ if (magic_setflags(ms, flags) == -1) {
+ errno = EINVAL;
+ goto free;
+ }
+
+ ms->o.buf = ms->o.pbuf = NULL;
+ len = (ms->c.len = 10) * sizeof(*ms->c.li);
+
+ if ((ms->c.li = CAST(struct level_info *, emalloc(len))) == NULL)
+ goto free;
+
+ ms->event_flags = 0;
+ ms->error = -1;
+ for (i = 0; i < MAGIC_SETS; i++)
+ ms->mlist[i] = NULL;
+ ms->file = "unknown";
+ ms->line = 0;
+ return ms;
+free:
+ efree(ms);
+ return NULL;
+}
+
+private void
+apprentice_unmap(struct magic_map *map)
+{
+ if (map == NULL)
+ return;
+ if (map->p != NULL && map->p != php_magic_database) {
+ efree(map->p);
+ }
+ efree(map);
+}
+
+private struct mlist *
+mlist_alloc(void)
+{
+ struct mlist *mlist;
+ if ((mlist = CAST(struct mlist *, ecalloc(1, sizeof(*mlist)))) == NULL) {
+ return NULL;
}
+ mlist->next = mlist->prev = mlist;
+ return mlist;
+}
+
+private void
+mlist_free(struct mlist *mlist)
+{
+ struct mlist *ml;
+
+ if (mlist == NULL)
+ return;
+
+ for (ml = mlist->next; ml != mlist;) {
+ struct mlist *next = ml->next;
+ if (ml->map)
+ apprentice_unmap(ml->map);
+ efree(ml);
+ ml = next;
+ }
+ efree(ml);
}
/* const char *fn: list of magic files and directories */
-protected struct mlist *
+protected int
file_apprentice(struct magic_set *ms, const char *fn, int action)
{
char *p, *mfn;
int file_err, errs = -1;
- struct mlist *mlist;
+ size_t i;
/* XXX disabling default magic loading so the compiled in data is used */
#if 0
if ((fn = magic_getpath(fn, action)) == NULL)
- return NULL;
+ return -1;
#endif
init_file_tables();
@@ -345,17 +545,36 @@ file_apprentice(struct magic_set *ms, const char *fn, int action)
if (fn == NULL)
fn = getenv("MAGIC");
if (fn == NULL) {
- mlist = emalloc(sizeof(*mlist));
- mlist->next = mlist->prev = mlist;
- apprentice_1(ms, fn, action, mlist);
- return mlist;
+ for (i = 0; i < MAGIC_SETS; i++) {
+ mlist_free(ms->mlist[i]);
+ if ((ms->mlist[i] = mlist_alloc()) == NULL) {
+ file_oomem(ms, sizeof(*ms->mlist[i]));
+ return -1;
+ }
+ }
+ return apprentice_1(ms, fn, action);
}
- mfn = estrdup(fn);
- fn = mfn;
+ if ((mfn = estrdup(fn)) == NULL) {
+ file_oomem(ms, strlen(fn));
+ return -1;
+ }
- mlist = emalloc(sizeof(*mlist));
- mlist->next = mlist->prev = mlist;
+ for (i = 0; i < MAGIC_SETS; i++) {
+ mlist_free(ms->mlist[i]);
+ if ((ms->mlist[i] = mlist_alloc()) == NULL) {
+ file_oomem(ms, sizeof(*ms->mlist[i]));
+ if (i != 0) {
+ --i;
+ do
+ mlist_free(ms->mlist[i]);
+ while (i != 0);
+ }
+ efree(mfn);
+ return -1;
+ }
+ }
+ fn = mfn;
while (fn) {
p = strchr(fn, PATHSEP);
@@ -363,19 +582,39 @@ file_apprentice(struct magic_set *ms, const char *fn, int action)
*p++ = '\0';
if (*fn == '\0')
break;
- file_err = apprentice_1(ms, fn, action, mlist);
+ file_err = apprentice_1(ms, fn, action);
errs = MAX(errs, file_err);
fn = p;
}
+
+ efree(mfn);
+
if (errs == -1) {
- efree(mfn);
- efree(mlist);
- mlist = NULL;
- file_error(ms, 0, "could not find any magic files!");
- return NULL;
+ for (i = 0; i < MAGIC_SETS; i++) {
+ mlist_free(ms->mlist[i]);
+ ms->mlist[i] = NULL;
+ }
+ file_error(ms, 0, "could not find any valid magic files!");
+ return -1;
+ }
+
+ if (action == FILE_LOAD)
+ return 0;
+
+ for (i = 0; i < MAGIC_SETS; i++) {
+ mlist_free(ms->mlist[i]);
+ ms->mlist[i] = NULL;
+ }
+
+ switch (action) {
+ case FILE_COMPILE:
+ case FILE_CHECK:
+ case FILE_LIST:
+ return 0;
+ default:
+ file_error(ms, 0, "Invalid action %d", action);
+ return -1;
}
- efree(mfn);
- return mlist;
}
/*
@@ -448,12 +687,20 @@ apprentice_magic_strength(const struct magic *m)
case FILE_QLDATE:
case FILE_LEQLDATE:
case FILE_BEQLDATE:
+ case FILE_QWDATE:
+ case FILE_LEQWDATE:
+ case FILE_BEQWDATE:
case FILE_DOUBLE:
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
val += 8 * MULT;
break;
+ case FILE_INDIRECT:
+ case FILE_NAME:
+ case FILE_USE:
+ break;
+
default:
val = 0;
(void)fprintf(stderr, "Bad type %d\n", m->type);
@@ -507,7 +754,6 @@ apprentice_magic_strength(const struct magic *m)
abort();
}
-
/*
* Magic entries with no description get a bonus because they depend
* on subsequent magic entries to print something.
@@ -523,8 +769,8 @@ apprentice_magic_strength(const struct magic *m)
private int
apprentice_sort(const void *a, const void *b)
{
- const struct magic_entry *ma = a;
- const struct magic_entry *mb = b;
+ const struct magic_entry *ma = CAST(const struct magic_entry *, a);
+ const struct magic_entry *mb = CAST(const struct magic_entry *, b);
size_t sa = apprentice_magic_strength(ma->mp);
size_t sb = apprentice_magic_strength(mb->mp);
if (sa == sb)
@@ -601,6 +847,9 @@ set_test_type(struct magic *mstart, struct magic *m)
case FILE_QLDATE:
case FILE_LEQLDATE:
case FILE_BEQLDATE:
+ case FILE_QWDATE:
+ case FILE_LEQWDATE:
+ case FILE_BEQWDATE:
case FILE_FLOAT:
case FILE_BEFLOAT:
case FILE_LEFLOAT:
@@ -648,22 +897,48 @@ set_test_type(struct magic *mstart, struct magic *m)
}
}
+private int
+addentry(struct magic_set *ms, struct magic_entry *me,
+ struct magic_entry **mentry, uint32_t *mentrycount)
+{
+ size_t i = me->mp->type == FILE_NAME ? 1 : 0;
+ if (mentrycount[i] == maxmagic[i]) {
+ struct magic_entry *mp;
+
+ maxmagic[i] += ALLOC_INCR;
+ if ((mp = CAST(struct magic_entry *,
+ erealloc(mentry[i], sizeof(*mp) * maxmagic[i]))) ==
+ NULL) {
+ file_oomem(ms, sizeof(*mp) * maxmagic[i]);
+ return -1;
+ }
+ (void)memset(&mp[mentrycount[i]], 0, sizeof(*mp) *
+ ALLOC_INCR);
+ mentry[i] = mp;
+ }
+ mentry[i][mentrycount[i]++] = *me;
+ memset(me, 0, sizeof(*me));
+ return 0;
+}
+
/*
* Load and parse one file.
*/
private void
load_1(struct magic_set *ms, int action, const char *fn, int *errs,
- struct magic_entry **marray, uint32_t *marraycount)
+ struct magic_entry **mentry, uint32_t *mentrycount)
{
char buffer[BUFSIZ + 1];
char *line = NULL;
size_t len;
size_t lineno = 0;
+ struct magic_entry me;
php_stream *stream;
TSRMLS_FETCH();
+ ms->file = fn;
#if PHP_API_VERSION < 20100412
stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
#else
@@ -678,12 +953,9 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs,
return;
}
- /* read and parse this file */
-#if (PHP_MAJOR_VERSION < 6)
+ memset(&me, 0, sizeof(me));
+ /* read and parse this file */
for (ms->line = 1; (line = php_stream_get_line(stream, buffer , BUFSIZ, &len)) != NULL; ms->line++) {
-#else
- for (ms->line = 1; (line = php_stream_get_line(stream, ZSTR(buffer), BUFSIZ, &len)) != NULL; ms->line++) {
-#endif
if (len == 0) /* null line, garbage, etc */
continue;
if (line[len - 1] == '\n') {
@@ -710,15 +982,14 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs,
(*errs)++;
continue;
}
- if (*marraycount == 0) {
+ if (me.mp == NULL) {
file_error(ms, 0,
"No current entry for :!%s type",
bang[i].name);
(*errs)++;
continue;
}
- if ((*bang[i].fun)(ms,
- &(*marray)[*marraycount - 1],
+ if ((*bang[i].fun)(ms, &me,
line + bang[i].len + 2) != 0) {
(*errs)++;
continue;
@@ -727,12 +998,21 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs,
}
/*FALLTHROUGH*/
default:
- if (parse(ms, marray, marraycount, line, lineno,
- action) != 0)
+ again:
+ switch (parse(ms, &me, line, lineno, action)) {
+ case 0:
+ continue;
+ case 1:
+ (void)addentry(ms, &me, mentry, mentrycount);
+ goto again;
+ default:
(*errs)++;
break;
}
}
+ }
+ if (me.mp)
+ (void)addentry(ms, &me, mentry, mentrycount);
php_stream_close(stream);
}
@@ -746,16 +1026,109 @@ cmpstrp(const void *p1, const void *p2)
return strcmp(*(char *const *)p1, *(char *const *)p2);
}
+
+private uint32_t
+set_text_binary(struct magic_set *ms, struct magic_entry *me, uint32_t nme,
+ uint32_t starttest)
+{
+ static const char text[] = "text";
+ static const char binary[] = "binary";
+ static const size_t len = sizeof(text);
+
+ uint32_t i = starttest;
+
+ do {
+ set_test_type(me[starttest].mp, me[i].mp);
+ if ((ms->flags & MAGIC_DEBUG) == 0)
+ continue;
+ (void)fprintf(stderr, "%s%s%s: %s\n",
+ me[i].mp->mimetype,
+ me[i].mp->mimetype[0] == '\0' ? "" : "; ",
+ me[i].mp->desc[0] ? me[i].mp->desc : "(no description)",
+ me[i].mp->flag & BINTEST ? binary : text);
+ if (me[i].mp->flag & BINTEST) {
+ char *p = strstr(me[i].mp->desc, text);
+ if (p && (p == me[i].mp->desc ||
+ isspace((unsigned char)p[-1])) &&
+ (p + len - me[i].mp->desc == MAXstring
+ || (p[len] == '\0' ||
+ isspace((unsigned char)p[len]))))
+ (void)fprintf(stderr, "*** Possible "
+ "binary test for text type\n");
+ }
+ } while (++i < nme && me[i].mp->cont_level != 0);
+ return i;
+}
+
+private void
+set_last_default(struct magic_set *ms, struct magic_entry *me, uint32_t nme)
+{
+ uint32_t i;
+ for (i = 0; i < nme; i++) {
+ if (me[i].mp->cont_level == 0 &&
+ me[i].mp->type == FILE_DEFAULT) {
+ while (++i < nme)
+ if (me[i].mp->cont_level == 0)
+ break;
+ if (i != nme) {
+ /* XXX - Ugh! */
+ ms->line = me[i].mp->lineno;
+ file_magwarn(ms,
+ "level 0 \"default\" did not sort last");
+ }
+ return;
+ }
+ }
+}
+
private int
-apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
- const char *fn, int action)
+coalesce_entries(struct magic_set *ms, struct magic_entry *me, uint32_t nme,
+ struct magic **ma, uint32_t *nma)
+{
+ uint32_t i, mentrycount = 0;
+ size_t slen;
+
+ for (i = 0; i < nme; i++)
+ mentrycount += me[i].cont_count;
+
+ slen = sizeof(**ma) * mentrycount;
+ if ((*ma = CAST(struct magic *, emalloc(slen))) == NULL) {
+ file_oomem(ms, slen);
+ return -1;
+ }
+
+ mentrycount = 0;
+ for (i = 0; i < nme; i++) {
+ (void)memcpy(*ma + mentrycount, me[i].mp,
+ me[i].cont_count * sizeof(**ma));
+ mentrycount += me[i].cont_count;
+ }
+ *nma = mentrycount;
+ return 0;
+}
+
+private void
+magic_entry_free(struct magic_entry *me, uint32_t nme)
+{
+ uint32_t i;
+ if (me == NULL)
+ return;
+ for (i = 0; i < nme; i++)
+ efree(me[i].mp);
+ efree(me);
+}
+
+private struct magic_map *
+apprentice_load(struct magic_set *ms, const char *fn, int action)
{
int errs = 0;
- struct magic_entry *marray;
- uint32_t marraycount, i, mentrycount = 0, starttest;
+ struct magic_entry *mentry[MAGIC_SETS] = { NULL };
+ uint32_t mentrycount[MAGIC_SETS] = { 0 };
+ uint32_t i, j;
size_t files = 0, maxfiles = 0;
- char **filearr = NULL;
+ char **filearr = NULL, *mfn;
struct stat st;
+ struct magic_map *map;
php_stream *dir;
php_stream_dirent d;
@@ -763,14 +1136,25 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
ms->flags |= MAGIC_CHECK; /* Enable checks for parsed files */
- maxmagic = MAXMAGIS;
- marray = ecalloc(maxmagic, sizeof(*marray));
- marraycount = 0;
+ if ((map = CAST(struct magic_map *, ecalloc(1, sizeof(*map)))) == NULL) {
+ file_oomem(ms, sizeof(*map));
+ return NULL;
+ }
/* print silly verbose header for USG compat. */
if (action == FILE_CHECK)
(void)fprintf(stderr, "%s\n", usg_hdr);
+ {
+ /* XXX the maxmagic has to be reset each time we load some new magic file.
+ Where file commando is used it's not essential as the CLI process
+ ends, multiple loading within the same process wouldn't work. */
+ int k;
+ for (k = 0; k < MAGIC_SETS; k++) {
+ maxmagic[k] = 0;
+ }
+ }
+
/* load directory or file */
/* FIXME: Read file names and sort them to prevent
non-determinism. See Debian bug #488562. */
@@ -799,7 +1183,7 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
maxfiles = (maxfiles + 1) * 2;
mlen = maxfiles * sizeof(*filearr);
if ((filearr = CAST(char **,
- realloc(filearr, mlen))) == NULL) {
+ erealloc(filearr, mlen))) == NULL) {
file_oomem(ms, mlen);
php_stream_closedir(dir);
errs++;
@@ -811,100 +1195,55 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
php_stream_closedir(dir);
qsort(filearr, files, sizeof(*filearr), cmpstrp);
for (i = 0; i < files; i++) {
- load_1(ms, action, filearr[i], &errs, &marray,
- &marraycount);
+ load_1(ms, action, filearr[i], &errs, mentry,
+ mentrycount);
efree(filearr[i]);
}
- free(filearr);
+ efree(filearr);
} else
- load_1(ms, action, fn, &errs, &marray, &marraycount);
+ load_1(ms, action, fn, &errs, mentry, mentrycount);
if (errs)
goto out;
+ for (j = 0; j < MAGIC_SETS; j++) {
/* Set types of tests */
- for (i = 0; i < marraycount; ) {
- if (marray[i].mp->cont_level != 0) {
+ for (i = 0; i < mentrycount[j]; ) {
+ if (mentry[j][i].mp->cont_level != 0) {
i++;
continue;
}
-
- starttest = i;
- do {
- static const char text[] = "text";
- static const char binary[] = "binary";
- static const size_t len = sizeof(text);
- set_test_type(marray[starttest].mp, marray[i].mp);
- if ((ms->flags & MAGIC_DEBUG) == 0)
- continue;
- (void)fprintf(stderr, "%s%s%s: %s\n",
- marray[i].mp->mimetype,
- marray[i].mp->mimetype[0] == '\0' ? "" : "; ",
- marray[i].mp->desc[0] ? marray[i].mp->desc :
- "(no description)",
- marray[i].mp->flag & BINTEST ? binary : text);
- if (marray[i].mp->flag & BINTEST) {
- char *p = strstr(marray[i].mp->desc, text);
- if (p && (p == marray[i].mp->desc ||
- isspace((unsigned char)p[-1])) &&
- (p + len - marray[i].mp->desc ==
- MAXstring || (p[len] == '\0' ||
- isspace((unsigned char)p[len]))))
- (void)fprintf(stderr, "*** Possible "
- "binary test for text type\n");
+ i = set_text_binary(ms, mentry[j], mentrycount[j], i);
}
- } while (++i < marraycount && marray[i].mp->cont_level != 0);
- }
-
- qsort(marray, marraycount, sizeof(*marray), apprentice_sort);
+ qsort(mentry[j], mentrycount[j], sizeof(*mentry[j]),
+ apprentice_sort);
/*
- * Make sure that any level 0 "default" line is last (if one exists).
+ * Make sure that any level 0 "default" line is last
+ * (if one exists).
*/
- for (i = 0; i < marraycount; i++) {
- if (marray[i].mp->cont_level == 0 &&
- marray[i].mp->type == FILE_DEFAULT) {
- while (++i < marraycount)
- if (marray[i].mp->cont_level == 0)
- break;
- if (i != marraycount) {
- /* XXX - Ugh! */
- ms->line = marray[i].mp->lineno;
- file_magwarn(ms,
- "level 0 \"default\" did not sort last");
- }
- break;
+ set_last_default(ms, mentry[j], mentrycount[j]);
+
+ /* coalesce per file arrays into a single one */
+ if (coalesce_entries(ms, mentry[j], mentrycount[j],
+ &map->magic[j], &map->nmagic[j]) == -1) {
+ errs++;
+ goto out;
}
}
- for (i = 0; i < marraycount; i++)
- mentrycount += marray[i].cont_count;
-
- *magicp = emalloc(sizeof(**magicp) * mentrycount);
-
- mentrycount = 0;
- for (i = 0; i < marraycount; i++) {
- (void)memcpy(*magicp + mentrycount, marray[i].mp,
- marray[i].cont_count * sizeof(**magicp));
- mentrycount += marray[i].cont_count;
- }
out:
- for (i = 0; i < marraycount; i++) {
- if (marray[i].mp) {
- efree(marray[i].mp);
- }
- }
- if (marray) {
- efree(marray);
- }
+ for (j = 0; j < MAGIC_SETS; j++)
+ magic_entry_free(mentry[j], mentrycount[j]);
+
if (errs) {
- *magicp = NULL;
- *nmagicp = 0;
- return errs;
- } else {
- *nmagicp = mentrycount;
- return 0;
+ for (j = 0; j < MAGIC_SETS; j++) {
+ if (map->magic[j])
+ efree(map->magic[j]);
+ }
+ efree(map);
+ return NULL;
}
-
+ return map;
}
/*
@@ -950,10 +1289,13 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
case FILE_LEQUAD:
case FILE_QDATE:
case FILE_QLDATE:
+ case FILE_QWDATE:
case FILE_BEQDATE:
case FILE_BEQLDATE:
+ case FILE_BEQWDATE:
case FILE_LEQDATE:
case FILE_LEQLDATE:
+ case FILE_LEQWDATE:
case FILE_DOUBLE:
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
@@ -967,6 +1309,8 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
case FILE_SEARCH:
case FILE_DEFAULT:
case FILE_INDIRECT:
+ case FILE_NAME:
+ case FILE_USE:
break;
default:
if (ms->flags & MAGIC_CHECK)
@@ -1136,22 +1480,25 @@ check_cond(struct magic_set *ms, int cond, uint32_t cont_level)
* parse one line from magic file, put into magic[index++] if valid
*/
private int
-parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
- const char *line, size_t lineno, int action)
+parse(struct magic_set *ms, struct magic_entry *me, const char *line,
+ size_t lineno, int action)
{
#ifdef ENABLE_CONDITIONALS
static uint32_t last_cont_level = 0;
#endif
size_t i;
- struct magic_entry *me;
struct magic *m;
const char *l = line;
char *t;
int op;
uint32_t cont_level;
+ int32_t diff;
cont_level = 0;
+ /*
+ * Parse the offset.
+ */
while (*l == '>') {
++l; /* step over */
cont_level++;
@@ -1162,23 +1509,29 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
return -1;
last_cont_level = cont_level;
#endif
-
-#define ALLOC_CHUNK (size_t)10
-#define ALLOC_INCR (size_t)200
-
if (cont_level != 0) {
- if (*nmentryp == 0) {
- file_error(ms, 0, "No current entry for continuation");
+ if (me->mp == NULL) {
+ file_magerror(ms, "No current entry for continuation");
return -1;
}
- me = &(*mentryp)[*nmentryp - 1];
- if (me->mp == NULL) {
+ if (me->cont_count == 0) {
+ file_magerror(ms, "Continuations present with 0 count");
return -1;
}
+ m = &me->mp[me->cont_count - 1];
+ diff = (int32_t)cont_level - (int32_t)m->cont_level;
+ if (diff > 1)
+ file_magwarn(ms, "New continuation level %u is more "
+ "than one larger than current level %u", cont_level,
+ m->cont_level);
if (me->cont_count == me->max_count) {
struct magic *nm;
size_t cnt = me->max_count + ALLOC_CHUNK;
- nm = erealloc(me->mp, sizeof(*nm) * cnt);
+ if ((nm = CAST(struct magic *, erealloc(me->mp,
+ sizeof(*nm) * cnt))) == NULL) {
+ file_oomem(ms, sizeof(*nm) * cnt);
+ return -1;
+ }
me->mp = m = nm;
me->max_count = CAST(uint32_t, cnt);
}
@@ -1186,21 +1539,15 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
(void)memset(m, 0, sizeof(*m));
m->cont_level = cont_level;
} else {
- if (*nmentryp == maxmagic) {
- struct magic_entry *mp;
-
- maxmagic += ALLOC_INCR;
- mp = erealloc(*mentryp, sizeof(*mp) * maxmagic);
- (void)memset(&mp[*nmentryp], 0, sizeof(*mp) * ALLOC_INCR);
- *mentryp = mp;
+ static const size_t len = sizeof(*m) * ALLOC_CHUNK;
+ if (me->mp != NULL)
+ return 1;
+ if ((m = CAST(struct magic *, emalloc(len))) == NULL) {
+ file_oomem(ms, len);
+ return -1;
}
- me = &(*mentryp)[*nmentryp];
- if (me->mp == NULL) {
- m = safe_emalloc(sizeof(*m), ALLOC_CHUNK, 0);
- me->mp = m;
- me->max_count = ALLOC_CHUNK;
- } else
- m = me->mp;
+ me->mp = m;
+ me->max_count = ALLOC_CHUNK;
(void)memset(m, 0, sizeof(*m));
m->factor_op = FILE_FACTOR_OP_NONE;
m->cont_level = 0;
@@ -1330,12 +1677,54 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
EATAB;
#endif
+ /*
+ * Parse the type.
+ */
if (*l == 'u') {
+ /*
+ * Try it as a keyword type prefixed by "u"; match what
+ * follows the "u". If that fails, try it as an SUS
+ * integer type.
+ */
+ m->type = get_type(type_tbl, l + 1, &l);
+ if (m->type == FILE_INVALID) {
+ /*
+ * Not a keyword type; parse it as an SUS type,
+ * 'u' possibly followed by a number or C/S/L.
+ */
+ m->type = get_standard_integer_type(l, &l);
+ }
+ // It's unsigned.
+ if (m->type != FILE_INVALID)
+ m->flag |= UNSIGNED;
+ } else {
+ /*
+ * Try it as a keyword type. If that fails, try it as
+ * an SUS integer type if it begins with "d" or as an
+ * SUS string type if it begins with "s". In any case,
+ * it's not unsigned.
+ */
+ m->type = get_type(type_tbl, l, &l);
+ if (m->type == FILE_INVALID) {
+ /*
+ * Not a keyword type; parse it as an SUS type,
+ * either 'd' possibly followed by a number or
+ * C/S/L, or just 's'.
+ */
+ if (*l == 'd')
+ m->type = get_standard_integer_type(l, &l);
+ else if (*l == 's' && !isalpha((unsigned char)l[1])) {
+ m->type = FILE_STRING;
++l;
- m->flag |= UNSIGNED;
+ }
+ }
}
- m->type = get_type(l, &l);
+ if (m->type == FILE_INVALID) {
+ /* Not found - try it as a special keyword. */
+ m->type = get_type(special_tbl, l, &l);
+ }
+
if (m->type == FILE_INVALID) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "type `%s' invalid", l);
@@ -1412,6 +1801,9 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
case CHAR_TEXTTEST:
m->str_flags |= STRING_TEXTTEST;
break;
+ case CHAR_TRIM:
+ m->str_flags |= STRING_TRIM;
+ break;
case CHAR_PSTRING_1_LE:
if (m->type != FILE_PSTRING)
goto bad;
@@ -1549,8 +1941,6 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
return -1;
}
m->mimetype[0] = '\0'; /* initialise MIME type to none */
- if (m->cont_level == 0)
- ++(*nmentryp); /* make room for next */
return 0;
}
@@ -1714,6 +2104,7 @@ check_format_type(const char *ptr, int type)
case 'i':
case 'd':
case 'u':
+ case 'o':
case 'x':
case 'X':
return 0;
@@ -1728,6 +2119,7 @@ check_format_type(const char *ptr, int type)
case 'i':
case 'd':
case 'u':
+ case 'o':
case 'x':
case 'X':
return 0;
@@ -1744,6 +2136,7 @@ check_format_type(const char *ptr, int type)
case 'c':
case 'd':
case 'u':
+ case 'o':
case 'x':
case 'X':
return 0;
@@ -1872,6 +2265,8 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action)
case FILE_PSTRING:
case FILE_REGEX:
case FILE_SEARCH:
+ case FILE_NAME:
+ case FILE_USE:
*p = getstr(ms, m, *p, action == FILE_COMPILE);
if (*p == NULL) {
if (ms->flags & MAGIC_CHECK)
@@ -2180,29 +2575,31 @@ eatsize(const char **p)
/*
* handle a compiled file.
- * return -1 = error
- * return 1 = memory structure you can free
- * return 3 = bundled library from PHP
*/
-private int
-apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
- const char *fn)
+
+private struct magic_map *
+apprentice_map(struct magic_set *ms, const char *fn)
{
uint32_t *ptr;
- uint32_t version;
+ uint32_t version, entries, nentries;
int needsbyteswap;
char *dbname = NULL;
- void *mm = NULL;
- int ret = 0;
+ struct magic_map *map;
+ size_t i;
php_stream *stream = NULL;
php_stream_statbuf st;
TSRMLS_FETCH();
+ if ((map = CAST(struct magic_map *, ecalloc(1, sizeof(*map)))) == NULL) {
+ file_oomem(ms, sizeof(*map));
+ efree(map);
+ goto error;
+ }
+
if (fn == NULL) {
- mm = (void *)&php_magic_database;
- ret = 3;
+ map->p = (void *)&php_magic_database;
goto internal_loaded;
}
@@ -2211,14 +2608,14 @@ apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
return to give apprentice_load() a chance. */
if (php_stream_stat_path_ex(fn, 0, &st, NULL) == SUCCESS) {
if (st.sb.st_mode & S_IFDIR) {
- goto error2;
+ goto error;
}
}
#endif
dbname = mkdbname(ms, fn, 0);
if (dbname == NULL)
- goto error2;
+ goto error;
#if PHP_API_VERSION < 20100412
stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
@@ -2227,37 +2624,40 @@ apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
#endif
if (!stream) {
- goto error2;
+ goto error;
}
if (php_stream_stat(stream, &st) < 0) {
file_error(ms, errno, "cannot stat `%s'", dbname);
- goto error1;
+ goto error;
}
if (st.sb.st_size < 8) {
file_error(ms, 0, "file `%s' is too small", dbname);
- goto error1;
+ goto error;
}
- mm = emalloc((size_t)st.sb.st_size);
- if (php_stream_read(stream, mm, (size_t)st.sb.st_size) != (size_t)st.sb.st_size) {
+ map->len = (size_t)st.sb.st_size;
+ if ((map->p = CAST(void *, emalloc(map->len))) == NULL) {
+ file_oomem(ms, map->len);
+ goto error;
+ }
+ if (php_stream_read(stream, map->p, (size_t)st.sb.st_size) != (size_t)st.sb.st_size) {
file_badread(ms);
- ret = 1;
- goto error1;
+ goto error;
}
- ret = 1;
+ map->len = 0;
+#define RET 1
php_stream_close(stream);
stream = NULL;
internal_loaded:
- *magicp = mm;
- ptr = (uint32_t *)(void *)*magicp;
+ ptr = (uint32_t *)(void *)map->p;
if (*ptr != MAGICNO) {
if (swap4(*ptr) != MAGICNO) {
file_error(ms, 0, "bad magic in `%s'", dbname);
- goto error1;
+ goto error;
}
needsbyteswap = 1;
} else
@@ -2270,67 +2670,81 @@ internal_loaded:
file_error(ms, 0, "File %d.%d supports only version %d magic "
"files. `%s' is version %d", FILE_VERSION_MAJOR, patchlevel,
VERSIONNO, dbname, version);
- goto error1;
+ goto error;
}
/* php_magic_database is a const, performing writes will segfault. This is for big-endian
machines only, PPC and Sparc specifically. Consider static variable or MINIT in
future. */
if (needsbyteswap && fn == NULL) {
- mm = emalloc(sizeof(php_magic_database));
- mm = memcpy(mm, php_magic_database, sizeof(php_magic_database));
- *magicp = mm;
- ret = 1;
- }
-
- if (fn == NULL) {
- *nmagicp = (sizeof(php_magic_database) / sizeof(struct magic));
- } else {
- *nmagicp = (uint32_t)(st.sb.st_size / sizeof(struct magic));
+ map->p = emalloc(sizeof(php_magic_database));
+ map->p = memcpy(map->p, php_magic_database, sizeof(php_magic_database));
+ }
+
+ if (NULL != fn) {
+ nentries = (uint32_t)(st.sb.st_size / sizeof(struct magic));
+ entries = (uint32_t)(st.sb.st_size / sizeof(struct magic));
+ if ((off_t)(entries * sizeof(struct magic)) != st.sb.st_size) {
+ file_error(ms, 0, "Size of `%s' %llu is not a multiple of %zu",
+ dbname, (unsigned long long)st.sb.st_size,
+ sizeof(struct magic));
+ goto error;
+ }
}
- if (*nmagicp > 0) {
- (*nmagicp)--;
+ map->magic[0] = CAST(struct magic *, map->p) + 1;
+ nentries = 0;
+ for (i = 0; i < MAGIC_SETS; i++) {
+ if (needsbyteswap)
+ map->nmagic[i] = swap4(ptr[i + 2]);
+ else
+ map->nmagic[i] = ptr[i + 2];
+ if (i != MAGIC_SETS - 1)
+ map->magic[i + 1] = map->magic[i] + map->nmagic[i];
+ nentries += map->nmagic[i];
}
- (*magicp)++;
- if (needsbyteswap) {
- byteswap(*magicp, *nmagicp);
+ if (NULL != fn && entries != nentries + 1) {
+ file_error(ms, 0, "Inconsistent entries in `%s' %u != %u",
+ dbname, entries, nentries + 1);
+ goto error;
}
+ if (needsbyteswap)
+ for (i = 0; i < MAGIC_SETS; i++)
+ byteswap(map->magic[i], map->nmagic[i]);
+
if (dbname) {
efree(dbname);
}
- return ret;
+ return map;
-error1:
+error:
if (stream) {
php_stream_close(stream);
}
-
- if (mm && ret == 1) {
- efree(mm);
- } else {
- *magicp = NULL;
- *nmagicp = 0;
- }
-error2:
+ apprentice_unmap(map);
if (dbname) {
efree(dbname);
}
- return -1;
+ return NULL;
}
private const uint32_t ar[] = {
MAGICNO, VERSIONNO
};
+
/*
* handle an mmaped file.
*/
private int
-apprentice_compile(struct magic_set *ms, struct magic **magicp,
- uint32_t *nmagicp, const char *fn)
+apprentice_compile(struct magic_set *ms, struct magic_map *map, const char *fn)
{
+ static const size_t nm = sizeof(*map->nmagic) * MAGIC_SETS;
+ static const size_t m = sizeof(**map->magic);
+ int fd = -1;
+ size_t len;
char *dbname;
int rv = -1;
+ uint32_t i;
php_stream *stream;
TSRMLS_FETCH();
@@ -2352,22 +2766,34 @@ apprentice_compile(struct magic_set *ms, struct magic **magicp,
goto out;
}
- if (php_stream_write(stream, (char *)ar, sizeof(ar)) != (ssize_t)sizeof(ar)) {
+ if (write(fd, ar, sizeof(ar)) != (ssize_t)sizeof(ar)) {
file_error(ms, errno, "error writing `%s'", dbname);
goto out;
}
+ if (php_stream_write(stream, map->nmagic, nm) != (ssize_t)nm) {
+ file_error(ms, errno, "error writing `%s'", dbname);
+ goto out;
+ }
+
+ assert(nm + sizeof(ar) < m);
+
if (php_stream_seek(stream,(off_t)sizeof(struct magic), SEEK_SET) != sizeof(struct magic)) {
file_error(ms, errno, "error seeking `%s'", dbname);
goto out;
}
- if (php_stream_write(stream, (char *)*magicp, (sizeof(struct magic) * *nmagicp) != (ssize_t)(sizeof(struct magic) * *nmagicp))) {
- file_error(ms, errno, "error writing `%s'", dbname);
- goto out;
+ for (i = 0; i < MAGIC_SETS; i++) {
+ len = m * map->nmagic[i];
+ if (php_stream_write(stream, map->magic[i], len) != (ssize_t)len) {
+ file_error(ms, errno, "error writing `%s'", dbname);
+ goto out;
+ }
}
- php_stream_close(stream);
+ if (stream) {
+ php_stream_close(stream);
+ }
rv = 0;
out:
@@ -2564,3 +2990,30 @@ file_pstring_get_length(const struct magic *m, const char *s)
return len;
}
+
+protected int
+file_magicfind(struct magic_set *ms, const char *name, struct mlist *v)
+{
+ uint32_t i, j;
+ struct mlist *mlist, *ml;
+
+ mlist = ms->mlist[1];
+
+ for (ml = mlist->next; ml != mlist; ml = ml->next) {
+ struct magic *ma = ml->magic;
+ uint32_t nma = ml->nmagic;
+ for (i = 0; i < nma; i++) {
+ if (ma[i].type != FILE_NAME)
+ continue;
+ if (strcmp(ma[i].value.s, name) == 0) {
+ v->magic = &ma[i];
+ for (j = i + 1; j < nma; j++)
+ if (ma[j].cont_level == 0)
+ break;
+ v->nmagic = j - i;
+ return 0;
+ }
+ }
+ }
+ return -1;
+}
diff --git a/ext/fileinfo/libmagic/ascmagic.c b/ext/fileinfo/libmagic/ascmagic.c
index 9d8d15024f..209009764e 100644
--- a/ext/fileinfo/libmagic/ascmagic.c
+++ b/ext/fileinfo/libmagic/ascmagic.c
@@ -35,7 +35,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: ascmagic.c,v 1.84 2011/12/08 12:38:24 rrt Exp $")
+FILE_RCSID("@(#)$File: ascmagic.c,v 1.85 2012/08/09 16:33:15 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -134,13 +134,15 @@ file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf,
goto done;
}
- if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) {
+ if (ulen > 0 && (ms->flags & MAGIC_NO_CHECK_SOFT) == 0) {
/* Convert ubuf to UTF-8 and try text soft magic */
/* malloc size is a conservative overestimate; could be
improved, or at least realloced after conversion. */
mlen = ulen * 6;
- utf8_buf = emalloc(mlen);
-
+ if ((utf8_buf = CAST(unsigned char *, emalloc(mlen))) == NULL) {
+ file_oomem(ms, mlen);
+ goto done;
+ }
if ((utf8_end = encode_utf8(utf8_buf, mlen, ubuf, ulen))
== NULL)
goto done;
@@ -209,6 +211,7 @@ file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf,
case 0:
if (file_printf(ms, ", ") == -1)
goto done;
+ break;
case -1:
goto done;
default:
diff --git a/ext/fileinfo/libmagic/cdf.c b/ext/fileinfo/libmagic/cdf.c
index 7efa43e00f..dd7177ed90 100644
--- a/ext/fileinfo/libmagic/cdf.c
+++ b/ext/fileinfo/libmagic/cdf.c
@@ -35,7 +35,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: cdf.c,v 1.50 2012/02/20 22:35:29 christos Exp $")
+FILE_RCSID("@(#)$File: cdf.c,v 1.53 2013/02/26 16:20:42 christos Exp $")
#endif
#include <assert.h>
@@ -278,10 +278,10 @@ cdf_check_stream_offset(const cdf_stream_t *sst, const cdf_header_t *h,
const char *b = (const char *)sst->sst_tab;
const char *e = ((const char *)p) + tail;
(void)&line;
- if (e >= b && (size_t)(e - b) < CDF_SEC_SIZE(h) * sst->sst_len)
+ if (e >= b && (size_t)(e - b) <= CDF_SEC_SIZE(h) * sst->sst_len)
return 0;
- DPRINTF(("%d: offset begin %p end %p %" SIZE_T_FORMAT "u"
- " >= %" SIZE_T_FORMAT "u [%" SIZE_T_FORMAT "u %"
+ DPRINTF(("%d: offset begin %p < end %p || %" SIZE_T_FORMAT "u"
+ " > %" SIZE_T_FORMAT "u [%" SIZE_T_FORMAT "u %"
SIZE_T_FORMAT "u]\n", line, b, e, (size_t)(e - b),
CDF_SEC_SIZE(h) * sst->sst_len, CDF_SEC_SIZE(h), sst->sst_len));
errno = EFTYPE;
diff --git a/ext/fileinfo/libmagic/cdf.h b/ext/fileinfo/libmagic/cdf.h
index 84a2f95207..70eb519465 100644
--- a/ext/fileinfo/libmagic/cdf.h
+++ b/ext/fileinfo/libmagic/cdf.h
@@ -39,6 +39,8 @@
#include <winsock2.h>
#define timespec timeval
#define tv_nsec tv_usec
+#define asctime_r php_asctime_r
+#define ctime_r php_ctime_r
#endif
#ifdef __DJGPP__
#define timespec timeval
@@ -312,7 +314,7 @@ int cdf_print_elapsed_time(char *, size_t, cdf_timestamp_t);
uint16_t cdf_tole2(uint16_t);
uint32_t cdf_tole4(uint32_t);
uint64_t cdf_tole8(uint64_t);
-char *cdf_ctime(const time_t *);
+char *cdf_ctime(const time_t *, char *);
#ifdef CDF_DEBUG
void cdf_dump_header(const cdf_header_t *);
diff --git a/ext/fileinfo/libmagic/cdf_time.c b/ext/fileinfo/libmagic/cdf_time.c
index b75aa5be98..84b14b86f1 100644
--- a/ext/fileinfo/libmagic/cdf_time.c
+++ b/ext/fileinfo/libmagic/cdf_time.c
@@ -27,7 +27,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: cdf_time.c,v 1.11 2011/12/13 13:48:41 christos Exp $")
+FILE_RCSID("@(#)$File: cdf_time.c,v 1.12 2012/05/15 17:14:36 christos Exp $")
#endif
#include <time.h>
@@ -104,6 +104,7 @@ cdf_timestamp_to_timespec(struct timeval *ts, cdf_timestamp_t t)
#endif
int rdays;
+ /* XXX 5.14 at least introdced 100 ns intervals, this is to do */
/* Time interval, in microseconds */
ts->tv_usec = (t % CDF_TIME_PREC) * CDF_TIME_PREC;
@@ -166,15 +167,13 @@ cdf_timespec_to_timestamp(cdf_timestamp_t *t, const struct timeval *ts)
}
char *
-cdf_ctime(const time_t *sec)
+cdf_ctime(const time_t *sec, char *buf)
{
- static char ctbuf[26];
- char *ptr = ctime(sec);
+ char *ptr = ctime_r(sec, buf);
if (ptr != NULL)
- return ptr;
- (void)snprintf(ctbuf, sizeof(ctbuf), "*Bad* 0x%16.16llx\n",
- (long long)*sec);
- return ctbuf;
+ return buf;
+ (void)snprintf(buf, 26, "*Bad* 0x%16.16llx\n", (long long)*sec);
+ return buf;
}
@@ -183,12 +182,13 @@ int
main(int argc, char *argv[])
{
struct timeval ts;
+ char buf[25];
static const cdf_timestamp_t tst = 0x01A5E403C2D59C00ULL;
static const char *ref = "Sat Apr 23 01:30:00 1977";
char *p, *q;
cdf_timestamp_to_timespec(&ts, tst);
- p = cdf_ctime(&ts.tv_sec);
+ p = cdf_ctime(&ts.tv_sec, buf);
if ((q = strchr(p, '\n')) != NULL)
*q = '\0';
if (strcmp(ref, p) != 0)
diff --git a/ext/fileinfo/libmagic/compress.c b/ext/fileinfo/libmagic/compress.c
index 4d349cd419..9f26dd03d8 100644
--- a/ext/fileinfo/libmagic/compress.c
+++ b/ext/fileinfo/libmagic/compress.c
@@ -36,7 +36,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: compress.c,v 1.68 2011/12/08 12:38:24 rrt Exp $")
+FILE_RCSID("@(#)$File: compress.c,v 1.70 2012/11/07 17:54:48 christos Exp $")
#endif
#include "magic.h"
@@ -188,9 +188,9 @@ sread(int fd, void *buf, size_t n, int canbepipe)
goto nocheck;
#ifdef FIONREAD
- if ((canbepipe && (ioctl(fd, FIONREAD, &t) == -1)) || (t == 0)) {
+ if (canbepipe && (ioctl(fd, FIONREAD, &t) == -1 || t == 0)) {
#ifdef FD_ZERO
- int cnt;
+ ssize_t cnt;
for (cnt = 0;; cnt++) {
fd_set check;
struct timeval tout = {0, 100 * 1000};
@@ -247,9 +247,6 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf,
char buf[4096];
ssize_t r;
int tfd;
-#ifdef HAVE_MKSTEMP
- int te;
-#endif
(void)strlcpy(buf, "/tmp/file.XXXXXX", sizeof buf);
#ifndef HAVE_MKSTEMP
@@ -261,10 +258,13 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf,
errno = r;
}
#else
- tfd = mkstemp(buf);
- te = errno;
- (void)unlink(buf);
- errno = te;
+ {
+ int te;
+ tfd = mkstemp(buf);
+ te = errno;
+ (void)unlink(buf);
+ errno = te;
+ }
#endif
if (tfd == -1) {
file_error(ms, errno,
@@ -345,7 +345,9 @@ uncompressgzipped(struct magic_set *ms, const unsigned char *old,
if (data_start >= n)
return 0;
- *newch = (unsigned char *)emalloc(HOWMANY + 1));
+ if ((*newch = CAST(unsigned char *, emalloc(HOWMANY + 1))) == NULL) {
+ return 0;
+ }
/* XXX: const castaway, via strchr */
z.next_in = (Bytef *)strchr((const char *)old + data_start,
diff --git a/ext/fileinfo/libmagic/elfclass.h b/ext/fileinfo/libmagic/elfclass.h
index 2e7741b3fc..010958a429 100644
--- a/ext/fileinfo/libmagic/elfclass.h
+++ b/ext/fileinfo/libmagic/elfclass.h
@@ -59,7 +59,8 @@
(off_t)elf_getu(swap, elfhdr.e_shoff),
elf_getu16(swap, elfhdr.e_shnum),
(size_t)elf_getu16(swap, elfhdr.e_shentsize),
- fsize, &flags, elf_getu16(swap, elfhdr.e_machine)) == -1)
+ fsize, &flags, elf_getu16(swap, elfhdr.e_machine),
+ (int)elf_getu16(swap, elfhdr.e_shstrndx)) == -1)
return -1;
break;
diff --git a/ext/fileinfo/libmagic/file.h b/ext/fileinfo/libmagic/file.h
index 3879b47564..19b6872b49 100644
--- a/ext/fileinfo/libmagic/file.h
+++ b/ext/fileinfo/libmagic/file.h
@@ -27,7 +27,7 @@
*/
/*
* file.h - definitions for file(1) program
- * @(#)$File: file.h,v 1.135 2011/09/20 15:30:14 christos Exp $
+ * @(#)$File: file.h,v 1.144 2013/02/18 15:40:59 christos Exp $
*/
#ifndef __file_h__
@@ -90,10 +90,18 @@
#endif
#define private static
+
+#if HAVE_VISIBILITY
+#define public __attribute__ ((__visibility__("default")))
#ifndef protected
-#define protected
+#define protected __attribute__ ((__visibility__("hidden")))
#endif
+#else
#define public
+#ifndef protected
+#define protected
+#endif
+#endif
#ifndef __arraycount
#define __arraycount(a) (sizeof(a) / sizeof(a[0]))
@@ -122,12 +130,13 @@
#endif
#define MAXMAGIS 8192 /* max entries in any one magic file
or directory */
-#define MAXDESC 64 /* max leng of text description/MIME type */
-#define MAXstring 64 /* max leng of "string" types */
+#define MAXDESC 64 /* max len of text description/MIME type */
+#define MAXMIME 80 /* max len of text MIME type */
+#define MAXstring 64 /* max len of "string" types */
#define MAGICNO 0xF11E041C
-#define VERSIONNO 8
-#define FILE_MAGICSIZE 232
+#define VERSIONNO 10
+#define FILE_MAGICSIZE 248
#define FILE_LOAD 0
#define FILE_CHECK 1
@@ -210,7 +219,12 @@ struct magic {
#define FILE_BEID3 39
#define FILE_LEID3 40
#define FILE_INDIRECT 41
-#define FILE_NAMES_SIZE 42/* size of array to contain all names */
+#define FILE_QWDATE 42
+#define FILE_LEQWDATE 43
+#define FILE_BEQWDATE 44
+#define FILE_NAME 45
+#define FILE_USE 46
+#define FILE_NAMES_SIZE 47 /* size of array to contain all names */
#define IS_LIBMAGIC_STRING(t) \
((t) == FILE_STRING || \
@@ -219,6 +233,8 @@ struct magic {
(t) == FILE_LESTRING16 || \
(t) == FILE_REGEX || \
(t) == FILE_SEARCH || \
+ (t) == FILE_NAME || \
+ (t) == FILE_USE || \
(t) == FILE_DEFAULT)
#define FILE_FMT_NONE 0
@@ -287,9 +303,9 @@ struct magic {
union VALUETYPE value; /* either number or string */
/* Words 17-32 */
char desc[MAXDESC]; /* description */
- /* Words 33-48 */
- char mimetype[MAXDESC]; /* MIME type */
- /* Words 49-50 */
+ /* Words 33-52 */
+ char mimetype[MAXMIME]; /* MIME type */
+ /* Words 53-54 */
char apple[8];
};
@@ -310,12 +326,14 @@ struct magic {
#define PSTRING_LEN \
(PSTRING_1_BE|PSTRING_2_LE|PSTRING_2_BE|PSTRING_4_LE|PSTRING_4_BE)
#define PSTRING_LENGTH_INCLUDES_ITSELF BIT(12)
+#define STRING_TRIM BIT(13)
#define CHAR_COMPACT_WHITESPACE 'W'
#define CHAR_COMPACT_OPTIONAL_WHITESPACE 'w'
#define CHAR_IGNORE_LOWERCASE 'c'
#define CHAR_IGNORE_UPPERCASE 'C'
#define CHAR_REGEX_OFFSET_START 's'
#define CHAR_TEXTTEST 't'
+#define CHAR_TRIM 'T'
#define CHAR_BINTEST 'b'
#define CHAR_PSTRING_1_BE 'B'
#define CHAR_PSTRING_1_LE 'B'
@@ -332,9 +350,7 @@ struct magic {
struct mlist {
struct magic *magic; /* array of magic entries */
uint32_t nmagic; /* number of entries in array */
- int mapped; /* allocation type: 0 => apprentice_file
- * 1 => apprentice_map + malloc
- * 2 => apprentice_map + mmap */
+ void *map; /* internal resources used by entry */
struct mlist *next, *prev;
};
@@ -354,8 +370,11 @@ struct level_info {
int last_cond; /* used for error checking by parse() */
#endif
};
+
+#define MAGIC_SETS 2
+
struct magic_set {
- struct mlist *mlist;
+ struct mlist *mlist[MAGIC_SETS]; /* list of regular entries */
struct cont {
size_t len;
struct level_info *li;
@@ -389,10 +408,14 @@ struct magic_set {
typedef unsigned long unichar;
struct stat;
-protected const char *file_fmttime(uint32_t, int);
+#define FILE_T_LOCAL 1
+#define FILE_T_WINDOWS 2
+protected const char *file_fmttime(uint64_t, int, char *);
+protected struct magic_set *file_ms_alloc(int);
+protected void file_ms_free(struct magic_set *);
protected int file_buffer(struct magic_set *, php_stream *, const char *, const void *,
size_t);
-protected int file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *stream);
+protected int file_fsmagic(struct magic_set *, const char *, struct stat *, php_stream *);
protected int file_pipe2file(struct magic_set *, int, const void *, size_t);
protected int file_replace(struct magic_set *, const char *, const char *);
protected int file_printf(struct magic_set *, const char *, ...);
@@ -415,7 +438,8 @@ protected int file_encoding(struct magic_set *, const unsigned char *, size_t,
protected int file_is_tar(struct magic_set *, const unsigned char *, size_t);
protected int file_softmagic(struct magic_set *, const unsigned char *, size_t,
int, int);
-protected struct mlist *file_apprentice(struct magic_set *, const char *, int);
+protected int file_apprentice(struct magic_set *, const char *, int);
+protected int file_magicfind(struct magic_set *, const char *, struct mlist *);
protected uint64_t file_signextend(struct magic_set *, struct magic *,
uint64_t);
protected void file_delmagic(struct magic *, int type, size_t entries);
diff --git a/ext/fileinfo/libmagic/fsmagic.c b/ext/fileinfo/libmagic/fsmagic.c
index a762e593de..d1381bd2d5 100644
--- a/ext/fileinfo/libmagic/fsmagic.c
+++ b/ext/fileinfo/libmagic/fsmagic.c
@@ -32,7 +32,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: fsmagic.c,v 1.64 2011/08/14 09:03:12 christos Exp $")
+FILE_RCSID("@(#)$File: fsmagic.c,v 1.67 2013/03/17 15:43:20 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -92,16 +92,19 @@ handle_mime(struct magic_set *ms, int mime, const char *str)
protected int
file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *stream)
{
+ int ret, did = 0;
int mime = ms->flags & MAGIC_MIME;
TSRMLS_FETCH();
if (ms->flags & MAGIC_APPLE)
return 0;
- if (!fn && !stream) {
+ if (fn == NULL && !stream) {
return 0;
}
+#define COMMA (did++ ? ", " : "")
+
if (stream) {
php_stream_statbuf ssb;
if (php_stream_stat(stream, &ssb) < 0) {
@@ -122,20 +125,21 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *
}
}
+ ret = 1;
if (!mime) {
#ifdef S_ISUID
if (sb->st_mode & S_ISUID)
- if (file_printf(ms, "setuid ") == -1)
+ if (file_printf(ms, "%ssetuid", COMMA) == -1)
return -1;
#endif
#ifdef S_ISGID
if (sb->st_mode & S_ISGID)
- if (file_printf(ms, "setgid ") == -1)
+ if (file_printf(ms, "%ssetgid", COMMA) == -1)
return -1;
#endif
#ifdef S_ISVTX
if (sb->st_mode & S_ISVTX)
- if (file_printf(ms, "sticky ") == -1)
+ if (file_printf(ms, "%ssticky", COMMA) == -1)
return -1;
#endif
}
@@ -150,6 +154,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *
* are block special files and go on to the next file.
*/
if ((ms->flags & MAGIC_DEVICES) != 0) {
+ ret = 0;
break;
}
if (mime) {
@@ -158,18 +163,18 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *
} else {
# ifdef HAVE_STAT_ST_RDEV
# ifdef dv_unit
- if (file_printf(ms, "character special (%d/%d/%d)",
- major(sb->st_rdev), dv_unit(sb->st_rdev),
+ if (file_printf(ms, "%scharacter special (%d/%d/%d)",
+ COMMA, major(sb->st_rdev), dv_unit(sb->st_rdev),
dv_subunit(sb->st_rdev)) == -1)
return -1;
# else
- if (file_printf(ms, "character special (%ld/%ld)",
- (long)major(sb->st_rdev), (long)minor(sb->st_rdev))
- == -1)
+ if (file_printf(ms, "%scharacter special (%ld/%ld)",
+ COMMA, (long)major(sb->st_rdev),
+ (long)minor(sb->st_rdev)) == -1)
return -1;
# endif
# else
- if (file_printf(ms, "character special") == -1)
+ if (file_printf(ms, "%scharacter special", COMMA) == -1)
return -1;
# endif
}
@@ -184,18 +189,18 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *
if (mime) {
if (handle_mime(ms, mime, "fifo") == -1)
return -1;
- } else if (file_printf(ms, "fifo (named pipe)") == -1)
+ } else if (file_printf(ms, "%sfifo (named pipe)", COMMA) == -1)
return -1;
- return 1;
+ break;
#endif
#ifdef S_IFDOOR
case S_IFDOOR:
if (mime) {
if (handle_mime(ms, mime, "door") == -1)
return -1;
- } else if (file_printf(ms, "door") == -1)
+ } else if (file_printf(ms, "%sdoor", COMMA) == -1)
return -1;
- return 1;
+ break;
#endif
#ifdef S_IFLNK
case S_IFLNK:
@@ -213,40 +218,40 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *
if (mime) {
if (handle_mime(ms, mime, "socket") == -1)
return -1;
- } else if (file_printf(ms, "socket") == -1)
+ } else if (file_printf(ms, "%ssocket", COMMA) == -1)
return -1;
- return 1;
+ break;
#endif
#endif
-
case S_IFREG:
- break;
-
- default:
- file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
- return -1;
- /*NOTREACHED*/
- }
-
/*
* regular file, check next possibility
*
* If stat() tells us the file has zero length, report here that
* the file is empty, so we can skip all the work of opening and
* reading the file.
- * But if the -s option has been given, we skip this optimization,
- * since on some systems, stat() reports zero size for raw disk
- * partitions. (If the block special device really has zero length,
- * the fact that it is empty will be detected and reported correctly
- * when we read the file.)
+ * But if the -s option has been given, we skip this
+ * optimization, since on some systems, stat() reports zero
+ * size for raw disk partitions. (If the block special device
+ * really has zero length, the fact that it is empty will be
+ * detected and reported correctly when we read the file.)
*/
if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
if (mime) {
if (handle_mime(ms, mime, "x-empty") == -1)
return -1;
- } else if (file_printf(ms, "empty") == -1)
+ } else if (file_printf(ms, "%sempty", COMMA) == -1)
return -1;
- return 1;
+ break;
}
- return 0;
+ ret = 0;
+ break;
+
+ default:
+ file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
+ return -1;
+ /*NOTREACHED*/
+ }
+
+ return ret;
}
diff --git a/ext/fileinfo/libmagic/funcs.c b/ext/fileinfo/libmagic/funcs.c
index 2b379291e4..9c0d2bdb7c 100644
--- a/ext/fileinfo/libmagic/funcs.c
+++ b/ext/fileinfo/libmagic/funcs.c
@@ -27,7 +27,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: funcs.c,v 1.60 2011/12/08 12:38:24 rrt Exp $")
+FILE_RCSID("@(#)$File: funcs.c,v 1.61 2012/10/30 23:11:51 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -191,7 +191,7 @@ file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const
&code, &code_mime, &type);
}
-#if defined(__EMX__)
+#ifdef __EMX__
if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) {
switch (file_os2_apptype(ms, inname, buf, nb)) {
case -1:
@@ -307,7 +307,7 @@ file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const
protected int
file_reset(struct magic_set *ms)
{
- if (ms->mlist == NULL) {
+ if (ms->mlist[0] == NULL) {
file_error(ms, 0, "no magic files loaded");
return -1;
}
@@ -335,7 +335,7 @@ file_reset(struct magic_set *ms)
protected const char *
file_getbuffer(struct magic_set *ms)
{
- char *pbuf, *op, *np;
+ char *op, *np;
size_t psize, len;
if (ms->event_flags & EVENT_HAD_ERR)
@@ -353,8 +353,10 @@ file_getbuffer(struct magic_set *ms)
return NULL;
}
psize = len * 4 + 1;
- pbuf = erealloc(ms->o.pbuf, psize);
- ms->o.pbuf = pbuf;
+ if ((ms->o.pbuf = CAST(char *, erealloc(ms->o.pbuf, psize))) == NULL) {
+ file_oomem(ms, psize);
+ return NULL;
+ }
#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
{
@@ -413,7 +415,13 @@ file_check_mem(struct magic_set *ms, unsigned int level)
if (level >= ms->c.len) {
len = (ms->c.len += 20) * sizeof(*ms->c.li);
- ms->c.li = (ms->c.li == NULL) ? emalloc(len) : erealloc(ms->c.li, len);
+ ms->c.li = CAST(struct level_info *, (ms->c.li == NULL) ?
+ emalloc(len) :
+ erealloc(ms->c.li, len));
+ if (ms->c.li == NULL) {
+ file_oomem(ms, len);
+ return -1;
+ }
}
ms->c.li[level].got_match = 0;
#ifdef ENABLE_CONDITIONALS
@@ -445,11 +453,7 @@ file_replace(struct magic_set *ms, const char *pat, const char *rep)
ZVAL_STRINGL(patt, pat, strlen(pat), 0);
opts |= PCRE_MULTILINE;
convert_libmagic_pattern(patt, opts);
-#if (PHP_MAJOR_VERSION < 6)
if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(patt), Z_STRLEN_P(patt) TSRMLS_CC)) == NULL) {
-#else
- if ((pce = pcre_get_compiled_regex_cache(IS_STRING, Z_STRVAL_P(patt), Z_STRLEN_P(patt) TSRMLS_CC)) == NULL) {
-#endif
zval_dtor(patt);
FREE_ZVAL(patt);
return -1;
diff --git a/ext/fileinfo/libmagic/magic.c b/ext/fileinfo/libmagic/magic.c
index b4818aed55..15fd6be77f 100644
--- a/ext/fileinfo/libmagic/magic.c
+++ b/ext/fileinfo/libmagic/magic.c
@@ -28,7 +28,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: magic.c,v 1.74 2011/05/26 01:27:59 christos Exp $")
+FILE_RCSID("@(#)$File: magic.c,v 1.78 2013/01/07 18:20:19 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -110,6 +110,10 @@ get_default_magic(void)
if ((home = getenv("HOME")) == NULL)
return MAGIC;
+ if (asprintf(&hmagicpath, "%s/.magic.mgc", home) < 0)
+ return MAGIC;
+ if (stat(hmagicpath, &st) == -1) {
+ free(hmagicpath);
if (asprintf(&hmagicpath, "%s/.magic", home) < 0)
return MAGIC;
if (stat(hmagicpath, &st) == -1)
@@ -121,6 +125,7 @@ get_default_magic(void)
if (access(hmagicpath, R_OK) == -1)
goto out;
}
+ }
if (asprintf(&default_magic, "%s:%s", hmagicpath, MAGIC) < 0)
goto out;
@@ -221,46 +226,7 @@ magic_getpath(const char *magicfile, int action)
public struct magic_set *
magic_open(int flags)
{
- struct magic_set *ms;
-
- ms = ecalloc((size_t)1, sizeof(struct magic_set));
-
- if (magic_setflags(ms, flags) == -1) {
- errno = EINVAL;
- goto free;
- }
-
- ms->o.buf = ms->o.pbuf = NULL;
-
- ms->c.li = emalloc((ms->c.len = 10) * sizeof(*ms->c.li));
-
- ms->event_flags = 0;
- ms->error = -1;
- ms->mlist = NULL;
- ms->file = "unknown";
- ms->line = 0;
- return ms;
-free:
- efree(ms);
- return NULL;
-}
-
-private void
-free_mlist(struct mlist *mlist)
-{
- struct mlist *ml;
-
- if (mlist == NULL)
- return;
-
- for (ml = mlist->next; ml != mlist;) {
- struct mlist *next = ml->next;
- struct magic *mg = ml->magic;
- file_delmagic(mg, ml->mapped, ml->nmagic);
- efree(ml);
- ml = next;
- }
- efree(ml);
+ return file_ms_alloc(flags);
}
private int
@@ -284,19 +250,9 @@ unreadable_info(struct magic_set *ms, mode_t md, const char *file)
public void
magic_close(struct magic_set *ms)
{
- if (ms->mlist) {
- free_mlist(ms->mlist);
- }
- if (ms->o.pbuf) {
- efree(ms->o.pbuf);
- }
- if (ms->o.buf) {
- efree(ms->o.buf);
- }
- if (ms->c.li) {
- efree(ms->c.li);
- }
- efree(ms);
+ if (ms == NULL)
+ return;
+ file_ms_free(ms);
}
/*
@@ -305,30 +261,26 @@ magic_close(struct magic_set *ms)
public int
magic_load(struct magic_set *ms, const char *magicfile)
{
- struct mlist *ml = file_apprentice(ms, magicfile, FILE_LOAD);
- if (ml) {
- free_mlist(ms->mlist);
- ms->mlist = ml;
- return 0;
- }
+ if (ms == NULL)
return -1;
+ return file_apprentice(ms, magicfile, FILE_LOAD);
}
public int
magic_compile(struct magic_set *ms, const char *magicfile)
{
- struct mlist *ml = file_apprentice(ms, magicfile, FILE_COMPILE);
- free_mlist(ml);
- return ml ? 0 : -1;
+ if (ms == NULL)
+ return -1;
+ return file_apprentice(ms, magicfile, FILE_COMPILE);
}
public int
magic_list(struct magic_set *ms, const char *magicfile)
{
- struct mlist *ml = file_apprentice(ms, magicfile, FILE_LIST);
- free_mlist(ml);
- return ml ? 0 : -1;
+ if (ms == NULL)
+ return -1;
+ return file_apprentice(ms, magicfile, FILE_LIST);
}
private void
@@ -368,6 +320,8 @@ close_and_restore(const struct magic_set *ms, const char *name, int fd,
public const char *
magic_descriptor(struct magic_set *ms, int fd)
{
+ if (ms == NULL)
+ return NULL;
return file_or_stream(ms, NULL, NULL);
}
@@ -377,12 +331,16 @@ magic_descriptor(struct magic_set *ms, int fd)
public const char *
magic_file(struct magic_set *ms, const char *inname)
{
+ if (ms == NULL)
+ return NULL;
return file_or_stream(ms, inname, NULL);
}
public const char *
magic_stream(struct magic_set *ms, php_stream *stream)
{
+ if (ms == NULL)
+ return NULL;
return file_or_stream(ms, NULL, stream);
}
@@ -469,6 +427,8 @@ done:
public const char *
magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
{
+ if (ms == NULL)
+ return NULL;
if (file_reset(ms) == -1)
return NULL;
/*
@@ -484,18 +444,24 @@ magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
public const char *
magic_error(struct magic_set *ms)
{
+ if (ms == NULL)
+ return "Magic database is not open";
return (ms->event_flags & EVENT_HAD_ERR) ? ms->o.buf : NULL;
}
public int
magic_errno(struct magic_set *ms)
{
+ if (ms == NULL)
+ return EINVAL;
return (ms->event_flags & EVENT_HAD_ERR) ? ms->error : 0;
}
public int
magic_setflags(struct magic_set *ms, int flags)
{
+ if (ms == NULL)
+ return -1;
#if !defined(HAVE_UTIME) && !defined(HAVE_UTIMES)
if (flags & MAGIC_PRESERVE_ATIME)
return -1;
@@ -503,3 +469,9 @@ magic_setflags(struct magic_set *ms, int flags)
ms->flags = flags;
return 0;
}
+
+public int
+magic_version(void)
+{
+ return MAGIC_VERSION;
+}
diff --git a/ext/fileinfo/libmagic/magic.h b/ext/fileinfo/libmagic/magic.h
index 9996c48d6c..7785a4a39f 100644
--- a/ext/fileinfo/libmagic/magic.h
+++ b/ext/fileinfo/libmagic/magic.h
@@ -74,6 +74,8 @@
#define MAGIC_NO_CHECK_FORTRAN 0x000000 /* Don't check ascii/fortran */
#define MAGIC_NO_CHECK_TROFF 0x000000 /* Don't check ascii/troff */
+#define MAGIC_VERSION 514 /* This implementation */
+
#ifdef __cplusplus
extern "C" {
@@ -92,6 +94,7 @@ const char *magic_buffer(magic_t, const void *, size_t);
const char *magic_error(magic_t);
int magic_setflags(magic_t, int);
+int magic_version(void);
int magic_load(magic_t, const char *);
int magic_compile(magic_t, const char *);
int magic_list(magic_t, const char *);
diff --git a/ext/fileinfo/libmagic/patchlevel.h b/ext/fileinfo/libmagic/patchlevel.h
index f4afed6abe..3a7255fa85 100644
--- a/ext/fileinfo/libmagic/patchlevel.h
+++ b/ext/fileinfo/libmagic/patchlevel.h
@@ -1,11 +1,15 @@
#define FILE_VERSION_MAJOR 5
-#define patchlevel 11
+#define patchlevel 14
/*
* Patchlevel file for Ian Darwin's MAGIC command.
* $File: patchlevel.h,v 1.68 2008/03/22 21:39:43 christos Exp $
*
* $Log$
+ * Revision 1.7 2013/03/26 22:27:12 ab
+ * Update libmagic to 5.14
+ *
+ * $Log$
* Revision 1.6 2012/03/26 21:01:37 ab
* Update libmagic to 5.11
*
diff --git a/ext/fileinfo/libmagic/print.c b/ext/fileinfo/libmagic/print.c
index 8370f50c28..fff258b7ee 100644
--- a/ext/fileinfo/libmagic/print.c
+++ b/ext/fileinfo/libmagic/print.c
@@ -35,7 +35,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: print.c,v 1.71 2011/09/20 15:28:09 christos Exp $")
+FILE_RCSID("@(#)$File: print.c,v 1.76 2013/02/26 18:25:00 christos Exp $")
#endif /* lint */
#include <stdio.h>
@@ -47,6 +47,11 @@ FILE_RCSID("@(#)$File: print.c,v 1.71 2011/09/20 15:28:09 christos Exp $")
#endif
#include <time.h>
+#ifdef PHP_WIN32
+# define asctime_r php_asctime_r
+# define ctime_r php_ctime_r
+#endif
+
#define SZOF(a) (sizeof(a) / sizeof(a[0]))
/*VARARGS*/
@@ -67,14 +72,20 @@ file_magwarn(struct magic_set *ms, const char *f, ...)
}
protected const char *
-file_fmttime(uint32_t v, int local)
+file_fmttime(uint64_t v, int flags, char *buf)
{
char *pp;
time_t t = (time_t)v;
struct tm *tm;
- if (local) {
- pp = ctime(&t);
+ if (flags & FILE_T_WINDOWS) {
+ struct timeval ts;
+ cdf_timestamp_to_timespec(&ts, t);
+ t = ts.tv_sec;
+ }
+
+ if (flags & FILE_T_LOCAL) {
+ pp = ctime_r(&t, buf);
} else {
#ifndef HAVE_DAYLIGHT
private int daylight = 0;
@@ -96,7 +107,7 @@ file_fmttime(uint32_t v, int local)
tm = gmtime(&t);
if (tm == NULL)
goto out;
- pp = asctime(tm);
+ pp = asctime_r(tm, buf);
}
if (pp == NULL)
@@ -104,5 +115,5 @@ file_fmttime(uint32_t v, int local)
pp[strcspn(pp, "\n")] = '\0';
return pp;
out:
- return "*Invalid time*";
+ return strcpy(buf, "*Invalid time*");
}
diff --git a/ext/fileinfo/libmagic/readcdf.c b/ext/fileinfo/libmagic/readcdf.c
index 0c28ffbfa8..3abcc2e62e 100644
--- a/ext/fileinfo/libmagic/readcdf.c
+++ b/ext/fileinfo/libmagic/readcdf.c
@@ -26,7 +26,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: readcdf.c,v 1.29 2012/02/20 20:04:58 christos Exp $")
+FILE_RCSID("@(#)$File: readcdf.c,v 1.33 2012/06/20 21:52:36 christos Exp $")
#endif
#include <stdlib.h>
@@ -129,12 +129,12 @@ cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info,
case CDF_FILETIME:
tp = info[i].pi_tp;
if (tp != 0) {
+ char tbuf[64];
#if defined(PHP_WIN32) && _MSC_VER <= 1500
if (tp < 1000000000000000i64) {
#else
if (tp < 1000000000000000LL) {
#endif
- char tbuf[64];
cdf_print_elapsed_time(tbuf,
sizeof(tbuf), tp);
if (NOTMIME(ms) && file_printf(ms,
@@ -145,7 +145,7 @@ cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info,
if (cdf_timestamp_to_timespec(&ts, tp) == -1) {
return -1;
}
- c = cdf_ctime(&ts.tv_sec);
+ c = cdf_ctime(&ts.tv_sec, tbuf);
if ((ec = strchr(c, '\n')) != NULL)
*ec = '\0';
@@ -295,10 +295,14 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
d = &dir.dir_tab[j];
for (k = 0; k < sizeof(name); k++)
name[k] = (char)cdf_tole2(d->d_name[k]);
- if (strstr(name, "WordDocument") == 0) {
+ if (strstr(name, "WordDocument") != 0) {
str = "msword";
break;
}
+ if (strstr(name, "PowerPoint") != 0) {
+ str = "vnd.ms-powerpoint";
+ break;
+ }
}
if (file_printf(ms, "application/%s", str) == -1)
return -1;
@@ -315,13 +319,19 @@ out1:
free(sat.sat_tab);
out0:
if (i != 1) {
- if (i == -1)
- if (file_printf(ms, "Composite Document File V2 Document")
- == -1)
+ if (i == -1) {
+ if (NOTMIME(ms)) {
+ if (file_printf(ms,
+ "Composite Document File V2 Document") == -1)
return -1;
if (*expn)
if (file_printf(ms, ", %s%s", corrupt, expn) == -1)
return -1;
+ } else {
+ if (file_printf(ms, "application/CDFV2-corrupt") == -1)
+ return -1;
+ }
+ }
i = 1;
}
return i;
diff --git a/ext/fileinfo/libmagic/readelf.c b/ext/fileinfo/libmagic/readelf.c
index f18f7d2294..1c3845fc6b 100644
--- a/ext/fileinfo/libmagic/readelf.c
+++ b/ext/fileinfo/libmagic/readelf.c
@@ -27,7 +27,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: readelf.c,v 1.90 2011/08/23 08:01:12 christos Exp $")
+FILE_RCSID("@(#)$File: readelf.c,v 1.97 2013/03/06 03:35:30 christos Exp $")
#endif
#ifdef BUILTIN_ELF
@@ -139,9 +139,9 @@ getu64(int swap, uint64_t value)
? (void *) &sh32 \
: (void *) &sh64)
#define xsh_sizeof (clazz == ELFCLASS32 \
- ? sizeof sh32 \
- : sizeof sh64)
-#define xsh_size (clazz == ELFCLASS32 \
+ ? sizeof(sh32) \
+ : sizeof(sh64))
+#define xsh_size (size_t)(clazz == ELFCLASS32 \
? elf_getu32(swap, sh32.sh_size) \
: elf_getu64(swap, sh64.sh_size))
#define xsh_offset (off_t)(clazz == ELFCLASS32 \
@@ -150,12 +150,15 @@ getu64(int swap, uint64_t value)
#define xsh_type (clazz == ELFCLASS32 \
? elf_getu32(swap, sh32.sh_type) \
: elf_getu32(swap, sh64.sh_type))
+#define xsh_name (clazz == ELFCLASS32 \
+ ? elf_getu32(swap, sh32.sh_name) \
+ : elf_getu32(swap, sh64.sh_name))
#define xph_addr (clazz == ELFCLASS32 \
? (void *) &ph32 \
: (void *) &ph64)
#define xph_sizeof (clazz == ELFCLASS32 \
- ? sizeof ph32 \
- : sizeof ph64)
+ ? sizeof(ph32) \
+ : sizeof(ph64))
#define xph_type (clazz == ELFCLASS32 \
? elf_getu32(swap, ph32.p_type) \
: elf_getu32(swap, ph64.p_type))
@@ -357,7 +360,7 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
#endif
private size_t
-donote(struct magic_set *ms, unsigned char *nbuf, size_t offset, size_t size,
+donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
int clazz, int swap, size_t align, int *flags)
{
Elf32_Nhdr nh32;
@@ -367,6 +370,7 @@ donote(struct magic_set *ms, unsigned char *nbuf, size_t offset, size_t size,
int os_style = -1;
#endif
uint32_t namesz, descsz;
+ unsigned char *nbuf = CAST(unsigned char *, vbuf);
(void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
offset += xnh_sizeof;
@@ -415,6 +419,10 @@ donote(struct magic_set *ms, unsigned char *nbuf, size_t offset, size_t size,
(FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID))
goto core;
+ if (namesz == 5 && strcmp((char *)&nbuf[noff], "SuSE") == 0 &&
+ xnh_type == NT_GNU_VERSION && descsz == 2) {
+ file_printf(ms, ", for SuSE %d.%d", nbuf[doff], nbuf[doff + 1]);
+ }
if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
xnh_type == NT_GNU_VERSION && descsz == 16) {
uint32_t desc[4];
@@ -456,13 +464,14 @@ donote(struct magic_set *ms, unsigned char *nbuf, size_t offset, size_t size,
if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
xnh_type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) {
- uint32_t desc[5], i;
- if (file_printf(ms, ", BuildID[%s]=0x", descsz == 16 ? "md5/uuid" :
+ uint8_t desc[20];
+ uint32_t i;
+ if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" :
"sha1") == -1)
return size;
(void)memcpy(desc, &nbuf[doff], descsz);
- for (i = 0; i < descsz >> 2; i++)
- if (file_printf(ms, "%.8x", desc[i]) == -1)
+ for (i = 0; i < descsz; i++)
+ if (file_printf(ms, "%02x", desc[i]) == -1)
return size;
*flags |= FLAGS_DID_BUILD_ID;
}
@@ -841,15 +850,16 @@ static const cap_desc_t cap_desc_386[] = {
private int
doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
- size_t size, off_t fsize, int *flags, int mach)
+ size_t size, off_t fsize, int *flags, int mach, int strtab)
{
Elf32_Shdr sh32;
Elf64_Shdr sh64;
int stripped = 1;
void *nbuf;
- off_t noff, coff;
+ off_t noff, coff, name_off;
uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */
uint64_t cap_sf1 = 0; /* SunOS 5.x software capabilites */
+ char name[50];
if (size != xsh_sizeof) {
if (file_printf(ms, ", corrupted section header size") == -1)
diff --git a/ext/fileinfo/libmagic/softmagic.c b/ext/fileinfo/libmagic/softmagic.c
index f9c2836dd2..c69fdb5a3e 100644
--- a/ext/fileinfo/libmagic/softmagic.c
+++ b/ext/fileinfo/libmagic/softmagic.c
@@ -32,7 +32,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: softmagic.c,v 1.147 2011/11/05 15:44:22 rrt Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.165 2013/03/07 02:22:24 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -48,16 +48,18 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.147 2011/11/05 15:44:22 rrt Exp $")
private int match(struct magic_set *, struct magic *, uint32_t,
- const unsigned char *, size_t, int, int);
+ const unsigned char *, size_t, size_t, int, int, int, int, int *, int *,
+ int *);
private int mget(struct magic_set *, const unsigned char *,
- struct magic *, size_t, unsigned int, int);
+ struct magic *, size_t, size_t, unsigned int, int, int, int, int, int *,
+ int *, int *);
private int magiccheck(struct magic_set *, struct magic *);
private int32_t mprint(struct magic_set *, struct magic *);
private int32_t moffset(struct magic_set *, struct magic *);
private void mdebug(uint32_t, const char *, size_t);
private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
const unsigned char *, uint32_t, size_t, size_t);
-private int mconvert(struct magic_set *, struct magic *);
+private int mconvert(struct magic_set *, struct magic *, int);
private int print_sep(struct magic_set *, int);
private int handle_annotation(struct magic_set *, struct magic *);
private void cvt_8(union VALUETYPE *, const struct magic *);
@@ -75,10 +77,11 @@ file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
int mode, int text)
{
struct mlist *ml;
- int rv;
- for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
- if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, mode,
- text)) != 0)
+ int rv, printed_something = 0, need_separator = 0;
+ for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next)
+ if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode,
+ text, 0, 0, &printed_something, &need_separator,
+ NULL)) != 0)
return rv;
return 0;
@@ -113,16 +116,19 @@ file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
*/
private int
match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
- const unsigned char *s, size_t nbytes, int mode, int text)
+ const unsigned char *s, size_t nbytes, size_t offset, int mode, int text,
+ int flip, int recursion_level, int *printed_something, int *need_separator,
+ int *returnval)
{
uint32_t magindex = 0;
unsigned int cont_level = 0;
- int need_separator = 0;
- int returnval = 0, e; /* if a match is found it is set to 1*/
+ int returnvalv = 0, e; /* if a match is found it is set to 1*/
int firstline = 1; /* a flag to print X\n X\n- X */
- int printed_something = 0;
int print = (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0;
+ if (returnval == NULL)
+ returnval = &returnvalv;
+
if (file_check_mem(ms, cont_level) == -1)
return -1;
@@ -130,14 +136,17 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
int flush = 0;
struct magic *m = &magic[magindex];
+ if (m->type != FILE_NAME)
if ((IS_LIBMAGIC_STRING(m->type) &&
- ((text && (m->str_flags & (STRING_BINTEST | STRING_TEXTTEST)) == STRING_BINTEST) ||
- (!text && (m->str_flags & (STRING_TEXTTEST | STRING_BINTEST)) == STRING_TEXTTEST))) ||
+#define FLT (STRING_BINTEST | STRING_TEXTTEST)
+ ((text && (m->str_flags & FLT) == STRING_BINTEST) ||
+ (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) ||
(m->flag & mode) != mode) {
/* Skip sub-tests */
- while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) {
- magindex++;
- }
+ while (magindex + 1 < nmagic &&
+ magic[magindex + 1].cont_level != 0 &&
+ ++magindex)
+ continue;
continue; /* Skip to next top-level test*/
}
@@ -145,7 +154,9 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
ms->line = m->lineno;
/* if main entry matches, print it... */
- switch (mget(ms, s, m, nbytes, cont_level, text)) {
+ switch (mget(ms, s, m, nbytes, offset, cont_level, mode, text,
+ flip, recursion_level + 1, printed_something,
+ need_separator, returnval)) {
case -1:
return -1;
case 0:
@@ -153,7 +164,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
break;
default:
if (m->type == FILE_INDIRECT)
- returnval = 1;
+ *returnval = 1;
switch (magiccheck(ms, m)) {
case -1:
@@ -172,21 +183,23 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
* main entry didn't match,
* flush its continuations
*/
- while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) {
+ while (magindex < nmagic - 1 &&
+ magic[magindex + 1].cont_level != 0)
magindex++;
- }
continue;
}
- if ((e = handle_annotation(ms, m)) != 0)
+ if ((e = handle_annotation(ms, m)) != 0) {
+ *returnval = 1;
return e;
+ }
/*
* If we are going to print something, we'll need to print
* a blank before we print something else.
*/
if (*m->desc) {
- need_separator = 1;
- printed_something = 1;
+ *need_separator = 1;
+ *printed_something = 1;
if (print_sep(ms, firstline) == -1)
return -1;
}
@@ -201,8 +214,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
if (file_check_mem(ms, ++cont_level) == -1)
return -1;
- while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) {
- magindex++;
+ while (magindex + 1 < nmagic && magic[magindex+1].cont_level != 0 &&
+ ++magindex) {
m = &magic[magindex];
ms->line = m->lineno; /* for messages */
@@ -217,7 +230,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
}
ms->offset = m->offset;
if (m->flag & OFFADD) {
- ms->offset += ms->c.li[cont_level - 1].off;
+ ms->offset +=
+ ms->c.li[cont_level - 1].off;
}
#ifdef ENABLE_CONDITIONALS
@@ -227,7 +241,9 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
continue;
}
#endif
- switch (mget(ms, s, m, nbytes, cont_level, text)) {
+ switch (mget(ms, s, m, nbytes, offset, cont_level, mode,
+ text, flip, recursion_level + 1, printed_something,
+ need_separator, returnval)) {
case -1:
return -1;
case 0:
@@ -237,7 +253,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
break;
default:
if (m->type == FILE_INDIRECT)
- returnval = 1;
+ *returnval = 1;
flush = 0;
break;
}
@@ -260,15 +276,17 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
ms->c.li[cont_level].got_match = 0;
break;
}
- if ((e = handle_annotation(ms, m)) != 0)
+ if ((e = handle_annotation(ms, m)) != 0) {
+ *returnval = 1;
return e;
+ }
/*
* If we are going to print something,
* make sure that we have a separator first.
*/
if (*m->desc) {
- if (!printed_something) {
- printed_something = 1;
+ if (!*printed_something) {
+ *printed_something = 1;
if (print_sep(ms, firstline)
== -1)
return -1;
@@ -281,13 +299,13 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
* this item isn't empty.
*/
/* space if previous printed */
- if (need_separator
+ if (*need_separator
&& ((m->flag & NOSPACE) == 0)
&& *m->desc) {
if (print &&
file_printf(ms, " ") == -1)
return -1;
- need_separator = 0;
+ *need_separator = 0;
}
if (print && mprint(ms, m) == -1)
return -1;
@@ -295,7 +313,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
ms->c.li[cont_level].off = moffset(ms, m);
if (*m->desc)
- need_separator = 1;
+ *need_separator = 1;
/*
* If we see any continuations
@@ -307,16 +325,16 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
break;
}
}
- if (printed_something) {
+ if (*printed_something) {
firstline = 0;
if (print)
- returnval = 1;
+ *returnval = 1;
}
- if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) {
- return returnval; /* don't keep searching */
+ if ((ms->flags & MAGIC_CONTINUE) == 0 && *printed_something) {
+ return *returnval; /* don't keep searching */
}
}
- return returnval; /* This is hit if -k is set or there is no match */
+ return *returnval; /* This is hit if -k is set or there is no match */
}
private int
@@ -345,7 +363,7 @@ mprint(struct magic_set *ms, struct magic *m)
float vf;
double vd;
int64_t t = 0;
- char buf[128];
+ char buf[128], tbuf[26];
union VALUETYPE *p = &ms->ms_value;
switch (m->type) {
@@ -430,11 +448,30 @@ mprint(struct magic_set *ms, struct magic *m)
t = ms->offset + m->vallen;
}
else {
+ char *str = p->s;
+
+ /* compute t before we mangle the string? */
+ t = ms->offset + strlen(str);
+
if (*m->value.s == '\0')
- p->s[strcspn(p->s, "\n")] = '\0';
- if (file_printf(ms, m->desc, p->s) == -1)
+ str[strcspn(str, "\n")] = '\0';
+
+ if (m->str_flags & STRING_TRIM) {
+ char *last;
+ while (isspace((unsigned char)*str))
+ str++;
+ last = str;
+ while (*last)
+ last++;
+ --last;
+ while (isspace((unsigned char)*last))
+ last--;
+ *++last = '\0';
+ }
+
+ if (file_printf(ms, m->desc, str) == -1)
return -1;
- t = ms->offset + strlen(p->s);
+
if (m->type == FILE_PSTRING)
t += file_pstring_length_size(m);
}
@@ -444,25 +481,26 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BEDATE:
case FILE_LEDATE:
case FILE_MEDATE:
- if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
+ if (file_printf(ms, m->desc, file_fmttime(p->l, FILE_T_LOCAL,
+ tbuf)) == -1)
return -1;
- t = ms->offset + sizeof(time_t);
+ t = ms->offset + sizeof(uint32_t);
break;
case FILE_LDATE:
case FILE_BELDATE:
case FILE_LELDATE:
case FILE_MELDATE:
- if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
+ if (file_printf(ms, m->desc, file_fmttime(p->l, 0, tbuf)) == -1)
return -1;
- t = ms->offset + sizeof(time_t);
+ t = ms->offset + sizeof(uint32_t);
break;
case FILE_QDATE:
case FILE_BEQDATE:
case FILE_LEQDATE:
- if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q,
- 1)) == -1)
+ if (file_printf(ms, m->desc, file_fmttime(p->q, FILE_T_LOCAL,
+ tbuf)) == -1)
return -1;
t = ms->offset + sizeof(uint64_t);
break;
@@ -470,8 +508,16 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_QLDATE:
case FILE_BEQLDATE:
case FILE_LEQLDATE:
- if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q,
- 0)) == -1)
+ if (file_printf(ms, m->desc, file_fmttime(p->q, 0, tbuf)) == -1)
+ return -1;
+ t = ms->offset + sizeof(uint64_t);
+ break;
+
+ case FILE_QWDATE:
+ case FILE_BEQWDATE:
+ case FILE_LEQWDATE:
+ if (file_printf(ms, m->desc, file_fmttime(p->q, FILE_T_WINDOWS,
+ tbuf)) == -1)
return -1;
t = ms->offset + sizeof(uint64_t);
break;
@@ -521,7 +567,10 @@ mprint(struct magic_set *ms, struct magic *m)
int rval;
cp = estrndup((const char *)ms->search.s, ms->search.rm_len);
-
+ if (cp == NULL) {
+ file_oomem(ms, ms->search.rm_len);
+ return -1;
+ }
rval = file_printf(ms, m->desc, cp);
efree(cp);
@@ -551,6 +600,8 @@ mprint(struct magic_set *ms, struct magic *m)
break;
case FILE_INDIRECT:
+ case FILE_USE:
+ case FILE_NAME:
t = ms->offset;
break;
@@ -598,7 +649,7 @@ moffset(struct magic_set *ms, struct magic *m)
p->s[strcspn(p->s, "\n")] = '\0';
t = CAST(uint32_t, (ms->offset + strlen(p->s)));
if (m->type == FILE_PSTRING)
- t += file_pstring_length_size(m);
+ t += (uint32_t)file_pstring_length_size(m);
return t;
}
@@ -606,13 +657,13 @@ moffset(struct magic_set *ms, struct magic *m)
case FILE_BEDATE:
case FILE_LEDATE:
case FILE_MEDATE:
- return CAST(int32_t, (ms->offset + sizeof(time_t)));
+ return CAST(int32_t, (ms->offset + sizeof(uint32_t)));
case FILE_LDATE:
case FILE_BELDATE:
case FILE_LELDATE:
case FILE_MELDATE:
- return CAST(int32_t, (ms->offset + sizeof(time_t)));
+ return CAST(int32_t, (ms->offset + sizeof(uint32_t)));
case FILE_QDATE:
case FILE_BEQDATE:
@@ -658,6 +709,56 @@ moffset(struct magic_set *ms, struct magic *m)
}
}
+private int
+cvt_flip(int type, int flip)
+{
+ if (flip == 0)
+ return type;
+ switch (type) {
+ case FILE_BESHORT:
+ return FILE_LESHORT;
+ case FILE_BELONG:
+ return FILE_LELONG;
+ case FILE_BEDATE:
+ return FILE_LEDATE;
+ case FILE_BELDATE:
+ return FILE_LELDATE;
+ case FILE_BEQUAD:
+ return FILE_LEQUAD;
+ case FILE_BEQDATE:
+ return FILE_LEQDATE;
+ case FILE_BEQLDATE:
+ return FILE_LEQLDATE;
+ case FILE_BEQWDATE:
+ return FILE_LEQWDATE;
+ case FILE_LESHORT:
+ return FILE_BESHORT;
+ case FILE_LELONG:
+ return FILE_BELONG;
+ case FILE_LEDATE:
+ return FILE_BEDATE;
+ case FILE_LELDATE:
+ return FILE_BELDATE;
+ case FILE_LEQUAD:
+ return FILE_BEQUAD;
+ case FILE_LEQDATE:
+ return FILE_BEQDATE;
+ case FILE_LEQLDATE:
+ return FILE_BEQLDATE;
+ case FILE_LEQWDATE:
+ return FILE_BEQWDATE;
+ case FILE_BEFLOAT:
+ return FILE_LEFLOAT;
+ case FILE_LEFLOAT:
+ return FILE_BEFLOAT;
+ case FILE_BEDOUBLE:
+ return FILE_LEDOUBLE;
+ case FILE_LEDOUBLE:
+ return FILE_BEDOUBLE;
+ default:
+ return type;
+ }
+}
#define DO_CVT(fld, cast) \
if (m->num_mask) \
switch (m->mask_op & FILE_OPS_MASK) { \
@@ -748,11 +849,11 @@ cvt_double(union VALUETYPE *p, const struct magic *m)
* (unless you have a better idea)
*/
private int
-mconvert(struct magic_set *ms, struct magic *m)
+mconvert(struct magic_set *ms, struct magic *m, int flip)
{
union VALUETYPE *p = &ms->ms_value;
- switch (m->type) {
+ switch (cvt_flip(m->type, flip)) {
case FILE_BYTE:
cvt_8(p, m);
return 1;
@@ -767,6 +868,7 @@ mconvert(struct magic_set *ms, struct magic *m)
case FILE_QUAD:
case FILE_QDATE:
case FILE_QLDATE:
+ case FILE_QWDATE:
cvt_64(p, m);
return 1;
case FILE_STRING:
@@ -800,6 +902,7 @@ mconvert(struct magic_set *ms, struct magic *m)
case FILE_BEQUAD:
case FILE_BEQDATE:
case FILE_BEQLDATE:
+ case FILE_BEQWDATE:
p->q = (uint64_t)
(((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)|
((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)|
@@ -821,6 +924,7 @@ mconvert(struct magic_set *ms, struct magic *m)
case FILE_LEQUAD:
case FILE_LEQDATE:
case FILE_LEQLDATE:
+ case FILE_LEQWDATE:
p->q = (uint64_t)
(((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)|
((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)|
@@ -868,6 +972,8 @@ mconvert(struct magic_set *ms, struct magic *m)
case FILE_REGEX:
case FILE_SEARCH:
case FILE_DEFAULT:
+ case FILE_NAME:
+ case FILE_USE:
return 1;
default:
file_magerror(ms, "invalid type %d in mconvert()", m->type);
@@ -879,7 +985,7 @@ mconvert(struct magic_set *ms, struct magic *m)
private void
mdebug(uint32_t offset, const char *str, size_t len)
{
- (void) fprintf(stderr, "mget @%d: ", offset);
+ (void) fprintf(stderr, "mget/%zu @%d: ", len, offset);
file_showstr(stderr, str, len);
(void) fputc('\n', stderr);
(void) fputc('\n', stderr);
@@ -946,8 +1052,8 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
if (type == FILE_BESTRING16)
src++;
- /* check for pointer overflow */
- if (src < s) {
+ /* check that offset is within range */
+ if (offset >= nbytes) {
file_magerror(ms, "invalid offset %u in mcopy()",
offset);
return -1;
@@ -996,26 +1102,40 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
}
private int
-mget(struct magic_set *ms, const unsigned char *s,
- struct magic *m, size_t nbytes, unsigned int cont_level, int text)
+mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
+ size_t nbytes, size_t o, unsigned int cont_level, int mode, int text,
+ int flip, int recursion_level, int *printed_something,
+ int *need_separator, int *returnval)
{
- uint32_t offset = ms->offset;
+ uint32_t soffset, offset = ms->offset;
uint32_t count = m->str_range;
+ int rv, oneed_separator;
+ char *sbuf, *rbuf;
union VALUETYPE *p = &ms->ms_value;
+ struct mlist ml;
+
+ if (recursion_level >= 20) {
+ file_error(ms, 0, "recursion nesting exceeded");
+ return -1;
+ }
- if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1)
+ if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o),
+ (uint32_t)nbytes, count) == -1)
return -1;
if ((ms->flags & MAGIC_DEBUG) != 0) {
+ fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%zu, "
+ "nbytes=%zu, count=%u)\n", m->type, m->flag, offset, o,
+ nbytes, count);
mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
}
if (m->flag & INDIR) {
int off = m->in_offset;
if (m->in_op & FILE_OPINDIRECT) {
- const union VALUETYPE *q =
- ((const void *)(s + offset + off));
- switch (m->in_type) {
+ const union VALUETYPE *q = CAST(const union VALUETYPE *,
+ ((const void *)(s + offset + off)));
+ switch (cvt_flip(m->in_type, flip)) {
case FILE_BYTE:
off = q->b;
break;
@@ -1046,8 +1166,10 @@ mget(struct magic_set *ms, const unsigned char *s,
(q->hl[3]<<8)|(q->hl[2]));
break;
}
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ fprintf(stderr, "indirect offs=%u\n", off);
}
- switch (m->in_type) {
+ switch (cvt_flip(m->in_type, flip)) {
case FILE_BYTE:
if (nbytes < (offset + 1))
return 0;
@@ -1472,7 +1594,7 @@ mget(struct magic_set *ms, const unsigned char *s,
break;
}
- switch (m->in_type) {
+ switch (cvt_flip(m->in_type, flip)) {
case FILE_LEID3:
case FILE_BEID3:
offset = ((((offset >> 0) & 0x7f) << 0) |
@@ -1486,6 +1608,14 @@ mget(struct magic_set *ms, const unsigned char *s,
if (m->flag & INDIROFFADD) {
offset += ms->c.li[cont_level-1].off;
+ if (offset == 0) {
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ fprintf(stderr,
+ "indirect *zero* offset\n");
+ return 0;
+ }
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ fprintf(stderr, "indirect +offs=%u\n", offset);
}
if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
return -1;
@@ -1550,19 +1680,61 @@ mget(struct magic_set *ms, const unsigned char *s,
break;
case FILE_INDIRECT:
+ if (nbytes < offset)
+ return 0;
+ sbuf = ms->o.buf;
+ soffset = ms->offset;
+ ms->o.buf = NULL;
+ ms->offset = 0;
+ rv = file_softmagic(ms, s + offset, nbytes - offset,
+ BINTEST, text);
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv);
+ rbuf = ms->o.buf;
+ ms->o.buf = sbuf;
+ ms->offset = soffset;
+ if (rv == 1) {
if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 &&
- file_printf(ms, "%s", m->desc) == -1)
+ file_printf(ms, m->desc, offset) == -1)
return -1;
+ if (file_printf(ms, "%s", rbuf) == -1)
+ return -1;
+ free(rbuf);
+ }
+ return rv;
+
+ case FILE_USE:
if (nbytes < offset)
return 0;
- return file_softmagic(ms, s + offset, nbytes - offset,
- BINTEST, text);
+ sbuf = m->value.s;
+ if (*sbuf == '^') {
+ sbuf++;
+ flip = !flip;
+ }
+ if (file_magicfind(ms, sbuf, &ml) == -1) {
+ file_error(ms, 0, "cannot find entry `%s'", sbuf);
+ return -1;
+ }
+ oneed_separator = *need_separator;
+ if (m->flag & NOSPACE)
+ *need_separator = 0;
+ rv = match(ms, ml.magic, ml.nmagic, s, nbytes, offset + o,
+ mode, text, flip, recursion_level, printed_something,
+ need_separator, returnval);
+ if (rv != 1)
+ *need_separator = oneed_separator;
+ return rv;
+
+ case FILE_NAME:
+ if (file_printf(ms, "%s", m->desc) == -1)
+ return -1;
+ return 1;
case FILE_DEFAULT: /* nothing to check */
default:
break;
}
- if (!mconvert(ms, m))
+ if (!mconvert(ms, m, flip))
return 0;
return 1;
}
@@ -1723,6 +1895,9 @@ magiccheck(struct magic_set *ms, struct magic *m)
case FILE_QLDATE:
case FILE_BEQLDATE:
case FILE_LEQLDATE:
+ case FILE_QWDATE:
+ case FILE_BEQWDATE:
+ case FILE_LEQWDATE:
v = p->q;
break;
@@ -1851,11 +2026,7 @@ magiccheck(struct magic_set *ms, struct magic *m)
convert_libmagic_pattern(pattern, options);
l = v = 0;
-#if (PHP_MAJOR_VERSION < 6)
if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(pattern), Z_STRLEN_P(pattern) TSRMLS_CC)) == NULL) {
-#else
- if ((pce = pcre_get_compiled_regex_cache(IS_STRING, Z_STRVAL_P(pattern), Z_STRLEN_P(pattern) TSRMLS_CC)) == NULL) {
-#endif
zval_dtor(pattern);
FREE_ZVAL(pattern);
return -1;
@@ -1872,11 +2043,7 @@ magiccheck(struct magic_set *ms, struct magic *m)
haystack = estrndup(ms->search.s, ms->search.s_len);
/* match v = 0, no match v = 1 */
-#if (PHP_MAJOR_VERSION < 6)
php_pcre_match_impl(pce, haystack, ms->search.s_len, retval, subpats, 1, 1, PREG_OFFSET_CAPTURE, 0 TSRMLS_CC);
-#else
- php_pcre_match_impl(pce, IS_STRING, haystack, ms->search.s_len, retval, subpats, 1, 1, PREG_OFFSET_CAPTURE, 0 TSRMLS_CC);
-#endif
/* Free haystack */
efree(haystack);
@@ -1990,6 +2157,8 @@ magiccheck(struct magic_set *ms, struct magic *m)
break;
}
case FILE_INDIRECT:
+ case FILE_USE:
+ case FILE_NAME:
return 1;
default:
file_magerror(ms, "invalid type %d in magiccheck()", m->type);