summaryrefslogtreecommitdiff
path: root/src/softmagic.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/softmagic.c')
-rw-r--r--src/softmagic.c158
1 files changed, 113 insertions, 45 deletions
diff --git a/src/softmagic.c b/src/softmagic.c
index 2edae41df4da3..95061e56fc899 100644
--- a/src/softmagic.c
+++ b/src/softmagic.c
@@ -32,7 +32,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: softmagic.c,v 1.286 2019/05/17 02:24:59 christos Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.299 2020/06/07 21:58:01 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -331,6 +331,13 @@ flush:
if (msetoffset(ms, m, &bb, b, offset, cont_level) == -1)
goto flush;
if (m->flag & OFFADD) {
+ if (cont_level == 0) {
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ fprintf(stderr,
+ "direct *zero*"
+ " cont_level\n");
+ return 0;
+ }
ms->offset +=
ms->c.li[cont_level - 1].off;
}
@@ -642,6 +649,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_QUAD:
case FILE_BEQUAD:
case FILE_LEQUAD:
+ case FILE_OFFSET:
v = file_signextend(ms, m, p->q);
switch (check_fmt(ms, desc)) {
case -1:
@@ -699,8 +707,12 @@ mprint(struct magic_set *ms, struct magic *m)
sizeof(p->s) - (str - p->s))) == -1)
return -1;
- if (m->type == FILE_PSTRING)
- t += file_pstring_length_size(m);
+ if (m->type == FILE_PSTRING) {
+ size_t l = file_pstring_length_size(ms, m);
+ if (l == FILE_BADSIZE)
+ return -1;
+ t += l;
+ }
}
break;
@@ -709,7 +721,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_LEDATE:
case FILE_MEDATE:
if (file_printf(ms, F(ms, desc, "%s"),
- file_fmttime(p->l, 0, tbuf)) == -1)
+ file_fmttime(tbuf, sizeof(tbuf), p->l, 0)) == -1)
return -1;
t = ms->offset + sizeof(uint32_t);
break;
@@ -719,7 +731,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_LELDATE:
case FILE_MELDATE:
if (file_printf(ms, F(ms, desc, "%s"),
- file_fmttime(p->l, FILE_T_LOCAL, tbuf)) == -1)
+ file_fmttime(tbuf, sizeof(tbuf), p->l, FILE_T_LOCAL)) == -1)
return -1;
t = ms->offset + sizeof(uint32_t);
break;
@@ -728,7 +740,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BEQDATE:
case FILE_LEQDATE:
if (file_printf(ms, F(ms, desc, "%s"),
- file_fmttime(p->q, 0, tbuf)) == -1)
+ file_fmttime(tbuf, sizeof(tbuf), p->q, 0)) == -1)
return -1;
t = ms->offset + sizeof(uint64_t);
break;
@@ -737,7 +749,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BEQLDATE:
case FILE_LEQLDATE:
if (file_printf(ms, F(ms, desc, "%s"),
- file_fmttime(p->q, FILE_T_LOCAL, tbuf)) == -1)
+ file_fmttime(tbuf, sizeof(tbuf), p->q, FILE_T_LOCAL)) == -1)
return -1;
t = ms->offset + sizeof(uint64_t);
break;
@@ -746,7 +758,8 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BEQWDATE:
case FILE_LEQWDATE:
if (file_printf(ms, F(ms, desc, "%s"),
- file_fmttime(p->q, FILE_T_WINDOWS, tbuf)) == -1)
+ file_fmttime(tbuf, sizeof(tbuf), p->q, FILE_T_WINDOWS))
+ == -1)
return -1;
t = ms->offset + sizeof(uint64_t);
break;
@@ -835,6 +848,12 @@ mprint(struct magic_set *ms, struct magic *m)
return -1;
t = ms->offset;
break;
+ case FILE_GUID:
+ (void) file_print_guid(buf, sizeof(buf), ms->ms_value.guid);
+ if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
+ return -1;
+ t = ms->offset;
+ break;
default:
file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
return -1;
@@ -885,9 +904,12 @@ moffset(struct magic_set *ms, struct magic *m, const struct buffer *b,
if (*m->value.s == '\0')
p->s[strcspn(p->s, "\r\n")] = '\0';
o = CAST(uint32_t, (ms->offset + strlen(p->s)));
- if (m->type == FILE_PSTRING)
- o += CAST(uint32_t,
- file_pstring_length_size(m));
+ if (m->type == FILE_PSTRING) {
+ size_t l = file_pstring_length_size(ms, m);
+ if (l == FILE_BADSIZE)
+ return -1;
+ o += CAST(uint32_t, l);
+ }
}
break;
@@ -947,23 +969,26 @@ moffset(struct magic_set *ms, struct magic *m, const struct buffer *b,
case FILE_CLEAR:
case FILE_DEFAULT:
case FILE_INDIRECT:
+ case FILE_OFFSET:
o = ms->offset;
break;
case FILE_DER:
- {
- o = der_offs(ms, m, nbytes);
- if (o == -1 || CAST(size_t, o) > nbytes) {
- if ((ms->flags & MAGIC_DEBUG) != 0) {
- (void)fprintf(stderr,
- "Bad DER offset %d nbytes=%"
- SIZE_T_FORMAT "u", o, nbytes);
- }
- *op = 0;
- return 0;
+ o = der_offs(ms, m, nbytes);
+ if (o == -1 || CAST(size_t, o) > nbytes) {
+ if ((ms->flags & MAGIC_DEBUG) != 0) {
+ (void)fprintf(stderr,
+ "Bad DER offset %d nbytes=%"
+ SIZE_T_FORMAT "u", o, nbytes);
}
- break;
+ *op = 0;
+ return 0;
}
+ break;
+
+ case FILE_GUID:
+ o = CAST(int32_t, (ms->offset + 2 * sizeof(uint64_t)));
+ break;
default:
o = 0;
@@ -1168,6 +1193,7 @@ mconvert(struct magic_set *ms, struct magic *m, int flip)
case FILE_QDATE:
case FILE_QLDATE:
case FILE_QWDATE:
+ case FILE_OFFSET:
if (cvt_64(p, m) == -1)
goto out;
return 1;
@@ -1179,9 +1205,15 @@ mconvert(struct magic_set *ms, struct magic *m, int flip)
return 1;
}
case FILE_PSTRING: {
- size_t sz = file_pstring_length_size(m);
- char *ptr1 = p->s, *ptr2 = ptr1 + sz;
- size_t len = file_pstring_get_length(m, ptr1);
+ char *ptr1, *ptr2;
+ size_t len, sz = file_pstring_length_size(ms, m);
+ if (sz == FILE_BADSIZE)
+ return 0;
+ ptr1 = p->s;
+ ptr2 = ptr1 + sz;
+ len = file_pstring_get_length(ms, m, ptr1);
+ if (len == FILE_BADSIZE)
+ return 0;
sz = sizeof(p->s) - sz; /* maximum length of string */
if (len >= sz) {
/*
@@ -1281,6 +1313,7 @@ mconvert(struct magic_set *ms, struct magic *m, int flip)
case FILE_NAME:
case FILE_USE:
case FILE_DER:
+ case FILE_GUID:
return 1;
default:
file_magerror(ms, "invalid type %d in mconvert()", m->type);
@@ -1407,6 +1440,12 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
}
}
+ if (type == FILE_OFFSET) {
+ (void)memset(p, '\0', sizeof(*p));
+ p->q = offset;
+ return 0;
+ }
+
if (offset >= nbytes) {
(void)memset(p, '\0', sizeof(*p));
return 0;
@@ -1471,7 +1510,9 @@ private int
msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb,
const struct buffer *b, size_t o, unsigned int cont_level)
{
- if (m->offset < 0) {
+ int32_t offset;
+ if (m->flag & OFFNEGATIVE) {
+ offset = -m->offset;
if (cont_level > 0) {
if (m->flag & (OFFADD|INDIROFFADD))
goto normal;
@@ -1489,26 +1530,28 @@ msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb,
"u at level %u", o, cont_level);
return -1;
}
- if (CAST(size_t, -m->offset) > b->elen)
+ if (CAST(size_t, m->offset) > b->elen)
return -1;
buffer_init(bb, -1, NULL, b->ebuf, b->elen);
- ms->eoffset = ms->offset = CAST(int32_t, b->elen + m->offset);
+ ms->eoffset = ms->offset = CAST(int32_t, b->elen - m->offset);
} else {
+ offset = m->offset;
if (cont_level == 0) {
normal:
// XXX: Pass real fd, then who frees bb?
buffer_init(bb, -1, NULL, b->fbuf, b->flen);
- ms->offset = m->offset;
+ ms->offset = offset;
ms->eoffset = 0;
} else {
- ms->offset = ms->eoffset + m->offset;
+ ms->offset = ms->eoffset + offset;
}
}
if ((ms->flags & MAGIC_DEBUG) != 0) {
- fprintf(stderr, "bb=[%p,%" SIZE_T_FORMAT "u], %d [b=%p,%"
- SIZE_T_FORMAT "u], [o=%#x, c=%d]\n",
- bb->fbuf, bb->flen, ms->offset, b->fbuf, b->flen,
- m->offset, cont_level);
+ fprintf(stderr, "bb=[%p,%" SIZE_T_FORMAT "u,%"
+ SIZE_T_FORMAT "u], %d [b=%p,%"
+ SIZE_T_FORMAT "u,%" SIZE_T_FORMAT "u], [o=%#x, c=%d]\n",
+ bb->fbuf, bb->flen, bb->elen, ms->offset, b->fbuf,
+ b->flen, b->elen, offset, cont_level);
}
return 0;
}
@@ -1566,7 +1609,8 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
if (m->in_op & FILE_OPINDIRECT) {
const union VALUETYPE *q = CAST(const union VALUETYPE *,
RCAST(const void *, s + offset + off));
- switch (cvt_flip(m->in_type, flip)) {
+ int op;
+ switch (op = cvt_flip(m->in_type, flip)) {
case FILE_BYTE:
if (OFFSET_OOB(nbytes, offset + off, 1))
return 0;
@@ -1620,7 +1664,9 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
off = SEXT(sgn,64,LE64(q));
break;
default:
- abort();
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ fprintf(stderr, "bad op=%d\n", op);
+ return 0;
}
if ((ms->flags & MAGIC_DEBUG) != 0)
fprintf(stderr, "indirect offs=%jd\n", off);
@@ -1685,11 +1731,19 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
offset = do_ops(m, SEXT(sgn,64,BE64(p)), off);
break;
default:
- abort();
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ fprintf(stderr, "bad in_type=%d\n", in_type);
+ return 0;
}
if (m->flag & INDIROFFADD) {
- offset += ms->c.li[cont_level-1].off;
+ if (cont_level == 0) {
+ if ((ms->flags & MAGIC_DEBUG) != 0)
+ fprintf(stderr,
+ "indirect *zero* cont_level\n");
+ return 0;
+ }
+ offset += ms->c.li[cont_level - 1].off;
if (offset == 0) {
if ((ms->flags & MAGIC_DEBUG) != 0)
fprintf(stderr,
@@ -1752,6 +1806,11 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
return 0;
break;
+ case FILE_GUID:
+ if (OFFSET_OOB(nbytes, offset, 16))
+ return 0;
+ break;
+
case FILE_STRING:
case FILE_PSTRING:
case FILE_SEARCH:
@@ -1847,7 +1906,8 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
}
private uint64_t
-file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
+file_strncmp(const char *s1, const char *s2, size_t len, size_t maxlen,
+ uint32_t flags)
{
/*
* Convert the source args to unsigned here so that (1) the
@@ -1857,7 +1917,9 @@ file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
*/
const unsigned char *a = RCAST(const unsigned char *, s1);
const unsigned char *b = RCAST(const unsigned char *, s2);
- const unsigned char *eb = b + len;
+ uint32_t ws = flags & (STRING_COMPACT_WHITESPACE |
+ STRING_COMPACT_OPTIONAL_WHITESPACE);
+ const unsigned char *eb = b + (ws ? maxlen : len);
uint64_t v;
/*
@@ -1915,7 +1977,8 @@ file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
}
private uint64_t
-file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags)
+file_strncmp16(const char *a, const char *b, size_t len, size_t maxlen,
+ uint32_t flags)
{
/*
* XXX - The 16-bit string compare probably needs to be done
@@ -1923,7 +1986,7 @@ file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags)
* At the moment, I am unsure.
*/
flags = 0;
- return file_strncmp(a, b, len, flags);
+ return file_strncmp(a, b, len, maxlen, flags);
}
private int
@@ -1974,6 +2037,7 @@ magiccheck(struct magic_set *ms, struct magic *m)
case FILE_QWDATE:
case FILE_BEQWDATE:
case FILE_LEQWDATE:
+ case FILE_OFFSET:
v = p->q;
break;
@@ -2052,14 +2116,14 @@ magiccheck(struct magic_set *ms, struct magic *m)
case FILE_PSTRING:
l = 0;
v = file_strncmp(m->value.s, p->s, CAST(size_t, m->vallen),
- m->str_flags);
+ sizeof(p->s), m->str_flags);
break;
case FILE_BESTRING16:
case FILE_LESTRING16:
l = 0;
v = file_strncmp16(m->value.s, p->s, CAST(size_t, m->vallen),
- m->str_flags);
+ sizeof(p->s), m->str_flags);
break;
case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
@@ -2094,7 +2158,7 @@ magiccheck(struct magic_set *ms, struct magic *m)
return 0;
v = file_strncmp(m->value.s, ms->search.s + idx, slen,
- m->str_flags);
+ ms->search.s_len - idx, m->str_flags);
if (v == 0) { /* found match */
ms->search.offset += idx;
ms->search.rm_len = ms->search.s_len - idx;
@@ -2179,6 +2243,10 @@ magiccheck(struct magic_set *ms, struct magic *m)
return 0;
}
return matched;
+ case FILE_GUID:
+ l = 0;
+ v = memcmp(m->value.guid, p->guid, sizeof(p->guid));
+ break;
default:
file_magerror(ms, "invalid type %d in magiccheck()", m->type);
return -1;