summaryrefslogtreecommitdiff
path: root/ext/fileinfo/libmagic
diff options
context:
space:
mode:
authorAnatol Belski <ab@php.net>2019-05-30 02:18:48 +0200
committerAnatol Belski <ab@php.net>2019-05-30 02:22:40 +0200
commit622b10f06e5f9ba080b748b7b5b1807b142f27fd (patch)
treef03fc1e3e906ba884c2a32881802c64df989bef4 /ext/fileinfo/libmagic
parent24e22eb31b299acf2720aab068bfce3e0bee6923 (diff)
downloadphp-git-622b10f06e5f9ba080b748b7b5b1807b142f27fd.tar.gz
Ported limagic 5.37
Diffstat (limited to 'ext/fileinfo/libmagic')
-rw-r--r--ext/fileinfo/libmagic/apprentice.c231
-rw-r--r--ext/fileinfo/libmagic/apptype.c2
-rw-r--r--ext/fileinfo/libmagic/ascmagic.c84
-rw-r--r--ext/fileinfo/libmagic/buffer.c19
-rw-r--r--ext/fileinfo/libmagic/cdf.c163
-rw-r--r--ext/fileinfo/libmagic/cdf.h4
-rw-r--r--ext/fileinfo/libmagic/cdf_time.c24
-rw-r--r--ext/fileinfo/libmagic/compress.c359
-rw-r--r--ext/fileinfo/libmagic/der.c31
-rw-r--r--ext/fileinfo/libmagic/elfclass.h14
-rw-r--r--ext/fileinfo/libmagic/encoding.c79
-rw-r--r--ext/fileinfo/libmagic/file.h26
-rw-r--r--ext/fileinfo/libmagic/fsmagic.c45
-rw-r--r--ext/fileinfo/libmagic/funcs.c196
-rw-r--r--ext/fileinfo/libmagic/is_json.c462
-rw-r--r--ext/fileinfo/libmagic/is_tar.c15
-rw-r--r--ext/fileinfo/libmagic/magic.c68
-rw-r--r--ext/fileinfo/libmagic/magic.h6
-rw-r--r--ext/fileinfo/libmagic/patchlevel.h6
-rw-r--r--ext/fileinfo/libmagic/print.c32
-rw-r--r--ext/fileinfo/libmagic/readcdf.c391
-rw-r--r--ext/fileinfo/libmagic/softmagic.c493
22 files changed, 1827 insertions, 923 deletions
diff --git a/ext/fileinfo/libmagic/apprentice.c b/ext/fileinfo/libmagic/apprentice.c
index b9bb65898c..ed3c26db2b 100644
--- a/ext/fileinfo/libmagic/apprentice.c
+++ b/ext/fileinfo/libmagic/apprentice.c
@@ -66,10 +66,11 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.270 2018/02/21 21:26:48 christos Exp $")
#define MAXMAGIC_SIZE SSIZE_MAX
#endif
-#define EATAB {while (isascii((unsigned char) *l) && \
- isspace((unsigned char) *l)) ++l;}
-#define LOWCASE(l) (isupper((unsigned char) (l)) ? \
- tolower((unsigned char) (l)) : (l))
+
+#define EATAB {while (isascii(CAST(unsigned char, *l)) && \
+ isspace(CAST(unsigned char, *l))) ++l;}
+#define LOWCASE(l) (isupper(CAST(unsigned char, l)) ? \
+ tolower(CAST(unsigned char, l)) : (l))
/*
* Work around a bug in headers on Digital Unix.
* At least confirmed for: OSF1 V4.0 878
@@ -92,8 +93,8 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.270 2018/02/21 21:26:48 christos Exp $")
#define MAP_FILE 0
#endif
-#define ALLOC_CHUNK (size_t)10
-#define ALLOC_INCR (size_t)200
+#define ALLOC_CHUNK CAST(size_t, 10)
+#define ALLOC_INCR CAST(size_t, 200)
#define MAP_TYPE_USER 0
#define MAP_TYPE_MALLOC 1
@@ -275,12 +276,21 @@ get_type(const struct type_tbl_s *tbl, const char *l, const char **t)
return p->type;
}
+private off_t
+maxoff_t(void) {
+ if (/*CONSTCOND*/sizeof(off_t) == sizeof(int))
+ return CAST(off_t, INT_MAX);
+ if (/*CONSTCOND*/sizeof(off_t) == sizeof(long))
+ return CAST(off_t, LONG_MAX);
+ return 0x7fffffff;
+}
+
private int
get_standard_integer_type(const char *l, const char **t)
{
int type;
- if (isalpha((unsigned char)l[1])) {
+ if (isalpha(CAST(unsigned char, l[1]))) {
switch (l[1]) {
case 'C':
/* "dC" and "uC" */
@@ -315,7 +325,7 @@ get_standard_integer_type(const char *l, const char **t)
return FILE_INVALID;
}
l += 2;
- } else if (isdigit((unsigned char)l[1])) {
+ } else if (isdigit(CAST(unsigned char, l[1]))) {
/*
* "d{num}" and "u{num}"; we only support {num} values
* of 1, 2, 4, and 8 - the Single UNIX Specification
@@ -326,7 +336,7 @@ get_standard_integer_type(const char *l, const char **t)
* neither of them support values bigger than 8 or
* non-power-of-2 values.
*/
- if (isdigit((unsigned char)l[2])) {
+ if (isdigit(CAST(unsigned char, l[2]))) {
/* Multi-digit, so > 9 */
return FILE_INVALID;
}
@@ -410,8 +420,8 @@ apprentice_1(struct magic_set *ms, const char *fn, int action)
if (magicsize != FILE_MAGICSIZE) {
file_error(ms, 0, "magic element size %lu != %lu",
- (unsigned long)sizeof(*map->magic[0]),
- (unsigned long)FILE_MAGICSIZE);
+ CAST(unsigned long, sizeof(*map->magic[0])),
+ CAST(unsigned long, FILE_MAGICSIZE));
return -1;
}
@@ -423,7 +433,7 @@ apprentice_1(struct magic_set *ms, const char *fn, int action)
}
map = apprentice_map(ms, fn);
- if (map == (struct magic_map *)-1)
+ if (map == RCAST(struct magic_map *, -1))
return -1;
if (map == NULL) {
if (fn) {
@@ -480,7 +490,7 @@ file_ms_alloc(int flags)
struct magic_set *ms;
size_t i, len;
- if ((ms = CAST(struct magic_set *, ecalloc((size_t)1,
+ if ((ms = CAST(struct magic_set *, ecalloc(CAST(size_t, 1u),
sizeof(struct magic_set)))) == NULL)
return NULL;
@@ -546,6 +556,14 @@ mlist_alloc(void)
}
private void
+mlist_free_one(struct mlist *ml)
+{
+ if (ml->map)
+ apprentice_unmap(CAST(struct magic_map *, ml->map));
+ efree(ml);
+}
+
+private void
mlist_free(struct mlist *mlist)
{
struct mlist *ml, *next;
@@ -553,14 +571,11 @@ mlist_free(struct mlist *mlist)
if (mlist == NULL)
return;
- ml = mlist->next;
- for (ml = mlist->next; (next = ml->next) != NULL; ml = next) {
- if (ml->map)
- apprentice_unmap(CAST(struct magic_map *, ml->map));
- efree(ml);
- if (ml == mlist)
- break;
+ for (ml = mlist->next; ml != mlist; ml = next) {
+ next = ml->next;
+ mlist_free_one(ml);
}
+ mlist_free_one(mlist);
}
/* const char *fn: list of magic files and directories */
@@ -571,8 +586,7 @@ file_apprentice(struct magic_set *ms, const char *fn, int action)
int fileerr, errs = -1;
size_t i;
- if (ms->mlist[0] != NULL)
- (void)file_reset(ms, 0);
+ (void)file_reset(ms, 0);
/* XXX disabling default magic loading so the compiled in data is used */
#if 0
@@ -759,7 +773,7 @@ typesize(int type)
case FILE_LEDOUBLE:
return 8;
default:
- return (size_t)~0;
+ return CAST(size_t, ~0);
}
}
@@ -769,8 +783,9 @@ typesize(int type)
private size_t
apprentice_magic_strength(const struct magic *m)
{
-#define MULT 10
- size_t ts, v, val = 2 * MULT; /* baseline strength */
+#define MULT 10U
+ size_t ts, v;
+ ssize_t val = 2 * MULT; /* baseline strength */
switch (m->type) {
case FILE_DEFAULT: /* make sure this sorts last */
@@ -813,7 +828,7 @@ apprentice_magic_strength(const struct magic *m)
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
ts = typesize(m->type);
- if (ts == (size_t)~0)
+ if (ts == CAST(size_t, ~0))
abort();
val += ts * MULT;
break;
@@ -829,6 +844,8 @@ apprentice_magic_strength(const struct magic *m)
break;
case FILE_SEARCH:
+ if (m->vallen == 0)
+ break;
val += m->vallen * MAX(MULT / m->vallen, 1);
break;
@@ -876,9 +893,6 @@ apprentice_magic_strength(const struct magic *m)
abort();
}
- if (val == 0) /* ensure we only return 0 for FILE_DEFAULT */
- val = 1;
-
switch (m->factor_op) {
case FILE_FACTOR_OP_NONE:
break;
@@ -898,6 +912,9 @@ apprentice_magic_strength(const struct magic *m)
abort();
}
+ if (val <= 0) /* ensure we only return 0 for FILE_DEFAULT */
+ val = 1;
+
/*
* Magic entries with no description get a bonus because they depend
* on subsequent magic entries to print something.
@@ -1026,7 +1043,7 @@ set_test_type(struct magic *mstart, struct magic *m)
break;
/* binary test if pattern is not text */
- if (file_looks_utf8(m->value.us, (size_t)m->vallen, NULL,
+ if (file_looks_utf8(m->value.us, CAST(size_t, m->vallen), NULL,
NULL) <= 0)
mstart->flag |= BINTEST;
else
@@ -1076,7 +1093,7 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs,
{
char buffer[BUFSIZ + 1];
char *line = NULL;
- size_t len;
+ ssize_t len;
size_t lineno = 0;
struct magic_entry me;
@@ -1112,7 +1129,7 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs,
size_t i;
for (i = 0; bang[i].name != NULL; i++) {
- if ((size_t)(len - 2) > bang[i].len &&
+ if (CAST(size_t, len - 2) > bang[i].len &&
memcmp(bang[i].name, line + 2,
bang[i].len) == 0)
break;
@@ -1165,7 +1182,7 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs,
private int
cmpstrp(const void *p1, const void *p2)
{
- return strcmp(*(char *const *)p1, *(char *const *)p2);
+ return strcmp(*RCAST(char *const *, p1), *RCAST(char *const *, p2));
}
@@ -1191,10 +1208,10 @@ set_text_binary(struct magic_set *ms, struct magic_entry *me, uint32_t nme,
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])) &&
+ isspace(CAST(unsigned char, p[-1]))) &&
(p + len - me[i].mp->desc == MAXstring
|| (p[len] == '\0' ||
- isspace((unsigned char)p[len]))))
+ isspace(CAST(unsigned char, p[len])))))
(void)fprintf(stderr, "*** Possible "
"binary test for text type\n");
}
@@ -1327,12 +1344,14 @@ apprentice_load(struct magic_set *ms, const char *fn, int action)
filearr[files++] = estrndup(mfn, (mflen > sizeof(mfn) - 1)? sizeof(mfn) - 1: mflen);
}
php_stream_closedir(dir);
- qsort(filearr, files, sizeof(*filearr), cmpstrp);
- for (i = 0; i < files; i++) {
- load_1(ms, action, filearr[i], &errs, mset);
- efree(filearr[i]);
+ if (filearr) {
+ qsort(filearr, files, sizeof(*filearr), cmpstrp);
+ for (i = 0; i < files; i++) {
+ load_1(ms, action, filearr[i], &errs, mset);
+ efree(filearr[i]);
+ }
+ efree(filearr);
}
- efree(filearr);
} else
load_1(ms, action, fn, &errs, mset);
if (errs)
@@ -1390,12 +1409,12 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
* the sign extension must have happened.
*/
case FILE_BYTE:
- v = (signed char) v;
+ v = CAST(signed char, v);
break;
case FILE_SHORT:
case FILE_BESHORT:
case FILE_LESHORT:
- v = (short) v;
+ v = CAST(short, v);
break;
case FILE_DATE:
case FILE_BEDATE:
@@ -1412,7 +1431,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
case FILE_FLOAT:
case FILE_BEFLOAT:
case FILE_LEFLOAT:
- v = (int32_t) v;
+ v = CAST(int32_t, v);
break;
case FILE_QUAD:
case FILE_BEQUAD:
@@ -1429,7 +1448,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
case FILE_DOUBLE:
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
- v = (int64_t) v;
+ v = CAST(int64_t, v);
break;
case FILE_STRING:
case FILE_PSTRING:
@@ -1556,7 +1575,7 @@ get_cond(const char *l, const char **t)
for (p = cond_tbl; p->len; p++) {
if (strncmp(l, p->name, p->len) == 0 &&
- isspace((unsigned char)l[p->len])) {
+ isspace(CAST(unsigned char, l[p->len]))) {
if (t)
*t = l + p->len;
break;
@@ -1614,7 +1633,7 @@ parse_indirect_modifier(struct magic_set *ms, struct magic *m, const char **lp)
{
const char *l = *lp;
- while (!isspace((unsigned char)*++l))
+ while (!isspace(CAST(unsigned char, *++l)))
switch (*l) {
case CHAR_INDIRECT_RELATIVE:
m->str_flags |= INDIRECT_RELATIVE;
@@ -1640,7 +1659,7 @@ parse_op_modifier(struct magic_set *ms, struct magic *m, const char **lp,
++l;
m->mask_op |= op;
- val = (uint64_t)strtoull(l, &t, 0);
+ val = CAST(uint64_t, strtoull(l, &t, 0));
l = t;
m->num_mask = file_signextend(ms, m, val);
eatsize(&l);
@@ -1654,7 +1673,7 @@ parse_string_modifier(struct magic_set *ms, struct magic *m, const char **lp)
char *t;
int have_range = 0;
- while (!isspace((unsigned char)*++l)) {
+ while (!isspace(CAST(unsigned char, *++l))) {
switch (*l) {
case '0': case '1': case '2':
case '3': case '4': case '5':
@@ -1736,7 +1755,7 @@ parse_string_modifier(struct magic_set *ms, struct magic *m, const char **lp)
goto out;
}
/* allow multiple '/' for readability */
- if (l[1] == '/' && !isspace((unsigned char)l[2]))
+ if (l[1] == '/' && !isspace(CAST(unsigned char, l[2])))
l++;
}
if (string_modifier_check(ms, m) == -1)
@@ -1791,7 +1810,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
return -1;
}
m = &me->mp[me->cont_count - 1];
- diff = (int32_t)cont_level - (int32_t)m->cont_level;
+ diff = CAST(int32_t, cont_level) - CAST(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,
@@ -1804,7 +1823,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
file_oomem(ms, sizeof(*nm) * cnt);
return -1;
}
- me->mp = m = nm;
+ me->mp = nm;
me->max_count = CAST(uint32_t, cnt);
}
m = &me->mp[me->cont_count++];
@@ -1850,7 +1869,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
}
/* get offset, then skip over it */
- m->offset = (int32_t)strtol(l, &t, 0);
+ m->offset = CAST(int32_t, strtol(l, &t, 0));
if (l == t) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "offset `%s' invalid", l);
@@ -1909,6 +1928,12 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
case 'I':
m->in_type = FILE_BEID3;
break;
+ case 'q':
+ m->in_type = FILE_LEQUAD;
+ break;
+ case 'Q':
+ m->in_type = FILE_BEQUAD;
+ break;
default:
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms,
@@ -1931,8 +1956,8 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
m->in_op |= FILE_OPINDIRECT;
l++;
}
- if (isdigit((unsigned char)*l) || *l == '-') {
- m->in_offset = (int32_t)strtol(l, &t, 0);
+ if (isdigit(CAST(unsigned char, *l)) || *l == '-') {
+ m->in_offset = CAST(int32_t, strtol(l, &t, 0));
if (l == t) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms,
@@ -1995,7 +2020,8 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
*/
if (*l == 'd')
m->type = get_standard_integer_type(l, &l);
- else if (*l == 's' && !isalpha((unsigned char)l[1])) {
+ else if (*l == 's'
+ && !isalpha(CAST(unsigned char, l[1]))) {
m->type = FILE_STRING;
++l;
}
@@ -2085,8 +2111,8 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
break;
default:
m->reln = '='; /* the default relation */
- if (*l == 'x' && ((isascii((unsigned char)l[1]) &&
- isspace((unsigned char)l[1])) || !l[1])) {
+ if (*l == 'x' && ((isascii(CAST(unsigned char, l[1])) &&
+ isspace(CAST(unsigned char, l[1]))) || !l[1])) {
m->reln = *l;
++l;
}
@@ -2178,11 +2204,11 @@ parse_strength(struct magic_set *ms, struct magic_entry *me, const char *line)
file_magwarn(ms, "Too large factor `%lu'", factor);
goto out;
}
- if (*el && !isspace((unsigned char)*el)) {
+ if (*el && !isspace(CAST(unsigned char, *el))) {
file_magwarn(ms, "Bad factor `%s'", l);
goto out;
}
- m->factor = (uint8_t)factor;
+ m->factor = CAST(uint8_t, factor);
if (m->factor == 0 && m->factor_op == FILE_FACTOR_OP_DIV) {
file_magwarn(ms, "Cannot have factor op `%c' and factor %u",
m->factor_op, m->factor);
@@ -2213,7 +2239,7 @@ parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line,
if (buf[0] != '\0') {
len = nt ? strlen(buf) : len;
file_magwarn(ms, "Current entry already has a %s type "
- "`%.*s', new type `%s'", name, (int)len, buf, l);
+ "`%.*s', new type `%s'", name, CAST(int, len), buf, l);
return -1;
}
@@ -2234,7 +2260,7 @@ parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line,
file_magwarn(ms, "%s type `%s' truncated %"
SIZE_T_FORMAT "u", name, line, i);
} else {
- if (!isspace((unsigned char)*l) && !goodchar(*l, extra))
+ if (!isspace(CAST(unsigned char, *l)) && !goodchar(*l, extra))
file_magwarn(ms, "%s type `%s' has bad char '%c'",
name, line, *l);
if (nt)
@@ -2336,7 +2362,7 @@ check_format_type(const char *ptr, int type, const char **estr)
if (*ptr == '#')
ptr++;
#define CHECKLEN() do { \
- for (len = cnt = 0; isdigit((unsigned char)*ptr); ptr++, cnt++) \
+ for (len = cnt = 0; isdigit(CAST(unsigned char, *ptr)); ptr++, cnt++) \
len = len * 10 + (*ptr - '0'); \
if (cnt > 5 || len > 1024) \
goto toolong; \
@@ -2454,11 +2480,11 @@ check_format_type(const char *ptr, int type, const char **estr)
case FILE_FMT_STR:
if (*ptr == '-')
ptr++;
- while (isdigit((unsigned char )*ptr))
+ while (isdigit(CAST(unsigned char, *ptr)))
ptr++;
if (*ptr == '.') {
ptr++;
- while (isdigit((unsigned char )*ptr))
+ while (isdigit(CAST(unsigned char , *ptr)))
ptr++;
}
@@ -2608,7 +2634,7 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action)
return 0;
default:
errno = 0;
- ull = (uint64_t)strtoull(*p, &ep, 0);
+ ull = CAST(uint64_t, strtoull(*p, &ep, 0));
m->value.q = file_signextend(ms, m, ull);
if (*p == ep) {
file_magwarn(ms, "Unparseable number `%s'", *p);
@@ -2617,24 +2643,24 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action)
uint64_t x;
const char *q;
- if (ts == (size_t)~0) {
+ if (ts == CAST(size_t, ~0)) {
file_magwarn(ms,
"Expected numeric type got `%s'",
type_tbl[m->type].name);
}
- for (q = *p; isspace((unsigned char)*q); q++)
+ for (q = *p; isspace(CAST(unsigned char, *q)); q++)
continue;
if (*q == '-')
- ull = -(int64_t)ull;
+ ull = -CAST(int64_t, ull);
switch (ts) {
case 1:
- x = (uint64_t)(ull & ~0xffULL);
+ x = CAST(uint64_t, ull & ~0xffULL);
break;
case 2:
- x = (uint64_t)(ull & ~0xffffULL);
+ x = CAST(uint64_t, ull & ~0xffffULL);
break;
case 4:
- x = (uint64_t)(ull & ~0xffffffffULL);
+ x = CAST(uint64_t, ull & ~0xffffffffULL);
break;
case 8:
x = 0;
@@ -2674,7 +2700,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn)
int val;
while ((c = *s++) != '\0') {
- if (isspace((unsigned char) c))
+ if (isspace(CAST(unsigned char, c)))
break;
if (p >= pmax) {
file_error(ms, 0, "string too long: `%s'", origs);
@@ -2698,7 +2724,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn)
/*FALLTHROUGH*/
default:
if (warn) {
- if (isprint((unsigned char)c)) {
+ if (isprint(CAST(unsigned char, c))) {
/* Allow escaping of
* ``relations'' */
if (strchr("<>&^=!", c) == NULL
@@ -2736,7 +2762,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn)
case '!':
/* and baskslash itself */
case '\\':
- *p++ = (char) c;
+ *p++ = CAST(char, c);
break;
case 'a':
@@ -2788,7 +2814,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn)
}
else
--s;
- *p++ = (char)val;
+ *p++ = CAST(char, val);
break;
/* \x and up to 2 hex digits */
@@ -2804,18 +2830,18 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn)
--s;
} else
--s;
- *p++ = (char)val;
+ *p++ = CAST(char, val);
break;
}
} else
- *p++ = (char)c;
+ *p++ = CAST(char, c);
}
--s;
out:
*p = '\0';
m->vallen = CAST(unsigned char, (p - origp));
if (m->type == FILE_PSTRING)
- m->vallen += (unsigned char)file_pstring_length_size(m);
+ m->vallen += CAST(unsigned char, file_pstring_length_size(m));
return s;
}
@@ -2824,9 +2850,9 @@ out:
private int
hextoint(int c)
{
- if (!isascii((unsigned char) c))
+ if (!isascii(CAST(unsigned char, c)))
return -1;
- if (isdigit((unsigned char) c))
+ if (isdigit(CAST(unsigned char, c)))
return c - '0';
if ((c >= 'a') && (c <= 'f'))
return c + 10 - 'a';
@@ -2931,7 +2957,7 @@ apprentice_buf(struct magic_set *ms, struct magic *buf, size_t len)
{
struct magic_map *map;
- if ((map = CAST(struct magic_map *, ecalloc(1, sizeof(*map)))) == NULL) {
+ if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) {
file_oomem(ms, sizeof(*map));
return NULL;
}
@@ -2979,7 +3005,7 @@ apprentice_map(struct magic_set *ms, const char *fn)
return to give apprentice_load() a chance. */
if (php_stream_stat_path_ex((char *)fn, 0, &st, NULL) == SUCCESS) {
if (st.sb.st_mode & S_IFDIR) {
- return NULL;
+ goto error;
}
}
#endif
@@ -2994,27 +3020,26 @@ apprentice_map(struct magic_set *ms, const char *fn)
goto error;
}
+#ifndef PHP_WIN32
if (php_stream_stat(stream, &st) < 0) {
file_error(ms, errno, "cannot stat `%s'", dbname);
goto error;
}
- if (st.sb.st_size < 8 || st.sb.st_size > MAXMAGIC_SIZE) {
+#endif
+ if (st.sb.st_size < 8 || st.sb.st_size > maxoff_t()) {
file_error(ms, 0, "file `%s' is too %s", dbname,
st.sb.st_size < 8 ? "small" : "large");
goto error;
}
- map->len = (size_t)st.sb.st_size;
- if ((map->p = CAST(void *, emalloc(map->len))) == NULL) {
- file_oomem(ms, map->len);
- goto error;
- }
+ map->type = MAP_TYPE_MALLOC;
+ map->len = CAST(size_t, st.sb.st_size);
+ map->p = CAST(void *, emalloc(map->len));
+
if (php_stream_read(stream, map->p, (size_t)st.sb.st_size) != (size_t)st.sb.st_size) {
file_badread(ms);
goto error;
}
- map->len = 0;
-#define RET 1
php_stream_close(stream);
stream = NULL;
@@ -3122,7 +3147,7 @@ check_buffer(struct magic_set *ms, struct magic_map *map, const char *dbname)
VERSIONNO, dbname, version);
return -1;
}
- entries = (uint32_t)(map->len / sizeof(struct magic));
+ entries = CAST(uint32_t, map->len / sizeof(struct magic));
if ((entries * sizeof(struct magic)) != map->len) {
file_error(ms, 0, "Size of `%s' %" SIZE_T_FORMAT "u is not "
"a multiple of %" SIZE_T_FORMAT "u",
@@ -3239,7 +3264,7 @@ mkdbname(struct magic_set *ms, const char *fn, int strip)
q++;
/* Compatibility with old code that looked in .mime */
if (ms->flags & MAGIC_MIME) {
- spprintf(&buf, MAXPATHLEN, "%.*s.mime%s", (int)(q - fn), fn, ext);
+ spprintf(&buf, MAXPATHLEN, "%.*s.mime%s", CAST(int, q - fn), fn, ext);
#ifdef PHP_WIN32
if (VCWD_ACCESS(buf, R_OK) == 0) {
#else
@@ -3250,7 +3275,7 @@ mkdbname(struct magic_set *ms, const char *fn, int strip)
}
efree(buf);
}
- spprintf(&buf, MAXPATHLEN, "%.*s%s", (int)(q - fn), fn, ext);
+ spprintf(&buf, MAXPATHLEN, "%.*s%s", CAST(int, q - fn), fn, ext);
/* Compatibility with old code that looked in .mime */
if (strstr(fn, ".mime") != NULL)
@@ -3276,8 +3301,8 @@ private uint16_t
swap2(uint16_t sv)
{
uint16_t rv;
- uint8_t *s = (uint8_t *)(void *)&sv;
- uint8_t *d = (uint8_t *)(void *)&rv;
+ uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv));
+ uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv));
d[0] = s[1];
d[1] = s[0];
return rv;
@@ -3290,8 +3315,8 @@ private uint32_t
swap4(uint32_t sv)
{
uint32_t rv;
- uint8_t *s = (uint8_t *)(void *)&sv;
- uint8_t *d = (uint8_t *)(void *)&rv;
+ uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv));
+ uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv));
d[0] = s[3];
d[1] = s[2];
d[2] = s[1];
@@ -3306,8 +3331,8 @@ private uint64_t
swap8(uint64_t sv)
{
uint64_t rv;
- uint8_t *s = (uint8_t *)(void *)&sv;
- uint8_t *d = (uint8_t *)(void *)&rv;
+ uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv));
+ uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv));
#if 0
d[0] = s[3];
d[1] = s[2];
@@ -3337,9 +3362,9 @@ private void
bs1(struct magic *m)
{
m->cont_level = swap2(m->cont_level);
- m->offset = swap4((int32_t)m->offset);
- m->in_offset = swap4((uint32_t)m->in_offset);
- m->lineno = swap4((uint32_t)m->lineno);
+ m->offset = swap4(CAST(uint32_t, m->offset));
+ m->in_offset = swap4(CAST(uint32_t, m->in_offset));
+ m->lineno = swap4(CAST(uint32_t, m->lineno));
if (IS_LIBMAGIC_STRING(m->type)) {
m->str_range = swap4(m->str_range);
m->str_flags = swap4(m->str_flags);
@@ -3371,7 +3396,7 @@ protected size_t
file_pstring_get_length(const struct magic *m, const char *ss)
{
size_t len = 0;
- const unsigned char *s = (const unsigned char *)ss;
+ const unsigned char *s = RCAST(const unsigned char *, ss);
unsigned int s3, s2, s1, s0;
switch (m->str_flags & PSTRING_LEN) {
diff --git a/ext/fileinfo/libmagic/apptype.c b/ext/fileinfo/libmagic/apptype.c
index 6c441a4939..1bb33e41c2 100644
--- a/ext/fileinfo/libmagic/apptype.c
+++ b/ext/fileinfo/libmagic/apptype.c
@@ -27,7 +27,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: apptype.c,v 1.13 2011/09/07 21:57:15 christos Exp $")
+FILE_RCSID("@(#)$File: apptype.c,v 1.14 2018/09/09 20:33:28 christos Exp $")
#endif /* lint */
#include <stdlib.h>
diff --git a/ext/fileinfo/libmagic/ascmagic.c b/ext/fileinfo/libmagic/ascmagic.c
index 3848301c87..0bc0cce1de 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.98 2017/11/02 20:25:39 christos Exp $")
+FILE_RCSID("@(#)$File: ascmagic.c,v 1.104 2019/05/07 02:27:11 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -80,7 +80,13 @@ file_ascmagic(struct magic_set *ms, const struct buffer *b, int text)
const char *type = NULL;
bb = *b;
- bb.flen = trim_nuls(b->fbuf, b->flen);
+ bb.flen = trim_nuls(CAST(const unsigned char *, b->fbuf), b->flen);
+ /*
+ * Avoid trimming at an odd byte if the original buffer was evenly
+ * sized; this avoids losing the last character on UTF-16 LE text
+ */
+ if ((bb.flen & 1) && !(b->flen & 1))
+ bb.flen++;
/* If file doesn't look like any sort of text, give up. */
if (file_encoding(ms, &bb, &ubuf, &ulen, &code, &code_mime,
@@ -96,17 +102,18 @@ file_ascmagic(struct magic_set *ms, const struct buffer *b, int text)
}
protected int
-file_ascmagic_with_encoding(struct magic_set *ms,
+file_ascmagic_with_encoding(struct magic_set *ms,
const struct buffer *b, unichar *ubuf, size_t ulen, const char *code,
const char *type, int text)
{
struct buffer bb;
- const unsigned char *buf = b->fbuf;
+ const unsigned char *buf = CAST(const unsigned char *, b->fbuf);
size_t nbytes = b->flen;
unsigned char *utf8_buf = NULL, *utf8_end;
- size_t mlen, i;
+ size_t mlen, i, len;
int rv = -1;
int mime = ms->flags & MAGIC_MIME;
+ int need_separator = 0;
const char *subtype = NULL;
const char *subtype_mime = NULL;
@@ -121,7 +128,7 @@ file_ascmagic_with_encoding(struct magic_set *ms,
int n_nel = 0;
int executable = 0;
- size_t last_line_end = (size_t)-1;
+ size_t last_line_end = CAST(size_t, -1);
int has_long_lines = 0;
nbytes = trim_nuls(buf, nbytes);
@@ -144,12 +151,14 @@ file_ascmagic_with_encoding(struct magic_set *ms,
if ((utf8_end = encode_utf8(utf8_buf, mlen, ubuf, ulen))
== NULL)
goto done;
- buffer_init(&bb, b->fd, utf8_buf,
- (size_t)(utf8_end - utf8_buf));
+ buffer_init(&bb, b->fd, &b->st, utf8_buf,
+ CAST(size_t, utf8_end - utf8_buf));
if ((rv = file_softmagic(ms, &bb, NULL, NULL,
TEXTTEST, text)) == 0)
rv = -1;
+ else
+ need_separator = 1;
buffer_fini(&bb);
if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))) {
rv = rv == -1 ? 0 : 1;
@@ -200,8 +209,21 @@ file_ascmagic_with_encoding(struct magic_set *ms,
rv = 0;
goto done;
}
+ len = file_printedlen(ms);
if (mime) {
- if (!file_printedlen(ms) && (mime & MAGIC_MIME_TYPE) != 0) {
+ if ((mime & MAGIC_MIME_TYPE) != 0) {
+ if (len) {
+ /*
+ * Softmagic printed something, we
+ * are either done, or we need a separator
+ */
+ if ((ms->flags & MAGIC_CONTINUE) == 0) {
+ rv = 1;
+ goto done;
+ }
+ if (need_separator && file_separator(ms) == -1)
+ goto done;
+ }
if (subtype_mime) {
if (file_printf(ms, "%s", subtype_mime) == -1)
goto done;
@@ -211,7 +233,7 @@ file_ascmagic_with_encoding(struct magic_set *ms,
}
}
} else {
- if (file_printedlen(ms)) {
+ if (len) {
switch (file_replace(ms, " text$", ", ")) {
case 0:
switch (file_replace(ms, " text executable$",
@@ -325,42 +347,42 @@ encode_utf8(unsigned char *buf, size_t len, unichar *ubuf, size_t ulen)
if (ubuf[i] <= 0x7f) {
if (end - buf < 1)
return NULL;
- *buf++ = (unsigned char)ubuf[i];
+ *buf++ = CAST(unsigned char, ubuf[i]);
} else if (ubuf[i] <= 0x7ff) {
if (end - buf < 2)
return NULL;
- *buf++ = (unsigned char)((ubuf[i] >> 6) + 0xc0);
- *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, (ubuf[i] >> 6) + 0xc0);
+ *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80);
} else if (ubuf[i] <= 0xffff) {
if (end - buf < 3)
return NULL;
- *buf++ = (unsigned char)((ubuf[i] >> 12) + 0xe0);
- *buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80);
- *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, (ubuf[i] >> 12) + 0xe0);
+ *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80);
} else if (ubuf[i] <= 0x1fffff) {
if (end - buf < 4)
return NULL;
- *buf++ = (unsigned char)((ubuf[i] >> 18) + 0xf0);
- *buf++ = (unsigned char)(((ubuf[i] >> 12) & 0x3f) + 0x80);
- *buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80);
- *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, (ubuf[i] >> 18) + 0xf0);
+ *buf++ = CAST(unsigned char, ((ubuf[i] >> 12) & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80);
} else if (ubuf[i] <= 0x3ffffff) {
if (end - buf < 5)
return NULL;
- *buf++ = (unsigned char)((ubuf[i] >> 24) + 0xf8);
- *buf++ = (unsigned char)(((ubuf[i] >> 18) & 0x3f) + 0x80);
- *buf++ = (unsigned char)(((ubuf[i] >> 12) & 0x3f) + 0x80);
- *buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80);
- *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, (ubuf[i] >> 24) + 0xf8);
+ *buf++ = CAST(unsigned char, ((ubuf[i] >> 18) & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, ((ubuf[i] >> 12) & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80);
} else if (ubuf[i] <= 0x7fffffff) {
if (end - buf < 6)
return NULL;
- *buf++ = (unsigned char)((ubuf[i] >> 30) + 0xfc);
- *buf++ = (unsigned char)(((ubuf[i] >> 24) & 0x3f) + 0x80);
- *buf++ = (unsigned char)(((ubuf[i] >> 18) & 0x3f) + 0x80);
- *buf++ = (unsigned char)(((ubuf[i] >> 12) & 0x3f) + 0x80);
- *buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80);
- *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, (ubuf[i] >> 30) + 0xfc);
+ *buf++ = CAST(unsigned char, ((ubuf[i] >> 24) & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, ((ubuf[i] >> 18) & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, ((ubuf[i] >> 12) & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80);
+ *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80);
} else /* Invalid character */
return NULL;
}
diff --git a/ext/fileinfo/libmagic/buffer.c b/ext/fileinfo/libmagic/buffer.c
index d2ea9a0d61..30cef1acbd 100644
--- a/ext/fileinfo/libmagic/buffer.c
+++ b/ext/fileinfo/libmagic/buffer.c
@@ -27,7 +27,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: buffer.c,v 1.4 2018/02/21 21:26:00 christos Exp $")
+FILE_RCSID("@(#)$File: buffer.c,v 1.6 2019/05/07 02:27:11 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -41,10 +41,13 @@ FILE_RCSID("@(#)$File: buffer.c,v 1.4 2018/02/21 21:26:00 christos Exp $")
#include <sys/stat.h>
void
-buffer_init(struct buffer *b, int fd, const void *data, size_t len)
+buffer_init(struct buffer *b, int fd, const zend_stat_t *st, const void *data,
+ size_t len)
{
b->fd = fd;
- if (b->fd == -1 || zend_fstat(b->fd, &b->st) == -1)
+ if (st)
+ memcpy(&b->st, st, sizeof(b->st));
+ else if (b->fd == -1 || zend_fstat(b->fd, &b->st) == -1)
memset(&b->st, 0, sizeof(b->st));
b->fbuf = data;
b->flen = len;
@@ -56,7 +59,7 @@ buffer_init(struct buffer *b, int fd, const void *data, size_t len)
void
buffer_fini(struct buffer *b)
{
- efree(b->ebuf);
+ efree(b->ebuf);
}
int
@@ -65,13 +68,13 @@ buffer_fill(const struct buffer *bb)
struct buffer *b = CCAST(struct buffer *, bb);
if (b->elen != 0)
- return b->elen == (size_t)~0 ? -1 : 0;
+ return b->elen == CAST(size_t, ~0) ? -1 : 0;
if (!S_ISREG(b->st.st_mode))
goto out;
- b->elen = (size_t)b->st.st_size < b->flen ?
- (size_t)b->st.st_size : b->flen;
+ b->elen = CAST(size_t, b->st.st_size) < b->flen ?
+ CAST(size_t, b->st.st_size) : b->flen;
if ((b->ebuf = emalloc(b->elen)) == NULL)
goto out;
@@ -85,6 +88,6 @@ buffer_fill(const struct buffer *bb)
return 0;
out:
- b->elen = (size_t)~0;
+ b->elen = CAST(size_t, ~0);
return -1;
}
diff --git a/ext/fileinfo/libmagic/cdf.c b/ext/fileinfo/libmagic/cdf.c
index ac70e5bac1..1a6b149570 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.110 2017/12/19 00:21:21 christos Exp $")
+FILE_RCSID("@(#)$File: cdf.c,v 1.114 2019/02/20 02:35:27 christos Exp $")
#endif
#include <assert.h>
@@ -57,9 +57,7 @@ FILE_RCSID("@(#)$File: cdf.c,v 1.110 2017/12/19 00:21:21 christos Exp $")
#include <string.h>
#include <time.h>
#include <ctype.h>
-#ifdef HAVE_LIMITS_H
#include <limits.h>
-#endif
#ifndef EFTYPE
#define EFTYPE EINVAL
@@ -78,11 +76,14 @@ static union {
uint32_t u;
} cdf_bo;
-#define NEED_SWAP (cdf_bo.u == (uint32_t)0x01020304)
+#define NEED_SWAP (cdf_bo.u == CAST(uint32_t, 0x01020304))
-#define CDF_TOLE8(x) ((uint64_t)(NEED_SWAP ? _cdf_tole8(x) : (uint64_t)(x)))
-#define CDF_TOLE4(x) ((uint32_t)(NEED_SWAP ? _cdf_tole4(x) : (uint32_t)(x)))
-#define CDF_TOLE2(x) ((uint16_t)(NEED_SWAP ? _cdf_tole2(x) : (uint16_t)(x)))
+#define CDF_TOLE8(x) \
+ (CAST(uint64_t, NEED_SWAP ? _cdf_tole8(x) : CAST(uint64_t, x)))
+#define CDF_TOLE4(x) \
+ (CAST(uint32_t, NEED_SWAP ? _cdf_tole4(x) : CAST(uint32_t, x)))
+#define CDF_TOLE2(x) \
+ (CAST(uint16_t, NEED_SWAP ? _cdf_tole2(x) : CAST(uint16_t, x)))
#define CDF_TOLE(x) (/*CONSTCOND*/sizeof(x) == 2 ? \
CDF_TOLE2(CAST(uint16_t, x)) : \
(/*CONSTCOND*/sizeof(x) == 4 ? \
@@ -101,8 +102,8 @@ static uint16_t
_cdf_tole2(uint16_t sv)
{
uint16_t rv;
- uint8_t *s = (uint8_t *)(void *)&sv;
- uint8_t *d = (uint8_t *)(void *)&rv;
+ uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv));
+ uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv));
d[0] = s[1];
d[1] = s[0];
return rv;
@@ -115,8 +116,8 @@ static uint32_t
_cdf_tole4(uint32_t sv)
{
uint32_t rv;
- uint8_t *s = (uint8_t *)(void *)&sv;
- uint8_t *d = (uint8_t *)(void *)&rv;
+ uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv));
+ uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv));
d[0] = s[3];
d[1] = s[2];
d[2] = s[1];
@@ -131,8 +132,8 @@ static uint64_t
_cdf_tole8(uint64_t sv)
{
uint64_t rv;
- uint8_t *s = (uint8_t *)(void *)&sv;
- uint8_t *d = (uint8_t *)(void *)&rv;
+ uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv));
+ uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv));
d[0] = s[7];
d[1] = s[6];
d[2] = s[5];
@@ -197,15 +198,17 @@ cdf_swap_header(cdf_header_t *h)
h->h_min_size_standard_stream =
CDF_TOLE4(h->h_min_size_standard_stream);
h->h_secid_first_sector_in_short_sat =
- CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_short_sat);
+ CDF_TOLE4(CAST(uint32_t, h->h_secid_first_sector_in_short_sat));
h->h_num_sectors_in_short_sat =
CDF_TOLE4(h->h_num_sectors_in_short_sat);
h->h_secid_first_sector_in_master_sat =
- CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_master_sat);
+ CDF_TOLE4(CAST(uint32_t, h->h_secid_first_sector_in_master_sat));
h->h_num_sectors_in_master_sat =
CDF_TOLE4(h->h_num_sectors_in_master_sat);
- for (i = 0; i < __arraycount(h->h_master_sat); i++)
- h->h_master_sat[i] = CDF_TOLE4((uint32_t)h->h_master_sat[i]);
+ for (i = 0; i < __arraycount(h->h_master_sat); i++) {
+ h->h_master_sat[i] =
+ CDF_TOLE4(CAST(uint32_t, h->h_master_sat[i]));
+ }
}
void
@@ -238,15 +241,16 @@ void
cdf_swap_dir(cdf_directory_t *d)
{
d->d_namelen = CDF_TOLE2(d->d_namelen);
- d->d_left_child = CDF_TOLE4((uint32_t)d->d_left_child);
- d->d_right_child = CDF_TOLE4((uint32_t)d->d_right_child);
- d->d_storage = CDF_TOLE4((uint32_t)d->d_storage);
+ d->d_left_child = CDF_TOLE4(CAST(uint32_t, d->d_left_child));
+ d->d_right_child = CDF_TOLE4(CAST(uint32_t, d->d_right_child));
+ d->d_storage = CDF_TOLE4(CAST(uint32_t, d->d_storage));
d->d_storage_uuid[0] = CDF_TOLE8(d->d_storage_uuid[0]);
d->d_storage_uuid[1] = CDF_TOLE8(d->d_storage_uuid[1]);
d->d_flags = CDF_TOLE4(d->d_flags);
- d->d_created = CDF_TOLE8((uint64_t)d->d_created);
- d->d_modified = CDF_TOLE8((uint64_t)d->d_modified);
- d->d_stream_first_sector = CDF_TOLE4((uint32_t)d->d_stream_first_sector);
+ d->d_created = CDF_TOLE8(CAST(uint64_t, d->d_created));
+ d->d_modified = CDF_TOLE8(CAST(uint64_t, d->d_modified));
+ d->d_stream_first_sector = CDF_TOLE4(
+ CAST(uint32_t, d->d_stream_first_sector));
d->d_size = CDF_TOLE4(d->d_size);
}
@@ -305,11 +309,11 @@ static int
cdf_check_stream_offset(const cdf_stream_t *sst, const cdf_header_t *h,
const void *p, size_t tail, int line)
{
- const char *b = (const char *)sst->sst_tab;
- const char *e = ((const char *)p) + tail;
+ const char *b = RCAST(const char *, sst->sst_tab);
+ const char *e = RCAST(const char *, p) + tail;
size_t ss = cdf_check_stream(sst, h);
/*LINTED*/(void)&line;
- if (e >= b && (size_t)(e - b) <= ss * sst->sst_len)
+ if (e >= b && CAST(size_t, e - b) <= ss * sst->sst_len)
return 0;
DPRINTF(("%d: offset begin %p < end %p || %" SIZE_T_FORMAT "u"
" > %" SIZE_T_FORMAT "u [%" SIZE_T_FORMAT "u %"
@@ -322,15 +326,14 @@ cdf_check_stream_offset(const cdf_stream_t *sst, const cdf_header_t *h,
static ssize_t
cdf_read(const cdf_info_t *info, zend_off_t off, void *buf, size_t len)
{
- size_t siz = (size_t)off + len;
+ size_t siz = CAST(size_t, off + len);
- if ((zend_off_t)(off + len) != (zend_off_t)siz) {
+ if (CAST(zend_off_t, off + len) != CAST(zend_off_t, siz))
goto out;
- }
if (info->i_buf != NULL && info->i_len >= siz) {
(void)memcpy(buf, &info->i_buf[off], len);
- return (ssize_t)len;
+ return CAST(ssize_t, len);
}
if (info->i_fd == -1)
@@ -342,7 +345,7 @@ cdf_read(const cdf_info_t *info, zend_off_t off, void *buf, size_t len)
if (FINFO_READ_FUNC(info->i_fd, buf, len) != (ssize_t)len)
return -1;
- return (ssize_t)len;
+ return CAST(ssize_t, len);
out:
errno = EINVAL;
return -1;
@@ -354,7 +357,7 @@ cdf_read_header(const cdf_info_t *info, cdf_header_t *h)
char buf[512];
(void)memcpy(cdf_bo.s, "\01\02\03\04", 4);
- if (cdf_read(info, (zend_off_t)0, buf, sizeof(buf)) == -1)
+ if (cdf_read(info, CAST(zend_off_t, 0), buf, sizeof(buf)) == -1)
return -1;
cdf_unpack_header(h, buf);
cdf_swap_header(h);
@@ -385,25 +388,27 @@ ssize_t
cdf_read_sector(const cdf_info_t *info, void *buf, size_t offs, size_t len,
const cdf_header_t *h, cdf_secid_t id)
{
+ size_t ss = CDF_SEC_SIZE(h);
size_t pos = CDF_SEC_POS(h, id);
- assert(CDF_SEC_SIZE(h) == len);
- return cdf_read(info, (zend_off_t)pos, ((char *)buf) + offs, len);
+ assert(ss == len);
+ return cdf_read(info, CAST(zend_off_t, pos), RCAST(char *, buf) + offs, len);
}
ssize_t
cdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs,
size_t len, const cdf_header_t *h, cdf_secid_t id)
{
+ size_t ss = CDF_SHORT_SEC_SIZE(h);
size_t pos = CDF_SHORT_SEC_POS(h, id);
- assert(CDF_SHORT_SEC_SIZE(h) == len);
+ assert(ss == len);
if (pos + len > CDF_SEC_SIZE(h) * sst->sst_len) {
DPRINTF(("Out of bounds read %" SIZE_T_FORMAT "u > %"
SIZE_T_FORMAT "u\n",
pos + len, CDF_SEC_SIZE(h) * sst->sst_len));
goto out;
}
- (void)memcpy(((char *)buf) + offs,
- ((const char *)sst->sst_tab) + pos, len);
+ (void)memcpy(RCAST(char *, buf) + offs,
+ RCAST(const char *, sst->sst_tab) + pos, len);
return len;
out:
errno = EFTYPE;
@@ -446,7 +451,7 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat)
if (h->h_master_sat[i] < 0)
break;
if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h,
- h->h_master_sat[i]) != (ssize_t)ss) {
+ h->h_master_sat[i]) != CAST(ssize_t, ss)) {
DPRINTF(("Reading sector %d", h->h_master_sat[i]));
goto out1;
}
@@ -463,27 +468,29 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat)
DPRINTF(("Reading master sector loop limit"));
goto out3;
}
- if (cdf_read_sector(info, msa, 0, ss, h, mid) != (ssize_t)ss) {
+ if (cdf_read_sector(info, msa, 0, ss, h, mid) !=
+ CAST(ssize_t, ss)) {
DPRINTF(("Reading master sector %d", mid));
goto out2;
}
for (k = 0; k < nsatpersec; k++, i++) {
- sec = CDF_TOLE4((uint32_t)msa[k]);
+ sec = CDF_TOLE4(CAST(uint32_t, msa[k]));
if (sec < 0)
goto out;
if (i >= sat->sat_len) {
- DPRINTF(("Out of bounds reading MSA %" SIZE_T_FORMAT
- "u >= %" SIZE_T_FORMAT "u", i, sat->sat_len));
+ DPRINTF(("Out of bounds reading MSA %"
+ SIZE_T_FORMAT "u >= %" SIZE_T_FORMAT "u",
+ i, sat->sat_len));
goto out3;
}
if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h,
- sec) != (ssize_t)ss) {
+ sec) != CAST(ssize_t, ss)) {
DPRINTF(("Reading sector %d",
CDF_TOLE4(msa[k])));
goto out2;
}
}
- mid = CDF_TOLE4((uint32_t)msa[nsatpersec]);
+ mid = CDF_TOLE4(CAST(uint32_t, msa[nsatpersec]));
}
out:
sat->sat_len = i;
@@ -502,7 +509,7 @@ size_t
cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size)
{
size_t i, j;
- cdf_secid_t maxsector = (cdf_secid_t)((sat->sat_len * size)
+ cdf_secid_t maxsector = CAST(cdf_secid_t, (sat->sat_len * size)
/ sizeof(maxsector));
DPRINTF(("Chain:"));
@@ -522,7 +529,7 @@ cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size)
DPRINTF(("Sector %d >= %d\n", sid, maxsector));
goto out;
}
- sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]);
+ sid = CDF_TOLE4(CAST(uint32_t, sat->sat_tab[sid]));
}
if (i == 0) {
DPRINTF((" none, sid: %d\n", sid));
@@ -533,7 +540,7 @@ cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size)
return i;
out:
errno = EFTYPE;
- return (size_t)-1;
+ return CAST(size_t, -1);
}
int
@@ -550,7 +557,7 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h,
if (sid == CDF_SECID_END_OF_CHAIN || len == 0)
return cdf_zero_stream(scn);
- if (scn->sst_len == (size_t)-1)
+ if (scn->sst_len == CAST(size_t, -1))
goto out;
scn->sst_tab = CDF_CALLOC(scn->sst_len, ss);
@@ -569,7 +576,7 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h,
goto out;
}
if ((nr = cdf_read_sector(info, scn->sst_tab, i * ss, ss, h,
- sid)) != (ssize_t)ss) {
+ sid)) != CAST(ssize_t, ss)) {
if (i == scn->sst_len - 1 && nr > 0) {
/* Last sector might be truncated */
return 0;
@@ -577,7 +584,7 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h,
DPRINTF(("Reading long sector chain %d", sid));
goto out;
}
- sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]);
+ sid = CDF_TOLE4(CAST(uint32_t, sat->sat_tab[sid]));
}
return 0;
out:
@@ -596,7 +603,7 @@ cdf_read_short_sector_chain(const cdf_header_t *h,
scn->sst_dirlen = len;
scn->sst_ss = ss;
- if (scn->sst_len == (size_t)-1)
+ if (scn->sst_len == CAST(size_t, -1))
goto out;
scn->sst_tab = CDF_CALLOC(scn->sst_len, ss);
@@ -615,11 +622,11 @@ cdf_read_short_sector_chain(const cdf_header_t *h,
goto out;
}
if (cdf_read_short_sector(sst, scn->sst_tab, i * ss, ss, h,
- sid) != (ssize_t)ss) {
+ sid) != CAST(ssize_t, ss)) {
DPRINTF(("Reading short sector chain %d", sid));
goto out;
}
- sid = CDF_TOLE4((uint32_t)ssat->sat_tab[sid]);
+ sid = CDF_TOLE4(CAST(uint32_t, ssat->sat_tab[sid]));
}
return 0;
out:
@@ -650,7 +657,7 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h,
cdf_secid_t sid = h->h_secid_first_directory;
ns = cdf_count_chain(sat, sid, ss);
- if (ns == (size_t)-1)
+ if (ns == CAST(size_t, -1))
return -1;
nd = ss / CDF_DIRECTORY_SIZE;
@@ -671,7 +678,8 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h,
DPRINTF(("Read dir loop limit"));
goto out;
}
- if (cdf_read_sector(info, buf, 0, ss, h, sid) != (ssize_t)ss) {
+ if (cdf_read_sector(info, buf, 0, ss, h, sid) !=
+ CAST(ssize_t, ss)) {
DPRINTF(("Reading directory sector %d", sid));
goto out;
}
@@ -679,7 +687,7 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h,
cdf_unpack_dir(&dir->dir_tab[i * nd + j],
&buf[j * CDF_DIRECTORY_SIZE]);
}
- sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]);
+ sid = CDF_TOLE4(CAST(uint32_t, sat->sat_tab[sid]));
}
if (NEED_SWAP)
for (i = 0; i < dir->dir_len; i++)
@@ -704,7 +712,7 @@ cdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h,
ssat->sat_tab = NULL;
ssat->sat_len = cdf_count_chain(sat, sid, ss);
- if (ssat->sat_len == (size_t)-1)
+ if (ssat->sat_len == CAST(size_t, -1))
goto out;
ssat->sat_tab = CAST(cdf_secid_t *, CDF_CALLOC(ssat->sat_len, ss));
@@ -723,11 +731,11 @@ cdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h,
goto out;
}
if (cdf_read_sector(info, ssat->sat_tab, i * ss, ss, h, sid) !=
- (ssize_t)ss) {
+ CAST(ssize_t, ss)) {
DPRINTF(("Reading short sat sector %d", sid));
goto out1;
}
- sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]);
+ sid = CDF_TOLE4(CAST(uint32_t, sat->sat_tab[sid]));
}
return 0;
out:
@@ -777,7 +785,7 @@ cdf_namecmp(const char *d, const uint16_t *s, size_t l)
{
for (; l--; d++, s++)
if (*d != CDF_TOLE2(*s))
- return (unsigned char)*d - CDF_TOLE2(*s);
+ return CAST(unsigned char, *d) - CDF_TOLE2(*s);
return 0;
}
@@ -882,8 +890,8 @@ cdf_grow_info(cdf_property_info_t **info, size_t *maxcount, size_t incr)
size_t newcount = *maxcount + incr;
if (newcount > CDF_PROP_LIMIT) {
- DPRINTF(("exceeded property limit %zu > %zu\n",
- newcount, CDF_PROP_LIMIT));
+ DPRINTF(("exceeded property limit %" SIZE_T_FORMAT "u > %"
+ SIZE_T_FORMAT "u\n", newcount, CDF_PROP_LIMIT));
goto out;
}
inp = CAST(cdf_property_info_t *,
@@ -908,7 +916,7 @@ cdf_copy_info(cdf_property_info_t *inp, const void *p, const void *e,
if (inp->pi_type & CDF_VECTOR)
return 0;
- if ((size_t)(CAST(const char *, e) - CAST(const char *, p)) < len)
+ if (CAST(size_t, CAST(const char *, e) - CAST(const char *, p)) < len)
return 0;
(void)memcpy(&inp->pi_val, p, len);
@@ -1051,10 +1059,10 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h,
inp[i].pi_str.s_buf = CAST(const char *,
CAST(const void *, &q[o4]));
- DPRINTF(("o=%zu l=%d(%" SIZE_T_FORMAT
- "u), t=%zu s=%s\n", o4, l,
- CDF_ROUND(l, sizeof(l)), left,
- inp[i].pi_str.s_buf));
+ DPRINTF(("o=%" SIZE_T_FORMAT "u l=%d(%"
+ SIZE_T_FORMAT "u), t=%" SIZE_T_FORMAT
+ "u s=%s\n", o4, l, CDF_ROUND(l, sizeof(l)),
+ left, inp[i].pi_str.s_buf));
if (l & 1)
l++;
@@ -1094,8 +1102,9 @@ cdf_unpack_summary_info(const cdf_stream_t *sst, const cdf_header_t *h,
const cdf_summary_info_header_t *si =
CAST(const cdf_summary_info_header_t *, sst->sst_tab);
const cdf_section_declaration_t *sd =
- CAST(const cdf_section_declaration_t *, (const void *)
- ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET));
+ CAST(const cdf_section_declaration_t *, RCAST(const void *,
+ RCAST(const char *, sst->sst_tab)
+ + CDF_SECTION_DECLARATION_OFFSET));
if (cdf_check_stream_offset(sst, h, si, sizeof(*si), __LINE__) == -1 ||
cdf_check_stream_offset(sst, h, sd, sizeof(*sd), __LINE__) == -1)
@@ -1246,28 +1255,28 @@ cdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts)
int days, hours, mins, secs;
ts /= CDF_TIME_PREC;
- secs = (int)(ts % 60);
+ secs = CAST(int, ts % 60);
ts /= 60;
- mins = (int)(ts % 60);
+ mins = CAST(int, ts % 60);
ts /= 60;
- hours = (int)(ts % 24);
+ hours = CAST(int, ts % 24);
ts /= 24;
- days = (int)ts;
+ days = CAST(int, ts);
if (days) {
len += snprintf(buf + len, bufsiz - len, "%dd+", days);
- if ((size_t)len >= bufsiz)
+ if (CAST(size_t, len) >= bufsiz)
return len;
}
if (days || hours) {
len += snprintf(buf + len, bufsiz - len, "%.2d:", hours);
- if ((size_t)len >= bufsiz)
+ if (CAST(size_t, len) >= bufsiz)
return len;
}
len += snprintf(buf + len, bufsiz - len, "%.2d:", mins);
- if ((size_t)len >= bufsiz)
+ if (CAST(size_t, len) >= bufsiz)
return len;
len += snprintf(buf + len, bufsiz - len, "%.2d", secs);
@@ -1279,7 +1288,7 @@ cdf_u16tos8(char *buf, size_t len, const uint16_t *p)
{
size_t i;
for (i = 0; i < len && p[i]; i++)
- buf[i] = (char)p[i];
+ buf[i] = CAST(char, p[i]);
buf[i] = '\0';
return buf;
}
diff --git a/ext/fileinfo/libmagic/cdf.h b/ext/fileinfo/libmagic/cdf.h
index c156d6e06a..a491528189 100644
--- a/ext/fileinfo/libmagic/cdf.h
+++ b/ext/fileinfo/libmagic/cdf.h
@@ -76,9 +76,9 @@ typedef struct {
cdf_secid_t h_master_sat[436/4];
} cdf_header_t;
-#define CDF_SEC_SIZE(h) ((size_t)(1 << (h)->h_sec_size_p2))
+#define CDF_SEC_SIZE(h) CAST(size_t, 1 << (h)->h_sec_size_p2)
#define CDF_SEC_POS(h, secid) (CDF_SEC_SIZE(h) + (secid) * CDF_SEC_SIZE(h))
-#define CDF_SHORT_SEC_SIZE(h) ((size_t)(1 << (h)->h_short_sec_size_p2))
+#define CDF_SHORT_SEC_SIZE(h) CAST(size_t, 1 << (h)->h_short_sec_size_p2)
#define CDF_SHORT_SEC_POS(h, secid) ((secid) * CDF_SHORT_SEC_SIZE(h))
typedef int32_t cdf_dirid_t;
diff --git a/ext/fileinfo/libmagic/cdf_time.c b/ext/fileinfo/libmagic/cdf_time.c
index bc1b99edaf..8b89b2838b 100644
--- a/ext/fileinfo/libmagic/cdf_time.c
+++ b/ext/fileinfo/libmagic/cdf_time.c
@@ -28,7 +28,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: cdf_time.c,v 1.16 2017/03/29 15:57:48 christos Exp $")
+FILE_RCSID("@(#)$File: cdf_time.c,v 1.19 2019/03/12 20:43:05 christos Exp $")
#endif
#include <time.h>
@@ -69,7 +69,7 @@ cdf_getday(int year, int days)
{
size_t m;
- for (m = 0; m < sizeof(mdays) / sizeof(mdays[0]); m++) {
+ for (m = 0; m < __arraycount(mdays); m++) {
int sub = mdays[m] + (m == 1 && isleap(year));
if (days < sub)
return days;
@@ -86,14 +86,14 @@ cdf_getmonth(int year, int days)
{
size_t m;
- for (m = 0; m < sizeof(mdays) / sizeof(mdays[0]); m++) {
+ for (m = 0; m < __arraycount(mdays); m++) {
days -= mdays[m];
if (m == 1 && isleap(year))
days--;
if (days <= 0)
- return (int)m;
+ return CAST(int, m);
}
- return (int)m;
+ return CAST(int, m);
}
int
@@ -109,22 +109,22 @@ cdf_timestamp_to_timespec(struct timespec *ts, cdf_timestamp_t t)
ts->tv_nsec = (t % CDF_TIME_PREC) * 100;
t /= CDF_TIME_PREC;
- tm.tm_sec = (int)(t % 60);
+ tm.tm_sec = CAST(int, t % 60);
t /= 60;
- tm.tm_min = (int)(t % 60);
+ tm.tm_min = CAST(int, t % 60);
t /= 60;
- tm.tm_hour = (int)(t % 24);
+ tm.tm_hour = CAST(int, t % 24);
t /= 24;
/* XXX: Approx */
- tm.tm_year = (int)(CDF_BASE_YEAR + (t / 365));
+ tm.tm_year = CAST(int, CDF_BASE_YEAR + (t / 365));
rdays = cdf_getdays(tm.tm_year);
t -= rdays - 1;
- tm.tm_mday = cdf_getday(tm.tm_year, (int)t);
- tm.tm_mon = cdf_getmonth(tm.tm_year, (int)t);
+ tm.tm_mday = cdf_getday(tm.tm_year, CAST(int, t));
+ tm.tm_mon = cdf_getmonth(tm.tm_year, CAST(int, t));
tm.tm_wday = 0;
tm.tm_yday = 0;
tm.tm_isdst = 0;
@@ -173,7 +173,7 @@ cdf_ctime(const time_t *sec, char *buf)
if (ptr != NULL)
return buf;
(void)snprintf(buf, 26, "*Bad* %#16.16" INT64_T_FORMAT "x\n",
- (long long)*sec);
+ CAST(long long, *sec));
return buf;
}
diff --git a/ext/fileinfo/libmagic/compress.c b/ext/fileinfo/libmagic/compress.c
index a66cf806bc..3e1b50c6ea 100644
--- a/ext/fileinfo/libmagic/compress.c
+++ b/ext/fileinfo/libmagic/compress.c
@@ -35,7 +35,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: compress.c,v 1.104 2017/03/29 15:57:48 christos Exp $")
+FILE_RCSID("@(#)$File: compress.c,v 1.121 2019/05/07 02:27:11 christos Exp $")
#endif
#include "magic.h"
@@ -67,6 +67,53 @@ typedef void (*sig_t)(int);
#undef FIONREAD
+#if defined(PHP_FILEINFO_UNCOMPRESS)
+#define BUILTIN_BZLIB
+#include <bzlib.h>
+#endif
+
+#ifdef DEBUG
+int tty = -1;
+#define DPRINTF(...) do { \
+ if (tty == -1) \
+ tty = open("/dev/tty", O_RDWR); \
+ if (tty == -1) \
+ abort(); \
+ dprintf(tty, __VA_ARGS__); \
+} while (/*CONSTCOND*/0)
+#else
+#define DPRINTF(...)
+#endif
+
+#ifdef ZLIBSUPPORT
+/*
+ * The following python code is not really used because ZLIBSUPPORT is only
+ * defined if we have a built-in zlib, and the built-in zlib handles that.
+ * That is not true for android where we have zlib.h and not -lz.
+ */
+static const char zlibcode[] =
+ "import sys, zlib; sys.stdout.write(zlib.decompress(sys.stdin.read()))";
+
+static const char *zlib_args[] = { "python", "-c", zlibcode, NULL };
+
+static int
+zlibcmp(const unsigned char *buf)
+{
+ unsigned short x = 1;
+ unsigned char *s = CAST(unsigned char *, CAST(void *, &x));
+
+ if ((buf[0] & 0xf) != 8 || (buf[0] & 0x80) != 0)
+ return 0;
+ if (s[0] != 1) /* endianness test */
+ x = buf[0] | (buf[1] << 8);
+ else
+ x = buf[1] | (buf[0] << 8);
+ if (x % 31)
+ return 0;
+ return 1;
+}
+#endif
+
#define gzip_flags "-cd"
#define lrzip_flags "-do"
#define lzip_flags gzip_flags
@@ -97,41 +144,45 @@ static const char *zstd_args[] = {
"zstd", "-cd", NULL
};
+#define do_zlib NULL
+#define do_bzlib NULL
+
private const struct {
const void *magic;
size_t maglen;
const char **argv;
+ void *unused;
} compr[] = {
- { "\037\235", 2, gzip_args }, /* compressed */
+ { "\037\235", 2, gzip_args, NULL }, /* compressed */
/* Uncompress can get stuck; so use gzip first if we have it
* Idea from Damien Clark, thanks! */
- { "\037\235", 2, uncompress_args }, /* compressed */
- { "\037\213", 2, gzip_args }, /* gzipped */
- { "\037\236", 2, gzip_args }, /* frozen */
- { "\037\240", 2, gzip_args }, /* SCO LZH */
+ { "\037\235", 2, uncompress_args, NULL }, /* compressed */
+ { "\037\213", 2, gzip_args, do_zlib }, /* gzipped */
+ { "\037\236", 2, gzip_args, NULL }, /* frozen */
+ { "\037\240", 2, gzip_args, NULL }, /* SCO LZH */
/* the standard pack utilities do not accept standard input */
- { "\037\036", 2, gzip_args }, /* packed */
- { "PK\3\4", 4, gzip_args }, /* pkzipped, */
+ { "\037\036", 2, gzip_args, NULL }, /* packed */
+ { "PK\3\4", 4, gzip_args, NULL }, /* pkzipped, */
/* ...only first file examined */
- { "BZh", 3, bzip2_args }, /* bzip2-ed */
- { "LZIP", 4, lzip_args }, /* lzip-ed */
- { "\3757zXZ\0", 6, xz_args }, /* XZ Utils */
- { "LRZI", 4, lrzip_args }, /* LRZIP */
- { "\004\"M\030",4, lz4_args }, /* LZ4 */
- { "\x28\xB5\x2F\xFD", 4, zstd_args }, /* zstd */
+ { "BZh", 3, bzip2_args, do_bzlib }, /* bzip2-ed */
+ { "LZIP", 4, lzip_args, NULL }, /* lzip-ed */
+ { "\3757zXZ\0", 6, xz_args, NULL }, /* XZ Utils */
+ { "LRZI", 4, lrzip_args, NULL }, /* LRZIP */
+ { "\004\"M\030",4, lz4_args, NULL }, /* LZ4 */
+ { "\x28\xB5\x2F\xFD", 4, zstd_args, NULL }, /* zstd */
#ifdef ZLIBSUPPORT
- { RCAST(const void *, zlibcmp), 0, zlib_args }, /* zlib */
+ { RCAST(const void *, zlibcmp), 0, zlib_args, NULL }, /* zlib */
#endif
};
-#endif
+
#define OKDATA 0
#define NODATA 1
#define ERRDATA 2
private ssize_t swrite(int, const void *, size_t);
-#ifdef PHP_FILEINFO_UNCOMPRESS
-private size_t ncompr = sizeof(compr) / sizeof(compr[0]);
+#if HAVE_FORK
+private size_t ncompr = __arraycount(compr);
private int uncompressbuf(int, size_t, size_t, const unsigned char *,
unsigned char **, size_t *);
#ifdef BUILTIN_DECOMPRESS
@@ -140,12 +191,33 @@ private int uncompresszlib(const unsigned char *, unsigned char **, size_t,
private int uncompressgzipped(const unsigned char *, unsigned char **, size_t,
size_t *);
#endif
+#ifdef BUILTIN_BZLIB
+private int uncompressbzlib(const unsigned char *, unsigned char **, size_t,
+ size_t *, int);
+#endif
+
static int makeerror(unsigned char **, size_t *, const char *, ...);
private const char *methodname(size_t);
+private int
+format_decompression_error(struct magic_set *ms, size_t i, unsigned char *buf)
+{
+ unsigned char *p;
+ int mime = ms->flags & MAGIC_MIME;
+
+ if (!mime)
+ return file_printf(ms, "ERROR:[%s: %s]", methodname(i), buf);
+
+ for (p = buf; *p; p++)
+ if (!isalnum(*p))
+ *p = '-';
+
+ return file_printf(ms, "application/x-decompression-error-%s-%s",
+ methodname(i), buf);
+}
+
protected int
-file_zmagic(struct magic_set *ms, int fd, const char *name,
- const unsigned char *buf, size_t nbytes)
+file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name)
{
unsigned char *newbuf = NULL;
size_t i, nsz;
@@ -153,16 +225,15 @@ file_zmagic(struct magic_set *ms, int fd, const char *name,
file_pushbuf_t *pb;
int urv, prv, rv = 0;
int mime = ms->flags & MAGIC_MIME;
-#ifdef HAVE_SIGNAL_H
- sig_t osigpipe;
-#endif
+ int fd = b->fd;
+ const unsigned char *buf = CAST(const unsigned char *, b->fbuf);
+ size_t nbytes = b->flen;
+ int sa_saved = 0;
+ struct sigaction sig_act;
if ((ms->flags & MAGIC_COMPRESS) == 0)
return 0;
-#ifdef HAVE_SIGNAL_H
- osigpipe = signal(SIGPIPE, SIG_IGN);
-#endif
for (i = 0; i < ncompr; i++) {
int zm;
if (nbytes < compr[i].maglen)
@@ -177,20 +248,28 @@ file_zmagic(struct magic_set *ms, int fd, const char *name,
if (!zm)
continue;
+
+ /* Prevent SIGPIPE death if child dies unexpectedly */
+ if (!sa_saved) {
+ //We can use sig_act for both new and old, but
+ struct sigaction new_act;
+ memset(&new_act, 0, sizeof(new_act));
+ new_act.sa_handler = SIG_IGN;
+ sa_saved = sigaction(SIGPIPE, &new_act, &sig_act) != -1;
+ }
+
nsz = nbytes;
urv = uncompressbuf(fd, ms->bytes_max, i, buf, &newbuf, &nsz);
- DPRINTF("uncompressbuf = %d, %s, %zu\n", urv, (char *)newbuf,
- nsz);
+ DPRINTF("uncompressbuf = %d, %s, %" SIZE_T_FORMAT "u\n", urv,
+ (char *)newbuf, nsz);
switch (urv) {
case OKDATA:
case ERRDATA:
-
ms->flags &= ~MAGIC_COMPRESS;
if (urv == ERRDATA)
- prv = file_printf(ms, "%s ERROR: %s",
- methodname(i), newbuf);
+ prv = format_decompression_error(ms, i, newbuf);
else
- prv = file_buffer(ms, -1, name, newbuf, nsz);
+ prv = file_buffer(ms, NULL, NULL, name, newbuf, nsz);
if (prv == -1)
goto error;
rv = 1;
@@ -207,8 +286,11 @@ file_zmagic(struct magic_set *ms, int fd, const char *name,
* XXX: If file_buffer fails here, we overwrite
* the compressed text. FIXME.
*/
- if (file_buffer(ms, -1, NULL, buf, nbytes) == -1)
+ if (file_buffer(ms, NULL, NULL, NULL, buf, nbytes) == -1) {
+ if (file_pop_buffer(ms, pb) != NULL)
+ abort();
goto error;
+ }
if ((rbuf = file_pop_buffer(ms, pb)) != NULL) {
if (file_printf(ms, "%s", rbuf) == -1) {
efree(rbuf);
@@ -232,9 +314,9 @@ file_zmagic(struct magic_set *ms, int fd, const char *name,
out:
DPRINTF("rv = %d\n", rv);
-#ifdef HAVE_SIGNAL_H
- (void)signal(SIGPIPE, osigpipe);
-#endif
+ if (sa_saved && sig_act.sa_handler != SIG_IGN)
+ (void)sigaction(SIGPIPE, &sig_act, NULL);
+
if (newbuf)
efree(newbuf);
ms->flags |= MAGIC_COMPRESS;
@@ -311,7 +393,7 @@ sread(int fd, void *buf, size_t n, int canbepipe)
(void)ioctl(fd, FIONREAD, &t);
}
- if (t > 0 && (size_t)t < n) {
+ if (t > 0 && CAST(size_t, t) < n) {
n = t;
rn = n;
}
@@ -356,6 +438,7 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf,
{
int te;
tfd = mkstemp(buf);
+ (void)umask(ou);
te = errno;
(void)unlink(buf);
errno = te;
@@ -367,11 +450,11 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf,
return -1;
}
- if (swrite(tfd, startbuf, nbytes) != (ssize_t)nbytes)
+ if (swrite(tfd, startbuf, nbytes) != CAST(ssize_t, nbytes))
r = 1;
else {
while ((r = sread(fd, buf, sizeof(buf), 1)) > 0)
- if (swrite(tfd, buf, (size_t)r) != r)
+ if (swrite(tfd, buf, CAST(size_t, r)) != r)
break;
}
@@ -474,7 +557,7 @@ uncompresszlib(const unsigned char *old, unsigned char **newch,
if (rc != Z_OK && rc != Z_STREAM_END)
goto err;
- *n = (size_t)z.total_out;
+ *n = CAST(size_t, z.total_out);
rc = inflateEnd(&z);
if (rc != Z_OK)
goto err;
@@ -484,8 +567,8 @@ uncompresszlib(const unsigned char *old, unsigned char **newch,
return OKDATA;
err:
- strlcpy((char *)*newch, z.msg ? z.msg : zError(rc), bytes_max);
- *n = strlen((char *)*newch);
+ strlcpy(RCAST(char *, *newch), z.msg ? z.msg : zError(rc), bytes_max);
+ *n = strlen(RCAST(char *, *newch));
return ERRDATA;
}
#endif
@@ -505,7 +588,7 @@ makeerror(unsigned char **buf, size_t *len, const char *fmt, ...)
*len = 0;
return NODATA;
}
- *buf = (unsigned char *)msg;
+ *buf = RCAST(unsigned char *, msg);
*len = strlen(msg);
return ERRDATA;
}
@@ -527,52 +610,42 @@ closep(int *fd)
closefd(fd, i);
}
-static void
-copydesc(int i, int *fd)
+static int
+copydesc(int i, int fd)
{
- int j = fd[i == STDIN_FILENO ? 0 : 1];
- if (j == i)
- return;
- if (dup2(j, i) == -1) {
- DPRINTF("dup(%d, %d) failed (%s)\n", j, i, strerror(errno));
+ if (fd == i)
+ return 0; /* "no dup was necessary" */
+ if (dup2(fd, i) == -1) {
+ DPRINTF("dup(%d, %d) failed (%s)\n", fd, i, strerror(errno));
exit(1);
}
- closep(fd);
+ return 1;
}
-static void
-writechild(int fdp[3][2], const void *old, size_t n)
+static pid_t
+writechild(int fd, const void *old, size_t n)
{
- int status;
+ pid_t pid;
- closefd(fdp[STDIN_FILENO], 0);
/*
* fork again, to avoid blocking because both
* pipes filled
*/
- switch (fork()) {
- case 0: /* child */
- closefd(fdp[STDOUT_FILENO], 0);
- if (swrite(fdp[STDIN_FILENO][1], old, n) != (ssize_t)n) {
- DPRINTF("Write failed (%s)\n", strerror(errno));
- exit(1);
- }
- exit(0);
- /*NOTREACHED*/
-
- case -1:
+ pid = fork();
+ if (pid == -1) {
DPRINTF("Fork failed (%s)\n", strerror(errno));
exit(1);
- /*NOTREACHED*/
-
- default: /* parent */
- if (wait(&status) == -1) {
- DPRINTF("Wait failed (%s)\n", strerror(errno));
+ }
+ if (pid == 0) {
+ /* child */
+ if (swrite(fd, old, n) != CAST(ssize_t, n)) {
+ DPRINTF("Write failed (%s)\n", strerror(errno));
exit(1);
}
- DPRINTF("Grandchild wait return %#x\n", status);
+ exit(0);
}
- closefd(fdp[STDIN_FILENO], 1);
+ /* parent */
+ return pid;
}
static ssize_t
@@ -582,17 +655,17 @@ filter_error(unsigned char *ubuf, ssize_t n)
char *buf;
ubuf[n] = '\0';
- buf = (char *)ubuf;
- while (isspace((unsigned char)*buf))
+ buf = RCAST(char *, ubuf);
+ while (isspace(CAST(unsigned char, *buf)))
buf++;
DPRINTF("Filter error[[[%s]]]\n", buf);
- if ((p = strchr((char *)buf, '\n')) != NULL)
+ if ((p = strchr(CAST(char *, buf), '\n')) != NULL)
*p = '\0';
- if ((p = strchr((char *)buf, ';')) != NULL)
+ if ((p = strchr(CAST(char *, buf), ';')) != NULL)
*p = '\0';
- if ((p = strrchr((char *)buf, ':')) != NULL) {
+ if ((p = strrchr(CAST(char *, buf), ':')) != NULL) {
++p;
- while (isspace((unsigned char)*p))
+ while (isspace(CAST(unsigned char, *p)))
p++;
n = strlen(p);
memmove(ubuf, p, CAST(size_t, n + 1));
@@ -619,7 +692,9 @@ uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old,
unsigned char **newch, size_t* n)
{
int fdp[3][2];
- int status, rv;
+ int status, rv, w;
+ pid_t pid;
+ pid_t writepid = -1;
size_t i;
ssize_t r;
@@ -643,43 +718,68 @@ uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old,
return makeerror(newch, n, "Cannot create pipe, %s",
strerror(errno));
}
- switch (fork()) {
- case 0: /* child */
+
+ /* For processes with large mapped virtual sizes, vfork
+ * may be _much_ faster (10-100 times) than fork.
+ */
+ pid = vfork();
+ if (pid == -1) {
+ return makeerror(newch, n, "Cannot vfork, %s",
+ strerror(errno));
+ }
+ if (pid == 0) {
+ /* child */
+ /* Note: we are after vfork, do not modify memory
+ * in a way which confuses parent. In particular,
+ * do not modify fdp[i][j].
+ */
if (fd != -1) {
- fdp[STDIN_FILENO][0] = fd;
- (void) lseek(fd, (off_t)0, SEEK_SET);
+ (void) lseek(fd, CAST(off_t, 0), SEEK_SET);
+ if (copydesc(STDIN_FILENO, fd))
+ (void) close(fd);
+ } else {
+ if (copydesc(STDIN_FILENO, fdp[STDIN_FILENO][0]))
+ (void) close(fdp[STDIN_FILENO][0]);
+ if (fdp[STDIN_FILENO][1] > 2)
+ (void) close(fdp[STDIN_FILENO][1]);
}
+///FIXME: if one of the fdp[i][j] is 0 or 1, this can bomb spectacularly
+ if (copydesc(STDOUT_FILENO, fdp[STDOUT_FILENO][1]))
+ (void) close(fdp[STDOUT_FILENO][1]);
+ if (fdp[STDOUT_FILENO][0] > 2)
+ (void) close(fdp[STDOUT_FILENO][0]);
- for (i = 0; i < __arraycount(fdp); i++)
- copydesc(CAST(int, i), fdp[i]);
+ if (copydesc(STDERR_FILENO, fdp[STDERR_FILENO][1]))
+ (void) close(fdp[STDERR_FILENO][1]);
+ if (fdp[STDERR_FILENO][0] > 2)
+ (void) close(fdp[STDERR_FILENO][0]);
(void)execvp(compr[method].argv[0],
- (char *const *)(intptr_t)compr[method].argv);
+ RCAST(char *const *, RCAST(intptr_t, compr[method].argv)));
dprintf(STDERR_FILENO, "exec `%s' failed, %s",
compr[method].argv[0], strerror(errno));
- exit(1);
- /*NOTREACHED*/
- case -1:
- return makeerror(newch, n, "Cannot fork, %s",
- strerror(errno));
-
- default: /* parent */
- for (i = 1; i < __arraycount(fdp); i++)
- closefd(fdp[i], 1);
-
- /* Write the buffer data to the child, if we don't have fd */
- if (fd == -1)
- writechild(fdp, old, *n);
+ _exit(1); /* _exit(), not exit(), because of vfork */
+ }
+ /* parent */
+ /* Close write sides of child stdout/err pipes */
+ for (i = 1; i < __arraycount(fdp); i++)
+ closefd(fdp[i], 1);
+ /* Write the buffer data to child stdin, if we don't have fd */
+ if (fd == -1) {
+ closefd(fdp[STDIN_FILENO], 0);
+ writepid = writechild(fdp[STDIN_FILENO][1], old, *n);
+ closefd(fdp[STDIN_FILENO], 1);
+ }
- *newch = CAST(unsigned char *, emalloc(bytes_max + 1));
- if (*newch == NULL) {
- rv = makeerror(newch, n, "No buffer, %s",
- strerror(errno));
- goto err;
- }
- rv = OKDATA;
- if ((r = sread(fdp[STDOUT_FILENO][0], *newch, bytes_max, 0)) > 0)
- break;
+ *newch = CAST(unsigned char *, malloc(bytes_max + 1));
+ if (*newch == NULL) {
+ rv = makeerror(newch, n, "No buffer, %s",
+ strerror(errno));
+ goto err;
+ }
+ rv = OKDATA;
+ r = sread(fdp[STDOUT_FILENO][0], *newch, bytes_max, 0);
+ if (r <= 0) {
DPRINTF("Read stdout failed %d (%s)\n", fdp[STDOUT_FILENO][0],
r != -1 ? strerror(errno) : "no data");
@@ -688,9 +788,9 @@ uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old,
(r = sread(fdp[STDERR_FILENO][0], *newch, bytes_max, 0)) > 0)
{
r = filter_error(*newch, r);
- break;
+ goto ok;
}
- efree(*newch);
+ free(*newch);
if (r == 0)
rv = makeerror(newch, n, "Read failed, %s",
strerror(errno));
@@ -698,5 +798,40 @@ uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old,
rv = makeerror(newch, n, "No data");
goto err;
}
+ok:
+ *n = r;
+ /* NUL terminate, as every buffer is handled here. */
+ (*newch)[*n] = '\0';
+err:
+ closefd(fdp[STDIN_FILENO], 1);
+ closefd(fdp[STDOUT_FILENO], 0);
+ closefd(fdp[STDERR_FILENO], 0);
+
+ w = waitpid(pid, &status, 0);
+wait_err:
+ if (w == -1) {
+ free(*newch);
+ rv = makeerror(newch, n, "Wait failed, %s", strerror(errno));
+ DPRINTF("Child wait return %#x\n", status);
+ } else if (!WIFEXITED(status)) {
+ DPRINTF("Child not exited (%#x)\n", status);
+ } else if (WEXITSTATUS(status) != 0) {
+ DPRINTF("Child exited (%#x)\n", WEXITSTATUS(status));
+ }
+ if (writepid > 0) {
+ /* _After_ we know decompressor has exited, our input writer
+ * definitely will exit now (at worst, writing fails in it,
+ * since output fd is closed now on the reading size).
+ */
+ w = waitpid(writepid, &status, 0);
+ writepid = -1;
+ goto wait_err;
+ }
+
+ closefd(fdp[STDIN_FILENO], 0); //why? it is already closed here!
+ DPRINTF("Returning %p n=%" SIZE_T_FORMAT "u rv=%d\n", *newch, *n, rv);
+
+ return rv;
}
-#endif /* if PHP_FILEINFO_UNCOMPRESS */
+#endif
+#endif
diff --git a/ext/fileinfo/libmagic/der.c b/ext/fileinfo/libmagic/der.c
index 160d9b2c13..5c22d9d642 100644
--- a/ext/fileinfo/libmagic/der.c
+++ b/ext/fileinfo/libmagic/der.c
@@ -35,7 +35,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: der.c,v 1.12 2017/02/10 18:14:01 christos Exp $")
+FILE_RCSID("@(#)$File: der.c,v 1.16 2019/02/20 02:35:27 christos Exp $")
#endif
#endif
@@ -58,7 +58,7 @@ FILE_RCSID("@(#)$File: der.c,v 1.12 2017/02/10 18:14:01 christos Exp $")
#include <err.h>
#endif
-#define DER_BAD ((uint32_t)-1)
+#define DER_BAD CAST(uint32_t, -1)
#define DER_CLASS_UNIVERSAL 0
#define DER_CLASS_APPLICATION 1
@@ -201,7 +201,7 @@ getlength(const uint8_t *c, size_t *p, size_t l)
for (i = 0; i < digits; i++)
len = (len << 8) | c[(*p)++];
- if (*p + len >= l)
+ if (len > UINT32_MAX - *p || *p + len >= l)
return DER_BAD;
return CAST(uint32_t, len);
}
@@ -227,7 +227,7 @@ der_data(char *buf, size_t blen, uint32_t tag, const void *q, uint32_t len)
case DER_TAG_UTF8_STRING:
case DER_TAG_IA5_STRING:
case DER_TAG_UTCTIME:
- return snprintf(buf, blen, "%.*s", len, (const char *)q);
+ return snprintf(buf, blen, "%.*s", len, RCAST(const char *, q));
default:
break;
}
@@ -248,18 +248,21 @@ der_offs(struct magic_set *ms, struct magic *m, size_t nbytes)
if (gettag(b, &offs, len) == DER_BAD)
return -1;
- DPRINTF(("%s1: %d %zu %u\n", __func__, ms->offset, offs, m->offset));
+ DPRINTF(("%s1: %d %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset,
+ offs, m->offset));
uint32_t tlen = getlength(b, &offs, len);
if (tlen == DER_BAD)
return -1;
- DPRINTF(("%s2: %d %zu %u\n", __func__, ms->offset, offs, tlen));
+ DPRINTF(("%s2: %d %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset,
+ offs, tlen));
offs += ms->offset + m->offset;
DPRINTF(("cont_level = %d\n", m->cont_level));
#ifdef DEBUG_DER
for (size_t i = 0; i < m->cont_level; i++)
- printf("cont_level[%zu] = %u\n", i, ms->c.li[i].off);
+ printf("cont_level[%" SIZE_T_FORMAT "u] = %u\n", i,
+ ms->c.li[i].off);
#endif
if (m->cont_level != 0) {
if (offs + tlen > nbytes)
@@ -307,22 +310,23 @@ again:
s++;
goto val;
default:
- if (!isdigit((unsigned char)*s))
+ if (!isdigit(CAST(unsigned char, *s)))
return 0;
slen = 0;
do
slen = slen * 10 + *s - '0';
- while (isdigit((unsigned char)*++s));
+ while (isdigit(CAST(unsigned char, *++s)));
if ((ms->flags & MAGIC_DEBUG) != 0)
- fprintf(stderr, "%s: len %zu %u\n", __func__,
- slen, tlen);
+ fprintf(stderr, "%s: len %" SIZE_T_FORMAT "u %u\n",
+ __func__, slen, tlen);
if (tlen != slen)
return 0;
goto again;
}
val:
- DPRINTF(("%s: before data %zu %u\n", __func__, offs, tlen));
+ DPRINTF(("%s: before data %" SIZE_T_FORMAT "u %u\n", __func__, offs,
+ tlen));
der_data(buf, sizeof(buf), tag, b + offs, tlen);
if ((ms->flags & MAGIC_DEBUG) != 0)
fprintf(stderr, "%s: data %s %s\n", __func__, buf, s);
@@ -371,7 +375,8 @@ printdata(size_t level, const void *v, size_t x, size_t l)
break;
uint32_t len = getlength(p, &x, ep - p + x);
- printf("%zu %zu-%zu %c,%c,%s,%u:", level, ox, x,
+ printf("%" SIZE_T_FORMAT "u %" SIZE_T_FORMAT "u-%"
+ SIZE_T_FORMAT "u %c,%c,%s,%u:", level, ox, x,
der_class[c], der_type[t],
der_tag(buf, sizeof(buf), tag), len);
q = p + x;
diff --git a/ext/fileinfo/libmagic/elfclass.h b/ext/fileinfo/libmagic/elfclass.h
index bca6447952..29a65f42ab 100644
--- a/ext/fileinfo/libmagic/elfclass.h
+++ b/ext/fileinfo/libmagic/elfclass.h
@@ -41,8 +41,8 @@
return toomany(ms, "program headers", phnum);
flags |= FLAGS_IS_CORE;
if (dophn_core(ms, clazz, swap, fd,
- (zend_off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
- (size_t)elf_getu16(swap, elfhdr.e_phentsize),
+ CAST(zend_off_t, elf_getu(swap, elfhdr.e_phoff)), phnum,
+ CAST(size_t, elf_getu16(swap, elfhdr.e_phentsize)),
fsize, &flags, &notecount) == -1)
return -1;
break;
@@ -56,8 +56,8 @@
if (shnum > ms->elf_shnum_max)
return toomany(ms, "section", shnum);
if (dophn_exec(ms, clazz, swap, fd,
- (zend_off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
- (size_t)elf_getu16(swap, elfhdr.e_phentsize),
+ CAST(zend_off_t, elf_getu(swap, elfhdr.e_phoff)), phnum,
+ CAST(size_t, elf_getu16(swap, elfhdr.e_phentsize)),
fsize, shnum, &flags, &notecount) == -1)
return -1;
/*FALLTHROUGH*/
@@ -66,10 +66,10 @@
if (shnum > ms->elf_shnum_max)
return toomany(ms, "section headers", shnum);
if (doshn(ms, clazz, swap, fd,
- (zend_off_t)elf_getu(swap, elfhdr.e_shoff), shnum,
- (size_t)elf_getu16(swap, elfhdr.e_shentsize),
+ CAST(zend_off_t, elf_getu(swap, elfhdr.e_shoff)), shnum,
+ CAST(size_t, elf_getu16(swap, elfhdr.e_shentsize)),
fsize, elf_getu16(swap, elfhdr.e_machine),
- (int)elf_getu16(swap, elfhdr.e_shstrndx),
+ CAST(int, elf_getu16(swap, elfhdr.e_shstrndx)),
&flags, &notecount) == -1)
return -1;
break;
diff --git a/ext/fileinfo/libmagic/encoding.c b/ext/fileinfo/libmagic/encoding.c
index 42aa200f36..121bbd7143 100644
--- a/ext/fileinfo/libmagic/encoding.c
+++ b/ext/fileinfo/libmagic/encoding.c
@@ -35,7 +35,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: encoding.c,v 1.14 2017/11/02 20:25:39 christos Exp $")
+FILE_RCSID("@(#)$File: encoding.c,v 1.20 2019/04/15 16:48:41 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -49,6 +49,7 @@ private int looks_utf8_with_BOM(const unsigned char *, size_t, unichar *,
size_t *);
private int looks_utf7(const unsigned char *, size_t, unichar *, size_t *);
private int looks_ucs16(const unsigned char *, size_t, unichar *, size_t *);
+private int looks_ucs32(const unsigned char *, size_t, unichar *, size_t *);
private int looks_latin1(const unsigned char *, size_t, unichar *, size_t *);
private int looks_extended(const unsigned char *, size_t, unichar *, size_t *);
private void from_ebcdic(const unsigned char *, size_t, unsigned char *);
@@ -69,7 +70,7 @@ protected int
file_encoding(struct magic_set *ms, const struct buffer *b, unichar **ubuf,
size_t *ulen, const char **code, const char **code_mime, const char **type)
{
- const unsigned char *buf = b->fbuf;
+ const unsigned char *buf = CAST(const unsigned char *, b->fbuf);
size_t nbytes = b->flen;
size_t mlen;
int rv = 1, ucs_type;
@@ -88,12 +89,13 @@ file_encoding(struct magic_set *ms, const struct buffer *b, unichar **ubuf,
*code_mime = "binary";
mlen = (nbytes + 1) * sizeof((*ubuf)[0]);
- if ((*ubuf = CAST(unichar *, ecalloc((size_t)1, mlen))) == NULL) {
+ if ((*ubuf = CAST(unichar *, ecalloc(CAST(size_t, 1), mlen))) == NULL) {
file_oomem(ms, mlen);
goto done;
}
mlen = (nbytes + 1) * sizeof(nbuf[0]);
- if ((nbuf = CAST(unsigned char *, ecalloc((size_t)1, mlen))) == NULL) {
+ if ((nbuf = CAST(unsigned char *,
+ ecalloc(CAST(size_t, 1), mlen))) == NULL) {
file_oomem(ms, mlen);
goto done;
}
@@ -116,6 +118,15 @@ file_encoding(struct magic_set *ms, const struct buffer *b, unichar **ubuf,
DPRINTF(("utf8 %" SIZE_T_FORMAT "u\n", *ulen));
*code = "UTF-8 Unicode";
*code_mime = "utf-8";
+ } else if ((ucs_type = looks_ucs32(buf, nbytes, *ubuf, ulen)) != 0) {
+ if (ucs_type == 1) {
+ *code = "Little-endian UTF-32 Unicode";
+ *code_mime = "utf-32le";
+ } else {
+ *code = "Big-endian UTF-32 Unicode";
+ *code_mime = "utf-32be";
+ }
+ DPRINTF(("ucs32 %" SIZE_T_FORMAT "u\n", *ulen));
} else if ((ucs_type = looks_ucs16(buf, nbytes, *ubuf, ulen)) != 0) {
if (ucs_type == 1) {
*code = "Little-endian UTF-16 Unicode";
@@ -410,7 +421,7 @@ looks_utf7(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen)
}
private int
-looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf,
+looks_ucs16(const unsigned char *bf, size_t nbytes, unichar *ubf,
size_t *ulen)
{
int bigend;
@@ -419,9 +430,9 @@ looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf,
if (nbytes < 2)
return 0;
- if (buf[0] == 0xff && buf[1] == 0xfe)
+ if (bf[0] == 0xff && bf[1] == 0xfe)
bigend = 0;
- else if (buf[0] == 0xfe && buf[1] == 0xff)
+ else if (bf[0] == 0xfe && bf[1] == 0xff)
bigend = 1;
else
return 0;
@@ -432,20 +443,64 @@ looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf,
/* XXX fix to properly handle chars > 65536 */
if (bigend)
- ubuf[(*ulen)++] = buf[i + 1] + 256 * buf[i];
+ ubf[(*ulen)++] = bf[i + 1]
+ | (CAST(unichar, bf[i]) << 8);
else
- ubuf[(*ulen)++] = buf[i] + 256 * buf[i + 1];
+ ubf[(*ulen)++] = bf[i]
+ | (CAST(unichar, bf[i + 1]) << 8);
- if (ubuf[*ulen - 1] == 0xfffe)
+ if (ubf[*ulen - 1] == 0xfffe)
return 0;
- if (ubuf[*ulen - 1] < 128 &&
- text_chars[(size_t)ubuf[*ulen - 1]] != T)
+ if (ubf[*ulen - 1] < 128 &&
+ text_chars[CAST(size_t, ubf[*ulen - 1])] != T)
return 0;
}
return 1 + bigend;
}
+private int
+looks_ucs32(const unsigned char *bf, size_t nbytes, unichar *ubf,
+ size_t *ulen)
+{
+ int bigend;
+ size_t i;
+
+ if (nbytes < 4)
+ return 0;
+
+ if (bf[0] == 0xff && bf[1] == 0xfe && bf[2] == 0 && bf[3] == 0)
+ bigend = 0;
+ else if (bf[0] == 0 && bf[1] == 0 && bf[2] == 0xfe && bf[3] == 0xff)
+ bigend = 1;
+ else
+ return 0;
+
+ *ulen = 0;
+
+ for (i = 4; i + 3 < nbytes; i += 4) {
+ /* XXX fix to properly handle chars > 65536 */
+
+ if (bigend)
+ ubf[(*ulen)++] = CAST(unichar, bf[i + 3])
+ | (CAST(unichar, bf[i + 2]) << 8)
+ | (CAST(unichar, bf[i + 1]) << 16)
+ | (CAST(unichar, bf[i]) << 24);
+ else
+ ubf[(*ulen)++] = CAST(unichar, bf[i + 0])
+ | (CAST(unichar, bf[i + 1]) << 8)
+ | (CAST(unichar, bf[i + 2]) << 16)
+ | (CAST(unichar, bf[i + 3]) << 24);
+
+ if (ubf[*ulen - 1] == 0xfffe)
+ return 0;
+ if (ubf[*ulen - 1] < 128 &&
+ text_chars[CAST(size_t, ubf[*ulen - 1])] != T)
+ return 0;
+ }
+
+ return 1 + bigend;
+}
#undef F
#undef T
#undef I
diff --git a/ext/fileinfo/libmagic/file.h b/ext/fileinfo/libmagic/file.h
index 9cb6dc540f..4d10fd9e69 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.182 2017/04/07 19:46:44 christos Exp $
+ * @(#)$File: file.h,v 1.206 2019/05/07 02:27:11 christos Exp $
*/
#ifndef __file_h__
@@ -56,6 +56,9 @@
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
#include <stdint.h>
#endif
#ifdef HAVE_INTTYPES_H
@@ -379,7 +382,7 @@ struct mlist {
#define CCAST(T, b) const_cast<T>(b)
#else
#define CAST(T, b) ((T)(b))
-#define RCAST(T, b) ((T)(b))
+#define RCAST(T, b) ((T)(uintptr_t)(b))
#define CCAST(T, b) ((T)(uintptr_t)(b))
#endif
@@ -413,6 +416,7 @@ struct magic_set {
#define EVENT_HAD_ERR 0x01
const char *file;
size_t line; /* current magic line number */
+ mode_t mode; /* copy of current stat mode */
/* data for searches */
struct {
@@ -448,10 +452,11 @@ typedef unsigned long unichar;
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 *,
+protected int file_buffer(struct magic_set *, php_stream *, zend_stat_t *, const char *, const void *,
size_t);
-protected int file_fsmagic(struct magic_set *, const char *, zend_stat_t *, php_stream *);
+protected int file_fsmagic(struct magic_set *, const char *, zend_stat_t *);
protected int file_pipe2file(struct magic_set *, int, const void *, size_t);
+protected int file_separator(struct magic_set *);
protected size_t file_printedlen(const struct magic_set *);
protected int file_replace(struct magic_set *, const char *, const char *);
protected int file_printf(struct magic_set *, const char *, ...);
@@ -468,6 +473,7 @@ protected int file_ascmagic_with_encoding(struct magic_set *,
const struct buffer *, unichar *, size_t, const char *, const char *, int);
protected int file_encoding(struct magic_set *, const struct buffer *,
unichar **, size_t *, const char **, const char **, const char **);
+protected int file_is_json(struct magic_set *, const struct buffer *);
protected int file_is_tar(struct magic_set *, const struct buffer *);
protected int file_softmagic(struct magic_set *, const struct buffer *,
uint16_t *, uint16_t *, int, int);
@@ -492,13 +498,14 @@ protected int file_looks_utf8(const unsigned char *, size_t, unichar *,
size_t *);
protected size_t file_pstring_length_size(const struct magic *);
protected size_t file_pstring_get_length(const struct magic *, const char *);
-protected char * file_printable(char *, size_t, const char *);
+protected char * file_printable(char *, size_t, const char *, size_t);
#ifdef __EMX__
protected int file_os2_apptype(struct magic_set *, const char *, const void *,
size_t);
#endif /* __EMX__ */
-protected void buffer_init(struct buffer *, int, const void *, size_t);
+protected void buffer_init(struct buffer *, int, const zend_stat_t *,
+ const void *, size_t);
protected void buffer_fini(struct buffer *);
protected int buffer_fill(const struct buffer *);
@@ -523,10 +530,6 @@ extern char *sys_errlist[];
(((e) >= 0 && (e) < sys_nerr) ? sys_errlist[(e)] : "Unknown error")
#endif
-#ifndef HAVE_STRTOUL
-#define strtoul(a, b, c) strtol(a, b, c)
-#endif
-
#ifndef strlcpy
size_t strlcpy(char *, const char *, size_t);
#endif
@@ -554,6 +557,9 @@ char *asctime_r(const struct tm *, char *);
#ifndef O_BINARY
#define O_BINARY 0
#endif
+#ifndef O_NONBLOCK
+#define O_NONBLOCK 0
+#endif
#ifndef __cplusplus
#if defined(__GNUC__) && (__GNUC__ >= 3)
diff --git a/ext/fileinfo/libmagic/fsmagic.c b/ext/fileinfo/libmagic/fsmagic.c
index b9334d17f7..938b526a37 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.77 2017/05/24 19:17:50 christos Exp $")
+FILE_RCSID("@(#)$File: fsmagic.c,v 1.80 2019/04/23 18:59:27 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -46,11 +46,14 @@ FILE_RCSID("@(#)$File: fsmagic.c,v 1.77 2017/05/24 19:17:50 christos Exp $")
# include <sys/mkdev.h>
# define HAVE_MAJOR
#endif
-#ifdef MAJOR_IN_SYSMACROS
+#ifdef HAVE_SYS_SYSMACROS_H
# include <sys/sysmacros.h>
+#endif
+#ifdef MAJOR_IN_SYSMACROS
# define HAVE_MAJOR
#endif
-#ifdef major /* Might be defined in sys/types.h. */
+#if defined(major) && !defined(HAVE_MAJOR)
+/* Might be defined in sys/types.h. */
# define HAVE_MAJOR
#endif
#ifdef WIN32
@@ -84,39 +87,27 @@ handle_mime(struct magic_set *ms, int mime, const char *str)
}
protected int
-file_fsmagic(struct magic_set *ms, const char *fn, zend_stat_t *sb, php_stream *stream)
+file_fsmagic(struct magic_set *ms, const char *fn, zend_stat_t *sb)
{
int ret, did = 0;
int mime = ms->flags & MAGIC_MIME;
int silent = ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION);
- if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))
+ if (fn == NULL)
return 0;
- if (fn == NULL && !stream) {
- return 0;
- }
-
#define COMMA (did++ ? ", " : "")
+ ret = php_sys_stat(fn, sb);
- if (stream) {
- php_stream_statbuf ssb;
- if (php_stream_stat(stream, &ssb) < 0) {
- if (ms->flags & MAGIC_ERROR) {
- file_error(ms, errno, "cannot stat `%s'", fn);
- return -1;
- }
- return 0;
- }
- memcpy(sb, &ssb.sb, sizeof(struct stat));
- } else {
- if (php_sys_stat(fn, sb) != 0) {
- if (ms->flags & MAGIC_ERROR) {
- file_error(ms, errno, "cannot stat `%s'", fn);
- return -1;
- }
- return 0;
+ if (ret) {
+ if (ms->flags & MAGIC_ERROR) {
+ file_error(ms, errno, "cannot stat `%s'", fn);
+ return -1;
}
+ if (file_printf(ms, "cannot open `%s' (%s)",
+ fn, strerror(errno)) == -1)
+ return -1;
+ return 0;
}
ret = 1;
@@ -183,6 +174,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, zend_stat_t *sb, php_stream *
if (mime) {
if (handle_mime(ms, mime, "fifo") == -1)
return -1;
+ } else if (silent) {
} else if (file_printf(ms, "%sfifo (named pipe)", COMMA) == -1)
return -1;
break;
@@ -192,6 +184,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, zend_stat_t *sb, php_stream *
if (mime) {
if (handle_mime(ms, mime, "door") == -1)
return -1;
+ } else if (silent) {
} else if (file_printf(ms, "%sdoor", COMMA) == -1)
return -1;
break;
diff --git a/ext/fileinfo/libmagic/funcs.c b/ext/fileinfo/libmagic/funcs.c
index 08ecaa393d..de7ffcfa50 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.94 2017/11/02 20:25:39 christos Exp $")
+FILE_RCSID("@(#)$File: funcs.c,v 1.104 2019/05/07 02:27:11 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -41,9 +41,7 @@ FILE_RCSID("@(#)$File: funcs.c,v 1.94 2017/11/02 20:25:39 christos Exp $")
#if defined(HAVE_WCTYPE_H)
#include <wctype.h>
#endif
-#if defined(HAVE_LOCALE_H)
-#include <locale.h>
-#endif
+#include <limits.h>
#ifndef SIZE_MAX
#define SIZE_MAX ((size_t)~0)
@@ -157,36 +155,83 @@ file_badread(struct magic_set *ms)
file_error(ms, errno, "error reading");
}
+protected int
+file_separator(struct magic_set *ms)
+{
+ return file_printf(ms, "\n- ");
+}
static int
checkdone(struct magic_set *ms, int *rv)
{
if ((ms->flags & MAGIC_CONTINUE) == 0)
return 1;
- if (file_printf(ms, "\n- ") == -1)
+ if (file_separator(ms) == -1)
*rv = -1;
return 0;
}
+protected int
+file_default(struct magic_set *ms, size_t nb)
+{
+ if (ms->flags & MAGIC_MIME) {
+ if ((ms->flags & MAGIC_MIME_TYPE) &&
+ file_printf(ms, "application/%s",
+ nb ? "octet-stream" : "x-empty") == -1)
+ return -1;
+ return 1;
+ }
+ if (ms->flags & MAGIC_APPLE) {
+ if (file_printf(ms, "UNKNUNKN") == -1)
+ return -1;
+ return 1;
+ }
+ if (ms->flags & MAGIC_EXTENSION) {
+ if (file_printf(ms, "???") == -1)
+ return -1;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * The magic detection functions return:
+ * 1: found
+ * 0: not found
+ * -1: error
+ */
/*ARGSUSED*/
protected int
-file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const void *buf,
- size_t nb)
+file_buffer(struct magic_set *ms, php_stream *stream, zend_stat_t *st,
+ const char *inname,
+ const void *buf, size_t nb)
{
int m = 0, rv = 0, looks_text = 0;
const char *code = NULL;
const char *code_mime = "binary";
- const char *type = "application/octet-stream";
const char *def = "data";
const char *ftype = NULL;
+ char *rbuf = NULL;
struct buffer b;
int fd = -1;
-
- buffer_init(&b, fd, buf, nb);
+
+ if (stream) {
+#ifdef _WIN64
+ php_socket_t _fd = fd;
+#else
+ int _fd;
+#endif
+ int _ret = php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&_fd, 0);
+ if (SUCCESS == _ret) {
+ fd = (int)_fd;
+ }
+ }
+
+ buffer_init(&b, fd, st, buf, nb);
+ ms->mode = b.st.st_mode;
if (nb == 0) {
def = "empty";
- type = "application/x-empty";
goto simple;
} else if (nb == 1) {
def = "very short file (no magic)";
@@ -235,50 +280,64 @@ file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const
}
}
+ /* Check if we have a JSON file */
+ if ((ms->flags & MAGIC_NO_CHECK_JSON) == 0) {
+ m = file_is_json(ms, &b);
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ (void)fprintf(stderr, "[try json %d]\n", m);
+ if (m) {
+ if (checkdone(ms, &rv))
+ goto done;
+ }
+ }
+
/* Check if we have a CDF file */
- if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0 && stream) {
-#ifdef _WIN64
- php_socket_t _fd = fd;
- int _ret = php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&_fd, 0);
- fd = (int)_fd;
-#else
- int _ret = php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&fd, 0);
-#endif
- if (SUCCESS == _ret) {
- m = file_trycdf(ms, &b);
- if ((ms->flags & MAGIC_DEBUG) != 0)
- (void)fprintf(stderr, "[try cdf %d]\n", m);
- if (m) {
- if (checkdone(ms, &rv))
- goto done;
- }
+ if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) {
+ m = file_trycdf(ms, &b);
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ (void)fprintf(stderr, "[try cdf %d]\n", m);
+ if (m) {
+ if (checkdone(ms, &rv))
+ goto done;
+ }
+ }
+#ifdef BUILTIN_ELF
+ if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && nb > 5 && fd != -1) {
+ file_pushbuf_t *pb;
+ /*
+ * We matched something in the file, so this
+ * *might* be an ELF file, and the file is at
+ * least 5 bytes long, so if it's an ELF file
+ * it has at least one byte past the ELF magic
+ * number - try extracting information from the
+ * ELF headers that cannot easily be extracted
+ * with rules in the magic file. We we don't
+ * print the information yet.
+ */
+ if ((pb = file_push_buffer(ms)) == NULL)
+ return -1;
+
+ rv = file_tryelf(ms, &b);
+ rbuf = file_pop_buffer(ms, pb);
+ if (rv == -1) {
+ free(rbuf);
+ rbuf = NULL;
}
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ (void)fprintf(stderr, "[try elf %d]\n", m);
}
+#endif
/* try soft magic tests */
if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) {
m = file_softmagic(ms, &b, NULL, NULL, BINTEST, looks_text);
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "[try softmagic %d]\n", m);
+ if (m == 1 && rbuf) {
+ if (file_printf(ms, "%s", rbuf) == -1)
+ goto done;
+ }
if (m) {
-#ifdef BUILTIN_ELF
- if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 &&
- nb > 5 && fd != -1) {
- /*
- * We matched something in the file, so this
- * *might* be an ELF file, and the file is at
- * least 5 bytes long, so if it's an ELF file
- * it has at least one byte past the ELF magic
- * number - try extracting information from the
- * ELF headers that cannot easily * be
- * extracted with rules in the magic file.
- */
- m = file_tryelf(ms, &b);
- if ((ms->flags & MAGIC_DEBUG) != 0)
- (void)fprintf(stderr, "[try elf %d]\n",
- m);
- }
-#endif
if (checkdone(ms, &rv))
goto done;
}
@@ -291,27 +350,18 @@ file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "[try ascmagic %d]\n", m);
if (m) {
- if (checkdone(ms, &rv))
- goto done;
+ goto done;
}
}
simple:
/* give up */
- m = 1;
- if (ms->flags & MAGIC_MIME) {
- if ((ms->flags & MAGIC_MIME_TYPE) &&
- file_printf(ms, "%s", type) == -1)
- rv = -1;
- } else if (ms->flags & MAGIC_APPLE) {
- if (file_printf(ms, "UNKNUNKN") == -1)
- rv = -1;
- } else if (ms->flags & MAGIC_EXTENSION) {
- if (file_printf(ms, "???") == -1)
- rv = -1;
- } else {
- if (file_printf(ms, "%s", def) == -1)
- rv = -1;
+ if (m == 0) {
+ m = 1;
+ rv = file_default(ms, nb);
+ if (rv == 0)
+ if (file_printf(ms, "%s", def) == -1)
+ rv = -1;
}
done:
if ((ms->flags & MAGIC_MIME_ENCODING) != 0) {
@@ -324,6 +374,7 @@ simple:
#if PHP_FILEINFO_UNCOMPRESS
done_encoding:
#endif
+ efree(rbuf);
buffer_fini(&b);
if (rv)
return rv;
@@ -354,9 +405,9 @@ file_reset(struct magic_set *ms, int checkloaded)
#define OCTALIFY(n, o) \
/*LINTED*/ \
(void)(*(n)++ = '\\', \
- *(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \
- *(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \
- *(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \
+ *(n)++ = ((CAST(uint32_t, *(o)) >> 6) & 3) + '0', \
+ *(n)++ = ((CAST(uint32_t, *(o)) >> 3) & 7) + '0', \
+ *(n)++ = ((CAST(uint32_t, *(o)) >> 0) & 7) + '0', \
(o)++)
protected const char *
@@ -402,9 +453,9 @@ file_getbuffer(struct magic_set *ms)
while (op < eop) {
bytesconsumed = mbrtowc(&nextchar, op,
- (size_t)(eop - op), &state);
- if (bytesconsumed == (size_t)(-1) ||
- bytesconsumed == (size_t)(-2)) {
+ CAST(size_t, eop - op), &state);
+ if (bytesconsumed == CAST(size_t, -1) ||
+ bytesconsumed == CAST(size_t, -2)) {
mb_conv = 0;
break;
}
@@ -427,7 +478,7 @@ file_getbuffer(struct magic_set *ms)
#endif
for (np = ms->o.pbuf, op = ms->o.buf; *op;) {
- if (isprint((unsigned char)*op)) {
+ if (isprint(CAST(unsigned char, *op))) {
*np++ = *op++;
} else {
OCTALIFY(np, op);
@@ -550,12 +601,13 @@ file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb)
* convert string to ascii printable format.
*/
protected char *
-file_printable(char *buf, size_t bufsiz, const char *str)
+file_printable(char *buf, size_t bufsiz, const char *str, size_t slen)
{
- char *ptr, *eptr;
- const unsigned char *s = (const unsigned char *)str;
+ char *ptr, *eptr = buf + bufsiz - 1;
+ const unsigned char *s = RCAST(const unsigned char *, str);
+ const unsigned char *es = s + slen;
- for (ptr = buf, eptr = ptr + bufsiz - 1; ptr < eptr && *s; s++) {
+ for (ptr = buf; ptr < eptr && s < es && *s; s++) {
if (isprint(*s)) {
*ptr++ = *s;
continue;
diff --git a/ext/fileinfo/libmagic/is_json.c b/ext/fileinfo/libmagic/is_json.c
new file mode 100644
index 0000000000..206ec3795e
--- /dev/null
+++ b/ext/fileinfo/libmagic/is_json.c
@@ -0,0 +1,462 @@
+/*-
+ * Copyright (c) 2018 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Parse JSON object serialization format (RFC-7159)
+ */
+
+#ifndef TEST
+#include "file.h"
+
+#ifndef lint
+FILE_RCSID("@(#)$File: is_json.c,v 1.13 2019/03/02 01:08:10 christos Exp $")
+#endif
+
+#include <string.h>
+#include "magic.h"
+#endif
+
+#ifdef DEBUG
+#include <stdio.h>
+#define DPRINTF(a, b, c) \
+ printf("%s [%.2x/%c] %.20s\n", (a), *(b), *(b), (const char *)(c))
+#else
+#define DPRINTF(a, b, c) do { } while (/*CONSTCOND*/0)
+#endif
+
+#define JSON_ARRAY 0
+#define JSON_CONSTANT 1
+#define JSON_NUMBER 2
+#define JSON_OBJECT 3
+#define JSON_STRING 4
+#define JSON_ARRAYN 5
+#define JSON_MAX 6
+
+/*
+ * if JSON_COUNT != 0:
+ * count all the objects, require that we have the whole data file
+ * otherwise:
+ * stop if we find an object or an array
+ */
+#ifndef JSON_COUNT
+#define JSON_COUNT 0
+#endif
+
+static int json_parse(const unsigned char **, const unsigned char *, size_t *,
+ size_t);
+
+static int
+json_isspace(const unsigned char uc)
+{
+ switch (uc) {
+ case ' ':
+ case '\n':
+ case '\r':
+ case '\t':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int
+json_isdigit(unsigned char uc)
+{
+ switch (uc) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int
+json_isxdigit(unsigned char uc)
+{
+ if (json_isdigit(uc))
+ return 1;
+ switch (uc) {
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static const unsigned char *
+json_skip_space(const unsigned char *uc, const unsigned char *ue)
+{
+ while (uc < ue && json_isspace(*uc))
+ uc++;
+ return uc;
+}
+
+static int
+json_parse_string(const unsigned char **ucp, const unsigned char *ue)
+{
+ const unsigned char *uc = *ucp;
+ size_t i;
+
+ DPRINTF("Parse string: ", uc, *ucp);
+ while (uc < ue) {
+ switch (*uc++) {
+ case '\0':
+ goto out;
+ case '\\':
+ if (uc == ue)
+ goto out;
+ switch (*uc++) {
+ case '\0':
+ goto out;
+ case '"':
+ case '\\':
+ case '/':
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+ continue;
+ case 'u':
+ if (ue - uc < 4) {
+ uc = ue;
+ goto out;
+ }
+ for (i = 0; i < 4; i++)
+ if (!json_isxdigit(*uc++))
+ goto out;
+ continue;
+ default:
+ goto out;
+ }
+ case '"':
+ *ucp = uc;
+ return 1;
+ default:
+ continue;
+ }
+ }
+out:
+ DPRINTF("Bad string: ", uc, *ucp);
+ *ucp = uc;
+ return 0;
+}
+
+static int
+json_parse_array(const unsigned char **ucp, const unsigned char *ue,
+ size_t *st, size_t lvl)
+{
+ const unsigned char *uc = *ucp;
+ int more = 0; /* Array has more than 1 element */
+
+ DPRINTF("Parse array: ", uc, *ucp);
+ while (uc < ue) {
+ if (!json_parse(&uc, ue, st, lvl + 1))
+ goto out;
+ if (uc == ue)
+ goto out;
+ switch (*uc) {
+ case ',':
+ more++;
+ uc++;
+ continue;
+ case ']':
+ if (more)
+ st[JSON_ARRAYN]++;
+ *ucp = uc + 1;
+ return 1;
+ default:
+ goto out;
+ }
+ }
+out:
+ DPRINTF("Bad array: ", uc, *ucp);
+ *ucp = uc;
+ return 0;
+}
+
+static int
+json_parse_object(const unsigned char **ucp, const unsigned char *ue,
+ size_t *st, size_t lvl)
+{
+ const unsigned char *uc = *ucp;
+ DPRINTF("Parse object: ", uc, *ucp);
+ while (uc < ue) {
+ uc = json_skip_space(uc, ue);
+ if (uc == ue)
+ goto out;
+ if (*uc++ != '"') {
+ DPRINTF("not string", uc, *ucp);
+ goto out;
+ }
+ DPRINTF("next field", uc, *ucp);
+ if (!json_parse_string(&uc, ue)) {
+ DPRINTF("not string", uc, *ucp);
+ goto out;
+ }
+ uc = json_skip_space(uc, ue);
+ if (uc == ue)
+ goto out;
+ if (*uc++ != ':') {
+ DPRINTF("not colon", uc, *ucp);
+ goto out;
+ }
+ if (!json_parse(&uc, ue, st, lvl + 1)) {
+ DPRINTF("not json", uc, *ucp);
+ goto out;
+ }
+ if (uc == ue)
+ goto out;
+ switch (*uc++) {
+ case ',':
+ continue;
+ case '}': /* { */
+ *ucp = uc;
+ DPRINTF("Good object: ", uc, *ucp);
+ return 1;
+ default:
+ *ucp = uc - 1;
+ DPRINTF("not more", uc, *ucp);
+ goto out;
+ }
+ }
+out:
+ DPRINTF("Bad object: ", uc, *ucp);
+ *ucp = uc;
+ return 0;
+}
+
+static int
+json_parse_number(const unsigned char **ucp, const unsigned char *ue)
+{
+ const unsigned char *uc = *ucp;
+ int got = 0;
+
+ DPRINTF("Parse number: ", uc, *ucp);
+ if (uc == ue)
+ return 0;
+ if (*uc == '-')
+ uc++;
+
+ for (; uc < ue; uc++) {
+ if (!json_isdigit(*uc))
+ break;
+ got = 1;
+ }
+ if (uc == ue)
+ goto out;
+ if (*uc == '.')
+ uc++;
+ for (; uc < ue; uc++) {
+ if (!json_isdigit(*uc))
+ break;
+ got = 1;
+ }
+ if (uc == ue)
+ goto out;
+ if (got && (*uc == 'e' || *uc == 'E')) {
+ uc++;
+ got = 0;
+ if (uc == ue)
+ goto out;
+ if (*uc == '+' || *uc == '-')
+ uc++;
+ for (; uc < ue; uc++) {
+ if (!json_isdigit(*uc))
+ break;
+ got = 1;
+ }
+ }
+out:
+ if (!got)
+ DPRINTF("Bad number: ", uc, *ucp);
+ else
+ DPRINTF("Good number: ", uc, *ucp);
+ *ucp = uc;
+ return got;
+}
+
+static int
+json_parse_const(const unsigned char **ucp, const unsigned char *ue,
+ const char *str, size_t len)
+{
+ const unsigned char *uc = *ucp;
+
+ DPRINTF("Parse const: ", uc, *ucp);
+ for (len--; uc < ue && --len;) {
+ if (*uc++ == *++str)
+ continue;
+ }
+ if (len)
+ DPRINTF("Bad const: ", uc, *ucp);
+ *ucp = uc;
+ return len == 0;
+}
+
+static int
+json_parse(const unsigned char **ucp, const unsigned char *ue,
+ size_t *st, size_t lvl)
+{
+ const unsigned char *uc;
+ int rv = 0;
+ int t;
+
+ uc = json_skip_space(*ucp, ue);
+ if (uc == ue)
+ goto out;
+
+ // Avoid recursion
+ if (lvl > 20)
+ return 0;
+#if JSON_COUNT
+ /* bail quickly if not counting */
+ if (lvl > 1 && (st[JSON_OBJECT] || st[JSON_ARRAYN]))
+ return 1;
+#endif
+
+ DPRINTF("Parse general: ", uc, *ucp);
+ switch (*uc++) {
+ case '"':
+ rv = json_parse_string(&uc, ue);
+ t = JSON_STRING;
+ break;
+ case '[':
+ rv = json_parse_array(&uc, ue, st, lvl + 1);
+ t = JSON_ARRAY;
+ break;
+ case '{': /* '}' */
+ rv = json_parse_object(&uc, ue, st, lvl + 1);
+ t = JSON_OBJECT;
+ break;
+ case 't':
+ rv = json_parse_const(&uc, ue, "true", sizeof("true"));
+ t = JSON_CONSTANT;
+ break;
+ case 'f':
+ rv = json_parse_const(&uc, ue, "false", sizeof("false"));
+ t = JSON_CONSTANT;
+ break;
+ case 'n':
+ rv = json_parse_const(&uc, ue, "null", sizeof("null"));
+ t = JSON_CONSTANT;
+ break;
+ default:
+ --uc;
+ rv = json_parse_number(&uc, ue);
+ t = JSON_NUMBER;
+ break;
+ }
+ if (rv)
+ st[t]++;
+ uc = json_skip_space(uc, ue);
+out:
+ *ucp = uc;
+ DPRINTF("End general: ", uc, *ucp);
+ if (lvl == 0)
+ return rv && (st[JSON_ARRAYN] || st[JSON_OBJECT]);
+ return rv;
+}
+
+#ifndef TEST
+int
+file_is_json(struct magic_set *ms, const struct buffer *b)
+{
+ const unsigned char *uc = CAST(const unsigned char *, b->fbuf);
+ const unsigned char *ue = uc + b->flen;
+ size_t st[JSON_MAX];
+ int mime = ms->flags & MAGIC_MIME;
+
+
+ if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) != 0)
+ return 0;
+
+ memset(st, 0, sizeof(st));
+
+ if (!json_parse(&uc, ue, st, 0))
+ return 0;
+
+ if (mime == MAGIC_MIME_ENCODING)
+ return 1;
+ if (mime) {
+ if (file_printf(ms, "application/json") == -1)
+ return -1;
+ return 1;
+ }
+ if (file_printf(ms, "JSON data") == -1)
+ return -1;
+#if JSON_COUNT
+#define P(n) st[n], st[n] > 1 ? "s" : ""
+ if (file_printf(ms, " (%" SIZE_T_FORMAT "u object%s, %" SIZE_T_FORMAT
+ "u array%s, %" SIZE_T_FORMAT "u string%s, %" SIZE_T_FORMAT
+ "u constant%s, %" SIZE_T_FORMAT "u number%s, %" SIZE_T_FORMAT
+ "u >1array%s)",
+ P(JSON_OBJECT), P(JSON_ARRAY), P(JSON_STRING), P(JSON_CONSTANT),
+ P(JSON_NUMBER), P(JSON_ARRAYN))
+ == -1)
+ return -1;
+#endif
+ return 1;
+}
+
+#else
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <err.h>
+
+int
+main(int argc, char *argv[])
+{
+ int fd, rv;
+ struct stat st;
+ unsigned char *p;
+ size_t stats[JSON_MAX];
+
+ if ((fd = open(argv[1], O_RDONLY)) == -1)
+ err(EXIT_FAILURE, "Can't open `%s'", argv[1]);
+
+ if (fstat(fd, &st) == -1)
+ err(EXIT_FAILURE, "Can't stat `%s'", argv[1]);
+
+ if ((p = malloc(st.st_size)) == NULL)
+ err(EXIT_FAILURE, "Can't allocate %jd bytes",
+ (intmax_t)st.st_size);
+ if (read(fd, p, st.st_size) != st.st_size)
+ err(EXIT_FAILURE, "Can't read %jd bytes",
+ (intmax_t)st.st_size);
+ memset(stats, 0, sizeof(stats));
+ printf("is json %d\n", json_parse((const unsigned char **)&p,
+ p + st.st_size, stats, 0));
+ return 0;
+}
+#endif
diff --git a/ext/fileinfo/libmagic/is_tar.c b/ext/fileinfo/libmagic/is_tar.c
index 7110604f9e..82b08051fb 100644
--- a/ext/fileinfo/libmagic/is_tar.c
+++ b/ext/fileinfo/libmagic/is_tar.c
@@ -40,7 +40,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: is_tar.c,v 1.41 2017/11/02 20:25:39 christos Exp $")
+FILE_RCSID("@(#)$File: is_tar.c,v 1.44 2019/02/20 02:35:27 christos Exp $")
#endif
#include "magic.h"
@@ -62,7 +62,7 @@ static const char tartype[][32] = { /* should be equal to messages */
protected int
file_is_tar(struct magic_set *ms, const struct buffer *b)
{
- const unsigned char *buf = b->fbuf;
+ const unsigned char *buf = CAST(const unsigned char *, b->fbuf);
size_t nbytes = b->flen;
/*
* Do the tar test first, because if the first file in the tar
@@ -78,9 +78,13 @@ file_is_tar(struct magic_set *ms, const struct buffer *b)
if (tar < 1 || tar > 3)
return 0;
+ if (mime == MAGIC_MIME_ENCODING)
+ return 1;
+
if (file_printf(ms, "%s", mime ? "application/x-tar" :
tartype[tar - 1]) == -1)
return -1;
+
return 1;
}
@@ -94,7 +98,8 @@ file_is_tar(struct magic_set *ms, const struct buffer *b)
private int
is_tar(const unsigned char *buf, size_t nbytes)
{
- const union record *header = (const union record *)(const void *)buf;
+ const union record *header = RCAST(const union record *,
+ RCAST(const void *, buf));
size_t i;
int sum, recsum;
const unsigned char *p, *ep;
@@ -143,7 +148,7 @@ from_oct(const char *where, size_t digs)
if (digs == 0)
return -1;
- while (isspace((unsigned char)*where)) { /* Skip spaces */
+ while (isspace(CAST(unsigned char, *where))) { /* Skip spaces */
where++;
if (digs-- == 0)
return -1; /* All blank field */
@@ -154,7 +159,7 @@ from_oct(const char *where, size_t digs)
digs--;
}
- if (digs > 0 && *where && !isspace((unsigned char)*where))
+ if (digs > 0 && *where && !isspace(CAST(unsigned char, *where)))
return -1; /* Ended on non-(space/NUL) */
return value;
diff --git a/ext/fileinfo/libmagic/magic.c b/ext/fileinfo/libmagic/magic.c
index 1cff11a5c0..56c8acfcac 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.102 2017/08/28 13:39:18 christos Exp $")
+FILE_RCSID("@(#)$File: magic.c,v 1.111 2019/05/07 02:27:11 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -45,7 +45,6 @@ FILE_RCSID("@(#)$File: magic.c,v 1.102 2017/08/28 13:39:18 christos Exp $")
#ifdef PHP_WIN32
#include <shlwapi.h>
#endif
-
#include <limits.h> /* for PIPE_BUF */
#if defined(HAVE_UTIMES)
@@ -233,10 +232,6 @@ file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
if (file_reset(ms, 1) == -1)
goto out;
- if (!inname && !stream) {
- return NULL;
- }
-
/*
* one extra for terminating '\0', and
* some overlapping space for matches near EOF
@@ -245,7 +240,7 @@ file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
if ((buf = CAST(unsigned char *, emalloc(ms->bytes_max + SLOP))) == NULL)
return NULL;
- switch (file_fsmagic(ms, inname, &sb, stream)) {
+ switch (file_fsmagic(ms, inname, &sb)) {
case -1: /* error */
goto done;
case 0: /* nothing found */
@@ -257,21 +252,26 @@ file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
errno = 0;
- if (!stream && inname) {
+ if (inname && !stream) {
no_in_stream = 1;
stream = php_stream_open_wrapper((char *)inname, "rb", REPORT_ERRORS, NULL);
+ if (!stream) {
+ if (unreadable_info(ms, sb.st_mode, inname) == -1)
+ goto done;
+ rv = -1;
+ goto done;
+ }
}
- if (!stream) {
- if (unreadable_info(ms, sb.st_mode, inname) == -1)
+ php_stream_statbuf ssb;
+ if (php_stream_stat(stream, &ssb) < 0) {
+ if (ms->flags & MAGIC_ERROR) {
+ file_error(ms, errno, "cannot stat `%s'", inname);
+ rv = -1;
goto done;
- rv = 0;
- goto done;
+ }
}
-
-#ifdef O_NONBLOCK
-/* we should be already be in non blocking mode for network socket */
-#endif
+ memcpy(&sb, &ssb.sb, sizeof(zend_stat_t));
/*
* try looking at the first ms->bytes_max bytes
@@ -282,7 +282,7 @@ file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
}
(void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */
- if (file_buffer(ms, stream, inname, buf, (size_t)nbytes) == -1)
+ if (file_buffer(ms, stream, &sb, inname, buf, CAST(size_t, nbytes)) == -1)
goto done;
rv = 0;
done:
@@ -307,7 +307,7 @@ magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
* The main work is done here!
* We have the file name and/or the data buffer to be identified.
*/
- if (file_buffer(ms, NULL, NULL, buf, nb) == -1) {
+ if (file_buffer(ms, NULL, NULL, NULL, buf, nb) == -1) {
return NULL;
}
return file_getbuffer(ms);
@@ -360,27 +360,29 @@ magic_version(void)
public int
magic_setparam(struct magic_set *ms, int param, const void *val)
{
+ if (ms == NULL)
+ return -1;
switch (param) {
case MAGIC_PARAM_INDIR_MAX:
- ms->indir_max = (uint16_t)*(const size_t *)val;
+ ms->indir_max = CAST(uint16_t, *CAST(const size_t *, val));
return 0;
case MAGIC_PARAM_NAME_MAX:
- ms->name_max = (uint16_t)*(const size_t *)val;
+ ms->name_max = CAST(uint16_t, *CAST(const size_t *, val));
return 0;
case MAGIC_PARAM_ELF_PHNUM_MAX:
- ms->elf_phnum_max = (uint16_t)*(const size_t *)val;
+ ms->elf_phnum_max = CAST(uint16_t, *CAST(const size_t *, val));
return 0;
case MAGIC_PARAM_ELF_SHNUM_MAX:
- ms->elf_shnum_max = (uint16_t)*(const size_t *)val;
+ ms->elf_shnum_max = CAST(uint16_t, *CAST(const size_t *, val));
return 0;
case MAGIC_PARAM_ELF_NOTES_MAX:
- ms->elf_notes_max = (uint16_t)*(const size_t *)val;
+ ms->elf_notes_max = CAST(uint16_t, *CAST(const size_t *, val));
return 0;
case MAGIC_PARAM_REGEX_MAX:
- ms->elf_notes_max = (uint16_t)*(const size_t *)val;
+ ms->regex_max = CAST(uint16_t, *CAST(const size_t *, val));
return 0;
case MAGIC_PARAM_BYTES_MAX:
- ms->bytes_max = *(const size_t *)val;
+ ms->bytes_max = *CAST(const size_t *, val);
return 0;
default:
errno = EINVAL;
@@ -391,27 +393,29 @@ magic_setparam(struct magic_set *ms, int param, const void *val)
public int
magic_getparam(struct magic_set *ms, int param, void *val)
{
+ if (ms == NULL)
+ return -1;
switch (param) {
case MAGIC_PARAM_INDIR_MAX:
- *(size_t *)val = ms->indir_max;
+ *CAST(size_t *, val) = ms->indir_max;
return 0;
case MAGIC_PARAM_NAME_MAX:
- *(size_t *)val = ms->name_max;
+ *CAST(size_t *, val) = ms->name_max;
return 0;
case MAGIC_PARAM_ELF_PHNUM_MAX:
- *(size_t *)val = ms->elf_phnum_max;
+ *CAST(size_t *, val) = ms->elf_phnum_max;
return 0;
case MAGIC_PARAM_ELF_SHNUM_MAX:
- *(size_t *)val = ms->elf_shnum_max;
+ *CAST(size_t *, val) = ms->elf_shnum_max;
return 0;
case MAGIC_PARAM_ELF_NOTES_MAX:
- *(size_t *)val = ms->elf_notes_max;
+ *CAST(size_t *, val) = ms->elf_notes_max;
return 0;
case MAGIC_PARAM_REGEX_MAX:
- *(size_t *)val = ms->regex_max;
+ *CAST(size_t *, val) = ms->regex_max;
return 0;
case MAGIC_PARAM_BYTES_MAX:
- *(size_t *)val = ms->bytes_max;
+ *CAST(size_t *, val) = ms->bytes_max;
return 0;
default:
errno = EINVAL;
diff --git a/ext/fileinfo/libmagic/magic.h b/ext/fileinfo/libmagic/magic.h
index a5ba79f059..ee0aa13678 100644
--- a/ext/fileinfo/libmagic/magic.h
+++ b/ext/fileinfo/libmagic/magic.h
@@ -58,6 +58,7 @@
#define MAGIC_NO_CHECK_CDF 0x0040000 /* Don't check for cdf files */
#define MAGIC_NO_CHECK_TOKENS 0x0100000 /* Don't check tokens */
#define MAGIC_NO_CHECK_ENCODING 0x0200000 /* Don't check text encodings */
+#define MAGIC_NO_CHECK_JSON 0x0400000 /* Don't check for JSON files */
/* No built-in tests; only consult the magic file */
#define MAGIC_NO_CHECK_BUILTIN ( \
@@ -70,6 +71,7 @@
MAGIC_NO_CHECK_CDF | \
MAGIC_NO_CHECK_TOKENS | \
MAGIC_NO_CHECK_ENCODING | \
+ MAGIC_NO_CHECK_JSON | \
0 \
)
@@ -96,7 +98,7 @@ b\22no_check_cdf\0\
b\23no_check_reserved0\0\
b\24no_check_tokens\0\
b\25no_check_encoding\0\
-b\26no_check_reserved1\0\
+b\26no_check_json\0\
b\27no_check_reserved2\0\
b\30extension\0\
b\31transp_compression\0\
@@ -109,7 +111,7 @@ b\31transp_compression\0\
#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 533 /* This implementation */
+#define MAGIC_VERSION 537 /* This implementation */
#ifdef __cplusplus
diff --git a/ext/fileinfo/libmagic/patchlevel.h b/ext/fileinfo/libmagic/patchlevel.h
index 40921601e5..a645509bdd 100644
--- a/ext/fileinfo/libmagic/patchlevel.h
+++ b/ext/fileinfo/libmagic/patchlevel.h
@@ -1,11 +1,15 @@
#define FILE_VERSION_MAJOR 5
-#define patchlevel 33
+#define patchlevel 37
/*
* Patchlevel file for Ian Darwin's MAGIC command.
* $File: patchlevel.h,v 1.68 2008/03/22 21:39:43 christos Exp $
*
* $Log$
+ * Revision 2.1 2019/05/30 22:27:12 ab
+ * Update libmagic to 5.37
+ *
+ * $Log$
* Revision 2.1 2018/04/26 22:27:12 ab
* Update libmagic to 5.33
*
diff --git a/ext/fileinfo/libmagic/print.c b/ext/fileinfo/libmagic/print.c
index 9102c55ec0..deb855d98e 100644
--- a/ext/fileinfo/libmagic/print.c
+++ b/ext/fileinfo/libmagic/print.c
@@ -33,7 +33,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: print.c,v 1.82 2017/02/10 18:14:01 christos Exp $")
+FILE_RCSID("@(#)$File: print.c,v 1.85 2019/03/12 20:43:05 christos Exp $")
#endif /* lint */
#include <string.h>
@@ -66,9 +66,9 @@ file_mdump(struct magic *m)
if (m->in_op & FILE_OPINVERSE)
(void) fputc('~', stderr);
(void) fprintf(stderr, "%c%u),",
- ((size_t)(m->in_op & FILE_OPS_MASK) <
- SZOF(optyp)) ? optyp[m->in_op & FILE_OPS_MASK] : '?',
- m->in_offset);
+ (CAST(size_t, m->in_op & FILE_OPS_MASK) <
+ __arraycount(optyp)) ?
+ optyp[m->in_op & FILE_OPS_MASK] : '?', m->in_offset);
}
(void) fprintf(stderr, " %s%s", (m->flag & UNSIGNED) ? "u" : "",
/* Note: type is unsigned */
@@ -79,16 +79,16 @@ file_mdump(struct magic *m)
if (IS_LIBMAGIC_STRING(m->type)) {
if (m->str_flags) {
(void) fputc('/', stderr);
- if (m->str_flags & STRING_COMPACT_WHITESPACE)
+ if (m->str_flags & STRING_COMPACT_WHITESPACE)
(void) fputc(CHAR_COMPACT_WHITESPACE, stderr);
- if (m->str_flags & STRING_COMPACT_OPTIONAL_WHITESPACE)
+ if (m->str_flags & STRING_COMPACT_OPTIONAL_WHITESPACE)
(void) fputc(CHAR_COMPACT_OPTIONAL_WHITESPACE,
stderr);
- if (m->str_flags & STRING_IGNORE_LOWERCASE)
+ if (m->str_flags & STRING_IGNORE_LOWERCASE)
(void) fputc(CHAR_IGNORE_LOWERCASE, stderr);
- if (m->str_flags & STRING_IGNORE_UPPERCASE)
+ if (m->str_flags & STRING_IGNORE_UPPERCASE)
(void) fputc(CHAR_IGNORE_UPPERCASE, stderr);
- if (m->str_flags & REGEX_OFFSET_START)
+ if (m->str_flags & REGEX_OFFSET_START)
(void) fputc(CHAR_REGEX_OFFSET_START, stderr);
if (m->str_flags & STRING_TEXTTEST)
(void) fputc(CHAR_TEXTTEST, stderr);
@@ -113,14 +113,15 @@ file_mdump(struct magic *m)
(void) fprintf(stderr, "/%u", m->str_range);
}
else {
- if ((size_t)(m->mask_op & FILE_OPS_MASK) < SZOF(optyp))
+ if (CAST(size_t, m->mask_op & FILE_OPS_MASK) <
+ __arraycount(optyp))
(void) fputc(optyp[m->mask_op & FILE_OPS_MASK], stderr);
else
(void) fputc('?', stderr);
-
+
if (m->num_mask) {
(void) fprintf(stderr, "%.8llx",
- (unsigned long long)m->num_mask);
+ CAST(unsigned long long, m->num_mask));
}
}
(void) fprintf(stderr, ",%c", m->reln);
@@ -142,7 +143,7 @@ file_mdump(struct magic *m)
case FILE_LEQUAD:
case FILE_QUAD:
(void) fprintf(stderr, "%" INT64_T_FORMAT "d",
- (unsigned long long)m->value.q);
+ CAST(long long, m->value.q));
break;
case FILE_PSTRING:
case FILE_STRING:
@@ -150,7 +151,8 @@ file_mdump(struct magic *m)
case FILE_BESTRING16:
case FILE_LESTRING16:
case FILE_SEARCH:
- file_showstr(stderr, m->value.s, (size_t)m->vallen);
+ file_showstr(stderr, m->value.s,
+ CAST(size_t, m->vallen));
break;
case FILE_DATE:
case FILE_LEDATE:
@@ -244,7 +246,7 @@ file_fmttime(uint64_t v, int flags, char *buf)
} else {
// XXX: perhaps detect and print something if overflow
// on 32 bit time_t?
- t = (time_t)v;
+ t = CAST(time_t, v);
}
if (flags & FILE_T_LOCAL) {
diff --git a/ext/fileinfo/libmagic/readcdf.c b/ext/fileinfo/libmagic/readcdf.c
index 4a3ddc60ff..f3b8f1ce7a 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.66 2017/11/02 20:25:39 christos Exp $")
+FILE_RCSID("@(#)$File: readcdf.c,v 1.73 2019/03/12 20:43:05 christos Exp $")
#endif
#include <assert.h>
@@ -43,10 +43,6 @@ FILE_RCSID("@(#)$File: readcdf.c,v 1.66 2017/11/02 20:25:39 christos Exp $")
#include "cdf.h"
#include "magic.h"
-#ifndef __arraycount
-#define __arraycount(a) (sizeof(a) / sizeof(a[0]))
-#endif
-
#define NOTMIME(ms) (((ms)->flags & MAGIC_MIME) == 0)
static const struct nv {
@@ -131,13 +127,13 @@ private int
cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info,
size_t count, const cdf_directory_t *root_storage)
{
- size_t i;
- cdf_timestamp_t tp;
- struct timespec ts;
- char buf[64];
- const char *str = NULL;
- const char *s, *e;
- int len;
+ size_t i;
+ cdf_timestamp_t tp;
+ struct timespec ts;
+ char buf[64];
+ const char *str = NULL;
+ const char *s, *e;
+ int len;
memset(&ts, 0, sizeof(ts));
@@ -145,106 +141,106 @@ cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info,
str = cdf_clsid_to_mime(root_storage->d_storage_uuid,
clsid2mime);
- for (i = 0; i < count; i++) {
- cdf_print_property_name(buf, sizeof(buf), info[i].pi_id);
- switch (info[i].pi_type) {
- case CDF_NULL:
- break;
- case CDF_SIGNED16:
- if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf,
- info[i].pi_s16) == -1)
- return -1;
- break;
- case CDF_SIGNED32:
- if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf,
- info[i].pi_s32) == -1)
- return -1;
- break;
- case CDF_UNSIGNED32:
- if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf,
- info[i].pi_u32) == -1)
- return -1;
- break;
- case CDF_FLOAT:
- if (NOTMIME(ms) && file_printf(ms, ", %s: %g", buf,
- info[i].pi_f) == -1)
- return -1;
- break;
- case CDF_DOUBLE:
- if (NOTMIME(ms) && file_printf(ms, ", %s: %g", buf,
- info[i].pi_d) == -1)
- return -1;
- break;
- case CDF_LENGTH32_STRING:
- case CDF_LENGTH32_WSTRING:
- len = info[i].pi_str.s_len;
- if (len > 1) {
- char vbuf[1024];
- size_t j, k = 1;
-
- if (info[i].pi_type == CDF_LENGTH32_WSTRING)
- k++;
- s = info[i].pi_str.s_buf;
+ for (i = 0; i < count; i++) {
+ cdf_print_property_name(buf, sizeof(buf), info[i].pi_id);
+ switch (info[i].pi_type) {
+ case CDF_NULL:
+ break;
+ case CDF_SIGNED16:
+ if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf,
+ info[i].pi_s16) == -1)
+ return -1;
+ break;
+ case CDF_SIGNED32:
+ if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf,
+ info[i].pi_s32) == -1)
+ return -1;
+ break;
+ case CDF_UNSIGNED32:
+ if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf,
+ info[i].pi_u32) == -1)
+ return -1;
+ break;
+ case CDF_FLOAT:
+ if (NOTMIME(ms) && file_printf(ms, ", %s: %g", buf,
+ info[i].pi_f) == -1)
+ return -1;
+ break;
+ case CDF_DOUBLE:
+ if (NOTMIME(ms) && file_printf(ms, ", %s: %g", buf,
+ info[i].pi_d) == -1)
+ return -1;
+ break;
+ case CDF_LENGTH32_STRING:
+ case CDF_LENGTH32_WSTRING:
+ len = info[i].pi_str.s_len;
+ if (len > 1) {
+ char vbuf[1024];
+ size_t j, k = 1;
+
+ if (info[i].pi_type == CDF_LENGTH32_WSTRING)
+ k++;
+ s = info[i].pi_str.s_buf;
e = info[i].pi_str.s_buf + len;
- for (j = 0; s < e && j < sizeof(vbuf)
+ for (j = 0; s < e && j < sizeof(vbuf)
&& len--; s += k) {
- if (*s == '\0')
- break;
- if (isprint((unsigned char)*s))
- vbuf[j++] = *s;
- }
- if (j == sizeof(vbuf))
- --j;
- vbuf[j] = '\0';
- if (NOTMIME(ms)) {
- if (vbuf[0]) {
- if (file_printf(ms, ", %s: %s",
- buf, vbuf) == -1)
- return -1;
- }
- } else if (str == NULL && info[i].pi_id ==
+ if (*s == '\0')
+ break;
+ if (isprint(CAST(unsigned char, *s)))
+ vbuf[j++] = *s;
+ }
+ if (j == sizeof(vbuf))
+ --j;
+ vbuf[j] = '\0';
+ if (NOTMIME(ms)) {
+ if (vbuf[0]) {
+ if (file_printf(ms, ", %s: %s",
+ buf, vbuf) == -1)
+ return -1;
+ }
+ } else if (str == NULL && info[i].pi_id ==
CDF_PROPERTY_NAME_OF_APPLICATION) {
str = cdf_app_to_mime(vbuf, app2mime);
}
}
- break;
- case CDF_FILETIME:
- tp = info[i].pi_tp;
- if (tp != 0) {
+ break;
+ case CDF_FILETIME:
+ tp = info[i].pi_tp;
+ if (tp != 0) {
char tbuf[64];
- if (tp < 1000000000000000LL) {
- cdf_print_elapsed_time(tbuf,
- sizeof(tbuf), tp);
- if (NOTMIME(ms) && file_printf(ms,
- ", %s: %s", buf, tbuf) == -1)
- return -1;
- } else {
- char *c, *ec;
- cdf_timestamp_to_timespec(&ts, tp);
- c = cdf_ctime(&ts.tv_sec, tbuf);
- if (c != NULL &&
+ if (tp < 1000000000000000LL) {
+ cdf_print_elapsed_time(tbuf,
+ sizeof(tbuf), tp);
+ if (NOTMIME(ms) && file_printf(ms,
+ ", %s: %s", buf, tbuf) == -1)
+ return -1;
+ } else {
+ char *c, *ec;
+ cdf_timestamp_to_timespec(&ts, tp);
+ c = cdf_ctime(&ts.tv_sec, tbuf);
+ if (c != NULL &&
(ec = strchr(c, '\n')) != NULL)
*ec = '\0';
- if (NOTMIME(ms) && file_printf(ms,
- ", %s: %s", buf, c) == -1)
- return -1;
- }
- }
- break;
- case CDF_CLIPBOARD:
- break;
- default:
- return -1;
- }
- }
- if (!NOTMIME(ms)) {
+ if (NOTMIME(ms) && file_printf(ms,
+ ", %s: %s", buf, c) == -1)
+ return -1;
+ }
+ }
+ break;
+ case CDF_CLIPBOARD:
+ break;
+ default:
+ return -1;
+ }
+ }
+ if (ms->flags & MAGIC_MIME_TYPE) {
if (str == NULL)
return 0;
- if (file_printf(ms, "application/%s", str) == -1)
- return -1;
- }
- return 1;
+ if (file_printf(ms, "application/%s", str) == -1)
+ return -1;
+ }
+ return 1;
}
private int
@@ -256,7 +252,7 @@ cdf_file_catalog(struct magic_set *ms, const cdf_header_t *h,
char buf[256];
cdf_catalog_entry_t *ce;
- if (NOTMIME(ms)) {
+ if (NOTMIME(ms)) {
if (file_printf(ms, "Microsoft Thumbs.db [") == -1)
return -1;
if (cdf_unpack_catalog(h, sst, &cat) == -1)
@@ -271,7 +267,7 @@ cdf_file_catalog(struct magic_set *ms, const cdf_header_t *h,
return -1;
}
efree(cat);
- } else {
+ } else if (ms->flags & MAGIC_MIME_TYPE) {
if (file_printf(ms, "application/CDFV2") == -1)
return -1;
}
@@ -282,44 +278,44 @@ private int
cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h,
const cdf_stream_t *sst, const cdf_directory_t *root_storage)
{
- cdf_summary_info_header_t si;
- cdf_property_info_t *info;
- size_t count;
- int m;
+ cdf_summary_info_header_t si;
+ cdf_property_info_t *info;
+ size_t count;
+ int m;
- if (cdf_unpack_summary_info(sst, h, &si, &info, &count) == -1)
- return -1;
+ if (cdf_unpack_summary_info(sst, h, &si, &info, &count) == -1)
+ return -1;
- if (NOTMIME(ms)) {
+ if (NOTMIME(ms)) {
const char *str;
- if (file_printf(ms, "Composite Document File V2 Document")
+ if (file_printf(ms, "Composite Document File V2 Document")
== -1)
- return -1;
-
- if (file_printf(ms, ", %s Endian",
- si.si_byte_order == 0xfffe ? "Little" : "Big") == -1)
- return -2;
- switch (si.si_os) {
- case 2:
- if (file_printf(ms, ", Os: Windows, Version %d.%d",
- si.si_os_version & 0xff,
- (uint32_t)si.si_os_version >> 8) == -1)
- return -2;
- break;
- case 1:
- if (file_printf(ms, ", Os: MacOS, Version %d.%d",
- (uint32_t)si.si_os_version >> 8,
- si.si_os_version & 0xff) == -1)
- return -2;
- break;
- default:
- if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os,
- si.si_os_version & 0xff,
- (uint32_t)si.si_os_version >> 8) == -1)
- return -2;
- break;
- }
+ return -1;
+
+ if (file_printf(ms, ", %s Endian",
+ si.si_byte_order == 0xfffe ? "Little" : "Big") == -1)
+ return -2;
+ switch (si.si_os) {
+ case 2:
+ if (file_printf(ms, ", Os: Windows, Version %d.%d",
+ si.si_os_version & 0xff,
+ CAST(uint32_t, si.si_os_version) >> 8) == -1)
+ return -2;
+ break;
+ case 1:
+ if (file_printf(ms, ", Os: MacOS, Version %d.%d",
+ CAST(uint32_t, si.si_os_version) >> 8,
+ si.si_os_version & 0xff) == -1)
+ return -2;
+ break;
+ default:
+ if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os,
+ si.si_os_version & 0xff,
+ CAST(uint32_t, si.si_os_version) >> 8) == -1)
+ return -2;
+ break;
+ }
if (root_storage) {
str = cdf_clsid_to_mime(root_storage->d_storage_uuid,
clsid2desc);
@@ -330,10 +326,10 @@ cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h,
}
}
- m = cdf_file_property_info(ms, info, count, root_storage);
- efree(info);
+ m = cdf_file_property_info(ms, info, count, root_storage);
+ efree(info);
- return m == -1 ? -2 : m;
+ return m == -1 ? -2 : m;
}
#ifdef notdef
@@ -381,10 +377,10 @@ cdf_check_summary_info(struct magic_set *ms, const cdf_info_t *info,
size_t j, k;
#ifdef CDF_DEBUG
- cdf_dump_summary_info(h, scn);
+ cdf_dump_summary_info(h, scn);
#endif
- if ((i = cdf_file_summary_info(ms, h, scn, root_storage)) < 0) {
- *expn = "Can't expand summary_info";
+ if ((i = cdf_file_summary_info(ms, h, scn, root_storage)) < 0) {
+ *expn = "Can't expand summary_info";
return i;
}
if (i == 1)
@@ -392,7 +388,7 @@ cdf_check_summary_info(struct magic_set *ms, const cdf_info_t *info,
for (j = 0; str == NULL && j < dir->dir_len; j++) {
d = &dir->dir_tab[j];
for (k = 0; k < sizeof(name); k++)
- name[k] = (char)cdf_tole2(d->d_name[k]);
+ name[k] = CAST(char, cdf_tole2(d->d_name[k]));
str = cdf_app_to_mime(name,
NOTMIME(ms) ? name2desc : name2mime);
}
@@ -402,7 +398,7 @@ cdf_check_summary_info(struct magic_set *ms, const cdf_info_t *info,
return -1;
i = 1;
}
- } else {
+ } else if (ms->flags & MAGIC_MIME_TYPE) {
if (str == NULL)
str = "vnd.ms-office";
if (file_printf(ms, "application/%s", str) == -1)
@@ -513,7 +509,7 @@ cdf_file_dir_info(struct magic_set *ms, const cdf_dir_t *dir)
if (NOTMIME(ms)) {
if (file_printf(ms, "CDFV2 %s", si->name) == -1)
return -1;
- } else {
+ } else if (ms->flags & MAGIC_MIME_TYPE) {
if (file_printf(ms, "application/%s", si->mime) == -1)
return -1;
}
@@ -526,57 +522,57 @@ protected int
file_trycdf(struct magic_set *ms, const struct buffer *b)
{
int fd = b->fd;
- const unsigned char *buf = b->fbuf;
+ const unsigned char *buf = CAST(const unsigned char *, b->fbuf);
size_t nbytes = b->flen;
- cdf_info_t info;
- cdf_header_t h;
- cdf_sat_t sat, ssat;
- cdf_stream_t sst, scn;
- cdf_dir_t dir;
- int i;
- const char *expn = "";
- const cdf_directory_t *root_storage;
-
- scn.sst_tab = NULL;
- info.i_fd = fd;
- info.i_buf = buf;
- info.i_len = nbytes;
- if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))
- return 0;
- if (cdf_read_header(&info, &h) == -1)
- return 0;
+ cdf_info_t info;
+ cdf_header_t h;
+ cdf_sat_t sat, ssat;
+ cdf_stream_t sst, scn;
+ cdf_dir_t dir;
+ int i;
+ const char *expn = "";
+ const cdf_directory_t *root_storage;
+
+ scn.sst_tab = NULL;
+ info.i_fd = fd;
+ info.i_buf = buf;
+ info.i_len = nbytes;
+ if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))
+ return 0;
+ if (cdf_read_header(&info, &h) == -1)
+ return 0;
#ifdef CDF_DEBUG
- cdf_dump_header(&h);
+ cdf_dump_header(&h);
#endif
- if ((i = cdf_read_sat(&info, &h, &sat)) == -1) {
- expn = "Can't read SAT";
- goto out0;
- }
+ if ((i = cdf_read_sat(&info, &h, &sat)) == -1) {
+ expn = "Can't read SAT";
+ goto out0;
+ }
#ifdef CDF_DEBUG
- cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h));
+ cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h));
#endif
- if ((i = cdf_read_ssat(&info, &h, &sat, &ssat)) == -1) {
- expn = "Can't read SSAT";
- goto out1;
- }
+ if ((i = cdf_read_ssat(&info, &h, &sat, &ssat)) == -1) {
+ expn = "Can't read SSAT";
+ goto out1;
+ }
#ifdef CDF_DEBUG
- cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h));
+ cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h));
#endif
- if ((i = cdf_read_dir(&info, &h, &sat, &dir)) == -1) {
- expn = "Can't read directory";
- goto out2;
- }
+ if ((i = cdf_read_dir(&info, &h, &sat, &dir)) == -1) {
+ expn = "Can't read directory";
+ goto out2;
+ }
- if ((i = cdf_read_short_stream(&info, &h, &sat, &dir, &sst,
+ if ((i = cdf_read_short_stream(&info, &h, &sat, &dir, &sst,
&root_storage)) == -1) {
- expn = "Cannot read short stream";
- goto out3;
- }
+ expn = "Cannot read short stream";
+ goto out3;
+ }
#ifdef CDF_DEBUG
- cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir);
+ cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir);
#endif
#ifdef notdef
if (root_storage) {
@@ -600,7 +596,7 @@ file_trycdf(struct magic_set *ms, const struct buffer *b)
if (file_printf(ms,
"Hangul (Korean) Word Processor File 5.x") == -1)
return -1;
- } else {
+ } else if (ms->flags & MAGIC_MIME_TYPE) {
if (file_printf(ms, "application/x-hwp") == -1)
return -1;
}
@@ -611,10 +607,10 @@ file_trycdf(struct magic_set *ms, const struct buffer *b)
}
}
- if ((i = cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir,
- &scn)) == -1) {
- if (errno != ESRCH) {
- expn = "Cannot read summary info";
+ if ((i = cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir,
+ &scn)) == -1) {
+ if (errno != ESRCH) {
+ expn = "Cannot read summary info";
}
} else {
i = cdf_check_summary_info(ms, &info, &h,
@@ -647,19 +643,20 @@ out2:
out1:
efree(sat.sat_tab);
out0:
- if (i == -1) {
- if (NOTMIME(ms)) {
+ /* If we handled it already, return */
+ if (i != -1)
+ return i;
+ /* Provide a default handler */
+ if (NOTMIME(ms)) {
if (file_printf(ms,
"Composite Document File V2 Document") == -1)
- return -1;
- if (*expn)
- if (file_printf(ms, ", %s", expn) == -1)
return -1;
- } else {
+ if (*expn)
+ if (file_printf(ms, ", %s", expn) == -1)
+ return -1;
+ } else if (ms->flags & MAGIC_MIME_TYPE) {
if (file_printf(ms, "application/CDFV2") == -1)
- return -1;
- }
- i = 1;
+ return -1;
}
- return i;
+ return 1;
}
diff --git a/ext/fileinfo/libmagic/softmagic.c b/ext/fileinfo/libmagic/softmagic.c
index 75bde73811..879a83b9a9 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.259 2018/03/11 01:23:52 christos Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.286 2019/05/17 02:24:59 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -49,16 +49,15 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.259 2018/03/11 01:23:52 christos Exp $")
private int match(struct magic_set *, struct magic *, uint32_t,
const struct buffer *, size_t, int, int, int, uint16_t *,
- uint16_t *, int *, int *, int *);
+ uint16_t *, int *, int *, int *, int *);
private int mget(struct magic_set *, struct magic *, const struct buffer *,
- const unsigned char *, size_t,
+ const unsigned char *, size_t,
size_t, unsigned int, int, int, int, uint16_t *,
- uint16_t *, int *, int *, int *);
+ uint16_t *, int *, int *, int *, int *);
private int msetoffset(struct magic_set *, struct magic *, struct buffer *,
const struct buffer *, size_t, unsigned int);
private int magiccheck(struct magic_set *, struct magic *);
-private int32_t mprint(struct magic_set *, struct magic *,
- const struct buffer *);
+private int32_t mprint(struct magic_set *, struct magic *);
private int moffset(struct magic_set *, struct magic *, const struct buffer *,
int32_t *);
private void mdebug(uint32_t, const char *, size_t);
@@ -66,31 +65,52 @@ private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
const unsigned char *, uint32_t, size_t, 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 *,
- const struct buffer *, int);
+private int handle_annotation(struct magic_set *, struct magic *, int);
private int cvt_8(union VALUETYPE *, const struct magic *);
private int cvt_16(union VALUETYPE *, const struct magic *);
private int cvt_32(union VALUETYPE *, const struct magic *);
private int cvt_64(union VALUETYPE *, const struct magic *);
-#define OFFSET_OOB(n, o, i) ((n) < (uint32_t)(o) || (i) > ((n) - (o)))
-#define BE64(p) (((uint64_t)(p)->hq[0]<<56)|((uint64_t)(p)->hq[1]<<48)| \
- ((uint64_t)(p)->hq[2]<<40)|((uint64_t)(p)->hq[3]<<32)| \
- ((uint64_t)(p)->hq[4]<<24)|((uint64_t)(p)->hq[5]<<16)| \
- ((uint64_t)(p)->hq[6]<<8)|((uint64_t)(p)->hq[7]))
-#define LE64(p) (((uint64_t)(p)->hq[7]<<56)|((uint64_t)(p)->hq[6]<<48)| \
- ((uint64_t)(p)->hq[5]<<40)|((uint64_t)(p)->hq[4]<<32)| \
- ((uint64_t)(p)->hq[3]<<24)|((uint64_t)(p)->hq[2]<<16)| \
- ((uint64_t)(p)->hq[1]<<8)|((uint64_t)(p)->hq[0]))
-#define LE32(p) (((uint32_t)(p)->hl[3]<<24)|((uint32_t)(p)->hl[2]<<16)| \
- ((uint32_t)(p)->hl[1]<<8)|((uint32_t)(p)->hl[0]))
-#define BE32(p) (((uint32_t)(p)->hl[0]<<24)|((uint32_t)(p)->hl[1]<<16)| \
- ((uint32_t)(p)->hl[2]<<8)|((uint32_t)(p)->hl[3]))
-#define ME32(p) (((uint32_t)(p)->hl[1]<<24)|((uint32_t)(p)->hl[0]<<16)| \
- ((uint32_t)(p)->hl[3]<<8)|((uint32_t)(p)->hl[2]))
-#define BE16(p) (((uint16_t)(p)->hs[0]<<8)|((uint16_t)(p)->hs[1]))
-#define LE16(p) (((uint16_t)(p)->hs[1]<<8)|((uint16_t)(p)->hs[0]))
-#define SEXT(s,v,p) ((s)?(intmax_t)(int##v##_t)(p):(intmax_t)(uint##v##_t)(p))
+#define OFFSET_OOB(n, o, i) ((n) < CAST(uint32_t, (o)) || (i) > ((n) - (o)))
+#define BE64(p) ( \
+ (CAST(uint64_t, (p)->hq[0])<<56)| \
+ (CAST(uint64_t, (p)->hq[1])<<48)| \
+ (CAST(uint64_t, (p)->hq[2])<<40)| \
+ (CAST(uint64_t, (p)->hq[3])<<32)| \
+ (CAST(uint64_t, (p)->hq[4])<<24)| \
+ (CAST(uint64_t, (p)->hq[5])<<16)| \
+ (CAST(uint64_t, (p)->hq[6])<<8)| \
+ (CAST(uint64_t, (p)->hq[7])))
+#define LE64(p) ( \
+ (CAST(uint64_t, (p)->hq[7])<<56)| \
+ (CAST(uint64_t, (p)->hq[6])<<48)| \
+ (CAST(uint64_t, (p)->hq[5])<<40)| \
+ (CAST(uint64_t, (p)->hq[4])<<32)| \
+ (CAST(uint64_t, (p)->hq[3])<<24)| \
+ (CAST(uint64_t, (p)->hq[2])<<16)| \
+ (CAST(uint64_t, (p)->hq[1])<<8)| \
+ (CAST(uint64_t, (p)->hq[0])))
+#define LE32(p) ( \
+ (CAST(uint32_t, (p)->hl[3])<<24)| \
+ (CAST(uint32_t, (p)->hl[2])<<16)| \
+ (CAST(uint32_t, (p)->hl[1])<<8)| \
+ (CAST(uint32_t, (p)->hl[0])))
+#define BE32(p) ( \
+ (CAST(uint32_t, (p)->hl[0])<<24)| \
+ (CAST(uint32_t, (p)->hl[1])<<16)| \
+ (CAST(uint32_t, (p)->hl[2])<<8)| \
+ (CAST(uint32_t, (p)->hl[3])))
+#define ME32(p) ( \
+ (CAST(uint32_t, (p)->hl[1])<<24)| \
+ (CAST(uint32_t, (p)->hl[0])<<16)| \
+ (CAST(uint32_t, (p)->hl[3])<<8)| \
+ (CAST(uint32_t, (p)->hl[2])))
+
+#define BE16(p) ((CAST(uint16_t, (p)->hs[0])<<8)|(CAST(uint16_t, (p)->hs[1])))
+#define LE16(p) ((CAST(uint16_t, (p)->hs[1])<<8)|(CAST(uint16_t, (p)->hs[0])))
+#define SEXT(s,v,p) ((s) ? \
+ CAST(intmax_t, CAST(int##v##_t, p)) : \
+ CAST(intmax_t, CAST(uint##v##_t, p)))
/*
* softmagic - lookup one file in parsed, in-memory copy of database
@@ -117,7 +137,7 @@ file_softmagic(struct magic_set *ms, const struct buffer *b,
for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next)
if ((rv = match(ms, ml->magic, ml->nmagic, b, 0, mode,
text, 0, indir_count, name_count,
- &printed_something, &need_separator, NULL)) != 0)
+ &printed_something, &need_separator, NULL, NULL)) != 0)
return rv;
return 0;
@@ -131,7 +151,12 @@ private const char * __attribute__((__format_arg__(3)))
file_fmtcheck(struct magic_set *ms, const char *desc, const char *def,
const char *file, size_t line)
{
- const char *ptr = fmtcheck(desc, def);
+ const char *ptr;
+
+ if (strchr(desc, '%') == NULL)
+ return desc;
+
+ ptr = fmtcheck(desc, def);
if (ptr == def)
file_magerror(ms,
"%s, %" SIZE_T_FORMAT "u: format `%s' does not match"
@@ -175,17 +200,25 @@ private int
match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
const struct buffer *b, size_t offset, int mode, int text,
int flip, uint16_t *indir_count, uint16_t *name_count,
- int *printed_something, int *need_separator, int *returnval)
+ int *printed_something, int *need_separator, int *returnval,
+ int *found_match)
{
uint32_t magindex = 0;
unsigned int cont_level = 0;
- int returnvalv = 0, e; /* if a match is found it is set to 1*/
+ int found_matchv = 0; /* if a match is found it is set to 1*/
+ int returnvalv = 0, e;
int firstline = 1; /* a flag to print X\n X\n- X */
struct buffer bb;
int print = (ms->flags & MAGIC_NODESC) == 0;
+ /*
+ * returnval can be 0 if a match is found, but there was no
+ * annotation to be printed.
+ */
if (returnval == NULL)
returnval = &returnvalv;
+ if (found_match == NULL)
+ found_match = &found_matchv;
if (file_check_mem(ms, cont_level) == -1)
return -1;
@@ -214,17 +247,21 @@ flush:
ms->line = m->lineno;
/* if main entry matches, print it... */
- switch (mget(ms, m, b, bb.fbuf, bb.flen, offset, cont_level,
+ switch (mget(ms, m, b, CAST(const unsigned char *, bb.fbuf),
+ bb.flen, offset, cont_level,
mode, text, flip, indir_count, name_count,
- printed_something, need_separator, returnval)) {
+ printed_something, need_separator, returnval, found_match))
+ {
case -1:
return -1;
case 0:
flush = m->reln != '!';
break;
default:
- if (m->type == FILE_INDIRECT)
+ if (m->type == FILE_INDIRECT) {
+ *found_match = 1;
*returnval = 1;
+ }
switch (magiccheck(ms, m)) {
case -1:
@@ -246,7 +283,11 @@ flush:
goto flush;
}
- if ((e = handle_annotation(ms, m, b, firstline)) != 0) {
+ if (*m->desc)
+ *found_match = 1;
+
+ if ((e = handle_annotation(ms, m, firstline)) != 0)
+ {
*need_separator = 1;
*printed_something = 1;
*returnval = 1;
@@ -257,16 +298,16 @@ flush:
* If we are going to print something, we'll need to print
* a blank before we print something else.
*/
- if (*m->desc) {
+ if (print && *m->desc) {
*need_separator = 1;
*printed_something = 1;
+ *returnval = 1;
if (print_sep(ms, firstline) == -1)
return -1;
+ if (mprint(ms, m) == -1)
+ return -1;
}
- if (print && mprint(ms, m, b) == -1)
- return -1;
-
switch (moffset(ms, m, &bb, &ms->c.li[cont_level].off)) {
case -1:
case 0:
@@ -307,10 +348,11 @@ flush:
continue;
}
#endif
- switch (mget(ms, m, b, bb.fbuf, bb.flen, offset,
+ switch (mget(ms, m, b, CAST(const unsigned char *,
+ bb.fbuf), bb.flen, offset,
cont_level, mode, text, flip, indir_count,
name_count, printed_something, need_separator,
- returnval)) {
+ returnval, found_match)) {
case -1:
return -1;
case 0:
@@ -319,8 +361,10 @@ flush:
flush = 1;
break;
default:
- if (m->type == FILE_INDIRECT)
+ if (m->type == FILE_INDIRECT) {
+ *found_match = 1;
*returnval = 1;
+ }
flush = 0;
break;
}
@@ -345,42 +389,46 @@ flush:
} else
ms->c.li[cont_level].got_match = 1;
- if ((e = handle_annotation(ms, m, b, firstline))
+ if (*m->desc)
+ *found_match = 1;
+
+ if ((e = handle_annotation(ms, m, firstline))
!= 0) {
*need_separator = 1;
*printed_something = 1;
*returnval = 1;
return e;
}
- /*
- * If we are going to print something,
- * make sure that we have a separator first.
- */
- if (*m->desc) {
+ if (print && *m->desc) {
+ /*
+ * This continuation matched. Print
+ * its message, with a blank before it
+ * if the previous item printed and
+ * this item isn't empty.
+ */
+ /*
+ * If we are going to print something,
+ * make sure that we have a separator
+ * first.
+ */
if (!*printed_something) {
*printed_something = 1;
if (print_sep(ms, firstline)
== -1)
return -1;
}
- }
- /*
- * This continuation matched. Print
- * its message, with a blank before it
- * if the previous item printed and
- * this item isn't empty.
- */
- /* space if previous printed */
- if (*need_separator
- && ((m->flag & NOSPACE) == 0)
- && *m->desc) {
- if (print &&
- file_printf(ms, " ") == -1)
- return -1;
+ /* space if previous printed */
+ if (*need_separator
+ && (m->flag & NOSPACE) == 0) {
+ if (file_printf(ms, " ") == -1)
+ return -1;
+ }
+ *returnval = 1;
*need_separator = 0;
+ if (mprint(ms, m) == -1)
+ return -1;
+ *need_separator = 1;
}
- if (print && mprint(ms, m, b) == -1)
- return -1;
switch (moffset(ms, m, &bb,
&ms->c.li[cont_level].off)) {
@@ -393,9 +441,6 @@ flush:
break;
}
- if (*m->desc)
- *need_separator = 1;
-
/*
* If we see any continuations
* at a higher level,
@@ -408,11 +453,13 @@ flush:
}
if (*printed_something) {
firstline = 0;
- if (print)
- *returnval = 1;
}
- if ((ms->flags & MAGIC_CONTINUE) == 0 && *printed_something) {
+ if (*found_match) {
+ if ((ms->flags & MAGIC_CONTINUE) == 0)
return *returnval; /* don't keep searching */
+ // So that we print a separator
+ *printed_something = 0;
+ firstline = 0;
}
cont_level = 0;
}
@@ -447,13 +494,13 @@ check_fmt(struct magic_set *ms, const char *fmt)
}
static int
-varexpand(char *buf, size_t len, const struct buffer *b, const char *str)
+varexpand(struct magic_set *ms, char *buf, size_t len, const char *str)
{
const char *ptr, *sptr, *e, *t, *ee, *et;
size_t l;
for (sptr = str; (ptr = strstr(sptr, "${")) != NULL;) {
- l = (size_t)(ptr - sptr);
+ l = CAST(size_t, ptr - sptr);
if (l >= len)
return -1;
memcpy(buf, sptr, l);
@@ -472,7 +519,7 @@ varexpand(char *buf, size_t len, const struct buffer *b, const char *str)
return -1;
switch (*ptr) {
case 'x':
- if (b->st.st_mode & 0111) {
+ if (ms->mode & 0111) {
ptr = t;
l = et - t;
} else {
@@ -502,7 +549,7 @@ varexpand(char *buf, size_t len, const struct buffer *b, const char *str)
private int32_t
-mprint(struct magic_set *ms, struct magic *m, const struct buffer *b)
+mprint(struct magic_set *ms, struct magic *m)
{
uint64_t v;
float vf;
@@ -512,26 +559,26 @@ mprint(struct magic_set *ms, struct magic *m, const struct buffer *b)
const char *desc;
union VALUETYPE *p = &ms->ms_value;
- if (varexpand(ebuf, sizeof(ebuf), b, m->desc) == -1)
+ if (varexpand(ms, ebuf, sizeof(ebuf), m->desc) == -1)
desc = m->desc;
else
desc = ebuf;
switch (m->type) {
case FILE_BYTE:
- v = file_signextend(ms, m, (uint64_t)p->b);
+ v = file_signextend(ms, m, CAST(uint64_t, p->b));
switch (check_fmt(ms, desc)) {
case -1:
return -1;
case 1:
(void)snprintf(buf, sizeof(buf), "%d",
- (unsigned char)v);
+ CAST(unsigned char, v));
if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
return -1;
break;
default:
if (file_printf(ms, F(ms, desc, "%d"),
- (unsigned char) v) == -1)
+ CAST(unsigned char, v)) == -1)
return -1;
break;
}
@@ -541,19 +588,19 @@ mprint(struct magic_set *ms, struct magic *m, const struct buffer *b)
case FILE_SHORT:
case FILE_BESHORT:
case FILE_LESHORT:
- v = file_signextend(ms, m, (uint64_t)p->h);
+ v = file_signextend(ms, m, CAST(uint64_t, p->h));
switch (check_fmt(ms, desc)) {
case -1:
return -1;
case 1:
(void)snprintf(buf, sizeof(buf), "%u",
- (unsigned short)v);
+ CAST(unsigned short, v));
if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
return -1;
break;
default:
if (file_printf(ms, F(ms, desc, "%u"),
- (unsigned short) v) == -1)
+ CAST(unsigned short, v)) == -1)
return -1;
break;
}
@@ -564,17 +611,19 @@ mprint(struct magic_set *ms, struct magic *m, const struct buffer *b)
case FILE_BELONG:
case FILE_LELONG:
case FILE_MELONG:
- v = file_signextend(ms, m, (uint64_t)p->l);
+ v = file_signextend(ms, m, CAST(uint64_t, p->l));
switch (check_fmt(ms, desc)) {
case -1:
return -1;
case 1:
- (void)snprintf(buf, sizeof(buf), "%u", (uint32_t) v);
+ (void)snprintf(buf, sizeof(buf), "%u",
+ CAST(uint32_t, v));
if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
return -1;
break;
default:
- if (file_printf(ms, F(ms, desc, "%u"), (uint32_t) v) == -1)
+ if (file_printf(ms, F(ms, desc, "%u"),
+ CAST(uint32_t, v)) == -1)
return -1;
break;
}
@@ -590,13 +639,13 @@ mprint(struct magic_set *ms, struct magic *m, const struct buffer *b)
return -1;
case 1:
(void)snprintf(buf, sizeof(buf), "%" INT64_T_FORMAT "u",
- (unsigned long long)v);
+ CAST(unsigned long long, v));
if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
return -1;
break;
default:
if (file_printf(ms, F(ms, desc, "%" INT64_T_FORMAT "u"),
- (unsigned long long) v) == -1)
+ CAST(unsigned long long, v)) == -1)
return -1;
break;
}
@@ -608,9 +657,9 @@ mprint(struct magic_set *ms, struct magic *m, const struct buffer *b)
case FILE_BESTRING16:
case FILE_LESTRING16:
if (m->reln == '=' || m->reln == '!') {
- if (file_printf(ms, F(ms, desc, "%s"),
- file_printable(sbuf, sizeof(sbuf), m->value.s))
- == -1)
+ if (file_printf(ms, F(ms, desc, "%s"),
+ file_printable(sbuf, sizeof(sbuf), m->value.s,
+ sizeof(m->value.s))) == -1)
return -1;
t = ms->offset + m->vallen;
}
@@ -625,19 +674,20 @@ mprint(struct magic_set *ms, struct magic *m, const struct buffer *b)
if (m->str_flags & STRING_TRIM) {
char *last;
- while (isspace((unsigned char)*str))
+ while (isspace(CAST(unsigned char, *str)))
str++;
last = str;
while (*last)
last++;
--last;
- while (isspace((unsigned char)*last))
+ while (isspace(CAST(unsigned char, *last)))
last--;
*++last = '\0';
}
if (file_printf(ms, F(ms, desc, "%s"),
- file_printable(sbuf, sizeof(sbuf), str)) == -1)
+ file_printable(sbuf, sizeof(sbuf), str,
+ sizeof(p->s) - (str - p->s))) == -1)
return -1;
if (m->type == FILE_PSTRING)
@@ -737,9 +787,10 @@ mprint(struct magic_set *ms, struct magic *m, const struct buffer *b)
char *cp;
int rval;
- cp = estrndup((const char *)ms->search.s, ms->search.rm_len);
+ cp = estrndup(RCAST(const char *, ms->search.s),
+ ms->search.rm_len);
rval = file_printf(ms, F(ms, desc, "%s"),
- file_printable(sbuf, sizeof(sbuf), cp));
+ file_printable(sbuf, sizeof(sbuf), cp, ms->search.rm_len));
efree(cp);
if (rval == -1)
@@ -765,8 +816,9 @@ mprint(struct magic_set *ms, struct magic *m, const struct buffer *b)
t = ms->offset;
break;
case FILE_DER:
- if (file_printf(ms, F(ms, desc, "%s"),
- file_printable(sbuf, sizeof(sbuf), ms->ms_value.s)) == -1)
+ if (file_printf(ms, F(ms, desc, "%s"),
+ file_printable(sbuf, sizeof(sbuf), ms->ms_value.s,
+ sizeof(ms->ms_value.s))) == -1)
return -1;
t = ms->offset;
break;
@@ -774,7 +826,7 @@ mprint(struct magic_set *ms, struct magic *m, const struct buffer *b)
file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
return -1;
}
- return (int32_t)t;
+ return CAST(int32_t, t);
}
private int
@@ -821,7 +873,8 @@ moffset(struct magic_set *ms, struct magic *m, const struct buffer *b,
p->s[strcspn(p->s, "\r\n")] = '\0';
o = CAST(uint32_t, (ms->offset + strlen(p->s)));
if (m->type == FILE_PSTRING)
- o += (uint32_t)file_pstring_length_size(m);
+ o += CAST(uint32_t,
+ file_pstring_length_size(m));
}
break;
@@ -887,11 +940,11 @@ moffset(struct magic_set *ms, struct magic *m, const struct buffer *b,
case FILE_DER:
{
o = der_offs(ms, m, nbytes);
- if (o == -1 || (size_t)o > nbytes) {
+ if (o == -1 || CAST(size_t, o) > nbytes) {
if ((ms->flags & MAGIC_DEBUG) != 0) {
(void)fprintf(stderr,
- "Bad DER offset %d nbytes=%zu",
- o, nbytes);
+ "Bad DER offset %d nbytes=%"
+ SIZE_T_FORMAT "u", o, nbytes);
}
*op = 0;
return 0;
@@ -904,10 +957,10 @@ moffset(struct magic_set *ms, struct magic *m, const struct buffer *b,
break;
}
- if ((size_t)o > nbytes) {
+ if (CAST(size_t, o) > nbytes) {
#if 0
- file_error(ms, 0, "Offset out of range %zu > %zu",
- (size_t)o, nbytes);
+ file_error(ms, 0, "Offset out of range %" SIZE_T_FORMAT
+ "u > %" SIZE_T_FORMAT "u", (size_t)o, nbytes);
#endif
return -1;
}
@@ -977,36 +1030,36 @@ cvt_flip(int type, int flip)
return type;
}
}
-#define DO_CVT(fld, cast) \
+#define DO_CVT(fld, type) \
if (m->num_mask) \
switch (m->mask_op & FILE_OPS_MASK) { \
case FILE_OPAND: \
- p->fld &= cast m->num_mask; \
+ p->fld &= CAST(type, m->num_mask); \
break; \
case FILE_OPOR: \
- p->fld |= cast m->num_mask; \
+ p->fld |= CAST(type, m->num_mask); \
break; \
case FILE_OPXOR: \
- p->fld ^= cast m->num_mask; \
+ p->fld ^= CAST(type, m->num_mask); \
break; \
case FILE_OPADD: \
- p->fld += cast m->num_mask; \
+ p->fld += CAST(type, m->num_mask); \
break; \
case FILE_OPMINUS: \
- p->fld -= cast m->num_mask; \
+ p->fld -= CAST(type, m->num_mask); \
break; \
case FILE_OPMULTIPLY: \
- p->fld *= cast m->num_mask; \
+ p->fld *= CAST(type, m->num_mask); \
break; \
case FILE_OPDIVIDE: \
- if (cast m->num_mask == 0) \
+ if (CAST(type, m->num_mask) == 0) \
return -1; \
- p->fld /= cast m->num_mask; \
+ p->fld /= CAST(type, m->num_mask); \
break; \
case FILE_OPMODULO: \
- if (cast m->num_mask == 0) \
+ if (CAST(type, m->num_mask) == 0) \
return -1; \
- p->fld %= cast m->num_mask; \
+ p->fld %= CAST(type, m->num_mask); \
break; \
} \
if (m->mask_op & FILE_OPINVERSE) \
@@ -1015,61 +1068,61 @@ cvt_flip(int type, int flip)
private int
cvt_8(union VALUETYPE *p, const struct magic *m)
{
- DO_CVT(b, (uint8_t));
+ DO_CVT(b, uint8_t);
return 0;
}
private int
cvt_16(union VALUETYPE *p, const struct magic *m)
{
- DO_CVT(h, (uint16_t));
+ DO_CVT(h, uint16_t);
return 0;
}
private int
cvt_32(union VALUETYPE *p, const struct magic *m)
{
- DO_CVT(l, (uint32_t));
+ DO_CVT(l, uint32_t);
return 0;
}
private int
cvt_64(union VALUETYPE *p, const struct magic *m)
{
- DO_CVT(q, (uint64_t));
+ DO_CVT(q, uint64_t);
return 0;
}
-#define DO_CVT2(fld, cast) \
+#define DO_CVT2(fld, type) \
if (m->num_mask) \
switch (m->mask_op & FILE_OPS_MASK) { \
case FILE_OPADD: \
- p->fld += cast m->num_mask; \
+ p->fld += CAST(type, m->num_mask); \
break; \
case FILE_OPMINUS: \
- p->fld -= cast m->num_mask; \
+ p->fld -= CAST(type, m->num_mask); \
break; \
case FILE_OPMULTIPLY: \
- p->fld *= cast m->num_mask; \
+ p->fld *= CAST(type, m->num_mask); \
break; \
case FILE_OPDIVIDE: \
- if (cast m->num_mask == 0) \
+ if (CAST(type, m->num_mask) == 0) \
return -1; \
- p->fld /= cast m->num_mask; \
+ p->fld /= CAST(type, m->num_mask); \
break; \
} \
private int
cvt_float(union VALUETYPE *p, const struct magic *m)
{
- DO_CVT2(f, (float));
+ DO_CVT2(f, float);
return 0;
}
private int
cvt_double(union VALUETYPE *p, const struct magic *m)
{
- DO_CVT2(d, (double));
+ DO_CVT2(d, double);
return 0;
}
@@ -1134,14 +1187,14 @@ mconvert(struct magic_set *ms, struct magic *m, int flip)
return 1;
}
case FILE_BESHORT:
- p->h = (short)BE16(p);
+ p->h = CAST(short, BE16(p));
if (cvt_16(p, m) == -1)
goto out;
return 1;
case FILE_BELONG:
case FILE_BEDATE:
case FILE_BELDATE:
- p->l = (int32_t)BE32(p);
+ p->l = CAST(int32_t, BE32(p));
if (cvt_32(p, m) == -1)
goto out;
return 1;
@@ -1149,19 +1202,19 @@ mconvert(struct magic_set *ms, struct magic *m, int flip)
case FILE_BEQDATE:
case FILE_BEQLDATE:
case FILE_BEQWDATE:
- p->q = (uint64_t)BE64(p);
+ p->q = CAST(uint64_t, BE64(p));
if (cvt_64(p, m) == -1)
goto out;
return 1;
case FILE_LESHORT:
- p->h = (short)LE16(p);
+ p->h = CAST(short, LE16(p));
if (cvt_16(p, m) == -1)
goto out;
return 1;
case FILE_LELONG:
case FILE_LEDATE:
case FILE_LELDATE:
- p->l = (int32_t)LE32(p);
+ p->l = CAST(int32_t, LE32(p));
if (cvt_32(p, m) == -1)
goto out;
return 1;
@@ -1169,14 +1222,14 @@ mconvert(struct magic_set *ms, struct magic *m, int flip)
case FILE_LEQDATE:
case FILE_LEQLDATE:
case FILE_LEQWDATE:
- p->q = (uint64_t)LE64(p);
+ p->q = CAST(uint64_t, LE64(p));
if (cvt_64(p, m) == -1)
goto out;
return 1;
case FILE_MELONG:
case FILE_MEDATE:
case FILE_MELDATE:
- p->l = (int32_t)ME32(p);
+ p->l = CAST(int32_t, ME32(p));
if (cvt_32(p, m) == -1)
goto out;
return 1;
@@ -1290,9 +1343,11 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
|| (b = CAST(const char *,
memchr(c, '\r', CAST(size_t, (end - c))))));
lines--, b++) {
- last = b;
if (b < end - 1 && b[0] == '\r' && b[1] == '\n')
b++;
+ if (b < end - 1 && b[0] == '\n')
+ b++;
+ last = b;
}
if (lines)
last = end;
@@ -1355,7 +1410,7 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
* might even cause problems
*/
if (nbytes < sizeof(*p))
- (void)memset(((char *)(void *)p) + nbytes, '\0',
+ (void)memset(RCAST(char *, RCAST(void *, p)) + nbytes, '\0',
sizeof(*p) - nbytes);
return 0;
}
@@ -1396,7 +1451,7 @@ do_ops(struct magic *m, intmax_t lhs, intmax_t off)
if (m->in_op & FILE_OPINVERSE)
offset = ~offset;
- return (uint32_t)offset;
+ return CAST(uint32_t, offset);
}
private int
@@ -1417,19 +1472,19 @@ msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb,
return -1;
if (o != 0) {
// Not yet!
- file_magerror(ms, "non zero offset %zu at"
- " level %u", o, cont_level);
+ file_magerror(ms, "non zero offset %" SIZE_T_FORMAT
+ "u at level %u", o, cont_level);
return -1;
}
- if ((size_t)-m->offset > b->elen)
+ if (CAST(size_t, -m->offset) > b->elen)
return -1;
- buffer_init(bb, -1, b->ebuf, b->elen);
- ms->eoffset = ms->offset = b->elen + m->offset;
+ buffer_init(bb, -1, NULL, b->ebuf, b->elen);
+ ms->eoffset = ms->offset = CAST(int32_t, b->elen + m->offset);
} else {
if (cont_level == 0) {
normal:
// XXX: Pass real fd, then who frees bb?
- buffer_init(bb, -1, b->fbuf, b->flen);
+ buffer_init(bb, -1, NULL, b->fbuf, b->flen);
ms->offset = m->offset;
ms->eoffset = 0;
} else {
@@ -1437,7 +1492,8 @@ normal:
}
}
if ((ms->flags & MAGIC_DEBUG) != 0) {
- fprintf(stderr, "bb=[%p,%zu], %d [b=%p,%zu], [o=%#x, c=%d]\n",
+ fprintf(stderr, "bb=[%p,%" SIZE_T_FORMAT "u], %d [b=%p,%"
+ SIZE_T_FORMAT "u], [o=%#x, c=%d]\n",
bb->fbuf, bb->flen, ms->offset, b->fbuf, b->flen,
m->offset, cont_level);
}
@@ -1448,7 +1504,8 @@ private int
mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
const unsigned char *s, size_t nbytes, size_t o, unsigned int cont_level,
int mode, int text, int flip, uint16_t *indir_count, uint16_t *name_count,
- int *printed_something, int *need_separator, int *returnval)
+ int *printed_something, int *need_separator, int *returnval,
+ int *found_match)
{
uint32_t offset = ms->offset;
struct buffer bb;
@@ -1471,8 +1528,10 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
return -1;
}
- if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o),
- (uint32_t)nbytes, m) == -1)
+
+
+ if (mcopy(ms, p, m->type, m->flag & INDIR, s,
+ CAST(uint32_t, offset + o), CAST(uint32_t, nbytes), m) == -1)
return -1;
if ((ms->flags & MAGIC_DEBUG) != 0) {
@@ -1481,7 +1540,8 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
"u, il=%hu, nc=%hu)\n",
m->type, m->flag, offset, o, nbytes,
*indir_count, *name_count);
- mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
+ mdebug(offset, RCAST(char *, RCAST(void *, p)),
+ sizeof(union VALUETYPE));
}
if (m->flag & INDIR) {
@@ -1489,36 +1549,62 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
const int sgn = m->in_op & FILE_OPSIGNED;
if (m->in_op & FILE_OPINDIRECT) {
const union VALUETYPE *q = CAST(const union VALUETYPE *,
- ((const void *)(s + offset + off)));
- if (OFFSET_OOB(nbytes, offset + off, sizeof(*q)))
- return 0;
+ RCAST(const void *, s + offset + off));
switch (cvt_flip(m->in_type, flip)) {
case FILE_BYTE:
+ if (OFFSET_OOB(nbytes, offset + off, 1))
+ return 0;
off = SEXT(sgn,8,q->b);
break;
case FILE_SHORT:
+ if (OFFSET_OOB(nbytes, offset + off, 2))
+ return 0;
off = SEXT(sgn,16,q->h);
break;
case FILE_BESHORT:
+ if (OFFSET_OOB(nbytes, offset + off, 2))
+ return 0;
off = SEXT(sgn,16,BE16(q));
break;
case FILE_LESHORT:
+ if (OFFSET_OOB(nbytes, offset + off, 2))
+ return 0;
off = SEXT(sgn,16,LE16(q));
break;
case FILE_LONG:
+ if (OFFSET_OOB(nbytes, offset + off, 4))
+ return 0;
off = SEXT(sgn,32,q->l);
break;
case FILE_BELONG:
case FILE_BEID3:
+ if (OFFSET_OOB(nbytes, offset + off, 4))
+ return 0;
off = SEXT(sgn,32,BE32(q));
break;
case FILE_LEID3:
case FILE_LELONG:
+ if (OFFSET_OOB(nbytes, offset + off, 4))
+ return 0;
off = SEXT(sgn,32,LE32(q));
break;
case FILE_MELONG:
+ if (OFFSET_OOB(nbytes, offset + off, 4))
+ return 0;
off = SEXT(sgn,32,ME32(q));
break;
+ case FILE_BEQUAD:
+ if (OFFSET_OOB(nbytes, offset + off, 8))
+ return 0;
+ off = SEXT(sgn,64,BE64(q));
+ break;
+ case FILE_LEQUAD:
+ if (OFFSET_OOB(nbytes, offset + off, 8))
+ return 0;
+ off = SEXT(sgn,64,LE64(q));
+ break;
+ default:
+ abort();
}
if ((ms->flags & MAGIC_DEBUG) != 0)
fprintf(stderr, "indirect offs=%jd\n", off);
@@ -1550,7 +1636,7 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
return 0;
lhs = BE32(p);
if (in_type == FILE_BEID3)
- lhs = cvt_id3(ms, (uint32_t)lhs);
+ lhs = cvt_id3(ms, CAST(uint32_t, lhs));
offset = do_ops(m, SEXT(sgn,32,lhs), off);
break;
case FILE_LELONG:
@@ -1559,7 +1645,7 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
return 0;
lhs = LE32(p);
if (in_type == FILE_LEID3)
- lhs = cvt_id3(ms, (uint32_t)lhs);
+ lhs = cvt_id3(ms, CAST(uint32_t, lhs));
offset = do_ops(m, SEXT(sgn,32,lhs), off);
break;
case FILE_MELONG:
@@ -1572,6 +1658,16 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
return 0;
offset = do_ops(m, SEXT(sgn,32,p->l), off);
break;
+ case FILE_LEQUAD:
+ if (OFFSET_OOB(nbytes, offset, 8))
+ return 0;
+ offset = do_ops(m, SEXT(sgn,64,LE64(p)), off);
+ break;
+ case FILE_BEQUAD:
+ if (OFFSET_OOB(nbytes, offset, 8))
+ return 0;
+ offset = do_ops(m, SEXT(sgn,64,BE64(p)), off);
+ break;
default:
break;
}
@@ -1592,7 +1688,7 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
ms->offset = offset;
if ((ms->flags & MAGIC_DEBUG) != 0) {
- mdebug(offset, (char *)(void *)p,
+ mdebug(offset, RCAST(char *, RCAST(void *, p)),
sizeof(union VALUETYPE));
}
}
@@ -1707,7 +1803,8 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
*need_separator = 0;
rv = match(ms, ml.magic, ml.nmagic, b, offset + o,
mode, text, flip, indir_count, name_count,
- printed_something, need_separator, returnval);
+ printed_something, need_separator, returnval, found_match);
+ (*name_count)--;
if (rv != 1)
*need_separator = oneed_separator;
return rv;
@@ -1738,8 +1835,8 @@ file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
* the ctype functions will work correctly without extra
* casting.
*/
- const unsigned char *a = (const unsigned char *)s1;
- const unsigned char *b = (const unsigned char *)s2;
+ const unsigned char *a = RCAST(const unsigned char *, s1);
+ const unsigned char *b = RCAST(const unsigned char *, s2);
const unsigned char *eb = b + len;
uint64_t v;
@@ -1825,6 +1922,12 @@ convert_libmagic_pattern(zval *pattern, char *val, size_t len, uint32_t options)
ZSTR_VAL(t)[j++] = '\\';
ZSTR_VAL(t)[j] = '~';
break;
+ case '\0':
+ ZSTR_VAL(t)[j++] = '\\';
+ ZSTR_VAL(t)[j++] = 'x';
+ ZSTR_VAL(t)[j++] = '0';
+ ZSTR_VAL(t)[j] = '0';
+ break;
default:
ZSTR_VAL(t)[j] = val[i];
break;
@@ -1969,13 +2072,15 @@ magiccheck(struct magic_set *ms, struct magic *m)
case FILE_STRING:
case FILE_PSTRING:
l = 0;
- v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
+ v = file_strncmp(m->value.s, p->s, CAST(size_t, m->vallen),
+ m->str_flags);
break;
case FILE_BESTRING16:
case FILE_LESTRING16:
l = 0;
- v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
+ v = file_strncmp16(m->value.s, p->s, CAST(size_t, m->vallen),
+ m->str_flags);
break;
case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
@@ -1988,6 +2093,22 @@ magiccheck(struct magic_set *ms, struct magic *m)
slen = MIN(m->vallen, sizeof(m->value.s));
l = 0;
v = 0;
+#ifdef HAVE_MEMMEM
+ if (slen > 0 && m->str_flags == 0) {
+ const char *found;
+ idx = m->str_range + slen;
+ if (m->str_range == 0 || ms->search.s_len < idx)
+ idx = ms->search.s_len;
+ found = CAST(const char *, memmem(ms->search.s, idx,
+ m->value.s, slen));
+ if (!found)
+ return 0;
+ idx = found - ms->search.s;
+ ms->search.offset += idx;
+ ms->search.rm_len = ms->search.s_len - idx;
+ break;
+ }
+#endif
for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
if (slen + idx > ms->search.s_len)
@@ -2102,7 +2223,7 @@ error_out:
case 'x':
if ((ms->flags & MAGIC_DEBUG) != 0)
(void) fprintf(stderr, "%" INT64_T_FORMAT
- "u == *any* = 1\n", (unsigned long long)v);
+ "u == *any* = 1\n", CAST(unsigned long long, v));
matched = 1;
break;
@@ -2110,16 +2231,18 @@ error_out:
matched = v != l;
if ((ms->flags & MAGIC_DEBUG) != 0)
(void) fprintf(stderr, "%" INT64_T_FORMAT "u != %"
- INT64_T_FORMAT "u = %d\n", (unsigned long long)v,
- (unsigned long long)l, matched);
+ INT64_T_FORMAT "u = %d\n",
+ CAST(unsigned long long, v),
+ CAST(unsigned long long, l), matched);
break;
case '=':
matched = v == l;
if ((ms->flags & MAGIC_DEBUG) != 0)
(void) fprintf(stderr, "%" INT64_T_FORMAT "u == %"
- INT64_T_FORMAT "u = %d\n", (unsigned long long)v,
- (unsigned long long)l, matched);
+ INT64_T_FORMAT "u = %d\n",
+ CAST(unsigned long long, v),
+ CAST(unsigned long long, l), matched);
break;
case '>':
@@ -2128,15 +2251,16 @@ error_out:
if ((ms->flags & MAGIC_DEBUG) != 0)
(void) fprintf(stderr, "%" INT64_T_FORMAT
"u > %" INT64_T_FORMAT "u = %d\n",
- (unsigned long long)v,
- (unsigned long long)l, matched);
+ CAST(unsigned long long, v),
+ CAST(unsigned long long, l), matched);
}
else {
- matched = (int64_t) v > (int64_t) l;
+ matched = CAST(int64_t, v) > CAST(int64_t, l);
if ((ms->flags & MAGIC_DEBUG) != 0)
(void) fprintf(stderr, "%" INT64_T_FORMAT
"d > %" INT64_T_FORMAT "d = %d\n",
- (long long)v, (long long)l, matched);
+ CAST(long long, v),
+ CAST(long long, l), matched);
}
break;
@@ -2146,15 +2270,16 @@ error_out:
if ((ms->flags & MAGIC_DEBUG) != 0)
(void) fprintf(stderr, "%" INT64_T_FORMAT
"u < %" INT64_T_FORMAT "u = %d\n",
- (unsigned long long)v,
- (unsigned long long)l, matched);
+ CAST(unsigned long long, v),
+ CAST(unsigned long long, l), matched);
}
else {
- matched = (int64_t) v < (int64_t) l;
+ matched = CAST(int64_t, v) < CAST(int64_t, l);
if ((ms->flags & MAGIC_DEBUG) != 0)
(void) fprintf(stderr, "%" INT64_T_FORMAT
"d < %" INT64_T_FORMAT "d = %d\n",
- (long long)v, (long long)l, matched);
+ CAST(long long, v),
+ CAST(long long, l), matched);
}
break;
@@ -2163,8 +2288,9 @@ error_out:
if ((ms->flags & MAGIC_DEBUG) != 0)
(void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
INT64_T_FORMAT "x) == %" INT64_T_FORMAT
- "x) = %d\n", (unsigned long long)v,
- (unsigned long long)l, (unsigned long long)l,
+ "x) = %d\n", CAST(unsigned long long, v),
+ CAST(unsigned long long, l),
+ CAST(unsigned long long, l),
matched);
break;
@@ -2173,9 +2299,9 @@ error_out:
if ((ms->flags & MAGIC_DEBUG) != 0)
(void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
INT64_T_FORMAT "x) != %" INT64_T_FORMAT
- "x) = %d\n", (unsigned long long)v,
- (unsigned long long)l, (unsigned long long)l,
- matched);
+ "x) = %d\n", CAST(unsigned long long, v),
+ CAST(unsigned long long, l),
+ CAST(unsigned long long, l), matched);
break;
default:
@@ -2188,18 +2314,17 @@ error_out:
}
private int
-handle_annotation(struct magic_set *ms, struct magic *m, const struct buffer *b,
- int firstline)
+handle_annotation(struct magic_set *ms, struct magic *m, int firstline)
{
if ((ms->flags & MAGIC_APPLE) && m->apple[0]) {
- if (!firstline && file_printf(ms, "\n- ") == -1)
+ if (print_sep(ms, firstline) == -1)
return -1;
if (file_printf(ms, "%.8s", m->apple) == -1)
return -1;
return 1;
}
if ((ms->flags & MAGIC_EXTENSION) && m->ext[0]) {
- if (!firstline && file_printf(ms, "\n- ") == -1)
+ if (print_sep(ms, firstline) == -1)
return -1;
if (file_printf(ms, "%s", m->ext) == -1)
return -1;
@@ -2208,9 +2333,9 @@ handle_annotation(struct magic_set *ms, struct magic *m, const struct buffer *b,
if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
char buf[1024];
const char *p;
- if (!firstline && file_printf(ms, "\n- ") == -1)
+ if (print_sep(ms, firstline) == -1)
return -1;
- if (varexpand(buf, sizeof(buf), b, m->mimetype) == -1)
+ if (varexpand(ms, buf, sizeof(buf), m->mimetype) == -1)
p = m->mimetype;
else
p = buf;
@@ -2224,13 +2349,11 @@ handle_annotation(struct magic_set *ms, struct magic *m, const struct buffer *b,
private int
print_sep(struct magic_set *ms, int firstline)
{
-// if (ms->flags & MAGIC_NODESC)
-// return 0;
if (firstline)
return 0;
/*
* we found another match
* put a newline and '-' to do some simple formatting
*/
- return file_printf(ms, "\n- ");
+ return file_separator(ms);
}