summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnon Ymous <ljt@astron.com>2007-01-16 14:58:48 +0000
committerAnon Ymous <ljt@astron.com>2007-01-16 14:58:48 +0000
commit5de6f2282209db98b4e8b90a4acfef9e9f6a5cd8 (patch)
tree83945b71129d1e4e5133b9a0251a25a1f60db870 /src
parente94fb095bc0cc14a72a7d075865fa0f1c2bb80b3 (diff)
downloadfile-git-5de6f2282209db98b4e8b90a4acfef9e9f6a5cd8.tar.gz
1) Add a "default" type to print a message if nothing previously
matched at that level or since the last default at that level. This is useful for setting up switch-like statements. It can also be used to do if/else constructions without a redundant second test. 2) Fix the "x" special case test so that one can test for that string with "=x". 3) Allow "search" to search the entire buffer if the "/N" search count is missing. 4) Make "regex" work! It now starts its search at the specified offset and takes an (optional) "/N" line count to specify the search range; otherwise it searches to the end of the file. The match is now grabbed correctly for format strings and the offset set to the end of the match. 5) Add a "/s" flag to "regex" and "search" to set the offset to the start of the match. By default the offset is set to the end of the match, as it is with other tests. This is mostly useful for "regex". 6) Make "search", "string" and "pstring" use the same file_strncmp() routine so that they support the same flags; "bestring16" and "lestring16" call the same routine, but with flags = 0. Also add a "/C" flag (in analogy to "/c") to ignore the case on uppercase (lowercase) characters in the test string. 7) Strict adherence to C style string escapes. A warnings are printed when compiling. Note: previously "\a" was incorrectly translated to 'a' instead of an <alert> (i.e., BELL, typically 0x07). 8) Make this compile with "-Wall -Wextra" and all the warning flags used with WARNS=4 in the NetBSD source. Also make it pass lint. 9) Many "cleanups" and hopefully not too many new bugs!
Diffstat (limited to 'src')
-rw-r--r--src/apprentice.c333
-rw-r--r--src/file.h163
-rw-r--r--src/funcs.c42
-rw-r--r--src/magic.c10
-rw-r--r--src/print.c52
-rw-r--r--src/softmagic.c693
6 files changed, 827 insertions, 466 deletions
diff --git a/src/apprentice.c b/src/apprentice.c
index 4040b739..e80e7dde 100644
--- a/src/apprentice.c
+++ b/src/apprentice.c
@@ -46,7 +46,7 @@
#endif
#ifndef lint
-FILE_RCSID("@(#)$File: apprentice.c,v 1.100 2006/12/11 21:48:49 christos Exp $")
+FILE_RCSID("@(#)$File: apprentice.c,v 1.101 2007/01/12 17:38:27 christos Exp $")
#endif /* lint */
#define EATAB {while (isascii((unsigned char) *l) && \
@@ -75,12 +75,6 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.100 2006/12/11 21:48:49 christos Exp $")
#define MAXPATHLEN 1024
#endif
-#define IS_PLAINSTRING(t) ((t) == FILE_STRING || (t) == FILE_PSTRING || \
- (t) == FILE_BESTRING16 || (t) == FILE_LESTRING16)
-
-#define IS_STRING(t) (IS_PLAINSTRING(t) || (t) == FILE_REGEX || \
- (t) == FILE_SEARCH)
-
struct magic_entry {
struct magic *mp;
uint32_t cont_count;
@@ -92,10 +86,10 @@ const size_t file_nformats = sizeof(file_formats) / sizeof(file_formats[0]);
const char *file_names[] = { FILE_FORMAT_NAME };
const size_t file_nnames = sizeof(file_names) / sizeof(file_names[0]);
-private int getvalue(struct magic_set *ms, struct magic *, const char **);
+private int getvalue(struct magic_set *ms, struct magic *, const char **, int);
private int hextoint(int);
private const char *getstr(struct magic_set *, const char *, char *, int,
- int *);
+ int *, int);
private int parse(struct magic_set *, struct magic_entry **, uint32_t *,
const char *, size_t, int);
private void eatsize(const char **);
@@ -316,6 +310,9 @@ apprentice_magic_strength(const struct magic *m)
size_t val = 2 * MULT; /* baseline strength */
switch (m->type) {
+ case FILE_DEFAULT: /* make sure this sorts last */
+ return 0;
+
case FILE_BYTE:
val += 1 * MULT;
break;
@@ -401,6 +398,10 @@ apprentice_magic_strength(const struct magic *m)
(void)fprintf(stderr, "Bad relation %c\n", m->reln);
abort();
}
+
+ if (val == 0) /* ensure we only return 0 for FILE_DEFAULT */
+ val = 1;
+
return val;
}
@@ -485,6 +486,23 @@ apprentice_file(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
#ifndef NOORDER
qsort(marray, marraycount, sizeof(*marray), apprentice_sort);
+ /*
+ * Make sure that any level 0 "default" line is last (if one exists).
+ */
+ for (i = 0; i < marraycount; i++) {
+ if (marray[i].mp->cont_level == 0 &&
+ marray[i].mp->type == FILE_DEFAULT) {
+ while (++i < marraycount)
+ if (marray[i].mp->cont_level == 0)
+ break;
+ if (i != marraycount) {
+ ms->line = marray[i].mp->lineno; /* XXX - Ugh! */
+ file_magwarn(ms,
+ "level 0 \"default\" did not sort last");
+ }
+ break;
+ }
+ }
#endif
for (i = 0; i < marraycount; i++)
@@ -523,7 +541,7 @@ out:
protected uint64_t
file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
{
- if (!(m->flag & UNSIGNED))
+ if (!(m->flag & UNSIGNED)) {
switch(m->type) {
/*
* Do not remove the casts below. They are
@@ -569,6 +587,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
case FILE_LESTRING16:
case FILE_REGEX:
case FILE_SEARCH:
+ case FILE_DEFAULT:
break;
default:
if (ms->flags & MAGIC_CHECK)
@@ -576,9 +595,79 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
m->type);
return ~0U;
}
+ }
return v;
}
+private int
+string_modifier_check(struct magic_set *ms, struct magic const *m)
+{
+ if ((ms->flags & MAGIC_CHECK) == 0)
+ return 0;
+
+ switch (m->type) {
+ case FILE_BESTRING16:
+ case FILE_LESTRING16:
+ if (m->str_flags != 0) {
+ file_magwarn(ms, "no modifiers allowed for 16-bit strings\n");
+ return -1;
+ }
+ break;
+ case FILE_STRING:
+ case FILE_PSTRING:
+ if ((m->str_flags & REGEX_OFFSET_START) != 0) {
+ file_magwarn(ms, "'/%c' only allowed on regex and search\n",
+ CHAR_REGEX_OFFSET_START);
+ return -1;
+ }
+ break;
+ case FILE_SEARCH:
+ break;
+ case FILE_REGEX:
+ if ((m->str_flags & STRING_COMPACT_BLANK) != 0) {
+ file_magwarn(ms, "'/%c' not allowed on regex\n",
+ CHAR_COMPACT_BLANK);
+ return -1;
+ }
+ if ((m->str_flags & STRING_COMPACT_OPTIONAL_BLANK) != 0) {
+ file_magwarn(ms, "'/%c' not allowed on regex\n",
+ CHAR_COMPACT_OPTIONAL_BLANK);
+ return -1;
+ }
+ break;
+ default:
+ file_magwarn(ms, "coding error: m->type=%d\n",
+ m->type);
+ return -1;
+ }
+ return 0;
+}
+
+private int
+get_op(char c)
+{
+ switch (c) {
+ case '&':
+ return FILE_OPAND;
+ case '|':
+ return FILE_OPOR;
+ case '^':
+ return FILE_OPXOR;
+ case '+':
+ return FILE_OPADD;
+ case '-':
+ return FILE_OPMINUS;
+ case '*':
+ return FILE_OPMULTIPLY;
+ case '/':
+ return FILE_OPDIVIDE;
+ case '%':
+ return FILE_OPMODULO;
+ default:
+ return -1;
+ }
+}
+
/*
* parse one line from magic file, put into magic[index++] if valid
*/
@@ -591,8 +680,7 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
struct magic *m;
const char *l = line;
char *t;
- private const char *fops = FILE_OPS;
- uint64_t val;
+ int op;
uint32_t cont_level;
cont_level = 0;
@@ -622,7 +710,7 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
me->max_count = cnt;
}
m = &me->mp[me->cont_count++];
- memset(m, 0, sizeof(*m));
+ (void)memset(m, 0, sizeof(*m));
m->cont_level = cont_level;
} else {
if (*nmentryp == maxmagic) {
@@ -648,26 +736,31 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
me->max_count = ALLOC_CHUNK;
} else
m = me->mp;
- memset(m, 0, sizeof(*m));
+ (void)memset(m, 0, sizeof(*m));
m->cont_level = 0;
me->cont_count = 1;
}
m->lineno = lineno;
- if (m->cont_level != 0 && *l == '&') {
+ if (*l == '&') { /* m->cont_level == 0 checked below. */
++l; /* step over */
m->flag |= OFFADD;
}
- if (m->cont_level != 0 && *l == '(') {
+ if (*l == '(') {
++l; /* step over */
m->flag |= INDIR;
if (m->flag & OFFADD)
m->flag = (m->flag & ~OFFADD) | INDIROFFADD;
+
+ if (*l == '&') { /* m->cont_level == 0 checked below */
+ ++l; /* step over */
+ m->flag |= OFFADD;
+ }
}
- if (m->cont_level != 0 && *l == '&') {
- ++l; /* step over */
- m->flag |= OFFADD;
- }
+ /* Indirect offsets are not valid at level 0. */
+ if (m->cont_level == 0 && (m->flag & (OFFADD | INDIROFFADD)))
+ if (ms->flags & MAGIC_CHECK)
+ file_magwarn(ms, "relative offset at level 0");
/* get offset, then skip over it */
m->offset = (uint32_t)strtoul(l, &t, 0);
@@ -717,43 +810,15 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
}
l++;
}
+
+ m->in_op = 0;
if (*l == '~') {
m->in_op |= FILE_OPINVERSE;
l++;
}
- switch (*l) {
- case '&':
- m->in_op |= FILE_OPAND;
- l++;
- break;
- case '|':
- m->in_op |= FILE_OPOR;
+ if ((op = get_op(*l)) != -1) {
+ m->in_op |= op;
l++;
- break;
- case '^':
- m->in_op |= FILE_OPXOR;
- l++;
- break;
- case '+':
- m->in_op |= FILE_OPADD;
- l++;
- break;
- case '-':
- m->in_op |= FILE_OPMINUS;
- l++;
- break;
- case '*':
- m->in_op |= FILE_OPMULTIPLY;
- l++;
- break;
- case '/':
- m->in_op |= FILE_OPDIVIDE;
- l++;
- break;
- case '%':
- m->in_op |= FILE_OPMODULO;
- l++;
- break;
}
if (*l == '(') {
m->in_op |= FILE_OPINDIRECT;
@@ -761,6 +826,10 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
}
if (isdigit((unsigned char)*l) || *l == '-') {
m->in_offset = (int32_t)strtol(l, &t, 0);
+ if (l == t)
+ if (ms->flags & MAGIC_CHECK)
+ file_magwarn(ms,
+ "in_offset `%s' invalid", l);
l = t;
}
if (*l++ != ')' ||
@@ -769,10 +838,6 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
file_magwarn(ms,
"missing ')' in indirect offset");
}
-
-
- while (isascii((unsigned char)*l) && isdigit((unsigned char)*l))
- ++l;
EATAB;
if (*l == 'u') {
@@ -794,36 +859,64 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
file_magwarn(ms, "type `%s' invalid", l);
return -1;
}
+
/* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */
/* New and improved: ~ & | ^ + - * / % -- exciting, isn't it? */
+
+ m->mask_op = 0;
if (*l == '~') {
if (!IS_STRING(m->type))
m->mask_op |= FILE_OPINVERSE;
+ else if (ms->flags & MAGIC_CHECK)
+ file_magwarn(ms, "'~' invalid for string types");
++l;
}
- if ((t = strchr(fops, *l)) != NULL) {
- uint32_t op = (uint32_t)(t - fops);
- if (op != FILE_OPDIVIDE || !IS_PLAINSTRING(m->type)) {
+ m->str_count = 0;
+ m->str_flags = 0;
+ m->num_mask = 0;
+ if ((op = get_op(*l)) != -1) {
+ if (!IS_STRING(m->type)) {
+ uint64_t val;
++l;
m->mask_op |= op;
val = (uint64_t)strtoull(l, &t, 0);
l = t;
- m->mask = file_signextend(ms, m, val);
+ m->num_mask = file_signextend(ms, m, val);
eatsize(&l);
- } else {
- m->mask = 0L;
+ }
+ else if (op == FILE_OPDIVIDE) {
+ int have_count = 0;
while (!isspace((unsigned char)*++l)) {
switch (*l) {
- case CHAR_IGNORE_LOWERCASE:
- m->mask |= STRING_IGNORE_LOWERCASE;
+ /* for portability avoid "case '0' ... '9':" */
+ case '0': case '1': case '2':
+ case '3': case '4': case '5':
+ case '6': case '7': case '8':
+ case '9': {
+ if (have_count && ms->flags & MAGIC_CHECK)
+ file_magwarn(ms,
+ "multiple counts");
+ have_count = 1;
+ m->str_count = strtoul(l, &t, 0);
+ l = t - 1;
break;
+ }
case CHAR_COMPACT_BLANK:
- m->mask |= STRING_COMPACT_BLANK;
+ m->str_flags |= STRING_COMPACT_BLANK;
break;
case CHAR_COMPACT_OPTIONAL_BLANK:
- m->mask |=
+ m->str_flags |=
STRING_COMPACT_OPTIONAL_BLANK;
break;
+ case CHAR_IGNORE_LOWERCASE:
+ m->str_flags |= STRING_IGNORE_LOWERCASE;
+ break;
+ case CHAR_IGNORE_UPPERCASE:
+ m->str_flags |= STRING_IGNORE_UPPERCASE;
+ break;
+ case CHAR_REGEX_OFFSET_START:
+ m->str_flags |= REGEX_OFFSET_START;
+ break;
default:
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms,
@@ -831,8 +924,17 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
*l);
return -1;
}
+ /* allow multiple '/' for readability */
+ if (l[1] == '/' && !isspace((unsigned char)l[2]))
+ l++;
}
- ++l;
+ if (string_modifier_check(ms, m) == -1)
+ return -1;
+ }
+ else {
+ if (ms->flags & MAGIC_CHECK)
+ file_magwarn(ms, "invalid string op: %c", *t);
+ return -1;
}
}
/*
@@ -860,19 +962,20 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
++l;
break;
default:
+ m->reln = '='; /* the default relation */
if (*l == 'x' && ((isascii((unsigned char)l[1]) &&
isspace((unsigned char)l[1])) || !l[1])) {
m->reln = *l;
++l;
- goto GetDesc; /* Bill The Cat */
}
- m->reln = '=';
break;
}
- EATAB;
-
- if (getvalue(ms, m, &l))
+ /*
+ * Grab the value part, except for an 'x' reln.
+ */
+ if (m->reln != 'x' && getvalue(ms, m, &l, action))
return -1;
+
/*
* TODO finish this macro and start using it!
* #define offsetcheck {if (offset > HOWMANY-1)
@@ -880,9 +983,8 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
*/
/*
- * now get last part - the description
+ * Now get last part - the description
*/
-GetDesc:
EATAB;
if (l[0] == '\b') {
++l;
@@ -1078,7 +1180,7 @@ check_format(struct magic_set *ms, struct magic *m)
* just after the number read. Return 0 for success, non-zero for failure.
*/
private int
-getvalue(struct magic_set *ms, struct magic *m, const char **p)
+getvalue(struct magic_set *ms, struct magic *m, const char **p, int action)
{
int slen;
@@ -1089,7 +1191,7 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p)
case FILE_PSTRING:
case FILE_REGEX:
case FILE_SEARCH:
- *p = getstr(ms, *p, m->value.s, sizeof(m->value.s), &slen);
+ *p = getstr(ms, *p, m->value.s, sizeof(m->value.s), &slen, action);
if (*p == NULL) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "cannot get string from `%s'",
@@ -1117,7 +1219,7 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p)
* Return updated scan pointer as function result.
*/
private const char *
-getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen)
+getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen, int action)
{
const char *origs = s;
char *origp = p;
@@ -1132,16 +1234,38 @@ getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen)
file_error(ms, 0, "string too long: `%s'", origs);
return NULL;
}
- if(c == '\\') {
+ if (c == '\\') {
switch(c = *s++) {
case '\0':
+ if (action == FILE_COMPILE)
+ file_magwarn(ms, "incomplete escape");
goto out;
default:
+ if (action == FILE_COMPILE)
+ file_magwarn(ms,
+ "unknown escape sequence: \\%03o", c);
+ /*FALLTHROUGH*/
+ case '\'':
+ case '"':
+ case '?':
+ case '\\':
*p++ = (char) c;
break;
+ case 'a':
+ *p++ = '\a';
+ break;
+
+ case 'b':
+ *p++ = '\b';
+ break;
+
+ case 'f':
+ *p++ = '\f';
+ break;
+
case 'n':
*p++ = '\n';
break;
@@ -1150,18 +1274,10 @@ getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen)
*p++ = '\r';
break;
- case 'b':
- *p++ = '\b';
- break;
-
case 't':
*p++ = '\t';
break;
- case 'f':
- *p++ = '\f';
- break;
-
case 'v':
*p++ = '\v';
break;
@@ -1177,11 +1293,11 @@ getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen)
case '7':
val = c - '0';
c = *s++; /* try for 2 */
- if(c >= '0' && c <= '7') {
- val = (val<<3) | (c - '0');
+ if (c >= '0' && c <= '7') {
+ val = (val << 3) | (c - '0');
c = *s++; /* try for 3 */
- if(c >= '0' && c <= '7')
- val = (val<<3) | (c-'0');
+ if (c >= '0' && c <= '7')
+ val = (val << 3) | (c-'0');
else
--s;
}
@@ -1224,9 +1340,9 @@ hextoint(int c)
return -1;
if (isdigit((unsigned char) c))
return c - '0';
- if ((c >= 'a')&&(c <= 'f'))
+ if ((c >= 'a') && (c <= 'f'))
return c + 10 - 'a';
- if (( c>= 'A')&&(c <= 'F'))
+ if (( c>= 'A') && (c <= 'F'))
return c + 10 - 'A';
return -1;
}
@@ -1250,12 +1366,23 @@ file_showstr(FILE *fp, const char *s, size_t len)
if (len-- == 0)
break;
}
- if(c >= 040 && c <= 0176) /* TODO isprint && !iscntrl */
+ if (c >= 040 && c <= 0176) /* TODO isprint && !iscntrl */
(void) fputc(c, fp);
else {
(void) fputc('\\', fp);
switch (c) {
-
+ case '\a':
+ (void) fputc('a', fp);
+ break;
+
+ case '\b':
+ (void) fputc('b', fp);
+ break;
+
+ case '\f':
+ (void) fputc('f', fp);
+ break;
+
case '\n':
(void) fputc('n', fp);
break;
@@ -1264,18 +1391,10 @@ file_showstr(FILE *fp, const char *s, size_t len)
(void) fputc('r', fp);
break;
- case '\b':
- (void) fputc('b', fp);
- break;
-
case '\t':
(void) fputc('t', fp);
break;
- case '\f':
- (void) fputc('f', fp);
- break;
-
case '\v':
(void) fputc('v', fp);
break;
@@ -1536,7 +1655,13 @@ bs1(struct magic *m)
m->cont_level = swap2(m->cont_level);
m->offset = swap4((uint32_t)m->offset);
m->in_offset = swap4((uint32_t)m->in_offset);
- if (!IS_STRING(m->type))
+ m->lineno = swap4((uint32_t)m->lineno);
+ if (IS_STRING(m->type)) {
+ m->str_count = swap4(m->str_count);
+ m->str_flags = swap4(m->str_flags);
+ }
+ else {
m->value.q = swap8(m->value.q);
- m->mask = swap8(m->mask);
+ m->num_mask = swap8(m->num_mask);
+ }
}
diff --git a/src/file.h b/src/file.h
index 3aa02f57..53f815a7 100644
--- a/src/file.h
+++ b/src/file.h
@@ -27,7 +27,7 @@
*/
/*
* file.h - definitions for file(1) program
- * @(#)$File: file.h,v 1.83 2006/12/11 21:48:49 christos Exp $
+ * @(#)$File: file.h,v 1.84 2007/01/12 17:38:28 christos Exp $
*/
#ifndef __file_h__
@@ -46,6 +46,7 @@
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
+#include <regex.h>
#include <sys/types.h>
/* Do this here and now, because struct stat gets re-defined on solaris */
#include <sys/stat.h>
@@ -66,6 +67,28 @@
#endif
#define public
+#ifndef __GNUC_PREREQ__
+#ifdef __GNUC__
+#define __GNUC_PREREQ__(x, y) \
+ ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \
+ (__GNUC__ > (x)))
+#else
+#define __GNUC_PREREQ__(x, y) 0
+#endif
+#endif
+
+#ifndef __unused
+#if __GNUC_PREREQ__(2, 7)
+#define __unused __attribute__((__unused__))
+#else
+#define __unused /* delete */
+#endif
+#endif
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
#ifndef HOWMANY
# define HOWMANY (256 * 1024) /* how much of the file to look at */
#endif
@@ -74,7 +97,7 @@
#define MAXstring 32 /* max leng of "string" types */
#define MAGICNO 0xF11E041C
-#define VERSIONNO 3
+#define VERSIONNO 4
#define FILE_MAGICSIZE (32 * 4)
#define FILE_LOAD 0
@@ -86,10 +109,10 @@ struct magic {
uint16_t cont_level; /* level of ">" */
uint8_t nospflag; /* supress space character */
uint8_t flag;
-#define INDIR 1 /* if '>(...)' appears, */
-#define UNSIGNED 2 /* comparison is unsigned */
-#define OFFADD 4 /* if '>&' appears, */
-#define INDIROFFADD 8 /* if '>&(' appears, */
+#define INDIR 1 /* if '(...)' appears */
+#define OFFADD 2 /* if '>&' or '>...(&' appears */
+#define INDIROFFADD 4 /* if '>&(' appears */
+#define UNSIGNED 8 /* comparison is unsigned */
/* Word 2 */
uint8_t reln; /* relation (0=eq, '>'=gt, etc) */
uint8_t vallen; /* length of string value, if any */
@@ -97,6 +120,7 @@ struct magic {
uint8_t in_type; /* type of indirrection */
#define FILE_BYTE 1
#define FILE_SHORT 2
+#define FILE_DEFAULT 3
#define FILE_LONG 4
#define FILE_STRING 5
#define FILE_DATE 6
@@ -127,11 +151,23 @@ struct magic {
#define FILE_LEQLDATE 31
#define FILE_BEQLDATE 32
+#define IS_PLAINSTRING(t) \
+ ((t) == FILE_STRING || \
+ (t) == FILE_PSTRING || \
+ (t) == FILE_BESTRING16 || \
+ (t) == FILE_LESTRING16)
+
+#define IS_STRING(t) \
+ (IS_PLAINSTRING(t) || \
+ (t) == FILE_REGEX || \
+ (t) == FILE_SEARCH || \
+ (t) == FILE_DEFAULT)
+
#define FILE_FORMAT_NAME \
/* 0 */ "invalid 0", \
/* 1 */ "byte", \
/* 2 */ "short", \
-/* 3 */ "invalid 3", \
+/* 3 */ "default", \
/* 4 */ "long", \
/* 5 */ "string", \
/* 6 */ "date", \
@@ -162,7 +198,6 @@ struct magic {
/* 31 */ "leqldate", \
/* 32 */ "beqldate",
-
#define FILE_FMT_NONE 0
#define FILE_FMT_NUM 1 /* "cduxXi" */
#define FILE_FMT_STR 2 /* "s" */
@@ -172,7 +207,7 @@ struct magic {
/* 0 */ FILE_FMT_NONE, \
/* 1 */ FILE_FMT_NUM, \
/* 2 */ FILE_FMT_NUM, \
-/* 3 */ FILE_FMT_NONE, \
+/* 3 */ FILE_FMT_STR, \
/* 4 */ FILE_FMT_NUM, \
/* 5 */ FILE_FMT_STR, \
/* 6 */ FILE_FMT_STR, \
@@ -203,12 +238,12 @@ struct magic {
/* 31 */ FILE_FMT_STR, \
/* 32 */ FILE_FMT_STR,
-
/* Word 3 */
uint8_t in_op; /* operator for indirection */
uint8_t mask_op; /* operator for mask */
uint8_t dummy1;
uint8_t dummy2;
+
#define FILE_OPS "&|^+-*/%"
#define FILE_OPAND 0
#define FILE_OPOR 1
@@ -218,8 +253,13 @@ struct magic {
#define FILE_OPMULTIPLY 5
#define FILE_OPDIVIDE 6
#define FILE_OPMODULO 7
+#define FILE_OPS_MASK 0x07 /* mask for above ops */
+#define FILE_UNUSED_1 0x08
+#define FILE_UNUSED_2 0x10
+#define FILE_UNUSED_3 0x20
#define FILE_OPINVERSE 0x40
#define FILE_OPINDIRECT 0x80
+
/* Word 4 */
uint32_t offset; /* offset to magic number */
/* Word 5 */
@@ -227,33 +267,46 @@ struct magic {
/* Word 6 */
uint32_t lineno; /* line number in magic file */
/* Word 7,8 */
- uint64_t mask; /* mask before comparison with value */
+ union {
+ uint64_t _mask; /* for use with numeric and date types */
+ struct {
+ uint32_t _count; /* repeat/line count */
+ uint32_t _flags; /* modifier flags */
+ } _s; /* for use with string types */
+ } _u;
+#define num_mask _u._mask
+#define str_count _u._s._count
+#define str_flags _u._s._flags
+
/* Words 9-16 */
union VALUETYPE {
- uint8_t b;
- uint16_t h;
- uint32_t l;
- uint64_t q;
- char s[MAXstring];
- struct {
- char *buf;
- size_t buflen;
- } search;
- uint8_t hs[2]; /* 2 bytes of a fixed-endian "short" */
- uint8_t hl[4]; /* 4 bytes of a fixed-endian "long" */
- uint8_t hq[8]; /* 8 bytes of a fixed-endian "quad" */
+// union NUMTYPE {
+ uint8_t b;
+ uint16_t h;
+ uint32_t l;
+ uint64_t q;
+ uint8_t hs[2]; /* 2 bytes of a fixed-endian "short" */
+ uint8_t hl[4]; /* 4 bytes of a fixed-endian "long" */
+ uint8_t hq[8]; /* 8 bytes of a fixed-endian "quad" */
+// } n;
+ char s[MAXstring]; /* the search string or regex pattern */
} value; /* either number or string */
/* Words 17..31 */
char desc[MAXDESC]; /* description */
};
#define BIT(A) (1 << (A))
-#define STRING_IGNORE_LOWERCASE BIT(0)
-#define STRING_COMPACT_BLANK BIT(1)
-#define STRING_COMPACT_OPTIONAL_BLANK BIT(2)
-#define CHAR_IGNORE_LOWERCASE 'c'
+#define STRING_COMPACT_BLANK BIT(0)
+#define STRING_COMPACT_OPTIONAL_BLANK BIT(1)
+#define STRING_IGNORE_LOWERCASE BIT(2)
+#define STRING_IGNORE_UPPERCASE BIT(3)
+#define REGEX_OFFSET_START BIT(4)
#define CHAR_COMPACT_BLANK 'B'
#define CHAR_COMPACT_OPTIONAL_BLANK 'b'
+#define CHAR_IGNORE_LOWERCASE 'c'
+#define CHAR_IGNORE_UPPERCASE 'C'
+#define CHAR_REGEX_OFFSET_START 's'
+#define STRING_IGNORE_CASE (STRING_IGNORE_LOWERCASE|STRING_IGNORE_UPPERCASE)
/* list of magic entries */
@@ -267,27 +320,40 @@ struct mlist {
};
struct magic_set {
- struct mlist *mlist;
- struct cont {
- size_t len;
- int32_t *off;
- } c;
- struct out {
- /* Accumulation buffer */
- char *buf;
- char *ptr;
- size_t len;
- size_t size;
- /* Printable buffer */
- char *pbuf;
- size_t psize;
- } o;
- uint32_t offset;
- int error;
- int flags;
- int haderr;
- const char *file;
- size_t line;
+ struct mlist *mlist;
+ struct cont {
+ size_t len;
+ struct level_info {
+ int32_t off;
+ int got_match;
+ } *li;
+ } c;
+ struct out {
+ /* Accumulation buffer */
+ char *buf;
+ char *ptr;
+ size_t len;
+ size_t size;
+ /* Printable buffer */
+ char *pbuf;
+ size_t psize;
+ } o;
+ uint32_t offset;
+ int error;
+ int flags;
+ int haderr;
+ const char *file;
+ size_t line; /* current magic line number */
+
+ /* data for searches */
+ struct {
+ const char *s; /* start of search in original source */
+ size_t s_len; /* length of search region */
+ size_t offset; /* starting offset in source: XXX - should this be off_t? */
+ size_t rm_len; /* match length */
+ } search;
+
+ union VALUETYPE ms_value; /* either number or string */
};
struct stat;
@@ -309,6 +375,7 @@ protected void file_badread(struct magic_set *);
protected void file_badseek(struct magic_set *);
protected void file_oomem(struct magic_set *, size_t);
protected void file_error(struct magic_set *, int, const char *, ...);
+protected void file_magerror(struct magic_set *, const char *, ...);
protected void file_magwarn(struct magic_set *, const char *, ...);
protected void file_mdump(struct magic *);
protected void file_showstr(FILE *, const char *, size_t);
diff --git a/src/funcs.c b/src/funcs.c
index 6afeac37..3df2193c 100644
--- a/src/funcs.c
+++ b/src/funcs.c
@@ -38,7 +38,7 @@
#endif
#ifndef lint
-FILE_RCSID("@(#)$File: funcs.c,v 1.23 2006/12/11 21:48:49 christos Exp $")
+FILE_RCSID("@(#)$File: funcs.c,v 1.24 2007/01/12 17:38:28 christos Exp $")
#endif /* lint */
#ifndef HAVE_VSNPRINTF
@@ -81,18 +81,22 @@ file_printf(struct magic_set *ms, const char *fmt, ...)
* error - print best error message possible
*/
/*VARARGS*/
-protected void
-file_error(struct magic_set *ms, int error, const char *f, ...)
+private void
+file_error_core(struct magic_set *ms, int error, const char *f, va_list va,
+ uint32_t lineno)
{
- va_list va;
+ size_t len;
/* Only the first error is ok */
if (ms->haderr)
return;
- va_start(va, f);
- (void)vsnprintf(ms->o.buf, ms->o.size, f, va);
- va_end(va);
+ len = 0;
+ if (lineno != 0) {
+ (void)snprintf(ms->o.buf, ms->o.size, "line %u: ", lineno);
+ len = strlen(ms->o.buf);
+ }
+ (void)vsnprintf(ms->o.buf + len, ms->o.size - len, f, va);
if (error > 0) {
- size_t len = strlen(ms->o.buf);
+ len = strlen(ms->o.buf);
(void)snprintf(ms->o.buf + len, ms->o.size - len, " (%s)",
strerror(error));
}
@@ -100,6 +104,28 @@ file_error(struct magic_set *ms, int error, const char *f, ...)
ms->error = error;
}
+/*VARARGS*/
+protected void
+file_error(struct magic_set *ms, int error, const char *f, ...)
+{
+ va_list va;
+ va_start(va, f);
+ file_error_core(ms, error, f, va, 0);
+ va_end(va);
+}
+
+/*
+ * Print an error with magic line number.
+ */
+/*VARARGS*/
+protected void
+file_magerror(struct magic_set *ms, const char *f, ...)
+{
+ va_list va;
+ va_start(va, f);
+ file_error_core(ms, 0, f, va, ms->line);
+ va_end(va);
+}
protected void
file_oomem(struct magic_set *ms, size_t len)
diff --git a/src/magic.c b/src/magic.c
index 3171b305..556b7153 100644
--- a/src/magic.c
+++ b/src/magic.c
@@ -63,7 +63,7 @@
#include "patchlevel.h"
#ifndef lint
-FILE_RCSID("@(#)$File: magic.c,v 1.35 2006/10/31 19:37:17 christos Exp $")
+FILE_RCSID("@(#)$File: magic.c,v 1.36 2007/01/12 17:38:28 christos Exp $")
#endif /* lint */
#ifdef __EMX__
@@ -102,8 +102,8 @@ magic_open(int flags)
if (ms->o.pbuf == NULL)
goto free2;
- ms->c.off = malloc((ms->c.len = 10) * sizeof(*ms->c.off));
- if (ms->c.off == NULL)
+ ms->c.li = malloc((ms->c.len = 10) * sizeof(*ms->c.li));
+ if (ms->c.li == NULL)
goto free3;
ms->o.len = 0;
@@ -162,7 +162,7 @@ magic_close(struct magic_set *ms)
free_mlist(ms->mlist);
free(ms->o.pbuf);
free(ms->o.buf);
- free(ms->c.off);
+ free(ms->c.li);
free(ms);
}
@@ -357,7 +357,7 @@ magic_file(struct magic_set *ms, const char *inname)
* information from the ELF headers that cannot easily
* be extracted with rules in the magic file.
*/
- file_tryelf(ms, fd, buf, (size_t)nbytes);
+ (void) file_tryelf(ms, fd, buf, (size_t)nbytes);
}
#endif
}
diff --git a/src/print.c b/src/print.c
index ba405f36..3502a1f7 100644
--- a/src/print.c
+++ b/src/print.c
@@ -41,7 +41,7 @@
#include <time.h>
#ifndef lint
-FILE_RCSID("@(#)$File: print.c,v 1.56 2006/12/08 20:31:07 christos Exp $")
+FILE_RCSID("@(#)$File: print.c,v 1.57 2007/01/12 17:38:28 christos Exp $")
#endif /* lint */
#define SZOF(a) (sizeof(a) / sizeof(a[0]))
@@ -64,8 +64,8 @@ file_mdump(struct magic *m)
if (m->in_op & FILE_OPINVERSE)
(void) fputc('~', stderr);
(void) fprintf(stderr, "%c%d),",
- ((m->in_op&0x7F) < SZOF(optyp)) ?
- optyp[m->in_op&0x7F] : '?',
+ ((m->in_op & FILE_OPS_MASK) < SZOF(optyp)) ?
+ optyp[m->in_op & FILE_OPS_MASK] : '?',
m->in_offset);
}
(void) fprintf(stderr, " %s%s", (m->flag & UNSIGNED) ? "u" : "",
@@ -73,25 +73,36 @@ file_mdump(struct magic *m)
(m->type < file_nnames) ? file_names[m->type] : "*bad*");
if (m->mask_op & FILE_OPINVERSE)
(void) fputc('~', stderr);
- if (m->mask) {
- if ((m->mask_op & 0x7F) < SZOF(optyp))
- fputc(optyp[m->mask_op&0x7F], stderr);
- else
- fputc('?', stderr);
- if (FILE_STRING != m->type || FILE_PSTRING != m->type)
- (void) fprintf(stderr, "%.8llx",
- (unsigned long long)m->mask);
- else {
- if (m->mask & STRING_IGNORE_LOWERCASE)
- (void) fputc(CHAR_IGNORE_LOWERCASE, stderr);
- if (m->mask & STRING_COMPACT_BLANK)
+
+ if (IS_STRING(m->type)) {
+ if (m->str_flags) {
+ (void) fputc('/', stderr);
+ if (m->str_flags & STRING_COMPACT_BLANK)
(void) fputc(CHAR_COMPACT_BLANK, stderr);
- if (m->mask & STRING_COMPACT_OPTIONAL_BLANK)
+ if (m->str_flags & STRING_COMPACT_OPTIONAL_BLANK)
(void) fputc(CHAR_COMPACT_OPTIONAL_BLANK,
- stderr);
+ stderr);
+ if (m->str_flags & STRING_IGNORE_LOWERCASE)
+ (void) fputc(CHAR_IGNORE_LOWERCASE, stderr);
+ if (m->str_flags & STRING_IGNORE_UPPERCASE)
+ (void) fputc(CHAR_IGNORE_UPPERCASE, stderr);
+ if (m->str_flags & REGEX_OFFSET_START)
+ (void) fputc(CHAR_REGEX_OFFSET_START, stderr);
+ }
+ if (m->str_count)
+ (void) fprintf(stderr, "/%u", m->str_count);
+ }
+ else {
+ if ((m->mask_op & FILE_OPS_MASK) < SZOF(optyp))
+ (void) fputc(optyp[m->mask_op & FILE_OPS_MASK], stderr);
+ else
+ (void) fputc('?', stderr);
+
+ if (m->num_mask) {
+ (void) fprintf(stderr, "%.8llx",
+ (unsigned long long)m->num_mask);
}
}
-
(void) fprintf(stderr, ",%c", m->reln);
if (m->reln != 'x') {
@@ -146,6 +157,9 @@ file_mdump(struct magic *m)
(void)fprintf(stderr, "%s,",
file_fmttime((uint32_t)m->value.q, 0));
break;
+ case FILE_DEFAULT:
+ /* XXX - do anything here? */
+ break;
default:
(void) fputs("*bad*", stderr);
break;
@@ -169,7 +183,7 @@ file_magwarn(struct magic_set *ms, const char *f, ...)
(unsigned long)ms->line);
(void) vfprintf(stderr, f, va);
va_end(va);
- fputc('\n', stderr);
+ (void) fputc('\n', stderr);
}
protected const char *
diff --git a/src/softmagic.c b/src/softmagic.c
index 75b4ddf4..30cc93cc 100644
--- a/src/softmagic.c
+++ b/src/softmagic.c
@@ -35,23 +35,22 @@
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
-#include <regex.h>
#ifndef lint
-FILE_RCSID("@(#)$File: softmagic.c,v 1.87 2006/12/11 21:48:49 christos Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.88 2007/01/12 17:38:28 christos Exp $")
#endif /* lint */
private int match(struct magic_set *, struct magic *, uint32_t,
const unsigned char *, size_t);
-private int mget(struct magic_set *, union VALUETYPE *, const unsigned char *,
+private int mget(struct magic_set *, const unsigned char *,
struct magic *, size_t, unsigned int);
-private int magiccheck(struct magic_set *, union VALUETYPE *, struct magic *);
-private int32_t mprint(struct magic_set *, union VALUETYPE *, struct magic *);
+private int magiccheck(struct magic_set *, struct magic *);
+private int32_t mprint(struct magic_set *, struct magic *);
private void mdebug(uint32_t, const char *, size_t);
private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
- const unsigned char *, uint32_t, size_t);
-private int mconvert(struct magic_set *, union VALUETYPE *, struct magic *);
+ const unsigned char *, uint32_t, size_t, size_t);
+private int mconvert(struct magic_set *, struct magic *);
private int check_mem(struct magic_set *, unsigned int);
private int print_sep(struct magic_set *, int);
private void cvt_8(union VALUETYPE *, const struct magic *);
@@ -110,8 +109,6 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
uint32_t magindex = 0;
unsigned int cont_level = 0;
int need_separator = 0;
- union VALUETYPE p;
- int32_t oldoff = 0;
int returnval = 0; /* if a match is found it is set to 1*/
int firstline = 1; /* a flag to print X\n X\n- X */
int printed_something = 0;
@@ -120,15 +117,18 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
return -1;
for (magindex = 0; magindex < nmagic; magindex++) {
- /* if main entry matches, print it... */
+ int flush;
+
ms->offset = magic[magindex].offset;
- int flush = !mget(ms, &p, s, &magic[magindex], nbytes,
- cont_level);
+ ms->line = magic[magindex].lineno;
+
+ /* if main entry matches, print it... */
+ flush = !mget(ms, s, &magic[magindex], nbytes, cont_level);
if (flush) {
if (magic[magindex].reln == '!')
flush = 0;
} else {
- switch (magiccheck(ms, &p, &magic[magindex])) {
+ switch (magiccheck(ms, &magic[magindex])) {
case -1:
return -1;
case 0:
@@ -144,8 +144,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
* flush its continuations
*/
while (magindex < nmagic - 1 &&
- magic[magindex + 1].cont_level != 0)
- magindex++;
+ magic[magindex + 1].cont_level != 0)
+ magindex++;
continue;
}
@@ -160,7 +160,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
return -1;
}
- if ((ms->c.off[cont_level] = mprint(ms, &p, &magic[magindex]))
+ if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex]))
== -1)
return -1;
@@ -168,8 +168,10 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
if (check_mem(ms, ++cont_level) == -1)
return -1;
- while (magic[magindex+1].cont_level != 0 &&
- ++magindex < nmagic) {
+ while (magic[magindex+1].cont_level != 0 &&
+ ++magindex < nmagic) {
+ ms->line = magic[magindex].lineno; /* for messages */
+
if (cont_level < magic[magindex].cont_level)
continue;
if (cont_level > magic[magindex].cont_level) {
@@ -182,20 +184,26 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
ms->offset = magic[magindex].offset;
if (magic[magindex].flag & OFFADD) {
ms->offset +=
- ms->c.off[cont_level - 1];
+ ms->c.li[cont_level - 1].off;
}
- flush = !mget(ms, &p, s, &magic[magindex], nbytes,
+ flush = !mget(ms, s, &magic[magindex], nbytes,
cont_level);
if (flush && magic[magindex].reln != '!')
continue;
- switch (flush ? 1 : magiccheck(ms, &p, &magic[magindex])) {
+ switch (flush ? 1 : magiccheck(ms, &magic[magindex])) {
case -1:
return -1;
case 0:
break;
default:
+ if (magic[magindex].type != FILE_DEFAULT)
+ ms->c.li[cont_level].got_match = 1;
+ else if (ms->c.li[cont_level].got_match) {
+ ms->c.li[cont_level].got_match = 0;
+ break;
+ }
/*
* If we are going to print something,
* make sure that we have a separator first.
@@ -220,8 +228,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
return -1;
need_separator = 0;
}
- if ((ms->c.off[cont_level] = mprint(ms, &p,
- &magic[magindex])) == -1)
+ if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex])) == -1)
return -1;
if (magic[magindex].desc[0])
need_separator = 1;
@@ -233,6 +240,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
*/
if (check_mem(ms, ++cont_level) == -1)
return -1;
+ break;
}
}
firstline = 0;
@@ -253,10 +261,12 @@ check_mem(struct magic_set *ms, unsigned int level)
if (level < ms->c.len)
return 0;
- len = (ms->c.len += 20) * sizeof(*ms->c.off);
- ms->c.off = (ms->c.off == NULL) ? malloc(len) : realloc(ms->c.off, len);
- if (ms->c.off != NULL)
+ len = (ms->c.len += 20) * sizeof(*ms->c.li);
+ ms->c.li = (ms->c.li == NULL) ? malloc(len) : realloc(ms->c.li, len);
+ if (ms->c.li != NULL) {
+ ms->c.li[level].got_match = 0;
return 0;
+ }
file_oomem(ms, len);
return -1;
}
@@ -273,8 +283,8 @@ check_fmt(struct magic_set *ms, struct magic *m)
rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB);
if (rc) {
char errmsg[512];
- regerror(rc, &rx, errmsg, sizeof(errmsg));
- file_error(ms, 0, "regex error %d, (%s)", rc, errmsg);
+ (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
+ file_magerror(ms, "regex error %d, (%s)", rc, errmsg);
return -1;
} else {
rc = regexec(&rx, m->desc, 0, 0, 0);
@@ -283,13 +293,33 @@ check_fmt(struct magic_set *ms, struct magic *m)
}
}
+#ifndef HAVE_STRNDUP
+char * strndup(const char *, size_t);
+
+char *
+strndup(const char *str, size_t n)
+{
+ size_t len;
+ char *copy;
+
+ len = strlen(str);
+ if (len > n)
+ len = n;
+ if (!(copy = malloc(len + 1)))
+ return (NULL);
+ (void) memcpy(copy, str, len + 1);
+ copy[len] = '\0';
+ return (copy);
+}
+#endif /* HAVE_STRNDUP */
+
private int32_t
-mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
+mprint(struct magic_set *ms, struct magic *m)
{
uint64_t v;
int32_t t = 0;
char buf[512];
-
+ union VALUETYPE *p = &ms->ms_value;
switch (m->type) {
case FILE_BYTE:
@@ -364,6 +394,7 @@ mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
return -1;
t = ms->offset + sizeof(int64_t);
break;
+
case FILE_STRING:
case FILE_PSTRING:
case FILE_BESTRING16:
@@ -421,20 +452,45 @@ mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
t = ms->offset + sizeof(uint64_t);
break;
- case FILE_REGEX:
- if (file_printf(ms, m->desc, p->s) == -1)
+ case FILE_REGEX: {
+ char *cp;
+ int rval;
+
+ cp = strndup((const char *)ms->search.s, ms->search.rm_len);
+ if (cp == NULL) {
+ file_oomem(ms, ms->search.rm_len);
return -1;
- t = ms->offset + strlen(p->s);
+ }
+ rval = file_printf(ms, m->desc, cp);
+ free(cp);
+
+ if (rval == -1)
+ return -1;
+
+ if ((m->str_flags & REGEX_OFFSET_START))
+ t = ms->search.offset;
+ else
+ t = ms->search.offset + ms->search.rm_len;
break;
+ }
case FILE_SEARCH:
if (file_printf(ms, m->desc, m->value.s) == -1)
return -1;
- t = ms->offset + m->vallen;
+ if ((m->str_flags & REGEX_OFFSET_START))
+ t = ms->search.offset;
+ else
+ t = ms->search.offset + m->vallen;
+ break;
+
+ case FILE_DEFAULT:
+ if (file_printf(ms, m->desc, m->value.s) == -1)
+ return -1;
+ t = ms->offset;
break;
default:
- file_error(ms, 0, "invalid m->type (%d) in mprint()", m->type);
+ file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
return -1;
}
return(t);
@@ -442,31 +498,31 @@ mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
#define DO_CVT(fld, cast) \
- if (m->mask) \
- switch (m->mask_op & 0x7F) { \
+ if (m->num_mask) \
+ switch (m->mask_op & FILE_OPS_MASK) { \
case FILE_OPAND: \
- p->fld &= cast m->mask; \
+ p->fld &= cast m->num_mask; \
break; \
case FILE_OPOR: \
- p->fld |= cast m->mask; \
+ p->fld |= cast m->num_mask; \
break; \
case FILE_OPXOR: \
- p->fld ^= cast m->mask; \
+ p->fld ^= cast m->num_mask; \
break; \
case FILE_OPADD: \
- p->fld += cast m->mask; \
+ p->fld += cast m->num_mask; \
break; \
case FILE_OPMINUS: \
- p->fld -= cast m->mask; \
+ p->fld -= cast m->num_mask; \
break; \
case FILE_OPMULTIPLY: \
- p->fld *= cast m->mask; \
+ p->fld *= cast m->num_mask; \
break; \
case FILE_OPDIVIDE: \
- p->fld /= cast m->mask; \
+ p->fld /= cast m->num_mask; \
break; \
case FILE_OPMODULO: \
- p->fld %= cast m->mask; \
+ p->fld %= cast m->num_mask; \
break; \
} \
if (m->mask_op & FILE_OPINVERSE) \
@@ -502,8 +558,10 @@ cvt_64(union VALUETYPE *p, const struct magic *m)
* (unless you have a better idea)
*/
private int
-mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
+mconvert(struct magic_set *ms, struct magic *m)
{
+ union VALUETYPE *p = &ms->ms_value;
+
switch (m->type) {
case FILE_BYTE:
cvt_8(p, m);
@@ -523,31 +581,29 @@ mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
return 1;
case FILE_STRING:
case FILE_BESTRING16:
- case FILE_LESTRING16:
- {
- size_t len;
-
- /* Null terminate and eat *trailing* return */
- p->s[sizeof(p->s) - 1] = '\0';
- len = strlen(p->s);
- if (len-- && p->s[len] == '\n')
- p->s[len] = '\0';
- return 1;
- }
- case FILE_PSTRING:
- {
- char *ptr1 = p->s, *ptr2 = ptr1 + 1;
- size_t len = *p->s;
- if (len >= sizeof(p->s))
- len = sizeof(p->s) - 1;
- while (len--)
- *ptr1++ = *ptr2++;
- *ptr1 = '\0';
- len = strlen(p->s);
- if (len-- && p->s[len] == '\n')
- p->s[len] = '\0';
- return 1;
- }
+ case FILE_LESTRING16: {
+ size_t len;
+
+ /* Null terminate and eat *trailing* return */
+ p->s[sizeof(p->s) - 1] = '\0';
+ len = strlen(p->s);
+ if (len-- && p->s[len] == '\n')
+ p->s[len] = '\0';
+ return 1;
+ }
+ case FILE_PSTRING: {
+ char *ptr1 = p->s, *ptr2 = ptr1 + 1;
+ size_t len = *p->s;
+ if (len >= sizeof(p->s))
+ len = sizeof(p->s) - 1;
+ while (len--)
+ *ptr1++ = *ptr2++;
+ *ptr1 = '\0';
+ len = strlen(p->s);
+ if (len-- && p->s[len] == '\n')
+ p->s[len] = '\0';
+ return 1;
+ }
case FILE_BESHORT:
p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
cvt_16(p, m);
@@ -597,9 +653,10 @@ mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
return 1;
case FILE_REGEX:
case FILE_SEARCH:
+ case FILE_DEFAULT:
return 1;
default:
- file_error(ms, 0, "invalid type %d in mconvert()", m->type);
+ file_magerror(ms, "invalid type %d in mconvert()", m->type);
return 0;
}
}
@@ -616,61 +673,86 @@ mdebug(uint32_t offset, const char *str, size_t len)
private int
mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
- const unsigned char *s, uint32_t offset, size_t nbytes)
+ const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
{
- if (type == FILE_REGEX && indir == 0) {
- /*
- * offset is interpreted as last line to search,
- * (starting at 1), not as bytes-from start-of-file
- */
- char *b, *c, *last = NULL;
- if (s == NULL) {
- p->search.buflen = 0;
- p->search.buf = NULL;
+ /*
+ * Note: FILE_SEARCH and FILE_REGEX do not actually copy
+ * anything, but setup pointers into the source
+ */
+ if (indir == 0) {
+ switch (type) {
+ case FILE_SEARCH:
+ ms->search.s = (const char *)s + offset;
+ ms->search.s_len = nbytes - offset;
return 0;
- }
- if ((p->search.buf = strdup((const char *)s)) == NULL) {
- file_oomem(ms, strlen((const char *)s));
- return -1;
- }
- for (b = p->search.buf; offset &&
- ((b = strchr(c = b, '\n')) || (b = strchr(c, '\r')));
- offset--, b++) {
- last = b;
- if (b[0] == '\r' && b[1] == '\n') b++;
- }
- if (last != NULL)
- *last = '\0';
- p->search.buflen = last - p->search.buf;
- return 0;
- }
-
- if (indir == 0 && (type == FILE_BESTRING16 || type == FILE_LESTRING16))
- {
- const unsigned char *src = s + offset;
- const unsigned char *esrc = s + nbytes;
- char *dst = p->s, *edst = &p->s[sizeof(p->s) - 1];
- if (type == FILE_BESTRING16)
- src++;
-
- /* check for pointer overflow */
- if (src < s) {
- file_error(ms, 0, "invalid offset %zu in mcopy()",
- offset);
- return -1;
+ case FILE_REGEX: {
+ /*
+ * offset is interpreted as last line to search,
+ * (starting at 1), not as bytes-from start-of-file
+ */
+ const char *b;
+ const char *c;
+ const char *last; /* end of search region */
+ const char *buf; /* start of search region */
+ size_t lines;
+
+ if (s == NULL) {
+ ms->search.s_len = 0;
+ ms->search.s = NULL;
+ return 0;
+ }
+ buf = (const char *)s + offset;
+ last = (const char *)s + nbytes;
+ /* mget() guarantees buf <= last */
+ for (lines = linecnt, b = buf;
+ lines && ((b = strchr(c = b, '\n')) || (b = strchr(c, '\r')));
+ lines--, b++) {
+ last = b;
+ if (b[0] == '\r' && b[1] == '\n')
+ b++;
+ }
+ if (lines)
+ last = (const char *)s + nbytes;
+
+ ms->search.s = buf;
+ ms->search.s_len = last - buf;
+ ms->search.offset = offset;
+ ms->search.rm_len = 0;
+ return 0;
}
-
- for (;src < esrc; src++, dst++) {
- if (dst < edst)
- *dst = *src++;
- else
- break;
- if (*dst == '\0')
- *dst = ' ';
+ case FILE_BESTRING16:
+ case FILE_LESTRING16: {
+ const unsigned char *src = s + offset;
+ const unsigned char *esrc = s + nbytes;
+ char *dst = p->s;
+ char *edst = &p->s[sizeof(p->s) - 1];
+
+ if (type == FILE_BESTRING16)
+ src++;
+
+ /* check for pointer overflow */
+ if (src < s) {
+ file_magerror(ms, "invalid offset %zu in mcopy()",
+ offset);
+ return -1;
+ }
+ for (/*EMPTY*/; src < esrc; src++, dst++) {
+ if (dst < edst)
+ *dst = *src++;
+ else
+ break;
+ if (*dst == '\0')
+ *dst = ' ';
+ }
+ *edst = '\0';
+ return 0;
+ }
+ case FILE_STRING: /* XXX - these two should not need */
+ case FILE_PSTRING: /* to copy anything, but do anyway. */
+ default:
+ break;
}
- *edst = '\0';
- return 0;
}
if (offset >= nbytes) {
@@ -695,12 +777,14 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
}
private int
-mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
+mget(struct magic_set *ms, const unsigned char *s,
struct magic *m, size_t nbytes, unsigned int cont_level)
{
uint32_t offset = ms->offset;
+ uint32_t count = m->str_count;
+ union VALUETYPE *p = &ms->ms_value;
- if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes) == -1)
+ if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1)
return -1;
if ((ms->flags & MAGIC_DEBUG) != 0) {
@@ -745,9 +829,10 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
}
switch (m->in_type) {
case FILE_BYTE:
- if (nbytes < (offset + 1)) return 0;
+ if (nbytes < (offset + 1))
+ return 0;
if (off) {
- switch (m->in_op & 0x3F) {
+ switch (m->in_op & FILE_OPS_MASK) {
case FILE_OPAND:
offset = p->b & off;
break;
@@ -782,7 +867,7 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
if (nbytes < (offset + 2))
return 0;
if (off) {
- switch (m->in_op & 0x7F) {
+ switch (m->in_op & FILE_OPS_MASK) {
case FILE_OPAND:
offset = (short)((p->hs[0]<<8)|
(p->hs[1])) &
@@ -834,7 +919,7 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
if (nbytes < (offset + 2))
return 0;
if (off) {
- switch (m->in_op & 0x7F) {
+ switch (m->in_op & FILE_OPS_MASK) {
case FILE_OPAND:
offset = (short)((p->hs[1]<<8)|
(p->hs[0])) &
@@ -886,7 +971,7 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
if (nbytes < (offset + 2))
return 0;
if (off) {
- switch (m->in_op & 0x7F) {
+ switch (m->in_op & FILE_OPS_MASK) {
case FILE_OPAND:
offset = p->h & off;
break;
@@ -922,7 +1007,7 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
if (nbytes < (offset + 4))
return 0;
if (off) {
- switch (m->in_op & 0x7F) {
+ switch (m->in_op & FILE_OPS_MASK) {
case FILE_OPAND:
offset = (int32_t)((p->hl[0]<<24)|
(p->hl[1]<<16)|
@@ -992,7 +1077,7 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
if (nbytes < (offset + 4))
return 0;
if (off) {
- switch (m->in_op & 0x7F) {
+ switch (m->in_op & FILE_OPS_MASK) {
case FILE_OPAND:
offset = (int32_t)((p->hl[3]<<24)|
(p->hl[2]<<16)|
@@ -1062,7 +1147,7 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
if (nbytes < (offset + 4))
return 0;
if (off) {
- switch (m->in_op & 0x7F) {
+ switch (m->in_op & FILE_OPS_MASK) {
case FILE_OPAND:
offset = (int32_t)((p->hl[1]<<24)|
(p->hl[0]<<16)|
@@ -1132,7 +1217,7 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
if (nbytes < (offset + 4))
return 0;
if (off) {
- switch (m->in_op & 0x7F) {
+ switch (m->in_op & FILE_OPS_MASK) {
case FILE_OPAND:
offset = p->l & off;
break;
@@ -1172,8 +1257,9 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
break;
}
- if (m->flag & INDIROFFADD) offset += ms->c.off[cont_level-1];
- if (mcopy(ms, p, m->type, 0, s, offset, nbytes) == -1)
+ if (m->flag & INDIROFFADD)
+ offset += ms->c.li[cont_level-1].off;
+ if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
return -1;
ms->offset = offset;
@@ -1186,73 +1272,138 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
/* Verify we have enough data to match magic type */
switch (m->type) {
- case FILE_BYTE:
- if (nbytes < (offset + 1)) /* should alway be true */
- return 0;
- break;
-
- case FILE_SHORT:
- case FILE_BESHORT:
- case FILE_LESHORT:
- if (nbytes < (offset + 2))
- return 0;
- break;
+ case FILE_BYTE:
+ if (nbytes < (offset + 1)) /* should alway be true */
+ return 0;
+ break;
+
+ case FILE_SHORT:
+ case FILE_BESHORT:
+ case FILE_LESHORT:
+ if (nbytes < (offset + 2))
+ return 0;
+ break;
+
+ case FILE_LONG:
+ case FILE_BELONG:
+ case FILE_LELONG:
+ case FILE_MELONG:
+ case FILE_DATE:
+ case FILE_BEDATE:
+ case FILE_LEDATE:
+ case FILE_MEDATE:
+ case FILE_LDATE:
+ case FILE_BELDATE:
+ case FILE_LELDATE:
+ case FILE_MELDATE:
+ if (nbytes < (offset + 4))
+ return 0;
+ break;
+
+ case FILE_STRING:
+ case FILE_PSTRING:
+ case FILE_SEARCH:
+ if (nbytes < (offset + m->vallen))
+ return 0;
+ break;
- case FILE_LONG:
- case FILE_BELONG:
- case FILE_LELONG:
- case FILE_MELONG:
- case FILE_DATE:
- case FILE_BEDATE:
- case FILE_LEDATE:
- case FILE_MEDATE:
- case FILE_LDATE:
- case FILE_BELDATE:
- case FILE_LELDATE:
- case FILE_MELDATE:
- if (nbytes < (offset + 4))
- return 0;
- break;
+ case FILE_REGEX:
+ if (nbytes < offset)
+ return 0;
+ break;
- case FILE_STRING:
- case FILE_PSTRING:
- case FILE_SEARCH:
- if (nbytes < (offset + m->vallen))
- return 0;
- break;
- default: break;
+ case FILE_DEFAULT: /* nothing to check */
+ default:
+ break;
}
+ if (!mconvert(ms, m))
+ return 0;
+ return 1;
+}
- if (m->type == FILE_SEARCH) {
- size_t mlen = (size_t)(m->mask + m->vallen);
- size_t flen = nbytes - offset;
- if (flen < mlen)
- mlen = flen;
- p->search.buflen = mlen;
- p->search.buf = malloc(mlen + 1);
- if (p->search.buf == NULL) {
- file_error(ms, errno, "Cannot allocate search buffer");
- return 0;
+private uint64_t
+file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
+{
+ /*
+ * Convert the source args to unsigned here so that (1) the
+ * compare will be unsigned as it is in strncmp() and (2) so
+ * the ctype functions will work correctly without extra
+ * casting.
+ */
+ const unsigned char *a = (const unsigned char *)s1;
+ const unsigned char *b = (const unsigned char *)s2;
+ uint64_t v;
+
+ /*
+ * What we want here is:
+ * v = strncmp(m->value.s, p->s, m->vallen);
+ * but ignoring any nulls. bcmp doesn't give -/+/0
+ * and isn't universally available anyway.
+ */
+ v = 0;
+ if (0L == flags) { /* normal string: do it fast */
+ while (len-- > 0)
+ if ((v = *b++ - *a++) != '\0')
+ break;
+ }
+ else { /* combine the others */
+ while (len-- > 0) {
+ if ((flags & STRING_IGNORE_LOWERCASE) &&
+ islower(*a)) {
+ if ((v = tolower(*b++) - *a++) != '\0')
+ break;
+ }
+ else if ((flags & STRING_IGNORE_UPPERCASE) &&
+ isupper(*a)) {
+ if ((v = toupper(*b++) - *a++) != '\0')
+ break;
+ }
+ else if ((flags & STRING_COMPACT_BLANK) &&
+ isspace(*a)) {
+ a++;
+ if (isspace(*b++)) {
+ while (isspace(*b))
+ b++;
+ }
+ else {
+ v = 1;
+ break;
+ }
+ }
+ else if ((flags & STRING_COMPACT_OPTIONAL_BLANK) &&
+ isspace(*a)) {
+ a++;
+ while (isspace(*b))
+ b++;
+ }
+ else {
+ if ((v = *b++ - *a++) != '\0')
+ break;
+ }
}
- (void)memcpy(p->search.buf, s + offset, mlen);
- p->search.buf[mlen] = '\0';
}
- if (!mconvert(ms, p, m))
- return 0;
- return 1;
+ return v;
+}
+
+private uint64_t
+file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags)
+{
+ /*
+ * XXX - The 16-bit string compare probably needs to be done
+ * differently, especially if the flags are to be supported.
+ * At the moment, I am unsure.
+ */
+ flags = 0;
+ return file_strncmp(a, b, len, flags);
}
private int
-magiccheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
+magiccheck(struct magic_set *ms, struct magic *m)
{
uint64_t l = m->value.q;
uint64_t v;
int matched;
-
- if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
- return 1;
- }
-
+ union VALUETYPE *p = &ms->ms_value;
switch (m->type) {
case FILE_BYTE:
@@ -1292,125 +1443,103 @@ magiccheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
v = p->q;
break;
+ case FILE_DEFAULT:
+ l = 0;
+ v = 0;
+ break;
+
case FILE_STRING:
+ case FILE_PSTRING:
+ l = 0;
+ v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
+ break;
+
case FILE_BESTRING16:
case FILE_LESTRING16:
- case FILE_PSTRING:
- {
- /*
- * What we want here is:
- * v = strncmp(m->value.s, p->s, m->vallen);
- * but ignoring any nulls. bcmp doesn't give -/+/0
- * and isn't universally available anyway.
- */
- unsigned char *a = (unsigned char*)m->value.s;
- unsigned char *b = (unsigned char*)p->s;
- int len = m->vallen;
+ l = 0;
+ v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
+ break;
+
+ case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
+ size_t slen;
+ size_t idx;
+
+ if (ms->search.s == NULL)
+ return 0;
+
+ slen = MIN(m->vallen, sizeof(m->value.s));
l = 0;
v = 0;
- if (0L == m->mask) { /* normal string: do it fast */
- while (--len >= 0)
- if ((v = *b++ - *a++) != '\0')
- break;
- } else { /* combine the others */
- while (--len >= 0) {
- if ((m->mask & STRING_IGNORE_LOWERCASE) &&
- islower(*a)) {
- if ((v = tolower(*b++) - *a++) != '\0')
- break;
- } else if ((m->mask & STRING_COMPACT_BLANK) &&
- isspace(*a)) {
- a++;
- if (isspace(*b++)) {
- while (isspace(*b))
- b++;
- } else {
- v = 1;
- break;
- }
- } else if (isspace(*a) &&
- (m->mask & STRING_COMPACT_OPTIONAL_BLANK)) {
- a++;
- while (isspace(*b))
- b++;
- } else {
- if ((v = *b++ - *a++) != '\0')
- break;
- }
+ ms->search.offset = m->offset;
+
+ for (idx = 0; m->str_count == 0 || idx < m->str_count; idx++) {
+ if (slen + idx > ms->search.s_len)
+ break;
+
+ v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags);
+ if (v == 0) { /* found match */
+ ms->search.offset = m->offset + idx;
+ break;
}
}
break;
}
- case FILE_REGEX:
- {
+ case FILE_REGEX: {
int rc;
regex_t rx;
char errmsg[512];
- if (p->search.buf == NULL)
+ if (ms->search.s == NULL)
return 0;
+ l = 0;
rc = regcomp(&rx, m->value.s,
- REG_EXTENDED|REG_NOSUB|REG_NEWLINE|
- ((m->mask & STRING_IGNORE_LOWERCASE) ? REG_ICASE : 0));
+ REG_EXTENDED|REG_NEWLINE|
+ ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
if (rc) {
- free(p->search.buf);
- p->search.buf = NULL;
- regerror(rc, &rx, errmsg, sizeof(errmsg));
- file_error(ms, 0, "regex error %d, (%s)", rc, errmsg);
- return -1;
- } else {
- rc = regexec(&rx, p->search.buf, 0, 0, 0);
- regfree(&rx);
- free(p->search.buf);
- p->search.buf = NULL;
- return !rc;
+ (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
+ file_magerror(ms, "regex error %d, (%s)",
+ rc, errmsg);
+ v = (uint64_t)-1;
}
- }
- case FILE_SEARCH:
- {
- /*
- * search for a string in a certain range
- */
- unsigned char *a = (unsigned char*)m->value.s;
- unsigned char *b = (unsigned char*)p->search.buf;
- size_t len, slen = m->vallen;
- size_t range = 0;
- if (slen > sizeof(m->value.s))
- slen = sizeof(m->value.s);
- l = 0;
- v = 0;
- if (b == NULL)
- return 0;
- len = slen;
- while (++range <= m->mask) {
- while (len-- > 0 && (v = *b++ - *a++) == 0)
- continue;
- if (!v) {
- ms->offset += range - 1;
+ else {
+ regmatch_t pmatch[1];
+ pmatch[0].rm_so = 0;
+ pmatch[0].rm_eo = ms->search.s_len;
+ rc = regexec(&rx, (const char *)ms->search.s,
+ 1, pmatch, REG_STARTEND);
+ switch (rc) {
+ case 0:
+ ms->search.s += (int)pmatch[0].rm_so;
+ ms->search.offset += (size_t)pmatch[0].rm_so;
+ ms->search.rm_len =
+ (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so);
+ v = 0;
break;
- }
- if (range + slen >= p->search.buflen) {
+
+ case REG_NOMATCH:
v = 1;
break;
+
+ default:
+ (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
+ file_magerror(ms, "regexec error %d, (%s)",
+ rc, errmsg);
+ v = (uint64_t)-1;
+ break;
}
- len = slen;
- a = (unsigned char*)m->value.s;
- b = (unsigned char*)p->search.buf + range;
+ regfree(&rx);
}
- free(p->search.buf);
- p->search.buf = NULL;
- if (v)
- return 0;
+ if (v == (uint64_t)-1)
+ return -1;
break;
}
default:
- file_error(ms, 0, "invalid type %d in magiccheck()", m->type);
+ file_magerror(ms, "invalid type %d in magiccheck()", m->type);
return -1;
}
- if (m->type != FILE_STRING && m->type != FILE_PSTRING)
- v = file_signextend(ms, m, v);
+ v = file_signextend(ms, m, v);
switch (m->reln) {
case 'x':
@@ -1445,7 +1574,7 @@ magiccheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
(unsigned long long)l, matched);
}
else {
- matched = (int32_t) v > (int32_t) l;
+ matched = (int64_t) v > (int64_t) l;
if ((ms->flags & MAGIC_DEBUG) != 0)
(void) fprintf(stderr, "%lld > %lld = %d\n",
(long long)v, (long long)l, matched);
@@ -1461,7 +1590,7 @@ magiccheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
(unsigned long long)l, matched);
}
else {
- matched = (int32_t) v < (int32_t) l;
+ matched = (int64_t) v < (int64_t) l;
if ((ms->flags & MAGIC_DEBUG) != 0)
(void) fprintf(stderr, "%lld < %lld = %d\n",
(long long)v, (long long)l, matched);
@@ -1486,7 +1615,7 @@ magiccheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
default:
matched = 0;
- file_error(ms, 0, "cannot happen: invalid relation `%c'",
+ file_magerror(ms, "cannot happen: invalid relation `%c'",
m->reln);
return -1;
}