diff options
Diffstat (limited to 'src/apprentice.c')
-rw-r--r-- | src/apprentice.c | 152 |
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; } |