summaryrefslogtreecommitdiff
path: root/src/apprentice.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/apprentice.c')
-rw-r--r--src/apprentice.c409
1 files changed, 296 insertions, 113 deletions
diff --git a/src/apprentice.c b/src/apprentice.c
index 47b4c87..a7b4dd8 100644
--- a/src/apprentice.c
+++ b/src/apprentice.c
@@ -32,7 +32,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: apprentice.c,v 1.229 2015/01/01 17:07:34 christos Exp $")
+FILE_RCSID("@(#)$File: apprentice.c,v 1.262 2017/08/28 13:39:18 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -86,9 +86,9 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.229 2015/01/01 17:07:34 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;
@@ -143,12 +143,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);
@@ -163,6 +164,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 }
@@ -266,6 +268,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 },
};
@@ -274,6 +277,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 },
@@ -404,11 +408,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 *, malloc(sizeof(*ml)))) == NULL)
return -1;
- ml->map = NULL;
+ ml->map = idx == 0 ? map : NULL;
ml->magic = map->magic[idx];
ml->nmagic = map->nmagic[idx];
@@ -447,6 +451,8 @@ apprentice_1(struct magic_set *ms, const char *fn, int action)
#ifndef COMPILE_ONLY
map = apprentice_map(ms, fn);
+ if (map == (struct magic_map *)-1)
+ return -1;
if (map == NULL) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "using regular magic file `%s'", fn);
@@ -458,7 +464,7 @@ 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));
- goto fail;
+ return -1;
}
}
@@ -472,12 +478,6 @@ apprentice_1(struct magic_set *ms, const char *fn, int action)
}
}
return 0;
-fail:
- for (i = 0; i < MAGIC_SETS; i++) {
- mlist_free(ms->mlist[i]);
- ms->mlist[i] = NULL;
- }
- return -1;
#else
return 0;
#endif /* COMPILE_ONLY */
@@ -529,6 +529,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:
free(ms);
@@ -538,21 +540,30 @@ free:
private void
apprentice_unmap(struct magic_map *map)
{
+ size_t i;
if (map == NULL)
return;
switch (map->type) {
-#ifdef QUICK
- case MAP_TYPE_MMAP:
- if (map->p)
- (void)munmap(map->p, map->len);
+ case MAP_TYPE_USER:
break;
-#endif
case MAP_TYPE_MALLOC:
+ for (i = 0; i < MAGIC_SETS; i++) {
+ void *b = map->magic[i];
+ void *p = map->p;
+ if (CAST(char *, b) >= CAST(char *, p) &&
+ CAST(char *, b) <= CAST(char *, p) + map->len)
+ continue;
+ free(map->magic[i]);
+ }
free(map->p);
break;
- case MAP_TYPE_USER:
+#ifdef QUICK
+ case MAP_TYPE_MMAP:
+ if (map->p && map->p != MAP_FAILED)
+ (void)munmap(map->p, map->len);
break;
+#endif
default:
abort();
}
@@ -581,7 +592,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));
free(ml);
if (ml == mlist)
break;
@@ -601,8 +612,7 @@ buffer_apprentice(struct magic_set *ms, struct magic **bufs,
if (nbufs == 0)
return -1;
- if (ms->mlist[0] != NULL)
- file_reset(ms);
+ (void)file_reset(ms, 0);
init_file_tables();
@@ -645,8 +655,7 @@ file_apprentice(struct magic_set *ms, const char *fn, int action)
int file_err, errs = -1;
size_t i;
- if (ms->mlist[0] != NULL)
- file_reset(ms);
+ (void)file_reset(ms, 0);
if ((fn = magic_getpath(fn, action)) == NULL)
return -1;
@@ -768,6 +777,59 @@ nonmagic(const char *str)
return rv == 0 ? 1 : rv; /* Return at least 1 */
}
+
+private size_t
+typesize(int type)
+{
+ switch (type) {
+ case FILE_BYTE:
+ return 1;
+
+ case FILE_SHORT:
+ case FILE_LESHORT:
+ case FILE_BESHORT:
+ return 2;
+
+ case FILE_LONG:
+ case FILE_LELONG:
+ case FILE_BELONG:
+ case FILE_MELONG:
+ return 4;
+
+ case FILE_DATE:
+ case FILE_LEDATE:
+ case FILE_BEDATE:
+ case FILE_MEDATE:
+ case FILE_LDATE:
+ case FILE_LELDATE:
+ case FILE_BELDATE:
+ case FILE_MELDATE:
+ case FILE_FLOAT:
+ case FILE_BEFLOAT:
+ case FILE_LEFLOAT:
+ return 4;
+
+ case FILE_QUAD:
+ case FILE_BEQUAD:
+ case FILE_LEQUAD:
+ case FILE_QDATE:
+ case FILE_LEQDATE:
+ case FILE_BEQDATE:
+ case FILE_QLDATE:
+ case FILE_LEQLDATE:
+ case FILE_BEQLDATE:
+ case FILE_QWDATE:
+ case FILE_LEQWDATE:
+ case FILE_BEQWDATE:
+ case FILE_DOUBLE:
+ case FILE_BEDOUBLE:
+ case FILE_LEDOUBLE:
+ return 8;
+ default:
+ return (size_t)~0;
+ }
+}
+
/*
* Get weight of this magic entry, for sorting purposes.
*/
@@ -775,7 +837,7 @@ private size_t
apprentice_magic_strength(const struct magic *m)
{
#define MULT 10
- size_t v, val = 2 * MULT; /* baseline strength */
+ size_t ts, v, val = 2 * MULT; /* baseline strength */
switch (m->type) {
case FILE_DEFAULT: /* make sure this sorts last */
@@ -784,41 +846,13 @@ apprentice_magic_strength(const struct magic *m)
return 0;
case FILE_BYTE:
- val += 1 * MULT;
- break;
-
case FILE_SHORT:
case FILE_LESHORT:
case FILE_BESHORT:
- val += 2 * MULT;
- break;
-
case FILE_LONG:
case FILE_LELONG:
case FILE_BELONG:
case FILE_MELONG:
- val += 4 * MULT;
- break;
-
- case FILE_PSTRING:
- case FILE_STRING:
- val += m->vallen * MULT;
- break;
-
- case FILE_BESTRING16:
- case FILE_LESTRING16:
- val += m->vallen * MULT / 2;
- break;
-
- case FILE_SEARCH:
- val += m->vallen * MAX(MULT / m->vallen, 1);
- break;
-
- case FILE_REGEX:
- v = nonmagic(m->value.s);
- val += v * MAX(MULT / v, 1);
- break;
-
case FILE_DATE:
case FILE_LEDATE:
case FILE_BEDATE:
@@ -830,9 +864,6 @@ apprentice_magic_strength(const struct magic *m)
case FILE_FLOAT:
case FILE_BEFLOAT:
case FILE_LEFLOAT:
- val += 4 * MULT;
- break;
-
case FILE_QUAD:
case FILE_BEQUAD:
case FILE_LEQUAD:
@@ -848,7 +879,29 @@ apprentice_magic_strength(const struct magic *m)
case FILE_DOUBLE:
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
- val += 8 * MULT;
+ ts = typesize(m->type);
+ if (ts == (size_t)~0)
+ abort();
+ val += ts * MULT;
+ break;
+
+ case FILE_PSTRING:
+ case FILE_STRING:
+ val += m->vallen * MULT;
+ break;
+
+ case FILE_BESTRING16:
+ case FILE_LESTRING16:
+ val += m->vallen * MULT / 2;
+ break;
+
+ case FILE_SEARCH:
+ val += m->vallen * MAX(MULT / m->vallen, 1);
+ break;
+
+ case FILE_REGEX:
+ v = nonmagic(m->value.s);
+ val += v * MAX(MULT / v, 1);
break;
case FILE_INDIRECT:
@@ -856,6 +909,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();
@@ -964,8 +1021,9 @@ apprentice_list(struct mlist *mlist, int mode)
*ml->magic[magindex].mimetype == '\0')
magindex++;
- printf("Strength = %3" SIZE_T_FORMAT "u : %s [%s]\n",
+ printf("Strength = %3" SIZE_T_FORMAT "u@%u: %s [%s]\n",
apprentice_magic_strength(m),
+ ml->magic[magindex].lineno,
ml->magic[magindex].desc,
ml->magic[magindex].mimetype);
}
@@ -1010,6 +1068,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:
@@ -1285,6 +1344,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)
@@ -1298,6 +1358,8 @@ apprentice_load(struct magic_set *ms, const char *fn, int action)
goto out;
}
while ((d = readdir(dir)) != NULL) {
+ if (d->d_name[0] == '.')
+ continue;
if (asprintf(&mfn, "%s/%s", fn, d->d_name) < 0) {
file_oomem(ms,
strlen(fn) + strlen(d->d_name) + 2);
@@ -1345,8 +1407,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
@@ -1439,6 +1502,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)
@@ -1839,24 +1903,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':
@@ -1903,12 +1974,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++;
@@ -1923,17 +1993,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;
@@ -2086,7 +2160,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"); }
*/
@@ -2199,7 +2273,7 @@ parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line,
size_t i;
const char *l = line;
struct magic *m = &me->mp[me->cont_count == 0 ? 0 : me->cont_count - 1];
- char *buf = (char *)m + off;
+ char *buf = CAST(char *, CAST(void *, m)) + off;
if (buf[0] != '\0') {
len = nt ? strlen(buf) : len;
@@ -2248,8 +2322,22 @@ parse_apple(struct magic_set *ms, struct magic_entry *me, const char *line)
{
struct magic *m = &me->mp[0];
- return parse_extra(ms, me, line, offsetof(struct magic, apple),
- sizeof(m->apple), "APPLE", "!+-./", 0);
+ return parse_extra(ms, me, line,
+ CAST(off_t, offsetof(struct magic, apple)),
+ 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);
}
/*
@@ -2261,16 +2349,19 @@ parse_mime(struct magic_set *ms, struct magic_entry *me, const char *line)
{
struct magic *m = &me->mp[0];
- return parse_extra(ms, me, line, offsetof(struct magic, mimetype),
+ return parse_extra(ms, me, line,
+ CAST(off_t, offsetof(struct magic, mimetype)),
sizeof(m->mimetype), "MIME", "+-/.", 1);
}
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;
}
@@ -2307,15 +2398,24 @@ check_format_type(const char *ptr, int type)
ptr++;
if (*ptr == '.')
ptr++;
- while (isdigit((unsigned char)*ptr)) ptr++;
+ if (*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++) {
@@ -2329,9 +2429,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;
}
/*
@@ -2340,11 +2442,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':
@@ -2354,7 +2456,7 @@ check_format_type(const char *ptr, int type)
case 'X':
return 0;
default:
- return -1;
+ goto invalid;
}
case 'i':
case 'd':
@@ -2362,13 +2464,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':
@@ -2376,12 +2482,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:
@@ -2390,11 +2498,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':
@@ -2405,7 +2512,7 @@ check_format_type(const char *ptr, int type)
return 0;
default:
- return -1;
+ goto invalid;
}
@@ -2424,14 +2531,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;
}
@@ -2443,6 +2553,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 == '%')
@@ -2466,13 +2577,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;
}
@@ -2506,6 +2617,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)
@@ -2529,12 +2641,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:
@@ -2542,17 +2656,59 @@ 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;
- m->value.q = file_signextend(ms, m,
- (uint64_t)strtoull(*p, &ep, 0));
- *p = ep;
- eatsize(p);
+ uint64_t ull;
+ errno = 0;
+ ull = (uint64_t)strtoull(*p, &ep, 0);
+ m->value.q = file_signextend(ms, m, ull);
+ if (*p == ep) {
+ file_magwarn(ms, "Unparseable number `%s'", *p);
+ } else {
+ size_t ts = typesize(m->type);
+ uint64_t x;
+ const char *q;
+
+ if (ts == (size_t)~0) {
+ file_magwarn(ms, "Expected numeric type got `%s'",
+ type_tbl[m->type].name);
+ }
+ for (q = *p; isspace((unsigned char)*q); q++)
+ continue;
+ if (*q == '-')
+ ull = -(int64_t)ull;
+ switch (ts) {
+ case 1:
+ x = ull & ~0xffULL;
+ break;
+ case 2:
+ x = ull & ~0xffffULL;
+ break;
+ case 4:
+ x = ull & ~0xffffffffULL;
+ break;
+ case 8:
+ x = 0;
+ break;
+ default:
+ abort();
+ }
+ if (x) {
+ file_magwarn(ms, "Overflow for numeric type `%s' value %#" PRIx64,
+ type_tbl[m->type].name, ull);
+ }
+ }
+ if (errno == 0) {
+ *p = ep;
+ eatsize(p);
+ }
}
return 0;
}
@@ -2588,6 +2744,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':
@@ -2711,6 +2868,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));
@@ -2855,12 +3013,14 @@ apprentice_map(struct magic_set *ms, const char *fn)
struct stat st;
char *dbname = NULL;
struct magic_map *map;
+ struct magic_map *rv = NULL;
fd = -1;
if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) {
file_oomem(ms, sizeof(*map));
goto error;
}
+ map->type = MAP_TYPE_USER; /* unspecified */
dbname = mkdbname(ms, fn, 0);
if (dbname == NULL)
@@ -2881,13 +3041,14 @@ apprentice_map(struct magic_set *ms, const char *fn)
map->len = (size_t)st.st_size;
#ifdef QUICK
+ map->type = MAP_TYPE_MMAP;
if ((map->p = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) {
file_error(ms, errno, "cannot map `%s'", dbname);
goto error;
}
- map->type = MAP_TYPE_MMAP;
#else
+ map->type = MAP_TYPE_MALLOC;
if ((map->p = CAST(void *, malloc(map->len))) == NULL) {
file_oomem(ms, map->len);
goto error;
@@ -2896,14 +3057,21 @@ apprentice_map(struct magic_set *ms, const char *fn)
file_badread(ms);
goto error;
}
- map->type = MAP_TYPE_MALLOC;
#define RET 1
#endif
(void)close(fd);
fd = -1;
- if (check_buffer(ms, map, dbname) != 0)
+ if (check_buffer(ms, map, dbname) != 0) {
+ rv = (struct magic_map *)-1;
+ goto error;
+ }
+#ifdef QUICK
+ if (mprotect(map->p, (size_t)st.st_size, PROT_READ) == -1) {
+ file_error(ms, errno, "cannot mprotect `%s'", dbname);
goto error;
+ }
+#endif
free(dbname);
return map;
@@ -2913,7 +3081,7 @@ error:
(void)close(fd);
apprentice_unmap(map);
free(dbname);
- return NULL;
+ return rv;
}
private int
@@ -3022,6 +3190,7 @@ apprentice_compile(struct magic_set *ms, struct magic_map *map, const char *fn)
(void)close(fd);
rv = 0;
out:
+ apprentice_unmap(map);
free(dbname);
return rv;
}
@@ -3068,7 +3237,7 @@ mkdbname(struct magic_set *ms, const char *fn, int strip)
return NULL;
/* 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;
}
@@ -3183,25 +3352,39 @@ 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;
+ unsigned int s3, s2, s1, s0;
switch (m->str_flags & PSTRING_LEN) {
case PSTRING_1_LE:
len = *s;
break;
case PSTRING_2_LE:
- len = (s[1] << 8) | s[0];
+ s0 = s[0];
+ s1 = s[1];
+ len = (s1 << 8) | s0;
break;
case PSTRING_2_BE:
- len = (s[0] << 8) | s[1];
+ s0 = s[0];
+ s1 = s[1];
+ len = (s0 << 8) | s1;
break;
case PSTRING_4_LE:
- len = (s[3] << 24) | (s[2] << 16) | (s[1] << 8) | s[0];
+ s0 = s[0];
+ s1 = s[1];
+ s2 = s[2];
+ s3 = s[3];
+ len = (s3 << 24) | (s2 << 16) | (s1 << 8) | s0;
break;
case PSTRING_4_BE:
- len = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
+ s0 = s[0];
+ s1 = s[1];
+ s2 = s[2];
+ s3 = s[3];
+ len = (s0 << 24) | (s1 << 16) | (s2 << 8) | s3;
break;
default:
abort(); /* Impossible */