summaryrefslogtreecommitdiff
path: root/src/apprentice.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/apprentice.c')
-rw-r--r--src/apprentice.c152
1 files changed, 108 insertions, 44 deletions
diff --git a/src/apprentice.c b/src/apprentice.c
index 7ebd6897bd048..1437bcc1179ea 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.284 2019/06/29 22:31:04 christos Exp $")
+FILE_RCSID("@(#)$File: apprentice.c,v 1.297 2020/05/09 18:57:15 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -120,6 +120,7 @@ private void apprentice_list(struct mlist *, int );
private struct magic_map *apprentice_load(struct magic_set *,
const char *, int);
private struct mlist *mlist_alloc(void);
+private void mlist_free_all(struct magic_set *);
private void mlist_free(struct mlist *);
private void byteswap(struct magic *, uint32_t);
private void bs1(struct magic *);
@@ -137,10 +138,14 @@ private int apprentice_compile(struct magic_set *, struct magic_map *,
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 int parse_mime(struct magic_set *, struct magic_entry *, const char *,
+ size_t);
+private int parse_strength(struct magic_set *, struct magic_entry *,
+ const char *, size_t);
+private int parse_apple(struct magic_set *, struct magic_entry *, const char *,
+ size_t);
+private int parse_ext(struct magic_set *, struct magic_entry *, const char *,
+ size_t);
private size_t magicsize = sizeof(struct magic);
@@ -150,7 +155,8 @@ private const char usg_hdr[] = "cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
private struct {
const char *name;
size_t len;
- int (*fun)(struct magic_set *, struct magic_entry *, const char *);
+ int (*fun)(struct magic_set *, struct magic_entry *, const char *,
+ size_t);
} bang[] = {
#define DECLARE_FIELD(name) { # name, sizeof(# name) - 1, parse_ ## name }
DECLARE_FIELD(mime),
@@ -260,6 +266,8 @@ static const struct type_tbl_s type_tbl[] = {
{ XX("use"), FILE_USE, FILE_FMT_NONE },
{ XX("clear"), FILE_CLEAR, FILE_FMT_NONE },
{ XX("der"), FILE_DER, FILE_FMT_STR },
+ { XX("guid"), FILE_GUID, FILE_FMT_STR },
+ { XX("offset"), FILE_OFFSET, FILE_FMT_QUAD },
{ XX_NULL, FILE_INVALID, FILE_FMT_NONE },
};
@@ -451,8 +459,6 @@ apprentice_1(struct magic_set *ms, const char *fn, int action)
#ifndef COMPILE_ONLY
map = apprentice_map(ms, fn);
- if (map == RCAST(struct magic_map *, -1))
- return -1;
if (map == NULL) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "using regular magic file `%s'", fn);
@@ -463,6 +469,11 @@ 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) {
+ /* failed to add to any list, free explicitly */
+ if (i == 0)
+ apprentice_unmap(map);
+ else
+ mlist_free_all(ms);
file_oomem(ms, sizeof(*ml));
return -1;
}
@@ -513,6 +524,7 @@ file_ms_alloc(int flags)
}
ms->o.buf = ms->o.pbuf = NULL;
+ ms->o.blen = 0;
len = (ms->c.len = 10) * sizeof(*ms->c.li);
if ((ms->c.li = CAST(struct level_info *, malloc(len))) == NULL)
@@ -582,6 +594,17 @@ mlist_alloc(void)
}
private void
+mlist_free_all(struct magic_set *ms)
+{
+ size_t i;
+
+ for (i = 0; i < MAGIC_SETS; i++) {
+ mlist_free(ms->mlist[i]);
+ ms->mlist[i] = NULL;
+ }
+}
+
+private void
mlist_free_one(struct mlist *ml)
{
if (ml->map)
@@ -597,9 +620,10 @@ mlist_free(struct mlist *mlist)
if (mlist == NULL)
return;
- for (ml = mlist->next; ml != mlist; ml = next) {
+ for (ml = mlist->next; ml != mlist;) {
next = ml->next;
mlist_free_one(ml);
+ ml = next;
}
mlist_free_one(mlist);
}
@@ -644,10 +668,7 @@ buffer_apprentice(struct magic_set *ms, struct magic **bufs,
return 0;
fail:
- for (i = 0; i < MAGIC_SETS; i++) {
- mlist_free(ms->mlist[i]);
- ms->mlist[i] = NULL;
- }
+ mlist_free_all(ms);
return -1;
}
#endif
@@ -658,7 +679,7 @@ file_apprentice(struct magic_set *ms, const char *fn, int action)
{
char *p, *mfn;
int fileerr, errs = -1;
- size_t i;
+ size_t i, j;
(void)file_reset(ms, 0);
@@ -676,9 +697,9 @@ file_apprentice(struct magic_set *ms, const char *fn, int action)
mlist_free(ms->mlist[i]);
if ((ms->mlist[i] = mlist_alloc()) == NULL) {
file_oomem(ms, sizeof(*ms->mlist[i]));
- while (i-- > 0) {
- mlist_free(ms->mlist[i]);
- ms->mlist[i] = NULL;
+ for (j = 0; j < i; j++) {
+ mlist_free(ms->mlist[j]);
+ ms->mlist[j] = NULL;
}
free(mfn);
return -1;
@@ -829,9 +850,14 @@ typesize(int type)
case FILE_DOUBLE:
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
+ case FILE_OFFSET:
return 8;
+
+ case FILE_GUID:
+ return 16;
+
default:
- return CAST(size_t, ~0);
+ return FILE_BADSIZE;
}
}
@@ -885,8 +911,10 @@ apprentice_magic_strength(const struct magic *m)
case FILE_DOUBLE:
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
+ case FILE_GUID:
+ case FILE_OFFSET:
ts = typesize(m->type);
- if (ts == CAST(size_t, ~0))
+ if (ts == FILE_BADSIZE)
abort();
val += ts * MULT;
break;
@@ -1077,6 +1105,8 @@ set_test_type(struct magic *mstart, struct magic *m)
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
case FILE_DER:
+ case FILE_GUID:
+ case FILE_OFFSET:
mstart->flag |= BINTEST;
break;
case FILE_STRING:
@@ -1201,7 +1231,8 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs,
continue;
}
if ((*bang[i].fun)(ms, &me,
- line + bang[i].len + 2) != 0) {
+ line + bang[i].len + 2,
+ len - bang[i].len - 2) != 0) {
(*errs)++;
continue;
}
@@ -1381,9 +1412,10 @@ apprentice_load(struct magic_set *ms, const char *fn, int action)
}
if (files >= maxfiles) {
size_t mlen;
+ char **nfilearr;
maxfiles = (maxfiles + 1) * 2;
mlen = maxfiles * sizeof(*filearr);
- if ((filearr = CAST(char **,
+ if ((nfilearr = CAST(char **,
realloc(filearr, mlen))) == NULL) {
file_oomem(ms, mlen);
free(mfn);
@@ -1391,6 +1423,7 @@ apprentice_load(struct magic_set *ms, const char *fn, int action)
errs++;
goto out;
}
+ filearr = nfilearr;
}
filearr[files++] = mfn;
}
@@ -1402,6 +1435,7 @@ apprentice_load(struct magic_set *ms, const char *fn, int action)
free(filearr[i]);
}
free(filearr);
+ filearr = NULL;
}
} else
load_1(ms, action, fn, &errs, mset);
@@ -1436,6 +1470,7 @@ apprentice_load(struct magic_set *ms, const char *fn, int action)
}
out:
+ free(filearr);
for (j = 0; j < MAGIC_SETS; j++)
magic_entry_free(mset[j].me, mset[j].count);
@@ -1499,6 +1534,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
case FILE_DOUBLE:
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
+ case FILE_OFFSET:
v = CAST(int64_t, v);
break;
case FILE_STRING:
@@ -1513,12 +1549,13 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
case FILE_USE:
case FILE_CLEAR:
case FILE_DER:
+ case FILE_GUID:
break;
default:
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "cannot happen: m->type=%d\n",
m->type);
- return ~0U;
+ return FILE_BADSIZE;
}
}
return v;
@@ -1920,6 +1957,10 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
}
/* get offset, then skip over it */
+ if (*l == '-') {
+ ++l; /* step over */
+ m->flag |= OFFNEGATIVE;
+ }
m->offset = CAST(int32_t, strtol(l, &t, 0));
if (l == t) {
if (ms->flags & MAGIC_CHECK)
@@ -2224,7 +2265,8 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
* if valid
*/
private int
-parse_strength(struct magic_set *ms, struct magic_entry *me, const char *line)
+parse_strength(struct magic_set *ms, struct magic_entry *me, const char *line,
+ size_t len __attribute__((__unused__)))
{
const char *l = line;
char *el;
@@ -2286,7 +2328,8 @@ goodchar(unsigned char x, const char *extra)
private int
parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line,
- off_t off, size_t len, const char *name, const char *extra, int nt)
+ size_t llen, off_t off, size_t len, const char *name, const char *extra,
+ int nt)
{
size_t i;
const char *l = line;
@@ -2307,7 +2350,8 @@ parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line,
}
EATAB;
- for (i = 0; *l && i < len && goodchar(*l, extra); buf[i++] = *l++)
+ for (i = 0; *l && i < llen && i < len && goodchar(*l, extra);
+ buf[i++] = *l++)
continue;
if (i == len && *l) {
@@ -2336,11 +2380,12 @@ parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line,
* magic[index - 1]
*/
private int
-parse_apple(struct magic_set *ms, struct magic_entry *me, const char *line)
+parse_apple(struct magic_set *ms, struct magic_entry *me, const char *line,
+ size_t len)
{
struct magic *m = &me->mp[0];
- return parse_extra(ms, me, line,
+ return parse_extra(ms, me, line, len,
CAST(off_t, offsetof(struct magic, apple)),
sizeof(m->apple), "APPLE", "!+-./?", 0);
}
@@ -2349,11 +2394,12 @@ parse_apple(struct magic_set *ms, struct magic_entry *me, const char *line)
* Parse a comma-separated list of extensions
*/
private int
-parse_ext(struct magic_set *ms, struct magic_entry *me, const char *line)
+parse_ext(struct magic_set *ms, struct magic_entry *me, const char *line,
+ size_t len)
{
struct magic *m = &me->mp[0];
- return parse_extra(ms, me, line,
+ return parse_extra(ms, me, line, len,
CAST(off_t, offsetof(struct magic, ext)),
sizeof(m->ext), "EXTENSION", ",!+-/@?_$", 0);
}
@@ -2363,11 +2409,12 @@ parse_ext(struct magic_set *ms, struct magic_entry *me, const char *line)
* if valid
*/
private int
-parse_mime(struct magic_set *ms, struct magic_entry *me, const char *line)
+parse_mime(struct magic_set *ms, struct magic_entry *me, const char *line,
+ size_t len)
{
struct magic *m = &me->mp[0];
- return parse_extra(ms, me, line,
+ return parse_extra(ms, me, line, len,
CAST(off_t, offsetof(struct magic, mimetype)),
sizeof(m->mimetype), "MIME", "+-/.$?:{}", 1);
}
@@ -2684,6 +2731,11 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action)
if (errno == 0)
*p = ep;
return 0;
+ case FILE_GUID:
+ if (file_parse_guid(*p, m->value.guid) == -1)
+ return -1;
+ *p += FILE_GUID_SIZE - 1;
+ return 0;
default:
errno = 0;
ull = CAST(uint64_t, strtoull(*p, &ep, 0));
@@ -2695,7 +2747,7 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action)
uint64_t x;
const char *q;
- if (ts == CAST(size_t, ~0)) {
+ if (ts == FILE_BADSIZE) {
file_magwarn(ms,
"Expected numeric type got `%s'",
type_tbl[m->type].name);
@@ -2892,8 +2944,12 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn)
out:
*p = '\0';
m->vallen = CAST(unsigned char, (p - origp));
- if (m->type == FILE_PSTRING)
- m->vallen += CAST(unsigned char, file_pstring_length_size(m));
+ if (m->type == FILE_PSTRING) {
+ size_t l = file_pstring_length_size(ms, m);
+ if (l == FILE_BADSIZE)
+ return NULL;
+ m->vallen += CAST(unsigned char, l);
+ }
return s;
}
@@ -2923,7 +2979,7 @@ file_showstr(FILE *fp, const char *s, size_t len)
char c;
for (;;) {
- if (len == ~0U) {
+ if (len == FILE_BADSIZE) {
c = *s++;
if (c == '\0')
break;
@@ -3077,13 +3133,11 @@ apprentice_map(struct magic_set *ms, const char *fn)
file_badread(ms);
goto error;
}
-#define RET 1
#endif
(void)close(fd);
fd = -1;
if (check_buffer(ms, map, dbname) != 0) {
- rv = RCAST(struct magic_map *, -1);
goto error;
}
#ifdef QUICK
@@ -3357,7 +3411,7 @@ bs1(struct magic *m)
}
protected size_t
-file_pstring_length_size(const struct magic *m)
+file_pstring_length_size(struct magic_set *ms, const struct magic *m)
{
switch (m->str_flags & PSTRING_LEN) {
case PSTRING_1_LE:
@@ -3369,12 +3423,15 @@ file_pstring_length_size(const struct magic *m)
case PSTRING_4_BE:
return 4;
default:
- abort(); /* Impossible */
- return 1;
+ file_error(ms, 0, "corrupt magic file "
+ "(bad pascal string length %d)",
+ m->str_flags & PSTRING_LEN);
+ return FILE_BADSIZE;
}
}
protected size_t
-file_pstring_get_length(const struct magic *m, const char *ss)
+file_pstring_get_length(struct magic_set *ms, const struct magic *m,
+ const char *ss)
{
size_t len = 0;
const unsigned char *s = RCAST(const unsigned char *, ss);
@@ -3409,11 +3466,18 @@ file_pstring_get_length(const struct magic *m, const char *ss)
len = (s0 << 24) | (s1 << 16) | (s2 << 8) | s3;
break;
default:
- abort(); /* Impossible */
+ file_error(ms, 0, "corrupt magic file "
+ "(bad pascal string length %d)",
+ m->str_flags & PSTRING_LEN);
+ return FILE_BADSIZE;
}
- if (m->str_flags & PSTRING_LENGTH_INCLUDES_ITSELF)
- len -= file_pstring_length_size(m);
+ if (m->str_flags & PSTRING_LENGTH_INCLUDES_ITSELF) {
+ size_t l = file_pstring_length_size(ms, m);
+ if (l == FILE_BADSIZE)
+ return l;
+ len -= l;
+ }
return len;
}