summaryrefslogtreecommitdiff
path: root/ext/fileinfo/libmagic
diff options
context:
space:
mode:
authorAnatol Belski <ab@php.net>2016-10-25 18:51:05 +0200
committerAnatol Belski <ab@php.net>2016-11-24 13:44:04 +0100
commit411e97c72d6a200930a7edc48a031a2ca64c0e0c (patch)
treed51bb62c1a3bc13364ac18f0dd83abf08c1a148e /ext/fileinfo/libmagic
parentb8664adc9b7f6050f345c38799d495fa3197a8e6 (diff)
downloadphp-git-411e97c72d6a200930a7edc48a031a2ca64c0e0c.tar.gz
Upgraded libmagic to 5.29
yet unfinished port to libmagic 5.28 catch with missing libmagic port pieces regenerate data file with magic from 5.28 test magic files from 5.28 missing files fix path pure c99 is still not supported move right to 5.29, yet some bugs present more sync with orig lib more ZMM usage use unpatched data for now partial revert according to bug #67705 Revert "more ZMM usage" This reverts commit 5e3c9b851034b455942b219b18bdc49c8315c3ee. several fixes, so it's now closer to the clean port
Diffstat (limited to 'ext/fileinfo/libmagic')
-rw-r--r--ext/fileinfo/libmagic/apprentice.c176
-rw-r--r--ext/fileinfo/libmagic/apptype.c2
-rw-r--r--ext/fileinfo/libmagic/ascmagic.c20
-rw-r--r--ext/fileinfo/libmagic/cdf.c171
-rw-r--r--ext/fileinfo/libmagic/cdf.h9
-rw-r--r--ext/fileinfo/libmagic/cdf_time.c2
-rw-r--r--ext/fileinfo/libmagic/compress.c517
-rw-r--r--ext/fileinfo/libmagic/der.c389
-rw-r--r--ext/fileinfo/libmagic/der.h28
-rw-r--r--ext/fileinfo/libmagic/encoding.c34
-rw-r--r--ext/fileinfo/libmagic/file.h46
-rw-r--r--ext/fileinfo/libmagic/fsmagic.c22
-rw-r--r--ext/fileinfo/libmagic/funcs.c117
-rw-r--r--ext/fileinfo/libmagic/is_tar.c4
-rw-r--r--ext/fileinfo/libmagic/magic.c162
-rw-r--r--ext/fileinfo/libmagic/magic.h55
-rw-r--r--ext/fileinfo/libmagic/patchlevel.h6
-rw-r--r--ext/fileinfo/libmagic/print.c6
-rw-r--r--ext/fileinfo/libmagic/readcdf.c197
-rw-r--r--ext/fileinfo/libmagic/softmagic.c761
-rw-r--r--ext/fileinfo/libmagic/tar.h2
21 files changed, 1699 insertions, 1027 deletions
diff --git a/ext/fileinfo/libmagic/apprentice.c b/ext/fileinfo/libmagic/apprentice.c
index 8347afdeb7..efde260343 100644
--- a/ext/fileinfo/libmagic/apprentice.c
+++ b/ext/fileinfo/libmagic/apprentice.c
@@ -34,7 +34,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: apprentice.c,v 1.230 2015/01/02 21:29:39 christos Exp $")
+FILE_RCSID("@(#)$File: apprentice.c,v 1.255 2016/10/24 18:02:17 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -91,9 +91,9 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.230 2015/01/02 21:29:39 christos Exp $")
#define ALLOC_CHUNK (size_t)10
#define ALLOC_INCR (size_t)200
-#define MAP_TYPE_MMAP 0
+#define MAP_TYPE_USER 0
#define MAP_TYPE_MALLOC 1
-#define MAP_TYPE_USER 2
+#define MAP_TYPE_MMAP 2
struct magic_entry {
struct magic *mp;
@@ -148,12 +148,13 @@ private int check_buffer(struct magic_set *, struct magic_map *, const char *);
private void apprentice_unmap(struct magic_map *);
private int apprentice_compile(struct magic_set *, struct magic_map *,
const char *);
-private int check_format_type(const char *, int);
+private int check_format_type(const char *, int, const char **);
private int check_format(struct magic_set *, struct magic *);
private int get_op(char);
private int parse_mime(struct magic_set *, struct magic_entry *, const char *);
private int parse_strength(struct magic_set *, struct magic_entry *, const char *);
private int parse_apple(struct magic_set *, struct magic_entry *, const char *);
+private int parse_ext(struct magic_set *, struct magic_entry *, const char *);
private size_t magicsize = sizeof(struct magic);
@@ -168,6 +169,7 @@ private struct {
#define DECLARE_FIELD(name) { # name, sizeof(# name) - 1, parse_ ## name }
DECLARE_FIELD(mime),
DECLARE_FIELD(apple),
+ DECLARE_FIELD(ext),
DECLARE_FIELD(strength),
#undef DECLARE_FIELD
{ NULL, 0, NULL }
@@ -240,6 +242,7 @@ static const struct type_tbl_s type_tbl[] = {
{ XX("name"), FILE_NAME, FILE_FMT_NONE },
{ XX("use"), FILE_USE, FILE_FMT_NONE },
{ XX("clear"), FILE_CLEAR, FILE_FMT_NONE },
+ { XX("der"), FILE_DER, FILE_FMT_STR },
{ XX_NULL, FILE_INVALID, FILE_FMT_NONE },
};
@@ -248,6 +251,7 @@ static const struct type_tbl_s type_tbl[] = {
* unsigned.
*/
static const struct type_tbl_s special_tbl[] = {
+ { XX("der"), FILE_DER, FILE_FMT_STR },
{ XX("name"), FILE_NAME, FILE_FMT_STR },
{ XX("use"), FILE_USE, FILE_FMT_STR },
{ XX_NULL, FILE_INVALID, FILE_FMT_NONE },
@@ -382,11 +386,11 @@ add_mlist(struct mlist *mlp, struct magic_map *map, size_t idx)
{
struct mlist *ml;
- mlp->map = idx == 0 ? map : NULL;
+ mlp->map = NULL;
if ((ml = CAST(struct mlist *, emalloc(sizeof(*ml)))) == NULL)
return -1;
- ml->map = NULL;
+ ml->map = idx == 0 ? map : NULL;
ml->magic = map->magic[idx];
ml->nmagic = map->nmagic[idx];
@@ -422,6 +426,8 @@ apprentice_1(struct magic_set *ms, const char *fn, int action)
}
map = apprentice_map(ms, fn);
+ if (map == (struct magic_map *)-1)
+ return -1;
if (map == NULL) {
if (fn) {
if (ms->flags & MAGIC_CHECK)
@@ -435,7 +441,6 @@ apprentice_1(struct magic_set *ms, const char *fn, int action)
for (i = 0; i < MAGIC_SETS; i++) {
if (add_mlist(ms->mlist[i], map, i) == -1) {
file_oomem(ms, sizeof(*ml));
- apprentice_unmap(map);
return -1;
}
}
@@ -504,6 +509,8 @@ file_ms_alloc(int flags)
ms->elf_shnum_max = FILE_ELF_SHNUM_MAX;
ms->elf_phnum_max = FILE_ELF_PHNUM_MAX;
ms->elf_notes_max = FILE_ELF_NOTES_MAX;
+ ms->regex_max = FILE_REGEX_MAX;
+ ms->bytes_max = FILE_BYTES_MAX;
return ms;
free:
efree(ms);
@@ -552,7 +559,7 @@ mlist_free(struct mlist *mlist)
ml = mlist->next;
for (ml = mlist->next; (next = ml->next) != NULL; ml = next) {
if (ml->map)
- apprentice_unmap(ml->map);
+ apprentice_unmap(CAST(struct magic_map *, ml->map));
efree(ml);
if (ml == mlist)
break;
@@ -794,6 +801,10 @@ apprentice_magic_strength(const struct magic *m)
case FILE_USE:
break;
+ case FILE_DER:
+ val += MULT;
+ break;
+
default:
(void)fprintf(stderr, "Bad type %d\n", m->type);
abort();
@@ -949,6 +960,7 @@ set_test_type(struct magic *mstart, struct magic *m)
case FILE_DOUBLE:
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
+ case FILE_DER:
mstart->flag |= BINTEST;
break;
case FILE_STRING:
@@ -1230,6 +1242,7 @@ apprentice_load(struct magic_set *ms, const char *fn, int action)
file_oomem(ms, sizeof(*map));
return NULL;
}
+ map->type = MAP_TYPE_MALLOC;
/* print silly verbose header for USG compat. */
if (action == FILE_CHECK)
@@ -1293,8 +1306,9 @@ apprentice_load(struct magic_set *ms, const char *fn, int action)
}
i = set_text_binary(ms, mset[j].me, mset[j].count, i);
}
- qsort(mset[j].me, mset[j].count, sizeof(*mset[j].me),
- apprentice_sort);
+ if (mset[j].me)
+ qsort(mset[j].me, mset[j].count, sizeof(*mset[j].me),
+ apprentice_sort);
/*
* Make sure that any level 0 "default" line is last
@@ -1387,6 +1401,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
case FILE_NAME:
case FILE_USE:
case FILE_CLEAR:
+ case FILE_DER:
break;
default:
if (ms->flags & MAGIC_CHECK)
@@ -1787,24 +1802,31 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
}
}
/* Indirect offsets are not valid at level 0. */
- if (m->cont_level == 0 && (m->flag & (OFFADD | INDIROFFADD)))
+ if (m->cont_level == 0 && (m->flag & (OFFADD | INDIROFFADD))) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "relative offset at level 0");
+ return -1;
+ }
/* get offset, then skip over it */
m->offset = (uint32_t)strtoul(l, &t, 0);
- if (l == t)
+ if (l == t) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "offset `%s' invalid", l);
+ return -1;
+ }
l = t;
if (m->flag & INDIR) {
m->in_type = FILE_LONG;
m->in_offset = 0;
+ m->in_op = 0;
/*
- * read [.lbs][+-]nnnnn)
+ * read [.,lbs][+-]nnnnn)
*/
- if (*l == '.') {
+ if (*l == '.' || *l == ',') {
+ if (*l == ',')
+ m->in_op |= FILE_OPSIGNED;
l++;
switch (*l) {
case 'l':
@@ -1851,12 +1873,11 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
file_magwarn(ms,
"indirect offset type `%c' invalid",
*l);
- break;
+ return -1;
}
l++;
}
- m->in_op = 0;
if (*l == '~') {
m->in_op |= FILE_OPINVERSE;
l++;
@@ -1871,17 +1892,21 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
}
if (isdigit((unsigned char)*l) || *l == '-') {
m->in_offset = (int32_t)strtol(l, &t, 0);
- if (l == t)
+ if (l == t) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms,
"in_offset `%s' invalid", l);
+ return -1;
+ }
l = t;
}
if (*l++ != ')' ||
- ((m->in_op & FILE_OPINDIRECT) && *l++ != ')'))
+ ((m->in_op & FILE_OPINDIRECT) && *l++ != ')')) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms,
"missing ')' in indirect offset");
+ return -1;
+ }
}
EATAB;
@@ -1931,7 +1956,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
m->type = get_standard_integer_type(l, &l);
else if (*l == 's' && !isalpha((unsigned char)l[1])) {
m->type = FILE_STRING;
- ++l;
+ ++l;
}
}
}
@@ -2034,7 +2059,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
/*
* TODO finish this macro and start using it!
- * #define offsetcheck {if (offset > HOWMANY-1)
+ * #define offsetcheck {if (offset > ms->bytes_max -1)
* magwarn("offset too big"); }
*/
@@ -2193,7 +2218,20 @@ parse_apple(struct magic_set *ms, struct magic_entry *me, const char *line)
return parse_extra(ms, me, line,
CAST(off_t, offsetof(struct magic, apple)),
- sizeof(m->apple), "APPLE", "!+-./", 0);
+ sizeof(m->apple), "APPLE", "!+-./?", 0);
+}
+
+/*
+ * Parse a comma-separated list of extensions
+ */
+private int
+parse_ext(struct magic_set *ms, struct magic_entry *me, const char *line)
+{
+ struct magic *m = &me->mp[0];
+
+ return parse_extra(ms, me, line,
+ CAST(off_t, offsetof(struct magic, ext)),
+ sizeof(m->ext), "EXTENSION", ",!+-/", 0);
}
/*
@@ -2211,11 +2249,13 @@ parse_mime(struct magic_set *ms, struct magic_entry *me, const char *line)
}
private int
-check_format_type(const char *ptr, int type)
+check_format_type(const char *ptr, int type, const char **estr)
{
int quad = 0, h;
+ size_t len, cnt;
if (*ptr == '\0') {
/* Missing format string; bad */
+ *estr = "missing format spec";
return -1;
}
@@ -2252,15 +2292,22 @@ check_format_type(const char *ptr, int type)
ptr++;
if (*ptr == '.')
ptr++;
- while (isdigit((unsigned char)*ptr)) ptr++;
+#define CHECKLEN() do { \
+ for (len = cnt = 0; isdigit((unsigned char)*ptr); ptr++, cnt++) \
+ len = len * 10 + (*ptr - '0'); \
+ if (cnt > 5 || len > 1024) \
+ goto toolong; \
+} while (/*CONSTCOND*/0)
+
+ CHECKLEN();
if (*ptr == '.')
ptr++;
- while (isdigit((unsigned char)*ptr)) ptr++;
+ CHECKLEN();
if (quad) {
if (*ptr++ != 'l')
- return -1;
+ goto invalid;
if (*ptr++ != 'l')
- return -1;
+ goto invalid;
}
switch (*ptr++) {
@@ -2274,9 +2321,11 @@ check_format_type(const char *ptr, int type)
case 'o':
case 'x':
case 'X':
- return h != 0 ? -1 : 0;
+ if (h == 0)
+ return 0;
+ /*FALLTHROUGH*/
default:
- return -1;
+ goto invalid;
}
/*
@@ -2285,11 +2334,11 @@ check_format_type(const char *ptr, int type)
*/
case 'h':
if (h-- <= 0)
- return -1;
+ goto invalid;
switch (*ptr++) {
case 'h':
if (h-- <= 0)
- return -1;
+ goto invalid;
switch (*ptr++) {
case 'i':
case 'd':
@@ -2299,7 +2348,7 @@ check_format_type(const char *ptr, int type)
case 'X':
return 0;
default:
- return -1;
+ goto invalid;
}
case 'i':
case 'd':
@@ -2307,13 +2356,17 @@ check_format_type(const char *ptr, int type)
case 'o':
case 'x':
case 'X':
- return h != 0 ? -1 : 0;
+ if (h == 0)
+ return 0;
+ /*FALLTHROUGH*/
default:
- return -1;
+ goto invalid;
}
#endif
case 'c':
- return h != 2 ? -1 : 0;
+ if (h == 2)
+ return 0;
+ goto invalid;
case 'i':
case 'd':
case 'u':
@@ -2321,12 +2374,14 @@ check_format_type(const char *ptr, int type)
case 'x':
case 'X':
#ifdef STRICT_FORMAT
- return h != 0 ? -1 : 0;
+ if (h == 0)
+ return 0;
+ /*FALLTHROUGH*/
#else
return 0;
#endif
default:
- return -1;
+ goto invalid;
}
case FILE_FMT_FLOAT:
@@ -2335,11 +2390,10 @@ check_format_type(const char *ptr, int type)
ptr++;
if (*ptr == '.')
ptr++;
- while (isdigit((unsigned char)*ptr)) ptr++;
+ CHECKLEN();
if (*ptr == '.')
ptr++;
- while (isdigit((unsigned char)*ptr)) ptr++;
-
+ CHECKLEN();
switch (*ptr++) {
case 'e':
case 'E':
@@ -2350,7 +2404,7 @@ check_format_type(const char *ptr, int type)
return 0;
default:
- return -1;
+ goto invalid;
}
@@ -2369,14 +2423,17 @@ check_format_type(const char *ptr, int type)
case 's':
return 0;
default:
- return -1;
+ goto invalid;
}
default:
/* internal error */
abort();
}
- /*NOTREACHED*/
+invalid:
+ *estr = "not valid";
+toolong:
+ *estr = "too long";
return -1;
}
@@ -2388,6 +2445,7 @@ private int
check_format(struct magic_set *ms, struct magic *m)
{
char *ptr;
+ const char *estr;
for (ptr = m->desc; *ptr; ptr++)
if (*ptr == '%')
@@ -2411,13 +2469,13 @@ check_format(struct magic_set *ms, struct magic *m)
}
ptr++;
- if (check_format_type(ptr, m->type) == -1) {
+ if (check_format_type(ptr, m->type, &estr) == -1) {
/*
* TODO: this error message is unhelpful if the format
* string is not one character long
*/
- file_magwarn(ms, "Printf format `%c' is not valid for type "
- "`%s' in description `%s'", *ptr ? *ptr : '?',
+ file_magwarn(ms, "Printf format is %s for type "
+ "`%s' in description `%s'", estr,
file_names[m->type], m->desc);
return -1;
}
@@ -2451,6 +2509,7 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action)
case FILE_SEARCH:
case FILE_NAME:
case FILE_USE:
+ case FILE_DER:
*p = getstr(ms, m, *p, action == FILE_COMPILE);
if (*p == NULL) {
if (ms->flags & MAGIC_CHECK)
@@ -2478,12 +2537,14 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action)
case FILE_LEFLOAT:
if (m->reln != 'x') {
char *ep;
+ errno = 0;
#ifdef HAVE_STRTOF
m->value.f = strtof(*p, &ep);
#else
m->value.f = (float)strtod(*p, &ep);
#endif
- *p = ep;
+ if (errno == 0)
+ *p = ep;
}
return 0;
case FILE_DOUBLE:
@@ -2491,17 +2552,22 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action)
case FILE_LEDOUBLE:
if (m->reln != 'x') {
char *ep;
+ errno = 0;
m->value.d = strtod(*p, &ep);
- *p = ep;
+ if (errno == 0)
+ *p = ep;
}
return 0;
default:
if (m->reln != 'x') {
char *ep;
+ errno = 0;
m->value.q = file_signextend(ms, m,
(uint64_t)strtoull(*p, &ep, 0));
- *p = ep;
- eatsize(p);
+ if (errno == 0) {
+ *p = ep;
+ eatsize(p);
+ }
}
return 0;
}
@@ -2537,6 +2603,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn)
case '\0':
if (warn)
file_magwarn(ms, "incomplete escape");
+ s--;
goto out;
case '\t':
@@ -2660,6 +2727,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn)
} else
*p++ = (char)c;
}
+ --s;
out:
*p = '\0';
m->vallen = CAST(unsigned char, (p - origp));
@@ -3015,10 +3083,9 @@ apprentice_compile(struct magic_set *ms, struct magic_map *map, const char *fn)
} hdr;
php_stream *stream;
+ dbname = mkdbname(ms, fn, 1);
- dbname = mkdbname(ms, fn, 0);
-
- if (dbname == NULL)
+ if (dbname == NULL)
goto out;
/* wb+ == O_WRONLY|O_CREAT|O_TRUNC|O_BINARY */
@@ -3099,7 +3166,7 @@ mkdbname(struct magic_set *ms, const char *fn, int strip)
spprintf(&buf, MAXPATHLEN, "%.*s%s", (int)(q - fn), fn, ext);
/* Compatibility with old code that looked in .mime */
- if (strstr(p, ".mime") != NULL)
+ if (strstr(fn, ".mime") != NULL)
ms->flags &= MAGIC_MIME_TYPE;
return buf;
}
@@ -3214,9 +3281,10 @@ file_pstring_length_size(const struct magic *m)
}
}
protected size_t
-file_pstring_get_length(const struct magic *m, const char *s)
+file_pstring_get_length(const struct magic *m, const char *ss)
{
size_t len = 0;
+ const unsigned char *s = (const unsigned char *)ss;
switch (m->str_flags & PSTRING_LEN) {
case PSTRING_1_LE:
diff --git a/ext/fileinfo/libmagic/apptype.c b/ext/fileinfo/libmagic/apptype.c
index 164c4f3704..fcd764e49a 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.12 2011/08/28 07:03:27 christos Exp $")
+FILE_RCSID("@(#)$File: apptype.c,v 1.13 2011/09/07 21:57:15 christos Exp $")
#endif /* lint */
#include <stdlib.h>
diff --git a/ext/fileinfo/libmagic/ascmagic.c b/ext/fileinfo/libmagic/ascmagic.c
index 2b096ac806..4756ed5b32 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.90 2014/11/28 02:35:05 christos Exp $")
+FILE_RCSID("@(#)$File: ascmagic.c,v 1.97 2016/06/27 20:56:25 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -79,9 +79,6 @@ file_ascmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
const char *code_mime = NULL;
const char *type = NULL;
- if (ms->flags & MAGIC_APPLE)
- return 0;
-
nbytes = trim_nuls(buf, nbytes);
/* If file doesn't look like any sort of text, give up. */
@@ -123,9 +120,6 @@ file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf,
size_t last_line_end = (size_t)-1;
int has_long_lines = 0;
- if (ms->flags & MAGIC_APPLE)
- return 0;
-
nbytes = trim_nuls(buf, nbytes);
/* If we have fewer than 2 bytes, give up. */
@@ -147,10 +141,16 @@ file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf,
== NULL)
goto done;
if ((rv = file_softmagic(ms, utf8_buf,
- (size_t)(utf8_end - utf8_buf), 0, NULL,
+ (size_t)(utf8_end - utf8_buf), NULL, NULL,
TEXTTEST, text)) == 0)
rv = -1;
+ if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))) {
+ rv = rv == -1 ? 0 : 1;
+ goto done;
+ }
}
+ if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)))
+ return 0;
/* Now try to discover other details about the file. */
for (i = 0; i < ulen; i++) {
@@ -183,10 +183,10 @@ file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf,
}
/* Beware, if the data has been truncated, the final CR could have
- been followed by a LF. If we have HOWMANY bytes, it indicates
+ been followed by a LF. If we have ms->bytes_max bytes, it indicates
that the data might have been truncated, probably even before
this function was called. */
- if (seen_cr && nbytes < HOWMANY)
+ if (seen_cr && nbytes < ms->bytes_max)
n_cr++;
if (strcmp(type, "binary") == 0) {
diff --git a/ext/fileinfo/libmagic/cdf.c b/ext/fileinfo/libmagic/cdf.c
index 28084fbe44..08822cf9b3 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.73 2015/01/11 16:58:25 christos Exp $")
+FILE_RCSID("@(#)$File: cdf.c,v 1.85 2016/10/24 18:02:17 christos Exp $")
#endif
#include <assert.h>
@@ -276,14 +276,33 @@ cdf_unpack_dir(cdf_directory_t *d, char *buf)
CDF_UNPACK(d->d_unused0);
}
+int
+cdf_zero_stream(cdf_stream_t *scn)
+{
+ scn->sst_len = 0;
+ scn->sst_dirlen = 0;
+ scn->sst_ss = 0;
+ free(scn->sst_tab);
+ scn->sst_tab = NULL;
+ return -1;
+}
+
+static size_t
+cdf_check_stream(const cdf_stream_t *sst, const cdf_header_t *h)
+{
+ size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ?
+ CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h);
+ assert(ss == sst->sst_ss);
+ return sst->sst_ss;
+}
+
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;
- size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ?
- CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h);
+ size_t ss = cdf_check_stream(sst, h);
/*LINTED*/(void)&line;
if (e >= b && (size_t)(e - b) <= ss * sst->sst_len)
return 0;
@@ -301,8 +320,7 @@ cdf_read(const cdf_info_t *info, zend_off_t off, void *buf, size_t len)
size_t siz = (size_t)off + len;
if ((zend_off_t)(off + len) != (zend_off_t)siz) {
- errno = EINVAL;
- return -1;
+ goto out;
}
if (info->i_buf != NULL && info->i_len >= siz) {
@@ -311,7 +329,7 @@ cdf_read(const cdf_info_t *info, zend_off_t off, void *buf, size_t len)
}
if (info->i_fd == -1)
- return -1;
+ goto out;
if (FINFO_LSEEK_FUNC(info->i_fd, off, SEEK_SET) == (zend_off_t)-1)
return -1;
@@ -320,6 +338,9 @@ cdf_read(const cdf_info_t *info, zend_off_t off, void *buf, size_t len)
return -1;
return (ssize_t)len;
+out:
+ errno = EINVAL;
+ return -1;
}
int
@@ -376,11 +397,14 @@ cdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs,
DPRINTF(("Out of bounds read %" SIZE_T_FORMAT "u > %"
SIZE_T_FORMAT "u\n",
pos + len, CDF_SEC_SIZE(h) * sst->sst_len));
- return -1;
+ goto out;
}
(void)memcpy(((char *)buf) + offs,
((const char *)sst->sst_tab) + pos, len);
return len;
+out:
+ errno = EFTYPE;
+ return -1;
}
/*
@@ -434,8 +458,7 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat)
goto out;
if (j >= CDF_LOOP_LIMIT) {
DPRINTF(("Reading master sector loop limit"));
- errno = EFTYPE;
- goto out2;
+ goto out3;
}
if (cdf_read_sector(info, msa, 0, ss, h, mid) != (ssize_t)ss) {
DPRINTF(("Reading master sector %d", mid));
@@ -448,8 +471,7 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat)
if (i >= sat->sat_len) {
DPRINTF(("Out of bounds reading MSA %" SIZE_T_FORMAT
"u >= %" SIZE_T_FORMAT "u", i, sat->sat_len));
- errno = EFTYPE;
- goto out2;
+ goto out3;
}
if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h,
sec) != (ssize_t)ss) {
@@ -464,6 +486,8 @@ out:
sat->sat_len = i;
free(msa);
return 0;
+out3:
+ errno = EFTYPE;
out2:
free(msa);
out1:
@@ -489,23 +513,24 @@ cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size)
DPRINTF((" %d", sid));
if (j >= CDF_LOOP_LIMIT) {
DPRINTF(("Counting chain loop limit"));
- errno = EFTYPE;
- return (size_t)-1;
+ goto out;
}
if (sid >= maxsector) {
DPRINTF(("Sector %d >= %d\n", sid, maxsector));
- errno = EFTYPE;
- return (size_t)-1;
+ goto out;
}
sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]);
}
if (i == 0) {
DPRINTF((" none, sid: %d\n", sid));
- return (size_t)-1;
+ goto out;
}
DPRINTF(("\n"));
return i;
+out:
+ errno = EFTYPE;
+ return (size_t)-1;
}
int
@@ -514,27 +539,27 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h,
{
size_t ss = CDF_SEC_SIZE(h), i, j;
ssize_t nr;
+ scn->sst_tab = NULL;
scn->sst_len = cdf_count_chain(sat, sid, ss);
scn->sst_dirlen = len;
+ scn->sst_ss = ss;
if (scn->sst_len == (size_t)-1)
- return -1;
+ goto out;
scn->sst_tab = calloc(scn->sst_len, ss);
if (scn->sst_tab == NULL)
- return -1;
+ return cdf_zero_stream(scn);
for (j = i = 0; sid >= 0; i++, j++) {
if (j >= CDF_LOOP_LIMIT) {
DPRINTF(("Read long sector chain loop limit"));
- errno = EFTYPE;
goto out;
}
if (i >= scn->sst_len) {
DPRINTF(("Out of bounds reading long sector chain "
"%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", i,
scn->sst_len));
- errno = EFTYPE;
goto out;
}
if ((nr = cdf_read_sector(info, scn->sst_tab, i * ss, ss, h,
@@ -550,8 +575,8 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h,
}
return 0;
out:
- free(scn->sst_tab);
- return -1;
+ errno = EFTYPE;
+ return cdf_zero_stream(scn);
}
int
@@ -560,27 +585,27 @@ cdf_read_short_sector_chain(const cdf_header_t *h,
cdf_secid_t sid, size_t len, cdf_stream_t *scn)
{
size_t ss = CDF_SHORT_SEC_SIZE(h), i, j;
+ scn->sst_tab = NULL;
scn->sst_len = cdf_count_chain(ssat, sid, CDF_SEC_SIZE(h));
scn->sst_dirlen = len;
+ scn->sst_ss = ss;
- if (sst->sst_tab == NULL || scn->sst_len == (size_t)-1)
- return -1;
+ if (scn->sst_len == (size_t)-1)
+ goto out;
scn->sst_tab = calloc(scn->sst_len, ss);
if (scn->sst_tab == NULL)
- return -1;
+ return cdf_zero_stream(scn);
for (j = i = 0; sid >= 0; i++, j++) {
if (j >= CDF_LOOP_LIMIT) {
DPRINTF(("Read short sector chain loop limit"));
- errno = EFTYPE;
goto out;
}
if (i >= scn->sst_len) {
DPRINTF(("Out of bounds reading short sector chain "
"%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n",
i, scn->sst_len));
- errno = EFTYPE;
goto out;
}
if (cdf_read_short_sector(sst, scn->sst_tab, i * ss, ss, h,
@@ -592,8 +617,8 @@ cdf_read_short_sector_chain(const cdf_header_t *h,
}
return 0;
out:
- free(scn->sst_tab);
- return -1;
+ errno = EFTYPE;
+ return cdf_zero_stream(scn);
}
int
@@ -638,7 +663,6 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h,
for (j = i = 0; i < ns; i++, j++) {
if (j >= CDF_LOOP_LIMIT) {
DPRINTF(("Read dir loop limit"));
- errno = EFTYPE;
goto out;
}
if (cdf_read_sector(info, buf, 0, ss, h, sid) != (ssize_t)ss) {
@@ -659,6 +683,7 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h,
out:
free(dir->dir_tab);
free(buf);
+ errno = EFTYPE;
return -1;
}
@@ -671,36 +696,37 @@ cdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h,
size_t ss = CDF_SEC_SIZE(h);
cdf_secid_t sid = h->h_secid_first_sector_in_short_sat;
- ssat->sat_len = cdf_count_chain(sat, sid, CDF_SEC_SIZE(h));
+ ssat->sat_tab = NULL;
+ ssat->sat_len = cdf_count_chain(sat, sid, ss);
if (ssat->sat_len == (size_t)-1)
- return -1;
+ goto out;
ssat->sat_tab = CAST(cdf_secid_t *, calloc(ssat->sat_len, ss));
if (ssat->sat_tab == NULL)
- return -1;
+ goto out1;
for (j = i = 0; sid >= 0; i++, j++) {
if (j >= CDF_LOOP_LIMIT) {
DPRINTF(("Read short sat sector loop limit"));
- errno = EFTYPE;
goto out;
}
if (i >= ssat->sat_len) {
DPRINTF(("Out of bounds reading short sector chain "
"%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", i,
ssat->sat_len));
- errno = EFTYPE;
goto out;
}
if (cdf_read_sector(info, ssat->sat_tab, i * ss, ss, h, sid) !=
(ssize_t)ss) {
DPRINTF(("Reading short sat sector %d", sid));
- goto out;
+ goto out1;
}
sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]);
}
return 0;
out:
+ errno = EFTYPE;
+out1:
free(ssat->sat_tab);
return -1;
}
@@ -719,21 +745,24 @@ cdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h,
break;
/* If the it is not there, just fake it; some docs don't have it */
- if (i == dir->dir_len)
+ if (i == dir->dir_len) {
+ DPRINTF(("Cannot find root storage dir\n"));
goto out;
+ }
d = &dir->dir_tab[i];
*root = d;
/* If the it is not there, just fake it; some docs don't have it */
- if (d->d_stream_first_sector < 0)
+ if (d->d_stream_first_sector < 0) {
+ DPRINTF(("No first secror in dir\n"));
goto out;
+ }
- return cdf_read_long_sector_chain(info, h, sat,
+ return cdf_read_long_sector_chain(info, h, sat,
d->d_stream_first_sector, d->d_size, scn);
out:
scn->sst_tab = NULL;
- scn->sst_len = 0;
- scn->sst_dirlen = 0;
+ (void)cdf_zero_stream(scn);
return 0;
}
@@ -747,6 +776,15 @@ cdf_namecmp(const char *d, const uint16_t *s, size_t l)
}
int
+cdf_read_doc_summary_info(const cdf_info_t *info, const cdf_header_t *h,
+ const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst,
+ const cdf_dir_t *dir, cdf_stream_t *scn)
+{
+ return cdf_read_user_stream(info, h, sat, ssat, sst, dir,
+ "\05DocumentSummaryInformation", scn);
+}
+
+int
cdf_read_summary_info(const cdf_info_t *info, const cdf_header_t *h,
const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst,
const cdf_dir_t *dir, cdf_stream_t *scn)
@@ -763,8 +801,10 @@ cdf_read_user_stream(const cdf_info_t *info, const cdf_header_t *h,
const cdf_directory_t *d;
int i = cdf_find_stream(dir, name, CDF_DIR_TYPE_USER_STREAM);
- if (i <= 0)
+ if (i <= 0) {
+ memset(scn, 0, sizeof(*scn));
return -1;
+ }
d = &dir->dir_tab[i - 1];
return cdf_read_sector_chain(info, h, sat, ssat, sst,
@@ -837,7 +877,7 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h,
malloc(*maxcount * sizeof(*inp)));
}
if (inp == NULL)
- goto out;
+ goto out1;
*info = inp;
inp += *count;
*count += sh.sh_properties;
@@ -944,7 +984,7 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h,
inp = CAST(cdf_property_info_t *,
realloc(*info, *maxcount * sizeof(*inp)));
if (inp == NULL)
- goto out;
+ goto out1;
*info = inp;
inp = *info + nelem;
}
@@ -989,6 +1029,8 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h,
}
return 0;
out:
+ errno = EFTYPE;
+out1:
free(*info);
return -1;
}
@@ -1035,35 +1077,40 @@ int
cdf_unpack_catalog(const cdf_header_t *h, const cdf_stream_t *sst,
cdf_catalog_t **cat)
{
- size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ?
- CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h);
+ size_t ss = cdf_check_stream(sst, h);
const char *b = CAST(const char *, sst->sst_tab);
const char *eb = b + ss * sst->sst_len;
- size_t nr, i, k;
+ size_t nr, i, j, k;
cdf_catalog_entry_t *ce;
uint16_t reclen;
const uint16_t *np;
- for (nr = 0; b < eb; nr++) {
+ for (nr = 0;; nr++) {
memcpy(&reclen, b, sizeof(reclen));
reclen = CDF_TOLE2(reclen);
if (reclen == 0)
break;
b += reclen;
+ if (b > eb)
+ break;
}
+ if (nr == 0)
+ return -1;
+ nr--;
*cat = CAST(cdf_catalog_t *,
malloc(sizeof(cdf_catalog_t) + nr * sizeof(*ce)));
- (*cat)->cat_num = nr;
+ if (*cat == NULL)
+ return -1;
ce = (*cat)->cat_e;
memset(ce, 0, nr * sizeof(*ce));
b = CAST(const char *, sst->sst_tab);
- for (i = 0; i < nr; i++, b += reclen) {
- cdf_catalog_entry_t *cep = &ce[i];
+ for (j = i = 0; i < nr; b += reclen) {
+ cdf_catalog_entry_t *cep = &ce[j];
uint16_t rlen;
extract_catalog_field(uint16_t, ce_namlen, 0);
- extract_catalog_field(uint16_t, ce_num, 2);
- extract_catalog_field(uint64_t, ce_timestamp, 6);
+ extract_catalog_field(uint16_t, ce_num, 4);
+ extract_catalog_field(uint64_t, ce_timestamp, 8);
reclen = cep->ce_namlen;
if (reclen < 14) {
@@ -1077,7 +1124,7 @@ cdf_unpack_catalog(const cdf_header_t *h, const cdf_stream_t *sst,
cep->ce_namlen = rlen;
np = CAST(const uint16_t *, CAST(const void *, (b + 16)));
- if (CAST(const char *, np + cep->ce_namlen) > eb) {
+ if (RCAST(const char *, np + cep->ce_namlen) > eb) {
cep->ce_namlen = 0;
break;
}
@@ -1085,7 +1132,10 @@ cdf_unpack_catalog(const cdf_header_t *h, const cdf_stream_t *sst,
for (k = 0; k < cep->ce_namlen; k++)
cep->ce_name[k] = np[k]; /* XXX: CDF_TOLE2? */
cep->ce_name[cep->ce_namlen] = 0;
+ j = i;
+ i++;
}
+ (*cat)->cat_num = j;
return 0;
}
@@ -1251,10 +1301,9 @@ cdf_dump(const void *v, size_t len)
}
void
-cdf_dump_stream(const cdf_header_t *h, const cdf_stream_t *sst)
+cdf_dump_stream(const cdf_stream_t *sst)
{
- size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ?
- CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h);
+ size_t ss = sst->sst_ss;
cdf_dump(sst->sst_tab, ss * sst->sst_len);
}
@@ -1308,7 +1357,7 @@ cdf_dump_dir(const cdf_info_t *info, const cdf_header_t *h,
name, d->d_stream_first_sector, d->d_size);
break;
}
- cdf_dump_stream(h, &scn);
+ cdf_dump_stream(&scn);
free(scn.sst_tab);
break;
default:
@@ -1481,7 +1530,7 @@ main(int argc, char *argv[])
== -1)
err(1, "Cannot read short stream");
#ifdef CDF_DEBUG
- cdf_dump_stream(&h, &sst);
+ cdf_dump_stream(&sst);
#endif
#ifdef CDF_DEBUG
@@ -1496,8 +1545,8 @@ main(int argc, char *argv[])
else
cdf_dump_summary_info(&h, &scn);
#endif
- if (cdf_read_catalog(&info, &h, &sat, &ssat, &sst, &dir,
- &scn) == -1)
+ if (cdf_read_user_stream(&info, &h, &sat, &ssat, &sst,
+ &dir, "Catalog", &scn) == -1)
warn("Cannot read catalog");
#ifdef CDF_DEBUG
else
diff --git a/ext/fileinfo/libmagic/cdf.h b/ext/fileinfo/libmagic/cdf.h
index 9006a686ef..9d5578c6ba 100644
--- a/ext/fileinfo/libmagic/cdf.h
+++ b/ext/fileinfo/libmagic/cdf.h
@@ -131,6 +131,7 @@ typedef struct {
void *sst_tab;
size_t sst_len;
size_t sst_dirlen;
+ size_t sst_ss;
} cdf_stream_t;
typedef struct {
@@ -279,7 +280,7 @@ typedef struct {
typedef struct {
size_t cat_num;
- cdf_catalog_entry_t cat_e[0];
+ cdf_catalog_entry_t cat_e[1];
} cdf_catalog_t;
struct timeval;
@@ -317,6 +318,10 @@ int cdf_read_user_stream(const cdf_info_t *, const cdf_header_t *,
const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *,
const cdf_dir_t *, const char *, cdf_stream_t *);
int cdf_find_stream(const cdf_dir_t *, const char *, int);
+int cdf_zero_stream(cdf_stream_t *);
+int cdf_read_doc_summary_info(const cdf_info_t *, const cdf_header_t *,
+ const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *,
+ const cdf_dir_t *, cdf_stream_t *);
int cdf_read_summary_info(const cdf_info_t *, const cdf_header_t *,
const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *,
const cdf_dir_t *, cdf_stream_t *);
@@ -337,7 +342,7 @@ char *cdf_u16tos8(char *, size_t, const uint16_t *);
void cdf_dump_header(const cdf_header_t *);
void cdf_dump_sat(const char *, const cdf_sat_t *, size_t);
void cdf_dump(const void *, size_t);
-void cdf_dump_stream(const cdf_header_t *, const cdf_stream_t *);
+void cdf_dump_stream(const cdf_stream_t *);
void cdf_dump_dir(const cdf_info_t *, const cdf_header_t *, const cdf_sat_t *,
const cdf_sat_t *, const cdf_stream_t *, const cdf_dir_t *);
void cdf_dump_property_info(const cdf_property_info_t *, size_t);
diff --git a/ext/fileinfo/libmagic/cdf_time.c b/ext/fileinfo/libmagic/cdf_time.c
index f659ada338..5f8af4355d 100644
--- a/ext/fileinfo/libmagic/cdf_time.c
+++ b/ext/fileinfo/libmagic/cdf_time.c
@@ -27,7 +27,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: cdf_time.c,v 1.14 2014/04/17 12:44:01 christos Exp $")
+FILE_RCSID("@(#)$File: cdf_time.c,v 1.15 2014/05/14 23:15:42 christos Exp $")
#endif
#include <time.h>
diff --git a/ext/fileinfo/libmagic/compress.c b/ext/fileinfo/libmagic/compress.c
index 61d75bcf08..07bb6ffab5 100644
--- a/ext/fileinfo/libmagic/compress.c
+++ b/ext/fileinfo/libmagic/compress.c
@@ -32,11 +32,10 @@
* uncompress(method, old, n, newch) - uncompress old into new,
* using method, return sizeof new
*/
-#include "config.h"
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: compress.c,v 1.77 2014/12/12 16:33:01 christos Exp $")
+FILE_RCSID("@(#)$File: compress.c,v 1.100 2016/10/24 18:02:17 christos Exp $")
#endif
#include "magic.h"
@@ -61,48 +60,86 @@ typedef void (*sig_t)(int);
#if defined(HAVE_SYS_TIME_H)
#include <sys/time.h>
#endif
-#if defined(HAVE_ZLIB_H) && defined(HAVE_LIBZ)
+#if defined(HAVE_ZLIB_H)
#define BUILTIN_DECOMPRESS
#include <zlib.h>
#endif
#undef FIONREAD
+#define gzip_flags "-cd"
+#define lrzip_flags "-do"
+#define lzip_flags gzip_flags
+
+static const char *gzip_args[] = {
+ "gzip", gzip_flags, NULL
+};
+static const char *uncompress_args[] = {
+ "uncompress", "-c", NULL
+};
+static const char *bzip2_args[] = {
+ "bzip2", "-cd", NULL
+};
+static const char *lzip_args[] = {
+ "lzip", lzip_flags, NULL
+};
+static const char *xz_args[] = {
+ "xz", "-cd", NULL
+};
+static const char *lrzip_args[] = {
+ "lrzip", lrzip_flags, NULL
+};
+static const char *lz4_args[] = {
+ "lz4", "-cd", NULL
+};
+static const char *zstd_args[] = {
+ "zstd", "-cd", NULL
+};
private const struct {
- const char magic[8];
+ const void *magic;
size_t maglen;
- const char *argv[3];
- int silent;
+ const char **argv;
} compr[] = {
- { "\037\235", 2, { "gzip", "-cdq", NULL }, 1 }, /* compressed */
+ { "\037\235", 2, gzip_args }, /* compressed */
/* Uncompress can get stuck; so use gzip first if we have it
* Idea from Damien Clark, thanks! */
- { "\037\235", 2, { "uncompress", "-c", NULL }, 1 }, /* compressed */
- { "\037\213", 2, { "gzip", "-cdq", NULL }, 1 }, /* gzipped */
- { "\037\236", 2, { "gzip", "-cdq", NULL }, 1 }, /* frozen */
- { "\037\240", 2, { "gzip", "-cdq", NULL }, 1 }, /* SCO LZH */
+ { "\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 */
/* the standard pack utilities do not accept standard input */
- { "\037\036", 2, { "gzip", "-cdq", NULL }, 0 }, /* packed */
- { "PK\3\4", 4, { "gzip", "-cdq", NULL }, 1 }, /* pkzipped, */
- /* ...only first file examined */
- { "BZh", 3, { "bzip2", "-cd", NULL }, 1 }, /* bzip2-ed */
- { "LZIP", 4, { "lzip", "-cdq", NULL }, 1 },
- { "\3757zXZ\0",6,{ "xz", "-cd", NULL }, 1 }, /* XZ Utils */
- { "LRZI", 4, { "lrzip", "-dqo-", NULL }, 1 }, /* LRZIP */
- { "\004\"M\030", 4, { "lz4", "-cd", NULL }, 1 }, /* LZ4 */
+ { "\037\036", 2, gzip_args }, /* packed */
+ { "PK\3\4", 4, gzip_args }, /* 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 */
+#ifdef ZLIBSUPPORT
+ { RCAST(const void *, zlibcmp), 0, zlib_args }, /* zlib */
+#endif
};
-#define NODATA ((size_t)~0)
+#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 uncompressbuf(struct magic_set *, int, size_t,
- const unsigned char *, unsigned char **, size_t);
+private size_t ncompr = sizeof(compr) / sizeof(compr[0]);
+private int uncompressbuf(int, size_t, size_t, const unsigned char *,
+ unsigned char **, size_t *);
#ifdef BUILTIN_DECOMPRESS
-private size_t uncompressgzipped(struct magic_set *, const unsigned char *,
- unsigned char **, size_t);
+private int uncompresszlib(const unsigned char *, unsigned char **, size_t,
+ size_t *, int);
+private int uncompressgzipped(const unsigned char *, unsigned char **, size_t,
+ size_t *);
#endif
+static int makeerror(unsigned char **, size_t *, const char *, ...);
+private const char *methodname(size_t);
protected int
file_zmagic(struct magic_set *ms, int fd, const char *name,
@@ -110,7 +147,9 @@ file_zmagic(struct magic_set *ms, int fd, const char *name,
{
unsigned char *newbuf = NULL;
size_t i, nsz;
- int rv = 0;
+ char *rbuf;
+ file_pushbuf_t *pb;
+ int urv, prv, rv = 0;
int mime = ms->flags & MAGIC_MIME;
#ifdef HAVE_SIGNAL_H
sig_t osigpipe;
@@ -123,37 +162,81 @@ file_zmagic(struct magic_set *ms, int fd, const char *name,
osigpipe = signal(SIGPIPE, SIG_IGN);
#endif
for (i = 0; i < ncompr; i++) {
+ int zm;
if (nbytes < compr[i].maglen)
continue;
- if (memcmp(buf, compr[i].magic, compr[i].maglen) == 0 &&
- (nsz = uncompressbuf(ms, fd, i, buf, &newbuf,
- nbytes)) != NODATA) {
+#ifdef ZLIBSUPPORT
+ if (compr[i].maglen == 0)
+ zm = (RCAST(int (*)(const unsigned char *),
+ CCAST(void *, compr[i].magic)))(buf);
+ else
+#endif
+ zm = memcmp(buf, compr[i].magic, compr[i].maglen) == 0;
+
+ if (!zm)
+ continue;
+ nsz = nbytes;
+ urv = uncompressbuf(fd, ms->bytes_max, i, buf, &newbuf, &nsz);
+ DPRINTF("uncompressbuf = %d, %s, %zu\n", urv, (char *)newbuf,
+ nsz);
+ switch (urv) {
+ case OKDATA:
+ case ERRDATA:
+
ms->flags &= ~MAGIC_COMPRESS;
- rv = -1;
- if (file_buffer(ms, -1, name, newbuf, nsz) == -1)
+ if (urv == ERRDATA)
+ prv = file_printf(ms, "%s ERROR: %s",
+ methodname(i), newbuf);
+ else
+ prv = file_buffer(ms, -1, name, newbuf, nsz);
+ if (prv == -1)
goto error;
-
- if (mime == MAGIC_MIME || mime == 0) {
- if (file_printf(ms, mime ?
- " compressed-encoding=" : " (") == -1)
- goto error;
- if (file_buffer(ms, -1, NULL, buf, nbytes) == -1)
- goto error;
- if (!mime && file_printf(ms, ")") == -1)
+ rv = 1;
+ if ((ms->flags & MAGIC_COMPRESS_TRANSP) != 0)
+ goto out;
+ if (mime != MAGIC_MIME && mime != 0)
+ goto out;
+ if ((file_printf(ms,
+ mime ? " compressed-encoding=" : " (")) == -1)
+ goto error;
+ if ((pb = file_push_buffer(ms)) == NULL)
+ goto error;
+ /*
+ * XXX: If file_buffer fails here, we overwrite
+ * the compressed text. FIXME.
+ */
+ if (file_buffer(ms, -1, NULL, buf, nbytes) == -1)
+ goto error;
+ if ((rbuf = file_pop_buffer(ms, pb)) != NULL) {
+ if (file_printf(ms, "%s", rbuf) == -1) {
+ free(rbuf);
goto error;
+ }
+ free(rbuf);
}
-
- rv = 1;
+ if (!mime && file_printf(ms, ")") == -1)
+ goto error;
+ /*FALLTHROUGH*/
+ case NODATA:
+ break;
+ default:
+ abort();
+ /*NOTREACHED*/
+ error:
+ rv = -1;
break;
}
}
-error:
+out:
+ DPRINTF("rv = %d\n", rv);
+
#ifdef HAVE_SIGNAL_H
(void)signal(SIGPIPE, osigpipe);
#endif
if (newbuf)
efree(newbuf);
ms->flags |= MAGIC_COMPRESS;
+ DPRINTF("Zmagic returns %d\n", rv);
return rv;
}
#endif
@@ -243,7 +326,7 @@ nocheck:
return rn - n;
default:
n -= rv;
- buf = ((char *)buf) + rv;
+ buf = CAST(char *, CCAST(void *, buf)) + rv;
break;
}
while (n > 0);
@@ -326,192 +409,292 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf,
#define FNAME (1 << 3)
#define FCOMMENT (1 << 4)
-private size_t
-uncompressgzipped(struct magic_set *ms, const unsigned char *old,
- unsigned char **newch, size_t n)
+
+private int
+uncompressgzipped(const unsigned char *old, unsigned char **newch,
+ size_t bytes_max, size_t *n)
{
unsigned char flg = old[3];
size_t data_start = 10;
- z_stream z;
- int rc;
if (flg & FEXTRA) {
- if (data_start+1 >= n)
- return 0;
+ if (data_start + 1 >= *n)
+ goto err;
data_start += 2 + old[data_start] + old[data_start + 1] * 256;
}
if (flg & FNAME) {
- while(data_start < n && old[data_start])
+ while(data_start < *n && old[data_start])
data_start++;
data_start++;
}
- if(flg & FCOMMENT) {
- while(data_start < n && old[data_start])
+ if (flg & FCOMMENT) {
+ while(data_start < *n && old[data_start])
data_start++;
data_start++;
}
- if(flg & FHCRC)
+ if (flg & FHCRC)
data_start += 2;
- if (data_start >= n)
- return 0;
- if ((*newch = CAST(unsigned char *, emalloc(HOWMANY + 1))) == NULL) {
- return 0;
- }
-
- /* XXX: const castaway, via strchr */
- z.next_in = (Bytef *)strchr((const char *)old + data_start,
- old[data_start]);
- z.avail_in = CAST(uint32_t, (n - data_start));
+ if (data_start >= *n)
+ goto err;
+
+ *n -= data_start;
+ old += data_start;
+ return uncompresszlib(old, newch, bytes_max, n, 0);
+err:
+ return makeerror(newch, n, "File too short");
+}
+
+private int
+uncompresszlib(const unsigned char *old, unsigned char **newch,
+ size_t bytes_max, size_t *n, int zlib)
+{
+ int rc;
+ z_stream z;
+
+ if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL)
+ return makeerror(newch, n, "No buffer, %s", strerror(errno));
+
+ z.next_in = CCAST(Bytef *, old);
+ z.avail_in = CAST(uint32_t, *n);
z.next_out = *newch;
- z.avail_out = HOWMANY;
+ z.avail_out = bytes_max;
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;
/* LINTED bug in header macro */
- rc = inflateInit2(&z, -15);
- if (rc != Z_OK) {
- file_error(ms, 0, "zlib: %s", z.msg);
- return 0;
- }
+ rc = zlib ? inflateInit(&z) : inflateInit2(&z, -15);
+ if (rc != Z_OK)
+ goto err;
rc = inflate(&z, Z_SYNC_FLUSH);
- if (rc != Z_OK && rc != Z_STREAM_END) {
- file_error(ms, 0, "zlib: %s", z.msg);
- return 0;
- }
+ if (rc != Z_OK && rc != Z_STREAM_END)
+ goto err;
- n = (size_t)z.total_out;
- (void)inflateEnd(&z);
+ *n = (size_t)z.total_out;
+ rc = inflateEnd(&z);
+ if (rc != Z_OK)
+ goto err;
/* let's keep the nul-terminate tradition */
- (*newch)[n] = '\0';
+ (*newch)[*n] = '\0';
- return n;
+ return OKDATA;
+err:
+ strlcpy((char *)*newch, z.msg ? z.msg : zError(rc), bytes_max);
+ *n = strlen((char *)*newch);
+ return ERRDATA;
}
#endif
-private size_t
-uncompressbuf(struct magic_set *ms, int fd, size_t method,
- const unsigned char *old, unsigned char **newch, size_t n)
+static int
+makeerror(unsigned char **buf, size_t *len, const char *fmt, ...)
+{
+ char *msg;
+ va_list ap;
+ int rv;
+
+ va_start(ap, fmt);
+ rv = vasprintf(&msg, fmt, ap);
+ va_end(ap);
+ if (rv < 0) {
+ *buf = NULL;
+ *len = 0;
+ return NODATA;
+ }
+ *buf = (unsigned char *)msg;
+ *len = strlen(msg);
+ return ERRDATA;
+}
+
+static void
+closefd(int *fd, size_t i)
+{
+ if (fd[i] == -1)
+ return;
+ (void) close(fd[i]);
+ fd[i] = -1;
+}
+
+static void
+closep(int *fd)
+{
+ size_t i;
+ for (i = 0; i < 2; i++)
+ closefd(fd, i);
+}
+
+static void
+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));
+ exit(1);
+ }
+ closep(fd);
+}
+
+static void
+writechild(int fdp[3][2], const void *old, size_t n)
{
- int fdin[2], fdout[2];
int status;
+
+ 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:
+ DPRINTF("Fork failed (%s)\n", strerror(errno));
+ exit(1);
+ /*NOTREACHED*/
+
+ default: /* parent */
+ if (wait(&status) == -1) {
+ DPRINTF("Wait failed (%s)\n", strerror(errno));
+ exit(1);
+ }
+ DPRINTF("Grandchild wait return %#x\n", status);
+ }
+ closefd(fdp[STDIN_FILENO], 1);
+}
+
+static ssize_t
+filter_error(unsigned char *ubuf, ssize_t n)
+{
+ char *p;
+ char *buf;
+
+ ubuf[n] = '\0';
+ buf = (char *)ubuf;
+ while (isspace((unsigned char)*buf))
+ buf++;
+ DPRINTF("Filter error[[[%s]]]\n", buf);
+ if ((p = strchr((char *)buf, '\n')) != NULL)
+ *p = '\0';
+ if ((p = strchr((char *)buf, ';')) != NULL)
+ *p = '\0';
+ if ((p = strrchr((char *)buf, ':')) != NULL) {
+ ++p;
+ while (isspace((unsigned char)*p))
+ p++;
+ n = strlen(p);
+ memmove(ubuf, p, n + 1);
+ }
+ DPRINTF("Filter error after[[[%s]]]\n", (char *)ubuf);
+ if (islower(*ubuf))
+ *ubuf = toupper(*ubuf);
+ return n;
+}
+
+private const char *
+methodname(size_t method)
+{
+#ifdef BUILTIN_DECOMPRESS
+ /* FIXME: This doesn't cope with bzip2 */
+ if (method == 2 || compr[method].maglen == 0)
+ return "zlib";
+#endif
+ return compr[method].argv[0];
+}
+
+private int
+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;
+ size_t i;
ssize_t r;
#ifdef BUILTIN_DECOMPRESS
/* FIXME: This doesn't cope with bzip2 */
if (method == 2)
- return uncompressgzipped(ms, old, newch, n);
+ return uncompressgzipped(old, newch, bytes_max, n);
+ if (compr[method].maglen == 0)
+ return uncompresszlib(old, newch, bytes_max, n, 1);
#endif
(void)fflush(stdout);
(void)fflush(stderr);
- if ((fd != -1 && pipe(fdin) == -1) || pipe(fdout) == -1) {
- file_error(ms, errno, "cannot create pipe");
- return NODATA;
+ for (i = 0; i < __arraycount(fdp); i++)
+ fdp[i][0] = fdp[i][1] = -1;
+
+ if ((fd == -1 && pipe(fdp[STDIN_FILENO]) == -1) ||
+ pipe(fdp[STDOUT_FILENO]) == -1 || pipe(fdp[STDERR_FILENO]) == -1) {
+ closep(fdp[STDIN_FILENO]);
+ closep(fdp[STDOUT_FILENO]);
+ return makeerror(newch, n, "Cannot create pipe, %s",
+ strerror(errno));
}
switch (fork()) {
case 0: /* child */
- (void) close(0);
if (fd != -1) {
- (void) dup(fd);
- (void) FINFO_LSEEK_FUNC(0, (zend_off_t)0, SEEK_SET);
- } else {
- (void) dup(fdin[0]);
- (void) close(fdin[0]);
- (void) close(fdin[1]);
+ fdp[STDIN_FILENO][0] = fd;
+ (void) lseek(fd, (off_t)0, SEEK_SET);
}
-
- (void) close(1);
- (void) dup(fdout[1]);
- (void) close(fdout[0]);
- (void) close(fdout[1]);
-#ifndef DEBUG
- if (compr[method].silent)
- (void)close(2);
-#endif
+
+ for (i = 0; i < __arraycount(fdp); i++)
+ copydesc(i, fdp[i]);
(void)execvp(compr[method].argv[0],
(char *const *)(intptr_t)compr[method].argv);
-#ifdef DEBUG
- (void)fprintf(stderr, "exec `%s' failed (%s)\n",
+ dprintf(STDERR_FILENO, "exec `%s' failed, %s",
compr[method].argv[0], strerror(errno));
-#endif
exit(1);
/*NOTREACHED*/
case -1:
- file_error(ms, errno, "could not fork");
- return NODATA;
+ return makeerror(newch, n, "Cannot fork, %s",
+ strerror(errno));
default: /* parent */
- (void) close(fdout[1]);
- if (fd == -1) {
- (void) close(fdin[0]);
- /*
- * fork again, to avoid blocking because both
- * pipes filled
- */
- switch (fork()) {
- case 0: /* child */
- (void)close(fdout[0]);
- if (swrite(fdin[1], old, n) != (ssize_t)n) {
-#ifdef DEBUG
- (void)fprintf(stderr,
- "Write failed (%s)\n",
- strerror(errno));
-#endif
- exit(1);
- }
- exit(0);
- /*NOTREACHED*/
-
- case -1:
-#ifdef DEBUG
- (void)fprintf(stderr, "Fork failed (%s)\n",
- strerror(errno));
-#endif
- exit(1);
- /*NOTREACHED*/
-
- default: /* parent */
- break;
- }
- (void) close(fdin[1]);
- fdin[1] = -1;
- }
+ for (i = 1; i < __arraycount(fdp); i++)
+ closefd(fdp[i], 1);
- *newch = (unsigned char *) emalloc(HOWMANY + 1);
+ /* Write the buffer data to the child, if we don't have fd */
+ if (fd == -1)
+ writechild(fdp, old, *n);
- if ((r = sread(fdout[0], *newch, HOWMANY, 0)) <= 0) {
-#ifdef DEBUG
- (void)fprintf(stderr, "Read failed (%s)\n",
+ *newch = CAST(unsigned char *, malloc(bytes_max + 1));
+ if (*newch == NULL) {
+ rv = makeerror(newch, n, "No buffer, %s",
strerror(errno));
-#endif
- efree(*newch);
- n = NODATA-;
- *newch = NULL;
goto err;
- } else {
- n = r;
}
- /* NUL terminate, as every buffer is handled here. */
- (*newch)[n] = '\0';
-err:
- if (fdin[1] != -1)
- (void) close(fdin[1]);
- (void) close(fdout[0]);
-#ifdef WNOHANG
- while (waitpid(pid, NULL, WNOHANG) != -1)
- continue;
-#else
- (void)wait(NULL);
-#endif
-
- (void) close(fdin[0]);
-
- return n;
+ rv = OKDATA;
+ if ((r = sread(fdp[STDOUT_FILENO][0], *newch, bytes_max, 0)) > 0)
+ break;
+ DPRINTF("Read stdout failed %d (%s)\n", fdp[STDOUT_FILENO][0],
+ r != -1 ? strerror(errno) : "no data");
+
+ rv = ERRDATA;
+ if (r == 0 &&
+ (r = sread(fdp[STDERR_FILENO][0], *newch, bytes_max, 0)) > 0)
+ {
+ r = filter_error(*newch, r);
+ break;
+ }
+ free(*newch);
+ if (r == 0)
+ rv = makeerror(newch, n, "Read failed, %s",
+ strerror(errno));
+ else
+ rv = makeerror(newch, n, "No data");
+ goto err;
}
}
#endif /* if PHP_FILEINFO_UNCOMPRESS */
diff --git a/ext/fileinfo/libmagic/der.c b/ext/fileinfo/libmagic/der.c
new file mode 100644
index 0000000000..a23b13e55f
--- /dev/null
+++ b/ext/fileinfo/libmagic/der.c
@@ -0,0 +1,389 @@
+/*-
+ * Copyright (c) 2016 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.
+ */
+/*
+ * DER (Distinguished Encoding Rules) Parser
+ *
+ * Sources:
+ * https://en.wikipedia.org/wiki/X.690
+ * http://fm4dd.com/openssl/certexamples.htm
+ * http://blog.engelke.com/2014/10/17/parsing-ber-and-der-encoded-asn-1-objects/
+ */
+#ifndef TEST_DER
+#include "file.h"
+
+#ifndef lint
+FILE_RCSID("@(#)$File: der.c,v 1.10 2016/10/24 18:02:17 christos Exp $")
+#endif
+#endif
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef TEST_DER
+#include "magic.h"
+#include "der.h"
+#else
+#ifndef PHP_WIN32
+#include <sys/mman.h>
+#endif
+#include <sys/stat.h>
+#include <err.h>
+#endif
+
+#define DER_BAD ((uint32_t)-1)
+
+#define DER_CLASS_UNIVERSAL 0
+#define DER_CLASS_APPLICATION 1
+#define DER_CLASS_CONTEXT 2
+#define DER_CLASS_PRIVATE 3
+#ifdef DEBUG_DER
+static const char der_class[] = "UACP";
+#endif
+
+#define DER_TYPE_PRIMITIVE 0
+#define DER_TYPE_CONSTRUCTED 1
+#ifdef DEBUG_DER
+static const char der_type[] = "PC";
+#endif
+
+#define DER_TAG_EOC 0x00
+#define DER_TAG_BOOLEAN 0x01
+#define DER_TAG_INTEGER 0x02
+#define DER_TAG_BIT STRING 0x03
+#define DER_TAG_OCTET_STRING 0x04
+#define DER_TAG_NULL 0x05
+#define DER_TAG_OBJECT_IDENTIFIER 0x06
+#define DER_TAG_OBJECT_DESCRIPTOR 0x07
+#define DER_TAG_EXTERNAL 0x08
+#define DER_TAG_REAL 0x09
+#define DER_TAG_ENUMERATED 0x0a
+#define DER_TAG_EMBEDDED_PDV 0x0b
+#define DER_TAG_UTF8_STRING 0x0c
+#define DER_TAG_RELATIVE_OID 0x0d
+#define DER_TAG_RESERVED_1 0x0e
+#define DER_TAG_RESERVED_2 0x0f
+#define DER_TAG_SEQUENCE 0x10
+#define DER_TAG_SET 0x11
+#define DER_TAG_NUMERIC_STRING 0x12
+#define DER_TAG_PRINTABLE_STRING 0x13
+#define DER_TAG_T61_STRING 0x14
+#define DER_TAG_VIDEOTEX_STRING 0x15
+#define DER_TAG_IA5_STRING 0x16
+#define DER_TAG_UTCTIME 0x17
+#define DER_TAG_GENERALIZED_TIME 0x18
+#define DER_TAG_GRAPHIC_STRING 0x19
+#define DER_TAG_VISIBLE_STRING 0x1a
+#define DER_TAG_GENERAL_STRING 0x1b
+#define DER_TAG_UNIVERSAL_STRING 0x1c
+#define DER_TAG_CHARACTER_STRING 0x1d
+#define DER_TAG_BMP_STRING 0x1e
+#define DER_TAG_LONG 0x1f
+
+static const char *der__tag[] = {
+ "eoc", "bool", "int", "bit_str", "octet_str",
+ "null", "obj_id", "obj_desc", "ext", "real",
+ "enum", "embed", "utf8_str", "oid", "res1",
+ "res2", "seq", "set", "num_str", "prt_str",
+ "t61_str", "vid_str", "ia5_str", "utc_time",
+ "gen_time", "gr_str", "vis_str", "gen_str",
+ "char_str", "bmp_str", "long"
+};
+
+#ifdef DEBUG_DER
+#define DPRINTF(a) printf a
+#else
+#define DPRINTF(a)
+#endif
+
+#ifdef TEST_DER
+static uint8_t
+getclass(uint8_t c)
+{
+ return c >> 6;
+}
+
+static uint8_t
+gettype(uint8_t c)
+{
+ return (c >> 5) & 1;
+}
+#endif
+
+static uint32_t
+gettag(const uint8_t *c, size_t *p, size_t l)
+{
+ uint32_t tag;
+
+ if (*p >= l)
+ return DER_BAD;
+
+ tag = c[(*p)++] & 0x1f;
+
+ if (tag != 0x1f)
+ return tag;
+
+ if (*p >= l)
+ return DER_BAD;
+
+ while (c[*p] >= 0x80) {
+ tag = tag * 128 + c[(*p)++] - 0x80;
+ if (*p >= l)
+ return DER_BAD;
+ }
+ return tag;
+}
+
+static uint32_t
+getlength(const uint8_t *c, size_t *p, size_t l)
+{
+ uint8_t digits, i;
+ size_t len;
+
+ if (*p >= l)
+ return DER_BAD;
+
+ digits = c[(*p)++];
+
+ if ((digits & 0x80) == 0)
+ return digits;
+
+ digits &= 0x7f;
+ len = 0;
+
+ if (*p + digits >= l)
+ return DER_BAD;
+
+ for (i = 0; i < digits; i++)
+ len = (len << 8) | c[(*p)++];
+ if (*p + len >= l)
+ return DER_BAD;
+ return len;
+}
+
+static const char *
+der_tag(char *buf, size_t len, uint32_t tag)
+{
+ if (tag < DER_TAG_LONG)
+ strlcpy(buf, der__tag[tag], len);
+ else
+ snprintf(buf, len, "%#x", tag);
+ return buf;
+}
+
+#ifndef TEST_DER
+static int
+der_data(char *buf, size_t blen, uint32_t tag, const void *q, uint32_t len)
+{
+ const uint8_t *d = CAST(const uint8_t *, q);
+ uint32_t i;
+ switch (tag) {
+ case DER_TAG_PRINTABLE_STRING:
+ case DER_TAG_UTF8_STRING:
+ case DER_TAG_IA5_STRING:
+ case DER_TAG_UTCTIME:
+ return snprintf(buf, blen, "%.*s", len, (const char *)q);
+ default:
+ break;
+ }
+
+ for (i = 0; i < len; i++) {
+ uint32_t z = i << 1;
+ if (z < blen - 2)
+ snprintf(buf + z, blen - z, "%.2x", d[i]);
+ }
+ return len * 2;
+}
+
+int32_t
+der_offs(struct magic_set *ms, struct magic *m, size_t nbytes)
+{
+ const uint8_t *b = RCAST(const uint8_t *, ms->search.s);
+ size_t offs = 0, len = ms->search.s_len ? ms->search.s_len : nbytes;
+
+ if (gettag(b, &offs, len) == DER_BAD)
+ return -1;
+ DPRINTF(("%s1: %d %zu %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));
+
+ 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);
+#endif
+ if (m->cont_level != 0) {
+ if (offs + tlen > nbytes)
+ return DER_BAD;
+ ms->c.li[m->cont_level - 1].off = offs + tlen;
+ DPRINTF(("cont_level[%u] = %u\n", m->cont_level - 1,
+ ms->c.li[m->cont_level - 1].off));
+ }
+ return offs;
+}
+
+int
+der_cmp(struct magic_set *ms, struct magic *m)
+{
+ const uint8_t *b = RCAST(const uint8_t *, ms->search.s);
+ const char *s = m->value.s;
+ size_t offs = 0, len = ms->search.s_len;
+ uint32_t tag, tlen;
+ char buf[128];
+
+ tag = gettag(b, &offs, len);
+ if (tag == DER_BAD)
+ return -1;
+
+ tlen = getlength(b, &offs, len);
+ if (tlen == DER_BAD)
+ return -1;
+
+ der_tag(buf, sizeof(buf), tag);
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ fprintf(stderr, "%s: tag %p got=%s exp=%s\n", __func__, b,
+ buf, s);
+ size_t slen = strlen(buf);
+
+ if (strncmp(buf, s, slen) != 0)
+ return 0;
+
+ s += slen;
+
+again:
+ switch (*s) {
+ case '\0':
+ return 1;
+ case '=':
+ s++;
+ goto val;
+ default:
+ if (!isdigit((unsigned char)*s))
+ return 0;
+
+ slen = 0;
+ do
+ slen = slen * 10 + *s - '0';
+ while (isdigit((unsigned char)*++s));
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ fprintf(stderr, "%s: len %zu %u\n", __func__,
+ slen, tlen);
+ if (tlen != slen)
+ return 0;
+ goto again;
+ }
+val:
+ DPRINTF(("%s: before data %zu %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);
+ if (strcmp(buf, s) != 0 && strcmp("x", s) != 0)
+ return 0;
+ strlcpy(ms->ms_value.s, buf, sizeof(ms->ms_value.s));
+ return 1;
+}
+#endif
+
+#ifdef TEST_DER
+static void
+printtag(uint32_t tag, const void *q, uint32_t len)
+{
+ const uint8_t *d = q;
+ switch (tag) {
+ case DER_TAG_PRINTABLE_STRING:
+ case DER_TAG_UTF8_STRING:
+ printf("%.*s\n", len, (const char *)q);
+ return;
+ default:
+ break;
+ }
+
+ for (uint32_t i = 0; i < len; i++)
+ printf("%.2x", d[i]);
+ printf("\n");
+}
+
+static void
+printdata(size_t level, const void *v, size_t x, size_t l)
+{
+ const uint8_t *p = v, *ep = p + l;
+ size_t ox;
+ char buf[128];
+
+ while (p + x < ep) {
+ const uint8_t *q;
+ uint8_t c = getclass(p[x]);
+ uint8_t t = gettype(p[x]);
+ ox = x;
+ if (x != 0)
+ printf("%.2x %.2x %.2x\n", p[x - 1], p[x], p[x + 1]);
+ uint32_t tag = gettag(p, &x, ep - p + x);
+ if (p + x >= ep)
+ break;
+ uint32_t len = getlength(p, &x, ep - p + x);
+
+ printf("%zu %zu-%zu %c,%c,%s,%u:", level, ox, x,
+ der_class[c], der_type[t],
+ der_tag(buf, sizeof(buf), tag), len);
+ q = p + x;
+ if (p + len > ep)
+ errx(EXIT_FAILURE, "corrupt der");
+ printtag(tag, q, len);
+ if (t != DER_TYPE_PRIMITIVE)
+ printdata(level + 1, p, x, len + x);
+ x += len;
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ int fd;
+ struct stat st;
+ size_t l;
+ void *p;
+
+ if ((fd = open(argv[1], O_RDONLY)) == -1)
+ err(EXIT_FAILURE, "open `%s'", argv[1]);
+ if (fstat(fd, &st) == -1)
+ err(EXIT_FAILURE, "stat `%s'", argv[1]);
+ l = (size_t)st.st_size;
+ if ((p = mmap(NULL, l, PROT_READ, MAP_FILE, fd, 0)) == MAP_FAILED)
+ err(EXIT_FAILURE, "mmap `%s'", argv[1]);
+
+ printdata(0, p, 0, l);
+ munmap(p, l);
+ return 0;
+}
+#endif
diff --git a/ext/fileinfo/libmagic/der.h b/ext/fileinfo/libmagic/der.h
new file mode 100644
index 0000000000..3333239201
--- /dev/null
+++ b/ext/fileinfo/libmagic/der.h
@@ -0,0 +1,28 @@
+/*-
+ * Copyright (c) 2016 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.
+ */
+
+extern int der_offs(struct magic_set *, struct magic *, size_t);
+extern int der_cmp(struct magic_set *, struct magic *);
diff --git a/ext/fileinfo/libmagic/encoding.c b/ext/fileinfo/libmagic/encoding.c
index a32d6b381e..3c116cd74f 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.10 2014/09/11 12:08:52 christos Exp $")
+FILE_RCSID("@(#)$File: encoding.c,v 1.13 2015/06/04 19:16:28 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -47,6 +47,7 @@ FILE_RCSID("@(#)$File: encoding.c,v 1.10 2014/09/11 12:08:52 christos Exp $")
private int looks_ascii(const unsigned char *, size_t, unichar *, size_t *);
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_latin1(const unsigned char *, size_t, unichar *, size_t *);
private int looks_extended(const unsigned char *, size_t, unichar *, size_t *);
@@ -88,9 +89,15 @@ file_encoding(struct magic_set *ms, const unsigned char *buf, size_t nbytes, uni
}
if (looks_ascii(buf, nbytes, *ubuf, ulen)) {
- DPRINTF(("ascii %" SIZE_T_FORMAT "u\n", *ulen));
- *code = "ASCII";
- *code_mime = "us-ascii";
+ if (looks_utf7(buf, nbytes, *ubuf, ulen) > 0) {
+ DPRINTF(("utf-7 %" SIZE_T_FORMAT "u\n", *ulen));
+ *code = "UTF-7 Unicode";
+ *code_mime = "utf-7";
+ } else {
+ DPRINTF(("ascii %" SIZE_T_FORMAT "u\n", *ulen));
+ *code = "ASCII";
+ *code_mime = "us-ascii";
+ }
} else if (looks_utf8_with_BOM(buf, nbytes, *ubuf, ulen) > 0) {
DPRINTF(("utf8/bom %" SIZE_T_FORMAT "u\n", *ulen));
*code = "UTF-8 Unicode (with BOM)";
@@ -372,6 +379,25 @@ looks_utf8_with_BOM(const unsigned char *buf, size_t nbytes, unichar *ubuf,
}
private int
+looks_utf7(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen)
+{
+ if (nbytes > 4 && buf[0] == '+' && buf[1] == '/' && buf[2] == 'v')
+ switch (buf[3]) {
+ case '8':
+ case '9':
+ case '+':
+ case '/':
+ if (ubuf)
+ *ulen = 0;
+ return 1;
+ default:
+ return -1;
+ }
+ else
+ return -1;
+}
+
+private int
looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf,
size_t *ulen)
{
diff --git a/ext/fileinfo/libmagic/file.h b/ext/fileinfo/libmagic/file.h
index 291a8b4faf..566b0f0fea 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.166 2015/01/09 19:28:32 christos Exp $
+ * @(#)$File: file.h,v 1.180 2016/07/20 11:27:08 christos Exp $
*/
#ifndef __file_h__
@@ -42,9 +42,11 @@
#define SIZE_T_FORMAT ""
#endif
#define INT64_T_FORMAT "I64"
+ #define INTMAX_T_FORMAT "I64"
#else
#define SIZE_T_FORMAT "z"
#define INT64_T_FORMAT "ll"
+ #define INTMAX_T_FORMAT "j"
#endif
#include <stdio.h> /* Include that here, to make sure __P gets defined */
@@ -125,18 +127,18 @@
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
-#ifndef HOWMANY
-# define HOWMANY (1024 * 1024) /* how much of the file to look at */
+#ifndef FILE_BYTES_MAX
+# define FILE_BYTES_MAX (1024 * 1024) /* how much of the file to look at */
#endif
#define MAXMAGIS 8192 /* max entries in any one magic file
or directory */
#define MAXDESC 64 /* max len of text description/MIME type */
#define MAXMIME 80 /* max len of text MIME type */
-#define MAXstring 64 /* max len of "string" types */
+#define MAXstring 96 /* max len of "string" types */
#define MAGICNO 0xF11E041C
-#define VERSIONNO 12
-#define FILE_MAGICSIZE 248
+#define VERSIONNO 14
+#define FILE_MAGICSIZE 344
#define FILE_LOAD 0
#define FILE_CHECK 1
@@ -225,7 +227,8 @@ struct magic {
#define FILE_NAME 45
#define FILE_USE 46
#define FILE_CLEAR 47
-#define FILE_NAMES_SIZE 48 /* size of array to contain all names */
+#define FILE_DER 48
+#define FILE_NAMES_SIZE 49 /* size of array to contain all names */
#define IS_LIBMAGIC_STRING(t) \
((t) == FILE_STRING || \
@@ -272,7 +275,7 @@ struct magic {
#define FILE_OPS_MASK 0x07 /* mask for above ops */
#define FILE_UNUSED_1 0x08
#define FILE_UNUSED_2 0x10
-#define FILE_UNUSED_3 0x20
+#define FILE_OPSIGNED 0x20
#define FILE_OPINVERSE 0x40
#define FILE_OPINDIRECT 0x80
@@ -300,14 +303,16 @@ struct magic {
#define num_mask _u._mask
#define str_range _u._s._count
#define str_flags _u._s._flags
- /* Words 9-16 */
+ /* Words 9-24 */
union VALUETYPE value; /* either number or string */
- /* Words 17-32 */
+ /* Words 25-40 */
char desc[MAXDESC]; /* description */
- /* Words 33-52 */
+ /* Words 41-60 */
char mimetype[MAXMIME]; /* MIME type */
- /* Words 53-54 */
- char apple[8];
+ /* Words 61-62 */
+ char apple[8]; /* APPLE CREATOR/TYPE */
+ /* Words 63-78 */
+ char ext[64]; /* Popular extensions */
};
#define BIT(A) (1 << (A))
@@ -361,9 +366,11 @@ struct mlist {
#ifdef __cplusplus
#define CAST(T, b) static_cast<T>(b)
#define RCAST(T, b) reinterpret_cast<T>(b)
+#define CCAST(T, b) const_cast<T>(b)
#else
-#define CAST(T, b) (T)(b)
-#define RCAST(T, b) (T)(b)
+#define CAST(T, b) ((T)(b))
+#define RCAST(T, b) ((T)(b))
+#define CCAST(T, b) ((T)(uintptr_t)(b))
#endif
struct level_info {
@@ -411,11 +418,14 @@ struct magic_set {
uint16_t elf_shnum_max;
uint16_t elf_phnum_max;
uint16_t elf_notes_max;
-#define FILE_INDIR_MAX 15
+ uint16_t regex_max;
+ size_t bytes_max; /* number of bytes to read from file */
+#define FILE_INDIR_MAX 50
#define FILE_NAME_MAX 30
#define FILE_ELF_SHNUM_MAX 32768
-#define FILE_ELF_PHNUM_MAX 128
+#define FILE_ELF_PHNUM_MAX 2048
#define FILE_ELF_NOTES_MAX 256
+#define FILE_REGEX_MAX 8192
};
/* Type for Unicode characters */
@@ -449,7 +459,7 @@ protected int file_encoding(struct magic_set *, const unsigned char *, size_t,
unichar **, size_t *, const char **, const char **, const char **);
protected int file_is_tar(struct magic_set *, const unsigned char *, size_t);
protected int file_softmagic(struct magic_set *, const unsigned char *, size_t,
- uint16_t, uint16_t *, int, int);
+ uint16_t *, uint16_t *, int, int);
protected int file_apprentice(struct magic_set *, const char *, int);
protected int buffer_apprentice(struct magic_set *, struct magic **,
size_t *, size_t);
diff --git a/ext/fileinfo/libmagic/fsmagic.c b/ext/fileinfo/libmagic/fsmagic.c
index 7f9211597d..8b16347c5c 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.74 2014/10/13 20:21:49 christos Exp $")
+FILE_RCSID("@(#)$File: fsmagic.c,v 1.76 2015/04/09 20:01:41 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -99,7 +99,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, zend_stat_t *sb, php_stream *
int ret, did = 0;
int mime = ms->flags & MAGIC_MIME;
- if (ms->flags & MAGIC_APPLE)
+ if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))
return 0;
if (fn == NULL && !stream) {
@@ -238,15 +238,15 @@ file_fsmagic(struct magic_set *ms, const char *fn, zend_stat_t *sb, php_stream *
* size for raw disk partitions. (If the block special device
* really has zero length, the fact that it is empty will be
* detected and reported correctly when we read the file.)
- */
- if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
- if (mime) {
- if (handle_mime(ms, mime, "x-empty") == -1)
- return -1;
+ */
+ if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
+ if (mime) {
+ if (handle_mime(ms, mime, "x-empty") == -1)
+ return -1;
} else if (file_printf(ms, "%sempty", COMMA) == -1)
- return -1;
+ return -1;
break;
- }
+ }
ret = 0;
break;
@@ -256,5 +256,9 @@ file_fsmagic(struct magic_set *ms, const char *fn, zend_stat_t *sb, php_stream *
/*NOTREACHED*/
}
+ if (!mime && did && ret == 0) {
+ if (file_printf(ms, " ") == -1)
+ return -1;
+ }
return ret;
}
diff --git a/ext/fileinfo/libmagic/funcs.c b/ext/fileinfo/libmagic/funcs.c
index 9ea5386ebf..70b0a2f45c 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.79 2014/12/16 20:52:49 christos Exp $")
+FILE_RCSID("@(#)$File: funcs.c,v 1.90 2016/10/19 20:51:17 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -61,6 +61,7 @@ extern public void convert_libmagic_pattern(zval *pattern, char *val, int len, i
protected int
file_printf(struct magic_set *ms, const char *fmt, ...)
{
+ int rv;
va_list ap;
int len;
char *buf = NULL, *newstr;
@@ -98,7 +99,7 @@ file_error_core(struct magic_set *ms, int error, const char *f, va_list va,
if (lineno != 0) {
efree(ms->o.buf);
ms->o.buf = NULL;
- file_printf(ms, "line %" SIZE_T_FORMAT "u: ", lineno);
+ file_printf(ms, "line %" SIZE_T_FORMAT "u:", lineno);
}
vspprintf(&buf, 0, f, va);
@@ -160,12 +161,23 @@ file_badread(struct magic_set *ms)
file_error(ms, errno, "error reading");
}
+
+static int
+checkdone(struct magic_set *ms, int *rv)
+{
+ if ((ms->flags & MAGIC_CONTINUE) == 0)
+ return 1;
+ if (file_printf(ms, "\n- ") == -1)
+ *rv = -1;
+ return 0;
+}
+
+/*ARGSUSED*/
protected int
file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const void *buf,
size_t nb)
{
int m = 0, rv = 0, looks_text = 0;
- int mime = ms->flags & MAGIC_MIME;
const unsigned char *ubuf = CAST(const unsigned char *, buf);
unichar *u8buf = NULL;
size_t ulen;
@@ -191,7 +203,10 @@ file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const
#ifdef __EMX__
if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) {
- switch (file_os2_apptype(ms, inname, buf, nb)) {
+ m = file_os2_apptype(ms, inname, buf, nb);
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ (void)fprintf(stderr, "[try os2_apptype %d]\n", m);
+ switch (m) {
case -1:
return -1;
case 0:
@@ -203,39 +218,47 @@ file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const
#endif
#if PHP_FILEINFO_UNCOMPRESS
- if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) == 0)
- if ((m = file_zmagic(ms, stream, inname, ubuf, nb)) != 0) {
- if ((ms->flags & MAGIC_DEBUG) != 0)
- (void)fprintf(stderr, "zmagic %d\n", m);
+ if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) == 0) {
+ m = file_zmagic(ms, stream, inname, ubuf, nb);
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ (void)fprintf(stderr, "[try zmagic %d]\n", m);
+ if (m) {
goto done_encoding;
}
+ }
#endif
/* Check if we have a tar file */
- if ((ms->flags & MAGIC_NO_CHECK_TAR) == 0)
- if ((m = file_is_tar(ms, ubuf, nb)) != 0) {
- if ((ms->flags & MAGIC_DEBUG) != 0)
- (void)fprintf(stderr, "tar %d\n", m);
- goto done;
+ if ((ms->flags & MAGIC_NO_CHECK_TAR) == 0) {
+ m = file_is_tar(ms, ubuf, nb);
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ (void)fprintf(stderr, "[try tar %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) {
php_socket_t fd;
- if (stream && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&fd, 0)) {
- if ((m = file_trycdf(ms, fd, ubuf, nb)) != 0) {
- if ((ms->flags & MAGIC_DEBUG) != 0)
- (void)fprintf(stderr, "cdf %d\n", m);
+ if (stream && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&fd, 0)) {
+ m = file_trycdf(ms, fd, ubuf, nb);
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ (void)fprintf(stderr, "[try cdf %d]\n", m);
+ if (m) {
+ if (checkdone(ms, &rv))
goto done;
}
}
}
/* try soft magic tests */
- if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0)
- if ((m = file_softmagic(ms, ubuf, nb, 0, NULL, BINTEST,
- looks_text)) != 0) {
- if ((ms->flags & MAGIC_DEBUG) != 0)
- (void)fprintf(stderr, "softmagic %d\n", m);
+ if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) {
+ m = file_softmagic(ms, ubuf, nb, NULL, NULL, BINTEST,
+ looks_text);
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ (void)fprintf(stderr, "[try softmagic %d]\n", m);
+ if (m) {
#ifdef BUILTIN_ELF
if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 &&
nb > 5 && fd != -1) {
@@ -248,31 +271,45 @@ file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const
* ELF headers that cannot easily * be
* extracted with rules in the magic file.
*/
- if ((m = file_tryelf(ms, fd, ubuf, nb)) != 0)
- if ((ms->flags & MAGIC_DEBUG) != 0)
- (void)fprintf(stderr,
- "elf %d\n", m);
+ m = file_tryelf(ms, fd, ubuf, nb);
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ (void)fprintf(stderr, "[try elf %d]\n",
+ m);
}
#endif
- goto done;
+ if (checkdone(ms, &rv))
+ goto done;
}
+ }
/* try text properties */
if ((ms->flags & MAGIC_NO_CHECK_TEXT) == 0) {
- if ((m = file_ascmagic(ms, ubuf, nb, looks_text)) != 0) {
- if ((ms->flags & MAGIC_DEBUG) != 0)
- (void)fprintf(stderr, "ascmagic %d\n", m);
- goto done;
+ m = file_ascmagic(ms, ubuf, nb, looks_text);
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ (void)fprintf(stderr, "[try ascmagic %d]\n", m);
+ if (m) {
+ if (checkdone(ms, &rv))
+ goto done;
}
}
simple:
/* give up */
m = 1;
- if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
- file_printf(ms, "%s", mime ? type : def) == -1) {
- rv = -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;
}
done:
if ((ms->flags & MAGIC_MIME_ENCODING) != 0) {
@@ -323,7 +360,7 @@ file_reset(struct magic_set *ms)
protected const char *
file_getbuffer(struct magic_set *ms)
{
- char *op, *np;
+ char *pbuf, *op, *np;
size_t psize, len;
if (ms->event_flags & EVENT_HAD_ERR)
@@ -342,10 +379,11 @@ file_getbuffer(struct magic_set *ms)
return NULL;
}
psize = len * 4 + 1;
- if ((ms->o.pbuf = CAST(char *, erealloc(ms->o.pbuf, psize))) == NULL) {
+ if ((pbuf = CAST(char *, erealloc(ms->o.pbuf, psize))) == NULL) {
file_oomem(ms, psize);
return NULL;
}
+ ms->o.pbuf = pbuf;
#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
{
@@ -523,11 +561,10 @@ file_printable(char *buf, size_t bufsiz, const char *str)
if (ptr >= eptr - 3)
break;
*ptr++ = '\\';
- *ptr++ = ((*s >> 6) & 7) + '0';
- *ptr++ = ((*s >> 3) & 7) + '0';
- *ptr++ = ((*s >> 0) & 7) + '0';
+ *ptr++ = ((CAST(unsigned int, *s) >> 6) & 7) + '0';
+ *ptr++ = ((CAST(unsigned int, *s) >> 3) & 7) + '0';
+ *ptr++ = ((CAST(unsigned int, *s) >> 0) & 7) + '0';
}
*ptr = '\0';
return buf;
}
-
diff --git a/ext/fileinfo/libmagic/is_tar.c b/ext/fileinfo/libmagic/is_tar.c
index 0c43d63013..a3e5dbf24c 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.36 2009/02/03 20:27:51 christos Exp $")
+FILE_RCSID("@(#)$File: is_tar.c,v 1.38 2015/04/09 20:01:41 christos Exp $")
#endif
#include "magic.h"
@@ -69,7 +69,7 @@ file_is_tar(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
int tar;
int mime = ms->flags & MAGIC_MIME;
- if ((ms->flags & MAGIC_APPLE) != 0)
+ if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) != 0)
return 0;
tar = is_tar(buf, nbytes);
diff --git a/ext/fileinfo/libmagic/magic.c b/ext/fileinfo/libmagic/magic.c
index 380cb72ce4..58aafb5c1c 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.91 2014/12/16 23:18:40 christos Exp $")
+FILE_RCSID("@(#)$File: magic.c,v 1.100 2016/07/18 11:43:05 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -92,138 +92,6 @@ private const char *file_or_stream(struct magic_set *, const char *, php_stream
#define STDIN_FILENO 0
#endif
-/* XXX this functionality is excluded in php, enable it in apprentice.c:340 */
-#if 0
-private const char *
-get_default_magic(void)
-{
- static const char hmagic[] = "/.magic/magic.mgc";
- static char *default_magic;
- char *home, *hmagicpath;
-
-#ifndef PHP_WIN32
- struct stat st;
-
- if (default_magic) {
- free(default_magic);
- default_magic = NULL;
- }
- if ((home = getenv("HOME")) == NULL)
- return MAGIC;
-
- if (asprintf(&hmagicpath, "%s/.magic.mgc", home) < 0)
- return MAGIC;
- if (stat(hmagicpath, &st) == -1) {
- free(hmagicpath);
- if (asprintf(&hmagicpath, "%s/.magic", home) < 0)
- return MAGIC;
- if (stat(hmagicpath, &st) == -1)
- goto out;
- if (S_ISDIR(st.st_mode)) {
- free(hmagicpath);
- if (asprintf(&hmagicpath, "%s/%s", home, hmagic) < 0)
- return MAGIC;
- if (access(hmagicpath, R_OK) == -1)
- goto out;
- }
- }
-
- if (asprintf(&default_magic, "%s:%s", hmagicpath, MAGIC) < 0)
- goto out;
- free(hmagicpath);
- return default_magic;
-out:
- default_magic = NULL;
- free(hmagicpath);
- return MAGIC;
-#else
- char *hmagicp = hmagicpath;
- char *tmppath = NULL;
- LPTSTR dllpath;
-
-#define APPENDPATH() \
- do { \
- if (tmppath && access(tmppath, R_OK) != -1) { \
- if (hmagicpath == NULL) \
- hmagicpath = tmppath; \
- else { \
- if (asprintf(&hmagicp, "%s%c%s", hmagicpath, \
- PATHSEP, tmppath) >= 0) { \
- free(hmagicpath); \
- hmagicpath = hmagicp; \
- } \
- free(tmppath); \
- } \
- tmppath = NULL; \
- } \
- } while (/*CONSTCOND*/0)
-
- if (default_magic) {
- free(default_magic);
- default_magic = NULL;
- }
-
- /* First, try to get user-specific magic file */
- if ((home = getenv("LOCALAPPDATA")) == NULL) {
- if ((home = getenv("USERPROFILE")) != NULL)
- if (asprintf(&tmppath,
- "%s/Local Settings/Application Data%s", home,
- hmagic) < 0)
- tmppath = NULL;
- } else {
- if (asprintf(&tmppath, "%s%s", home, hmagic) < 0)
- tmppath = NULL;
- }
-
- APPENDPATH();
-
- /* Second, try to get a magic file from Common Files */
- if ((home = getenv("COMMONPROGRAMFILES")) != NULL) {
- if (asprintf(&tmppath, "%s%s", home, hmagic) >= 0)
- APPENDPATH();
- }
-
- /* Third, try to get magic file relative to dll location */
- dllpath = malloc(sizeof(*dllpath) * (MAX_PATH + 1));
- dllpath[MAX_PATH] = 0; /* just in case long path gets truncated and not null terminated */
- if (GetModuleFileNameA(NULL, dllpath, MAX_PATH)){
- PathRemoveFileSpecA(dllpath);
- if (strlen(dllpath) > 3 &&
- stricmp(&dllpath[strlen(dllpath) - 3], "bin") == 0) {
- if (asprintf(&tmppath,
- "%s/../share/misc/magic.mgc", dllpath) >= 0)
- APPENDPATH();
- } else {
- if (asprintf(&tmppath,
- "%s/share/misc/magic.mgc", dllpath) >= 0)
- APPENDPATH();
- else if (asprintf(&tmppath,
- "%s/magic.mgc", dllpath) >= 0)
- APPENDPATH();
- }
- }
-
- /* Don't put MAGIC constant - it likely points to a file within MSys
- tree */
- default_magic = hmagicpath;
- return default_magic;
-#endif
-}
-
-public const char *
-magic_getpath(const char *magicfile, int action)
-{
- if (magicfile != NULL)
- return magicfile;
-
- magicfile = getenv("MAGIC");
- if (magicfile != NULL)
- return magicfile;
-
- return action == FILE_LOAD ? get_default_magic() : MAGIC;
-}
-#endif
-
public struct magic_set *
magic_open(int flags)
{
@@ -356,6 +224,9 @@ file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
ssize_t nbytes = 0; /* number of bytes read from a datafile */
int no_in_stream = 0;
+ if (file_reset(ms) == -1)
+ goto out;
+
if (!inname && !stream) {
return NULL;
}
@@ -365,10 +236,8 @@ file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
* some overlapping space for matches near EOF
*/
#define SLOP (1 + sizeof(union VALUETYPE))
- buf = emalloc(HOWMANY + SLOP);
-
- if (file_reset(ms) == -1)
- goto done;
+ if ((buf = CAST(unsigned char *, emalloc(ms->bytes_max + SLOP))) == NULL)
+ return NULL;
switch (file_fsmagic(ms, inname, &sb, stream)) {
case -1: /* error */
@@ -399,9 +268,9 @@ file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
#endif
/*
- * try looking at the first HOWMANY bytes
+ * try looking at the first ms->bytes_max bytes
*/
- if ((nbytes = php_stream_read(stream, (char *)buf, HOWMANY)) < 0) {
+ if ((nbytes = php_stream_read(stream, (char *)buf, ms->bytes_max - nbytes)) < 0) {
file_error(ms, errno, "cannot read `%s'", inname);
goto done;
}
@@ -416,8 +285,7 @@ done:
if (no_in_stream && stream) {
php_stream_close(stream);
}
-
- close_and_restore(ms, inname, 0, &sb);
+out:
return rv == 0 ? file_getbuffer(ms) : NULL;
}
@@ -493,6 +361,12 @@ magic_setparam(struct magic_set *ms, int param, const void *val)
case MAGIC_PARAM_ELF_NOTES_MAX:
ms->elf_notes_max = (uint16_t)*(const size_t *)val;
return 0;
+ case MAGIC_PARAM_REGEX_MAX:
+ ms->elf_notes_max = (uint16_t)*(const size_t *)val;
+ return 0;
+ case MAGIC_PARAM_BYTES_MAX:
+ ms->bytes_max = *(const size_t *)val;
+ return 0;
default:
errno = EINVAL;
return -1;
@@ -518,6 +392,12 @@ magic_getparam(struct magic_set *ms, int param, void *val)
case MAGIC_PARAM_ELF_NOTES_MAX:
*(size_t *)val = ms->elf_notes_max;
return 0;
+ case MAGIC_PARAM_REGEX_MAX:
+ *(size_t *)val = ms->regex_max;
+ return 0;
+ case MAGIC_PARAM_BYTES_MAX:
+ *(size_t *)val = ms->bytes_max;
+ return 0;
default:
errno = EINVAL;
return -1;
diff --git a/ext/fileinfo/libmagic/magic.h b/ext/fileinfo/libmagic/magic.h
index 1008347ab5..332b7154ad 100644
--- a/ext/fileinfo/libmagic/magic.h
+++ b/ext/fileinfo/libmagic/magic.h
@@ -29,30 +29,35 @@
#include <sys/types.h>
-#define MAGIC_NONE 0x000000 /* No flags */
-#define MAGIC_DEBUG 0x000001 /* Turn on debugging */
-#define MAGIC_SYMLINK 0x000002 /* Follow symlinks */
-#define MAGIC_COMPRESS 0x000004 /* Check inside compressed files */
-#define MAGIC_DEVICES 0x000008 /* Look at the contents of devices */
-#define MAGIC_MIME_TYPE 0x000010 /* Return the MIME type */
-#define MAGIC_CONTINUE 0x000020 /* Return all matches */
-#define MAGIC_CHECK 0x000040 /* Print warnings to stderr */
-#define MAGIC_PRESERVE_ATIME 0x000080 /* Restore access time on exit */
-#define MAGIC_RAW 0x000100 /* Don't translate unprintable chars */
-#define MAGIC_ERROR 0x000200 /* Handle ENOENT etc as real errors */
-#define MAGIC_MIME_ENCODING 0x000400 /* Return the MIME encoding */
+#define MAGIC_NONE 0x0000000 /* No flags */
+#define MAGIC_DEBUG 0x0000001 /* Turn on debugging */
+#define MAGIC_SYMLINK 0x0000002 /* Follow symlinks */
+#define MAGIC_COMPRESS 0x0000004 /* Check inside compressed files */
+#define MAGIC_DEVICES 0x0000008 /* Look at the contents of devices */
+#define MAGIC_MIME_TYPE 0x0000010 /* Return the MIME type */
+#define MAGIC_CONTINUE 0x0000020 /* Return all matches */
+#define MAGIC_CHECK 0x0000040 /* Print warnings to stderr */
+#define MAGIC_PRESERVE_ATIME 0x0000080 /* Restore access time on exit */
+#define MAGIC_RAW 0x0000100 /* Don't convert unprintable chars */
+#define MAGIC_ERROR 0x0000200 /* Handle ENOENT etc as real errors */
+#define MAGIC_MIME_ENCODING 0x0000400 /* Return the MIME encoding */
#define MAGIC_MIME (MAGIC_MIME_TYPE|MAGIC_MIME_ENCODING)
-#define MAGIC_APPLE 0x000800 /* Return the Apple creator and type */
-
-#define MAGIC_NO_CHECK_COMPRESS 0x001000 /* Don't check for compressed files */
-#define MAGIC_NO_CHECK_TAR 0x002000 /* Don't check for tar files */
-#define MAGIC_NO_CHECK_SOFT 0x004000 /* Don't check magic entries */
-#define MAGIC_NO_CHECK_APPTYPE 0x008000 /* Don't check application type */
-#define MAGIC_NO_CHECK_ELF 0x010000 /* Don't check for elf details */
-#define MAGIC_NO_CHECK_TEXT 0x020000 /* Don't check for text files */
-#define MAGIC_NO_CHECK_CDF 0x040000 /* Don't check for cdf files */
-#define MAGIC_NO_CHECK_TOKENS 0x100000 /* Don't check tokens */
-#define MAGIC_NO_CHECK_ENCODING 0x200000 /* Don't check text encodings */
+#define MAGIC_APPLE 0x0000800 /* Return the Apple creator/type */
+#define MAGIC_EXTENSION 0x1000000 /* Return a /-separated list of
+ * extensions */
+#define MAGIC_COMPRESS_TRANSP 0x2000000 /* Check inside compressed files
+ * but not report compression */
+#define MAGIC_NODESC (MAGIC_EXTENSION|MAGIC_MIME|MAGIC_APPLE)
+
+#define MAGIC_NO_CHECK_COMPRESS 0x0001000 /* Don't check for compressed files */
+#define MAGIC_NO_CHECK_TAR 0x0002000 /* Don't check for tar files */
+#define MAGIC_NO_CHECK_SOFT 0x0004000 /* Don't check magic entries */
+#define MAGIC_NO_CHECK_APPTYPE 0x0008000 /* Don't check application type */
+#define MAGIC_NO_CHECK_ELF 0x0010000 /* Don't check for elf details */
+#define MAGIC_NO_CHECK_TEXT 0x0020000 /* Don't check for text files */
+#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 */
/* No built-in tests; only consult the magic file */
#define MAGIC_NO_CHECK_BUILTIN ( \
@@ -75,7 +80,7 @@
#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 522 /* This implementation */
+#define MAGIC_VERSION 529 /* This implementation */
#ifdef __cplusplus
@@ -108,6 +113,8 @@ int magic_errno(magic_t);
#define MAGIC_PARAM_ELF_PHNUM_MAX 2
#define MAGIC_PARAM_ELF_SHNUM_MAX 3
#define MAGIC_PARAM_ELF_NOTES_MAX 4
+#define MAGIC_PARAM_REGEX_MAX 5
+#define MAGIC_PARAM_BYTES_MAX 6
int magic_setparam(magic_t, int, const void *);
int magic_getparam(magic_t, int, void *);
diff --git a/ext/fileinfo/libmagic/patchlevel.h b/ext/fileinfo/libmagic/patchlevel.h
index c710638eea..210968ec81 100644
--- a/ext/fileinfo/libmagic/patchlevel.h
+++ b/ext/fileinfo/libmagic/patchlevel.h
@@ -1,11 +1,15 @@
#define FILE_VERSION_MAJOR 5
-#define patchlevel 22
+#define patchlevel 28
/*
* Patchlevel file for Ian Darwin's MAGIC command.
* $File: patchlevel.h,v 1.68 2008/03/22 21:39:43 christos Exp $
*
* $Log$
+ * Revision 1.9 2016/10/11 22:27:12 ab
+ * Update libmagic to 5.28
+ *
+ * $Log$
* Revision 1.9 2015/03/06 22:27:12 ab
* Update libmagic to 5.2X
*
diff --git a/ext/fileinfo/libmagic/print.c b/ext/fileinfo/libmagic/print.c
index cdfbd37834..a72782a58e 100644
--- a/ext/fileinfo/libmagic/print.c
+++ b/ext/fileinfo/libmagic/print.c
@@ -32,13 +32,11 @@
#include "php.h"
#include "file.h"
-#include "cdf.h"
#ifndef lint
-FILE_RCSID("@(#)$File: print.c,v 1.78 2015/01/06 02:04:10 christos Exp $")
+FILE_RCSID("@(#)$File: print.c,v 1.81 2016/01/19 15:09:03 christos Exp $")
#endif /* lint */
-#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -54,6 +52,8 @@ FILE_RCSID("@(#)$File: print.c,v 1.78 2015/01/06 02:04:10 christos Exp $")
#define SZOF(a) (sizeof(a) / sizeof(a[0]))
+#include "cdf.h"
+
/*VARARGS*/
protected void
file_magwarn(struct magic_set *ms, const char *f, ...)
diff --git a/ext/fileinfo/libmagic/readcdf.c b/ext/fileinfo/libmagic/readcdf.c
index f6ed9c9e2f..f5176f6796 100644
--- a/ext/fileinfo/libmagic/readcdf.c
+++ b/ext/fileinfo/libmagic/readcdf.c
@@ -26,9 +26,10 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: readcdf.c,v 1.50 2015/01/02 21:29:39 christos Exp $")
+FILE_RCSID("@(#)$File: readcdf.c,v 1.63 2016/10/18 22:25:42 christos Exp $")
#endif
+#include <assert.h>
#include <stdlib.h>
#ifdef PHP_WIN32
#include "win32/unistd.h"
@@ -38,9 +39,6 @@ FILE_RCSID("@(#)$File: readcdf.c,v 1.50 2015/01/02 21:29:39 christos Exp $")
#include <string.h>
#include <time.h>
#include <ctype.h>
-#if defined(HAVE_LOCALE_H)
-#include <locale.h>
-#endif
#include "cdf.h"
#include "magic.h"
@@ -66,12 +64,16 @@ static const struct nv {
{ "Windows Installer", "vnd.ms-msi", },
{ NULL, NULL, },
}, name2mime[] = {
+ { "Book", "vnd.ms-excel", },
+ { "Workbook", "vnd.ms-excel", },
{ "WordDocument", "msword", },
{ "PowerPoint", "vnd.ms-powerpoint", },
{ "DigitalSignature", "vnd.ms-msi", },
{ NULL, NULL, },
}, name2desc[] = {
- { "WordDocument", "Microsoft Office Word",},
+ { "Book", "Microsoft Excel", },
+ { "Workbook", "Microsoft Excel", },
+ { "WordDocument", "Microsoft Word", },
{ "PowerPoint", "Microsoft PowerPoint", },
{ "DigitalSignature", "Microsoft Installer", },
{ NULL, NULL, },
@@ -91,7 +93,7 @@ static const struct cv {
},
{ { 0, 0 },
NULL,
- }
+ },
}, clsid2desc[] = {
{
{ 0x00000000000c1084ULL, 0x46000000000000c0ULL },
@@ -361,16 +363,64 @@ cdf_file_catalog_info(struct magic_set *ms, const cdf_info_t *info,
int i;
if ((i = cdf_read_user_stream(info, h, sat, ssat, sst,
- dir, "Catalog", scn)) <= 0)
+ dir, "Catalog", scn)) == -1)
return i;
#ifdef CDF_DEBUG
- cdf_dump_catalog(&h, &scn);
+ cdf_dump_catalog(h, scn);
#endif
if ((i = cdf_file_catalog(ms, h, scn)) == -1)
return -1;
return i;
}
+private int
+cdf_check_summary_info(struct magic_set *ms, const cdf_info_t *info,
+ const cdf_header_t *h, const cdf_sat_t *sat, const cdf_sat_t *ssat,
+ const cdf_stream_t *sst, const cdf_dir_t *dir, cdf_stream_t *scn,
+ const cdf_directory_t *root_storage, const char **expn)
+{
+ int i;
+ const char *str = NULL;
+ cdf_directory_t *d;
+ char name[__arraycount(d->d_name)];
+ size_t j, k;
+
+#ifdef CDF_DEBUG
+ 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";
+ return i;
+ }
+ if (i == 1)
+ return i;
+ 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]);
+ str = cdf_app_to_mime(name,
+ NOTMIME(ms) ? name2desc : name2mime);
+ }
+ if (NOTMIME(ms)) {
+ if (str != NULL) {
+ if (file_printf(ms, "%s", str) == -1)
+ return -1;
+ i = 1;
+ }
+ } else {
+ if (str == NULL)
+ str = "vnd.ms-office";
+ if (file_printf(ms, "application/%s", str) == -1)
+ return -1;
+ i = 1;
+ }
+ if (i <= 0) {
+ i = cdf_file_catalog_info(ms, info, h, sat, ssat, sst,
+ dir, scn);
+ }
+ return i;
+}
+
private struct sinfo {
const char *name;
const char *mime;
@@ -379,10 +429,13 @@ private struct sinfo {
} sectioninfo[] = {
{ "Encrypted", "encrypted",
{
- "EncryptedPackage", NULL, NULL, NULL, NULL,
+ "EncryptedPackage", "EncryptedSummary",
+ NULL, NULL, NULL,
},
{
- CDF_DIR_TYPE_USER_STREAM, 0, 0, 0, 0,
+ CDF_DIR_TYPE_USER_STREAM,
+ CDF_DIR_TYPE_USER_STREAM,
+ 0, 0, 0,
},
},
@@ -403,6 +456,46 @@ private struct sinfo {
0, 0, 0, 0
},
},
+ { "Microsoft Excel", "vnd.ms-excel",
+ {
+ "Book", "Workbook", NULL, NULL, NULL,
+ },
+ {
+ CDF_DIR_TYPE_USER_STREAM,
+ CDF_DIR_TYPE_USER_STREAM,
+ 0, 0, 0,
+ },
+ },
+ { "Microsoft Word", "msword",
+ {
+ "WordDocument", NULL, NULL, NULL, NULL,
+ },
+ {
+ CDF_DIR_TYPE_USER_STREAM,
+ 0, 0, 0, 0,
+ },
+ },
+ { "Microsoft PowerPoint", "vnd.ms-powerpoint",
+ {
+ "PowerPoint", NULL, NULL, NULL, NULL,
+ },
+ {
+ CDF_DIR_TYPE_USER_STREAM,
+ 0, 0, 0, 0,
+ },
+ },
+ { "Microsoft Outlook Message", "vnd.ms-outlook",
+ {
+ "__properties_version1.0",
+ "__recip_version1.0_#00000000",
+ NULL, NULL, NULL,
+ },
+ {
+ CDF_DIR_TYPE_USER_STREAM,
+ CDF_DIR_TYPE_USER_STORAGE,
+ 0, 0, 0,
+ },
+ },
};
private int
@@ -414,22 +507,19 @@ cdf_file_dir_info(struct magic_set *ms, const cdf_dir_t *dir)
const struct sinfo *si = &sectioninfo[sd];
for (j = 0; si->sections[j]; j++) {
if (cdf_find_stream(dir, si->sections[j], si->types[j])
- <= 0) {
+ > 0)
+ break;
#ifdef CDF_DEBUG
- fprintf(stderr, "Can't read %s\n",
- si->sections[j]);
+ fprintf(stderr, "Can't read %s\n", si->sections[j]);
#endif
- break;
- }
}
- if (si->sections[j] != NULL)
+ if (si->sections[j] == NULL)
continue;
if (NOTMIME(ms)) {
if (file_printf(ms, "CDFV2 %s", si->name) == -1)
return -1;
} else {
- if (file_printf(ms, "application/CDFV2-%s",
- si->mime) == -1)
+ if (file_printf(ms, "application/%s", si->mime) == -1)
return -1;
}
return 1;
@@ -450,10 +540,11 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
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)
+ if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))
return 0;
if (cdf_read_header(&info, &h) == -1)
return 0;
@@ -519,10 +610,7 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
i = 1;
goto out5;
} else {
- free(scn.sst_tab);
- scn.sst_tab = NULL;
- scn.sst_len = 0;
- scn.sst_dirlen = 0;
+ cdf_zero_stream(&scn);
}
}
@@ -530,56 +618,31 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
&scn)) == -1) {
if (errno != ESRCH) {
expn = "Cannot read summary info";
- goto out4;
}
- i = cdf_file_catalog_info(ms, &info, &h, &sat, &ssat, &sst,
- &dir, &scn);
- if (i > 0)
- goto out4;
- i = cdf_file_dir_info(ms, &dir);
- if (i < 0)
- expn = "Cannot read section info";
- goto out4;
+ } else {
+ i = cdf_check_summary_info(ms, &info, &h,
+ &sat, &ssat, &sst, &dir, &scn, root_storage, &expn);
+ cdf_zero_stream(&scn);
}
-
-
-#ifdef CDF_DEBUG
- 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 == 0) {
- const char *str = NULL;
- cdf_directory_t *d;
- char name[__arraycount(d->d_name)];
- size_t j, k;
-
- 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]);
- str = cdf_app_to_mime(name,
- NOTMIME(ms) ? name2desc : name2mime);
- }
- if (NOTMIME(ms)) {
- if (str != NULL) {
- if (file_printf(ms, "%s", str) == -1)
- return -1;
- i = 1;
+ if (i <= 0) {
+ if ((i = cdf_read_doc_summary_info(&info, &h, &sat, &ssat,
+ &sst, &dir, &scn)) == -1) {
+ if (errno != ESRCH) {
+ expn = "Cannot read summary info";
}
} else {
- if (str == NULL)
- str = "vnd.ms-office";
- if (file_printf(ms, "application/%s", str) == -1)
- return -1;
- i = 1;
+ i = cdf_check_summary_info(ms, &info, &h, &sat, &ssat,
+ &sst, &dir, &scn, root_storage, &expn);
}
}
+ if (i <= 0) {
+ i = cdf_file_dir_info(ms, &dir);
+ if (i < 0)
+ expn = "Cannot read section info";
+ }
out5:
- free(scn.sst_tab);
-out4:
- free(sst.sst_tab);
+ cdf_zero_stream(&scn);
+ cdf_zero_stream(&sst);
out3:
free(dir.dir_tab);
out2:
@@ -596,7 +659,7 @@ out0:
if (file_printf(ms, ", %s", expn) == -1)
return -1;
} else {
- if (file_printf(ms, "application/CDFV2-unknown") == -1)
+ if (file_printf(ms, "application/CDFV2") == -1)
return -1;
}
i = 1;
diff --git a/ext/fileinfo/libmagic/softmagic.c b/ext/fileinfo/libmagic/softmagic.c
index 41c4aa17d7..74f4d74a7d 100644
--- a/ext/fileinfo/libmagic/softmagic.c
+++ b/ext/fileinfo/libmagic/softmagic.c
@@ -32,45 +32,59 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: softmagic.c,v 1.212 2015/01/24 22:11:25 christos Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.238 2016/10/24 18:02:17 christos Exp $")
#endif /* lint */
#include "magic.h"
+#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
-#if defined(HAVE_LOCALE_H)
-#include <locale.h>
-#endif
+#include "der.h"
#ifndef PREG_OFFSET_CAPTURE
# define PREG_OFFSET_CAPTURE (1<<8)
#endif
-
-
private int match(struct magic_set *, struct magic *, uint32_t,
- const unsigned char *, size_t, size_t, int, int, int, uint16_t,
+ const unsigned char *, size_t, size_t, int, int, int, uint16_t *,
uint16_t *, int *, int *, int *);
private int mget(struct magic_set *, const unsigned char *,
- struct magic *, size_t, size_t, unsigned int, int, int, int, uint16_t,
+ struct magic *, size_t, size_t, unsigned int, int, int, int, uint16_t *,
uint16_t *, int *, int *, int *);
private int magiccheck(struct magic_set *, struct magic *);
private int32_t mprint(struct magic_set *, struct magic *);
-private int32_t moffset(struct magic_set *, struct magic *);
+private int moffset(struct magic_set *, struct magic *, size_t, int32_t *);
private void mdebug(uint32_t, const char *, size_t);
private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
const unsigned char *, uint32_t, size_t, struct magic *);
private int mconvert(struct magic_set *, struct magic *, int);
private int print_sep(struct magic_set *, int);
-private int handle_annotation(struct magic_set *, struct magic *);
-private void cvt_8(union VALUETYPE *, const struct magic *);
-private void cvt_16(union VALUETYPE *, const struct magic *);
-private void cvt_32(union VALUETYPE *, const struct magic *);
-private void cvt_64(union VALUETYPE *, const struct magic *);
-
-#define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o)))
+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))
/*
* softmagic - lookup one file in parsed, in-memory copy of database
@@ -79,20 +93,24 @@ private void cvt_64(union VALUETYPE *, const struct magic *);
/*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
protected int
file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
- uint16_t indir_level, uint16_t *name_count, int mode, int text)
+ uint16_t *indir_count, uint16_t *name_count, int mode, int text)
{
struct mlist *ml;
int rv, printed_something = 0, need_separator = 0;
- uint16_t nc;
+ uint16_t nc, ic;
if (name_count == NULL) {
nc = 0;
name_count = &nc;
}
+ if (indir_count == NULL) {
+ ic = 0;
+ indir_count = &ic;
+ }
for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next)
if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode,
- text, 0, indir_level, name_count,
+ text, 0, indir_count, name_count,
&printed_something, &need_separator, NULL)) != 0)
return rv;
@@ -150,14 +168,14 @@ file_fmtcheck(struct magic_set *ms, const struct magic *m, const char *def,
private int
match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
const unsigned char *s, size_t nbytes, size_t offset, int mode, int text,
- int flip, uint16_t indir_level, uint16_t *name_count,
+ int flip, uint16_t *indir_count, uint16_t *name_count,
int *printed_something, int *need_separator, int *returnval)
{
uint32_t magindex = 0;
unsigned int cont_level = 0;
int returnvalv = 0, e; /* if a match is found it is set to 1*/
int firstline = 1; /* a flag to print X\n X\n- X */
- int print = (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0;
+ int print = (ms->flags & MAGIC_NODESC) == 0;
if (returnval == NULL)
returnval = &returnvalv;
@@ -175,11 +193,11 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
((text && (m->str_flags & FLT) == STRING_BINTEST) ||
(!text && (m->str_flags & FLT) == STRING_TEXTTEST))) ||
(m->flag & mode) != mode) {
+flush:
/* Skip sub-tests */
- while (magindex + 1 < nmagic &&
- magic[magindex + 1].cont_level != 0 &&
- ++magindex)
- continue;
+ while (magindex < nmagic - 1 &&
+ magic[magindex + 1].cont_level != 0)
+ magindex++;
continue; /* Skip to next top-level test*/
}
@@ -188,7 +206,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
/* if main entry matches, print it... */
switch (mget(ms, s, m, nbytes, offset, cont_level, mode, text,
- flip, indir_level, name_count,
+ flip, indir_count, name_count,
printed_something, need_separator, returnval)) {
case -1:
return -1;
@@ -216,18 +234,16 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
* main entry didn't match,
* flush its continuations
*/
- while (magindex < nmagic - 1 &&
- magic[magindex + 1].cont_level != 0)
- magindex++;
- continue;
+ goto flush;
}
- if ((e = handle_annotation(ms, m)) != 0) {
+ 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, we'll need to print
* a blank before we print something else.
@@ -243,7 +259,13 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
if (print && mprint(ms, m) == -1)
return -1;
- ms->c.li[cont_level].off = moffset(ms, m);
+ switch (moffset(ms, m, nbytes, &ms->c.li[cont_level].off)) {
+ case -1:
+ case 0:
+ goto flush;
+ default:
+ break;
+ }
/* and any continuations that match */
if (file_check_mem(ms, ++cont_level) == -1)
@@ -277,7 +299,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
}
#endif
switch (mget(ms, s, m, nbytes, offset, cont_level, mode,
- text, flip, indir_level, name_count,
+ text, flip, indir_count, name_count,
printed_something, need_separator, returnval)) {
case -1:
return -1;
@@ -312,7 +334,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
break;
} else
ms->c.li[cont_level].got_match = 1;
- if ((e = handle_annotation(ms, m)) != 0) {
+
+ if ((e = handle_annotation(ms, m, firstline)) != 0) {
*need_separator = 1;
*printed_something = 1;
*returnval = 1;
@@ -348,7 +371,15 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
if (print && mprint(ms, m) == -1)
return -1;
- ms->c.li[cont_level].off = moffset(ms, m);
+ switch (moffset(ms, m, nbytes,
+ &ms->c.li[cont_level].off)) {
+ case -1:
+ case 0:
+ flush = 1;
+ break;
+ default:
+ break;
+ }
if (*m->desc)
*need_separator = 1;
@@ -668,7 +699,12 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_NAME:
t = ms->offset;
break;
-
+ case FILE_DER:
+ if (file_printf(ms, F(ms, m, "%s"),
+ file_printable(sbuf, sizeof(sbuf), ms->ms_value.s)) == -1)
+ return -1;
+ t = ms->offset;
+ break;
default:
file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
return -1;
@@ -676,100 +712,152 @@ mprint(struct magic_set *ms, struct magic *m)
return (int32_t)t;
}
-private int32_t
-moffset(struct magic_set *ms, struct magic *m)
+private int
+moffset(struct magic_set *ms, struct magic *m, size_t nbytes, int32_t *op)
{
+ int32_t o;
+
switch (m->type) {
case FILE_BYTE:
- return CAST(int32_t, (ms->offset + sizeof(char)));
+ o = CAST(int32_t, (ms->offset + sizeof(char)));
+ break;
case FILE_SHORT:
case FILE_BESHORT:
case FILE_LESHORT:
- return CAST(int32_t, (ms->offset + sizeof(short)));
+ o = CAST(int32_t, (ms->offset + sizeof(short)));
+ break;
case FILE_LONG:
case FILE_BELONG:
case FILE_LELONG:
case FILE_MELONG:
- return CAST(int32_t, (ms->offset + sizeof(int32_t)));
+ o = CAST(int32_t, (ms->offset + sizeof(int32_t)));
+ break;
case FILE_QUAD:
case FILE_BEQUAD:
case FILE_LEQUAD:
- return CAST(int32_t, (ms->offset + sizeof(int64_t)));
+ o = CAST(int32_t, (ms->offset + sizeof(int64_t)));
+ break;
case FILE_STRING:
case FILE_PSTRING:
case FILE_BESTRING16:
case FILE_LESTRING16:
- if (m->reln == '=' || m->reln == '!')
- return ms->offset + m->vallen;
- else {
+ if (m->reln == '=' || m->reln == '!') {
+ o = ms->offset + m->vallen;
+ } else {
union VALUETYPE *p = &ms->ms_value;
- uint32_t t;
if (*m->value.s == '\0')
p->s[strcspn(p->s, "\r\n")] = '\0';
- t = CAST(uint32_t, (ms->offset + strlen(p->s)));
+ o = CAST(uint32_t, (ms->offset + strlen(p->s)));
if (m->type == FILE_PSTRING)
- t += (uint32_t)file_pstring_length_size(m);
- return t;
+ o += (uint32_t)file_pstring_length_size(m);
}
+ break;
case FILE_DATE:
case FILE_BEDATE:
case FILE_LEDATE:
case FILE_MEDATE:
- return CAST(int32_t, (ms->offset + sizeof(uint32_t)));
+ o = CAST(int32_t, (ms->offset + sizeof(uint32_t)));
+ break;
case FILE_LDATE:
case FILE_BELDATE:
case FILE_LELDATE:
case FILE_MELDATE:
- return CAST(int32_t, (ms->offset + sizeof(uint32_t)));
+ o = CAST(int32_t, (ms->offset + sizeof(uint32_t)));
+ break;
case FILE_QDATE:
case FILE_BEQDATE:
case FILE_LEQDATE:
- return CAST(int32_t, (ms->offset + sizeof(uint64_t)));
+ o = CAST(int32_t, (ms->offset + sizeof(uint64_t)));
+ break;
case FILE_QLDATE:
case FILE_BEQLDATE:
case FILE_LEQLDATE:
- return CAST(int32_t, (ms->offset + sizeof(uint64_t)));
+ o = CAST(int32_t, (ms->offset + sizeof(uint64_t)));
+ break;
case FILE_FLOAT:
case FILE_BEFLOAT:
case FILE_LEFLOAT:
- return CAST(int32_t, (ms->offset + sizeof(float)));
+ o = CAST(int32_t, (ms->offset + sizeof(float)));
+ break;
case FILE_DOUBLE:
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
- return CAST(int32_t, (ms->offset + sizeof(double)));
+ o = CAST(int32_t, (ms->offset + sizeof(double)));
+ break;
case FILE_REGEX:
if ((m->str_flags & REGEX_OFFSET_START) != 0)
- return CAST(int32_t, ms->search.offset);
+ o = CAST(int32_t, ms->search.offset);
else
- return CAST(int32_t, (ms->search.offset +
- ms->search.rm_len));
+ o = CAST(int32_t,
+ (ms->search.offset + ms->search.rm_len));
+ break;
case FILE_SEARCH:
if ((m->str_flags & REGEX_OFFSET_START) != 0)
- return CAST(int32_t, ms->search.offset);
+ o = CAST(int32_t, ms->search.offset);
else
- return CAST(int32_t, (ms->search.offset + m->vallen));
+ o = CAST(int32_t, (ms->search.offset + m->vallen));
+ break;
case FILE_CLEAR:
case FILE_DEFAULT:
case FILE_INDIRECT:
- return ms->offset;
+ o = ms->offset;
+ break;
+
+ case FILE_DER:
+ {
+ o = der_offs(ms, m, nbytes);
+ if (o == -1 || (size_t)o > nbytes) {
+ if ((ms->flags & MAGIC_DEBUG) != 0) {
+ (void)fprintf(stderr,
+ "Bad DER offset %d nbytes=%zu",
+ o, nbytes);
+ }
+ *op = 0;
+ return 0;
+ }
+ break;
+ }
default:
- return 0;
+ o = 0;
+ break;
}
+
+ if ((size_t)o > nbytes) {
+#if 0
+ file_error(ms, 0, "Offset out of range %zu > %zu",
+ (size_t)o, nbytes);
+#endif
+ return -1;
+ }
+ *op = o;
+ return 1;
+}
+
+private uint32_t
+cvt_id3(struct magic_set *ms, uint32_t v)
+{
+ v = ((((v >> 0) & 0x7f) << 0) |
+ (((v >> 8) & 0x7f) << 7) |
+ (((v >> 16) & 0x7f) << 14) |
+ (((v >> 24) & 0x7f) << 21));
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ fprintf(stderr, "id3 offs=%u\n", v);
+ return v;
}
private int
@@ -844,66 +932,78 @@ cvt_flip(int type, int flip)
p->fld *= cast m->num_mask; \
break; \
case FILE_OPDIVIDE: \
+ if (cast m->num_mask == 0) \
+ return -1; \
p->fld /= cast m->num_mask; \
break; \
case FILE_OPMODULO: \
+ if (cast m->num_mask == 0) \
+ return -1; \
p->fld %= cast m->num_mask; \
break; \
} \
if (m->mask_op & FILE_OPINVERSE) \
p->fld = ~p->fld \
-private void
+private int
cvt_8(union VALUETYPE *p, const struct magic *m)
{
DO_CVT(b, (uint8_t));
+ return 0;
}
-private void
+private int
cvt_16(union VALUETYPE *p, const struct magic *m)
{
DO_CVT(h, (uint16_t));
+ return 0;
}
-private void
+private int
cvt_32(union VALUETYPE *p, const struct magic *m)
{
DO_CVT(l, (uint32_t));
+ return 0;
}
-private void
+private int
cvt_64(union VALUETYPE *p, const struct magic *m)
{
DO_CVT(q, (uint64_t));
+ return 0;
}
#define DO_CVT2(fld, cast) \
if (m->num_mask) \
switch (m->mask_op & FILE_OPS_MASK) { \
case FILE_OPADD: \
- p->fld += cast (int64_t)m->num_mask; \
+ p->fld += cast m->num_mask; \
break; \
case FILE_OPMINUS: \
- p->fld -= cast (int64_t)m->num_mask; \
+ p->fld -= cast m->num_mask; \
break; \
case FILE_OPMULTIPLY: \
- p->fld *= cast (int64_t)m->num_mask; \
+ p->fld *= cast m->num_mask; \
break; \
case FILE_OPDIVIDE: \
- p->fld /= cast (int64_t)m->num_mask; \
+ if (cast m->num_mask == 0) \
+ return -1; \
+ p->fld /= cast m->num_mask; \
break; \
} \
-private void
+private int
cvt_float(union VALUETYPE *p, const struct magic *m)
{
DO_CVT2(f, (float));
+ return 0;
}
-private void
+private int
cvt_double(union VALUETYPE *p, const struct magic *m)
{
DO_CVT2(d, (double));
+ return 0;
}
/*
@@ -919,21 +1019,25 @@ mconvert(struct magic_set *ms, struct magic *m, int flip)
switch (type = cvt_flip(m->type, flip)) {
case FILE_BYTE:
- cvt_8(p, m);
+ if (cvt_8(p, m) == -1)
+ goto out;
return 1;
case FILE_SHORT:
- cvt_16(p, m);
+ if (cvt_16(p, m) == -1)
+ goto out;
return 1;
case FILE_LONG:
case FILE_DATE:
case FILE_LDATE:
- cvt_32(p, m);
+ if (cvt_32(p, m) == -1)
+ goto out;
return 1;
case FILE_QUAD:
case FILE_QDATE:
case FILE_QLDATE:
case FILE_QWDATE:
- cvt_64(p, m);
+ if (cvt_64(p, m) == -1)
+ goto out;
return 1;
case FILE_STRING:
case FILE_BESTRING16:
@@ -964,85 +1068,79 @@ mconvert(struct magic_set *ms, struct magic *m, int flip)
return 1;
}
case FILE_BESHORT:
- p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
- cvt_16(p, m);
+ p->h = (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)
- ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
- cvt_32(p, m);
+ p->l = (int32_t)BE32(p);
+ if (cvt_32(p, m) == -1)
+ goto out;
return 1;
case FILE_BEQUAD:
case FILE_BEQDATE:
case FILE_BEQLDATE:
case FILE_BEQWDATE:
- p->q = (uint64_t)
- (((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)|
- ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)|
- ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)|
- ((uint64_t)p->hq[6]<<8)|((uint64_t)p->hq[7]));
- cvt_64(p, m);
+ p->q = (uint64_t)BE64(p);
+ if (cvt_64(p, m) == -1)
+ goto out;
return 1;
case FILE_LESHORT:
- p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
- cvt_16(p, m);
+ p->h = (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)
- ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
- cvt_32(p, m);
+ p->l = (int32_t)LE32(p);
+ if (cvt_32(p, m) == -1)
+ goto out;
return 1;
case FILE_LEQUAD:
case FILE_LEQDATE:
case FILE_LEQLDATE:
case FILE_LEQWDATE:
- p->q = (uint64_t)
- (((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)|
- ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)|
- ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)|
- ((uint64_t)p->hq[1]<<8)|((uint64_t)p->hq[0]));
- cvt_64(p, m);
+ p->q = (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)
- ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2]));
- cvt_32(p, m);
+ p->l = (int32_t)ME32(p);
+ if (cvt_32(p, m) == -1)
+ goto out;
return 1;
case FILE_FLOAT:
- cvt_float(p, m);
+ if (cvt_float(p, m) == -1)
+ goto out;
return 1;
case FILE_BEFLOAT:
- p->l = ((uint32_t)p->hl[0]<<24)|((uint32_t)p->hl[1]<<16)|
- ((uint32_t)p->hl[2]<<8) |((uint32_t)p->hl[3]);
- cvt_float(p, m);
+ p->l = BE32(p);
+ if (cvt_float(p, m) == -1)
+ goto out;
return 1;
case FILE_LEFLOAT:
- p->l = ((uint32_t)p->hl[3]<<24)|((uint32_t)p->hl[2]<<16)|
- ((uint32_t)p->hl[1]<<8) |((uint32_t)p->hl[0]);
- cvt_float(p, m);
+ p->l = LE32(p);
+ if (cvt_float(p, m) == -1)
+ goto out;
return 1;
case FILE_DOUBLE:
- cvt_double(p, m);
+ if (cvt_double(p, m) == -1)
+ goto out;
return 1;
case FILE_BEDOUBLE:
- p->q = ((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]);
- cvt_double(p, m);
+ p->q = BE64(p);
+ if (cvt_double(p, m) == -1)
+ goto out;
return 1;
case FILE_LEDOUBLE:
- p->q = ((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]);
- cvt_double(p, m);
+ p->q = LE64(p);
+ if (cvt_double(p, m) == -1)
+ goto out;
return 1;
case FILE_REGEX:
case FILE_SEARCH:
@@ -1050,11 +1148,15 @@ mconvert(struct magic_set *ms, struct magic *m, int flip)
case FILE_CLEAR:
case FILE_NAME:
case FILE_USE:
+ case FILE_DER:
return 1;
default:
file_magerror(ms, "invalid type %d in mconvert()", m->type);
return 0;
}
+out:
+ file_magerror(ms, "zerodivide in mconvert()");
+ return 0;
}
@@ -1077,7 +1179,10 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
*/
if (indir == 0) {
switch (type) {
+ case FILE_DER:
case FILE_SEARCH:
+ if (offset > nbytes)
+ offset = nbytes;
ms->search.s = RCAST(const char *, s) + offset;
ms->search.s_len = nbytes - offset;
ms->search.offset = offset;
@@ -1127,7 +1232,7 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
memchr(c, '\r', CAST(size_t, (end - c))))));
lines--, b++) {
last = b;
- if (b[0] == '\r' && b[1] == '\n')
+ if (b < end - 1 && b[0] == '\r' && b[1] == '\n')
b++;
}
if (lines)
@@ -1195,23 +1300,62 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
return 0;
}
+private uint32_t
+do_ops(struct magic *m, intmax_t lhs, intmax_t off)
+{
+ intmax_t offset;
+ if (off) {
+ switch (m->in_op & FILE_OPS_MASK) {
+ case FILE_OPAND:
+ offset = lhs & off;
+ break;
+ case FILE_OPOR:
+ offset = lhs | off;
+ break;
+ case FILE_OPXOR:
+ offset = lhs ^ off;
+ break;
+ case FILE_OPADD:
+ offset = lhs + off;
+ break;
+ case FILE_OPMINUS:
+ offset = lhs - off;
+ break;
+ case FILE_OPMULTIPLY:
+ offset = lhs * off;
+ break;
+ case FILE_OPDIVIDE:
+ offset = lhs / off;
+ break;
+ case FILE_OPMODULO:
+ offset = lhs % off;
+ break;
+ }
+ } else
+ offset = lhs;
+ if (m->in_op & FILE_OPINVERSE)
+ offset = ~offset;
+
+ return (uint32_t)offset;
+}
+
private int
mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
size_t nbytes, size_t o, unsigned int cont_level, int mode, int text,
- int flip, uint16_t indir_level, uint16_t *name_count,
+ int flip, uint16_t *indir_count, uint16_t *name_count,
int *printed_something, int *need_separator, int *returnval)
{
uint32_t offset = ms->offset;
- uint32_t lhs;
+ intmax_t lhs;
file_pushbuf_t *pb;
int rv, oneed_separator, in_type;
char *rbuf;
union VALUETYPE *p = &ms->ms_value;
struct mlist ml;
- if (indir_level >= ms->indir_max) {
- file_error(ms, 0, "indirect recursion nesting (%hu) exceeded",
- indir_level);
+ if (*indir_count >= ms->indir_max) {
+ file_error(ms, 0, "indirect count (%hu) exceeded",
+ *indir_count);
return -1;
}
@@ -1230,354 +1374,97 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
SIZE_T_FORMAT "u, " "nbytes=%" SIZE_T_FORMAT
"u, il=%hu, nc=%hu)\n",
m->type, m->flag, offset, o, nbytes,
- indir_level, *name_count);
+ *indir_count, *name_count);
mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
}
if (m->flag & INDIR) {
- int off = m->in_offset;
+ intmax_t off = m->in_offset;
+ 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;
switch (cvt_flip(m->in_type, flip)) {
case FILE_BYTE:
- off = q->b;
+ off = SEXT(sgn,8,q->b);
break;
case FILE_SHORT:
- off = q->h;
+ off = SEXT(sgn,16,q->h);
break;
case FILE_BESHORT:
- off = (short)((q->hs[0]<<8)|(q->hs[1]));
+ off = SEXT(sgn,16,BE16(q));
break;
case FILE_LESHORT:
- off = (short)((q->hs[1]<<8)|(q->hs[0]));
+ off = SEXT(sgn,16,LE16(q));
break;
case FILE_LONG:
- off = q->l;
+ off = SEXT(sgn,32,q->l);
break;
case FILE_BELONG:
case FILE_BEID3:
- off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
- (q->hl[2]<<8)|(q->hl[3]));
+ off = SEXT(sgn,32,BE32(q));
break;
case FILE_LEID3:
case FILE_LELONG:
- off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
- (q->hl[1]<<8)|(q->hl[0]));
+ off = SEXT(sgn,32,LE32(q));
break;
case FILE_MELONG:
- off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)|
- (q->hl[3]<<8)|(q->hl[2]));
+ off = SEXT(sgn,32,ME32(q));
break;
}
if ((ms->flags & MAGIC_DEBUG) != 0)
- fprintf(stderr, "indirect offs=%u\n", off);
+ fprintf(stderr, "indirect offs=%jd\n", off);
}
switch (in_type = cvt_flip(m->in_type, flip)) {
case FILE_BYTE:
if (OFFSET_OOB(nbytes, offset, 1))
return 0;
- if (off) {
- switch (m->in_op & FILE_OPS_MASK) {
- case FILE_OPAND:
- offset = p->b & off;
- break;
- case FILE_OPOR:
- offset = p->b | off;
- break;
- case FILE_OPXOR:
- offset = p->b ^ off;
- break;
- case FILE_OPADD:
- offset = p->b + off;
- break;
- case FILE_OPMINUS:
- offset = p->b - off;
- break;
- case FILE_OPMULTIPLY:
- offset = p->b * off;
- break;
- case FILE_OPDIVIDE:
- offset = p->b / off;
- break;
- case FILE_OPMODULO:
- offset = p->b % off;
- break;
- }
- } else
- offset = p->b;
- if (m->in_op & FILE_OPINVERSE)
- offset = ~offset;
+ offset = do_ops(m, SEXT(sgn,8,p->b), off);
break;
case FILE_BESHORT:
if (OFFSET_OOB(nbytes, offset, 2))
return 0;
- lhs = (p->hs[0] << 8) | p->hs[1];
- if (off) {
- switch (m->in_op & FILE_OPS_MASK) {
- case FILE_OPAND:
- offset = lhs & off;
- break;
- case FILE_OPOR:
- offset = lhs | off;
- break;
- case FILE_OPXOR:
- offset = lhs ^ off;
- break;
- case FILE_OPADD:
- offset = lhs + off;
- break;
- case FILE_OPMINUS:
- offset = lhs - off;
- break;
- case FILE_OPMULTIPLY:
- offset = lhs * off;
- break;
- case FILE_OPDIVIDE:
- offset = lhs / off;
- break;
- case FILE_OPMODULO:
- offset = lhs % off;
- break;
- }
- } else
- offset = lhs;
- if (m->in_op & FILE_OPINVERSE)
- offset = ~offset;
+ offset = do_ops(m, SEXT(sgn,16,BE16(p)), off);
break;
case FILE_LESHORT:
if (OFFSET_OOB(nbytes, offset, 2))
return 0;
- lhs = (p->hs[1] << 8) | p->hs[0];
- if (off) {
- switch (m->in_op & FILE_OPS_MASK) {
- case FILE_OPAND:
- offset = lhs & off;
- break;
- case FILE_OPOR:
- offset = lhs | off;
- break;
- case FILE_OPXOR:
- offset = lhs ^ off;
- break;
- case FILE_OPADD:
- offset = lhs + off;
- break;
- case FILE_OPMINUS:
- offset = lhs - off;
- break;
- case FILE_OPMULTIPLY:
- offset = lhs * off;
- break;
- case FILE_OPDIVIDE:
- offset = lhs / off;
- break;
- case FILE_OPMODULO:
- offset = lhs % off;
- break;
- }
- } else
- offset = lhs;
- if (m->in_op & FILE_OPINVERSE)
- offset = ~offset;
+ offset = do_ops(m, SEXT(sgn,16,LE16(p)), off);
break;
case FILE_SHORT:
if (OFFSET_OOB(nbytes, offset, 2))
return 0;
- if (off) {
- switch (m->in_op & FILE_OPS_MASK) {
- case FILE_OPAND:
- offset = p->h & off;
- break;
- case FILE_OPOR:
- offset = p->h | off;
- break;
- case FILE_OPXOR:
- offset = p->h ^ off;
- break;
- case FILE_OPADD:
- offset = p->h + off;
- break;
- case FILE_OPMINUS:
- offset = p->h - off;
- break;
- case FILE_OPMULTIPLY:
- offset = p->h * off;
- break;
- case FILE_OPDIVIDE:
- offset = p->h / off;
- break;
- case FILE_OPMODULO:
- offset = p->h % off;
- break;
- }
- }
- else
- offset = p->h;
- if (m->in_op & FILE_OPINVERSE)
- offset = ~offset;
+ offset = do_ops(m, SEXT(sgn,16,p->h), off);
break;
case FILE_BELONG:
case FILE_BEID3:
if (OFFSET_OOB(nbytes, offset, 4))
return 0;
- lhs = (p->hl[0] << 24) | (p->hl[1] << 16) |
- (p->hl[2] << 8) | p->hl[3];
- if (off) {
- switch (m->in_op & FILE_OPS_MASK) {
- case FILE_OPAND:
- offset = lhs & off;
- break;
- case FILE_OPOR:
- offset = lhs | off;
- break;
- case FILE_OPXOR:
- offset = lhs ^ off;
- break;
- case FILE_OPADD:
- offset = lhs + off;
- break;
- case FILE_OPMINUS:
- offset = lhs - off;
- break;
- case FILE_OPMULTIPLY:
- offset = lhs * off;
- break;
- case FILE_OPDIVIDE:
- offset = lhs / off;
- break;
- case FILE_OPMODULO:
- offset = lhs % off;
- break;
- }
- } else
- offset = lhs;
- if (m->in_op & FILE_OPINVERSE)
- offset = ~offset;
+ lhs = BE32(p);
+ if (in_type == FILE_BEID3)
+ lhs = cvt_id3(ms, (uint32_t)lhs);
+ offset = do_ops(m, SEXT(sgn,32,lhs), off);
break;
case FILE_LELONG:
case FILE_LEID3:
if (OFFSET_OOB(nbytes, offset, 4))
return 0;
- lhs = (p->hl[3] << 24) | (p->hl[2] << 16) |
- (p->hl[1] << 8) | p->hl[0];
- if (off) {
- switch (m->in_op & FILE_OPS_MASK) {
- case FILE_OPAND:
- offset = lhs & off;
- break;
- case FILE_OPOR:
- offset = lhs | off;
- break;
- case FILE_OPXOR:
- offset = lhs ^ off;
- break;
- case FILE_OPADD:
- offset = lhs + off;
- break;
- case FILE_OPMINUS:
- offset = lhs - off;
- break;
- case FILE_OPMULTIPLY:
- offset = lhs * off;
- break;
- case FILE_OPDIVIDE:
- offset = lhs / off;
- break;
- case FILE_OPMODULO:
- offset = lhs % off;
- break;
- }
- } else
- offset = lhs;
- if (m->in_op & FILE_OPINVERSE)
- offset = ~offset;
+ lhs = LE32(p);
+ if (in_type == FILE_LEID3)
+ lhs = cvt_id3(ms, (uint32_t)lhs);
+ offset = do_ops(m, SEXT(sgn,32,lhs), off);
break;
case FILE_MELONG:
if (OFFSET_OOB(nbytes, offset, 4))
return 0;
- lhs = (p->hl[1] << 24) | (p->hl[0] << 16) |
- (p->hl[3] << 8) | p->hl[2];
- if (off) {
- switch (m->in_op & FILE_OPS_MASK) {
- case FILE_OPAND:
- offset = lhs & off;
- break;
- case FILE_OPOR:
- offset = lhs | off;
- break;
- case FILE_OPXOR:
- offset = lhs ^ off;
- break;
- case FILE_OPADD:
- offset = lhs + off;
- break;
- case FILE_OPMINUS:
- offset = lhs - off;
- break;
- case FILE_OPMULTIPLY:
- offset = lhs * off;
- break;
- case FILE_OPDIVIDE:
- offset = lhs / off;
- break;
- case FILE_OPMODULO:
- offset = lhs % off;
- break;
- }
- } else
- offset = lhs;
- if (m->in_op & FILE_OPINVERSE)
- offset = ~offset;
+ offset = do_ops(m, SEXT(sgn,32,ME32(p)), off);
break;
case FILE_LONG:
if (OFFSET_OOB(nbytes, offset, 4))
return 0;
- if (off) {
- switch (m->in_op & FILE_OPS_MASK) {
- case FILE_OPAND:
- offset = p->l & off;
- break;
- case FILE_OPOR:
- offset = p->l | off;
- break;
- case FILE_OPXOR:
- offset = p->l ^ off;
- break;
- case FILE_OPADD:
- offset = p->l + off;
- break;
- case FILE_OPMINUS:
- offset = p->l - off;
- break;
- case FILE_OPMULTIPLY:
- offset = p->l * off;
- break;
- case FILE_OPDIVIDE:
- offset = p->l / off;
- break;
- case FILE_OPMODULO:
- offset = p->l % off;
- break;
- }
- } else
- offset = p->l;
- if (m->in_op & FILE_OPINVERSE)
- offset = ~offset;
- break;
- default:
- break;
- }
-
- switch (in_type) {
- case FILE_LEID3:
- case FILE_BEID3:
- offset = ((((offset >> 0) & 0x7f) << 0) |
- (((offset >> 8) & 0x7f) << 7) |
- (((offset >> 16) & 0x7f) << 14) |
- (((offset >> 24) & 0x7f) << 21));
- if ((ms->flags & MAGIC_DEBUG) != 0)
- fprintf(stderr, "id3 offs=%u\n", offset);
+ offset = do_ops(m, SEXT(sgn,32,p->l), off);
break;
default:
break;
@@ -1668,8 +1555,9 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
if ((pb = file_push_buffer(ms)) == NULL)
return -1;
+ (*indir_count)++;
rv = file_softmagic(ms, s + offset, nbytes - offset,
- indir_level + 1, name_count, BINTEST, text);
+ indir_count, name_count, BINTEST, text);
if ((ms->flags & MAGIC_DEBUG) != 0)
fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv);
@@ -1679,7 +1567,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
return -1;
if (rv == 1) {
- if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 &&
+ if ((ms->flags & MAGIC_NODESC) == 0 &&
file_printf(ms, F(ms, m, "%u"), offset) == -1) {
if (rbuf) efree(rbuf);
return -1;
@@ -1709,16 +1597,19 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
if (m->flag & NOSPACE)
*need_separator = 0;
rv = match(ms, ml.magic, ml.nmagic, s, nbytes, offset + o,
- mode, text, flip, indir_level, name_count,
+ mode, text, flip, indir_count, name_count,
printed_something, need_separator, returnval);
if (rv != 1)
*need_separator = oneed_separator;
- return rv;
+ return 1;
case FILE_NAME:
+ if (ms->flags & MAGIC_NODESC)
+ return 1;
if (file_printf(ms, "%s", m->desc) == -1)
return -1;
return 1;
+ case FILE_DER:
case FILE_DEFAULT: /* nothing to check */
case FILE_CLEAR:
default:
@@ -1768,9 +1659,14 @@ file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
isspace(*a)) {
a++;
if (isspace(*b++)) {
- if (!isspace(*a))
- while (isspace(*b))
+ if (!isspace(*a)) {
+ /* Limit to the remaining len only, otherwise
+ we risk to cause CVE-2014-3538. This
+ might be done better though, not sure. */
+ size_t remaining_len = len;
+ while (isspace(*b) && remaining_len-- > 0)
b++;
+ }
}
else {
v = 1;
@@ -1779,8 +1675,10 @@ file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
}
else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) &&
isspace(*a)) {
+ /* Same as the comment in the previous elif clause. */
+ size_t remaining_len = len;
a++;
- while (isspace(*b))
+ while (isspace(*b)&& remaining_len-- > 0)
b++;
}
else {
@@ -2076,6 +1974,16 @@ error_out:
case FILE_USE:
case FILE_NAME:
return 1;
+ case FILE_DER:
+ matched = der_cmp(ms, m);
+ if (matched == -1) {
+ if ((ms->flags & MAGIC_DEBUG) != 0) {
+ (void) fprintf(stderr,
+ "EOF comparing DER entries");
+ }
+ return 0;
+ }
+ return matched;
default:
file_magerror(ms, "invalid type %d in magiccheck()", m->type);
return -1;
@@ -2173,14 +2081,25 @@ error_out:
}
private int
-handle_annotation(struct magic_set *ms, struct magic *m)
+handle_annotation(struct magic_set *ms, struct magic *m, int firstline)
{
- if (ms->flags & MAGIC_APPLE) {
+ if ((ms->flags & MAGIC_APPLE) && m->apple[0]) {
+ if (!firstline && file_printf(ms, "\n- ") == -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)
+ return -1;
+ if (file_printf(ms, "%s", m->ext) == -1)
+ return -1;
+ return 1;
+ }
if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
+ if (!firstline && file_printf(ms, "\n- ") == -1)
+ return -1;
if (file_printf(ms, "%s", m->mimetype) == -1)
return -1;
return 1;
@@ -2191,8 +2110,8 @@ handle_annotation(struct magic_set *ms, struct magic *m)
private int
print_sep(struct magic_set *ms, int firstline)
{
- if (ms->flags & MAGIC_MIME)
- return 0;
+// if (ms->flags & MAGIC_NODESC)
+// return 0;
if (firstline)
return 0;
/*
diff --git a/ext/fileinfo/libmagic/tar.h b/ext/fileinfo/libmagic/tar.h
index c3d0297d11..854d4552e6 100644
--- a/ext/fileinfo/libmagic/tar.h
+++ b/ext/fileinfo/libmagic/tar.h
@@ -32,7 +32,7 @@
*
* Created 25 August 1985 by John Gilmore, ihnp4!hoptoad!gnu.
*
- * $File: tar.h,v 1.12 2008/02/07 00:58:52 christos Exp $ # checkin only
+ * $File: tar.h,v 1.13 2010/11/30 14:58:53 rrt Exp $ # checkin only
*/
/*