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;  } | 
