summaryrefslogtreecommitdiffstats
path: root/contrib/file/apprentice.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/file/apprentice.c')
-rw-r--r--contrib/file/apprentice.c547
1 files changed, 429 insertions, 118 deletions
diff --git a/contrib/file/apprentice.c b/contrib/file/apprentice.c
index 974fae9..d5a5bec 100644
--- a/contrib/file/apprentice.c
+++ b/contrib/file/apprentice.c
@@ -46,7 +46,7 @@
#endif
#ifndef lint
-FILE_RCSID("@(#)$Id: apprentice.c,v 1.100 2006/12/11 21:48:49 christos Exp $")
+FILE_RCSID("@(#)$File: apprentice.c,v 1.105 2007/05/16 20:51:40 christos Exp $")
#endif /* lint */
#define EATAB {while (isascii((unsigned char) *l) && \
@@ -75,27 +75,21 @@ FILE_RCSID("@(#)$Id: 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;
uint32_t max_count;
};
-const int file_formats[] = { FILE_FORMAT_STRING };
-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]);
+int file_formats[FILE_NAMES_SIZE];
+const size_t file_nformats = FILE_NAMES_SIZE;
+const char *file_names[FILE_NAMES_SIZE];
+const size_t file_nnames = FILE_NAMES_SIZE;
-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 **);
@@ -154,6 +148,82 @@ main(int argc, char *argv[])
}
#endif /* COMPILE_ONLY */
+static const struct type_tbl_s {
+ const char *name;
+ const size_t len;
+ const int type;
+ const int format;
+} type_tbl[] = {
+# define XX(s) s, (sizeof(s) - 1)
+# define XX_NULL NULL, 0
+ { XX("byte"), FILE_BYTE, FILE_FMT_NUM },
+ { XX("short"), FILE_SHORT, FILE_FMT_NUM },
+ { XX("default"), FILE_DEFAULT, FILE_FMT_STR },
+ { XX("long"), FILE_LONG, FILE_FMT_NUM },
+ { XX("string"), FILE_STRING, FILE_FMT_STR },
+ { XX("date"), FILE_DATE, FILE_FMT_STR },
+ { XX("beshort"), FILE_BESHORT, FILE_FMT_NUM },
+ { XX("belong"), FILE_BELONG, FILE_FMT_NUM },
+ { XX("bedate"), FILE_BEDATE, FILE_FMT_STR },
+ { XX("leshort"), FILE_LESHORT, FILE_FMT_NUM },
+ { XX("lelong"), FILE_LELONG, FILE_FMT_NUM },
+ { XX("ledate"), FILE_LEDATE, FILE_FMT_STR },
+ { XX("pstring"), FILE_PSTRING, FILE_FMT_STR },
+ { XX("ldate"), FILE_LDATE, FILE_FMT_STR },
+ { XX("beldate"), FILE_BELDATE, FILE_FMT_STR },
+ { XX("leldate"), FILE_LELDATE, FILE_FMT_STR },
+ { XX("regex"), FILE_REGEX, FILE_FMT_STR },
+ { XX("bestring16"), FILE_BESTRING16, FILE_FMT_STR },
+ { XX("lestring16"), FILE_LESTRING16, FILE_FMT_STR },
+ { XX("search"), FILE_SEARCH, FILE_FMT_STR },
+ { XX("medate"), FILE_MEDATE, FILE_FMT_STR },
+ { XX("meldate"), FILE_MELDATE, FILE_FMT_STR },
+ { XX("melong"), FILE_MELONG, FILE_FMT_NUM },
+ { XX("quad"), FILE_QUAD, FILE_FMT_QUAD },
+ { XX("lequad"), FILE_LEQUAD, FILE_FMT_QUAD },
+ { XX("bequad"), FILE_BEQUAD, FILE_FMT_QUAD },
+ { XX("qdate"), FILE_QDATE, FILE_FMT_STR },
+ { XX("leqdate"), FILE_LEQDATE, FILE_FMT_STR },
+ { XX("beqdate"), FILE_BEQDATE, FILE_FMT_STR },
+ { XX("qldate"), FILE_QLDATE, FILE_FMT_STR },
+ { XX("leqldate"), FILE_LEQLDATE, FILE_FMT_STR },
+ { XX("beqldate"), FILE_BEQLDATE, FILE_FMT_STR },
+ { XX_NULL, FILE_INVALID, FILE_FMT_NONE },
+# undef XX
+# undef XX_NULL
+};
+
+private int
+get_type(const char *l, const char **t)
+{
+ const struct type_tbl_s *p;
+
+ for (p = type_tbl; p->name; p++) {
+ if (strncmp(l, p->name, p->len) == 0) {
+ if (t)
+ *t = l + p->len;
+ break;
+ }
+ }
+ return p->type;
+}
+
+private void
+init_file_tables(void)
+{
+ static int done = 0;
+ const struct type_tbl_s *p;
+
+ if (done)
+ return;
+ done++;
+
+ for (p = type_tbl; p->name; p++) {
+ assert(p->type < FILE_NAMES_SIZE);
+ file_names[p->type] = p->name;
+ file_formats[p->type] = p->format;
+ }
+}
/*
* Handle one file.
@@ -241,7 +311,6 @@ file_delmagic(struct magic *p, int type, size_t entries)
}
}
-
/* const char *fn: list of magic files */
protected struct mlist *
file_apprentice(struct magic_set *ms, const char *fn, int action)
@@ -251,15 +320,18 @@ file_apprentice(struct magic_set *ms, const char *fn, int action)
struct mlist *mlist;
static const char mime[] = ".mime";
+ init_file_tables();
+
if (fn == NULL)
fn = getenv("MAGIC");
if (fn == NULL)
fn = MAGIC;
- if ((fn = mfn = strdup(fn)) == NULL) {
+ if ((mfn = strdup(fn)) == NULL) {
file_oomem(ms, strlen(fn));
return NULL;
}
+ fn = mfn;
if ((mlist = malloc(sizeof(*mlist))) == NULL) {
free(mfn);
@@ -316,6 +388,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 +476,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 +564,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 +619,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 +665,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 +673,150 @@ 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;
+ }
+}
+
+#ifdef ENABLE_CONDITIONALS
+private int
+get_cond(const char *l, const char **t)
+{
+ static struct cond_tbl_s {
+ const char *name;
+ const size_t len;
+ const int cond;
+ } cond_tbl[] = {
+ { "if", 2, COND_IF },
+ { "elif", 4, COND_ELIF },
+ { "else", 4, COND_ELSE },
+ { NULL, 0, COND_NONE },
+ };
+ struct cond_tbl_s *p;
+
+ for (p = cond_tbl; p->name; p++) {
+ if (strncmp(l, p->name, p->len) == 0 &&
+ isspace((unsigned char)l[p->len])) {
+ if (t)
+ *t = l + p->len;
+ break;
+ }
+ }
+ return p->cond;
+}
+
+private int
+check_cond(struct magic_set *ms, int cond, uint32_t cont_level)
+{
+ int last_cond;
+ last_cond = ms->c.li[cont_level].last_cond;
+
+ switch (cond) {
+ case COND_IF:
+ if (last_cond != COND_NONE && last_cond != COND_ELIF) {
+ if (ms->flags & MAGIC_CHECK)
+ file_magwarn(ms, "syntax error: `if'");
+ return -1;
+ }
+ last_cond = COND_IF;
+ break;
+
+ case COND_ELIF:
+ if (last_cond != COND_IF && last_cond != COND_ELIF) {
+ if (ms->flags & MAGIC_CHECK)
+ file_magwarn(ms, "syntax error: `elif'");
+ return -1;
+ }
+ last_cond = COND_ELIF;
+ break;
+
+ case COND_ELSE:
+ if (last_cond != COND_IF && last_cond != COND_ELIF) {
+ if (ms->flags & MAGIC_CHECK)
+ file_magwarn(ms, "syntax error: `else'");
+ return -1;
+ }
+ last_cond = COND_NONE;
+ break;
+
+ case COND_NONE:
+ last_cond = COND_NONE;
+ break;
+ }
+
+ ms->c.li[cont_level].last_cond = last_cond;
+ return 0;
+}
+#endif /* ENABLE_CONDITIONALS */
+
/*
* parse one line from magic file, put into magic[index++] if valid
*/
@@ -586,13 +824,15 @@ private int
parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
const char *line, size_t lineno, int action)
{
+#ifdef ENABLE_CONDITIONALS
+ static uint32_t last_cont_level = 0;
+#endif
size_t i;
struct magic_entry *me;
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;
@@ -601,6 +841,12 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
++l; /* step over */
cont_level++;
}
+#ifdef ENABLE_CONDITIONALS
+ if (cont_level == 0 || cont_level > last_cont_level)
+ if (file_check_mem(ms, cont_level) == -1)
+ return -1;
+ last_cont_level = cont_level;
+#endif
#define ALLOC_CHUNK (size_t)10
#define ALLOC_INCR (size_t)200
@@ -622,7 +868,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 +894,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 +968,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;
- 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;
+ if ((op = get_op(*l)) != -1) {
+ m->in_op |= op;
l++;
- break;
}
if (*l == '(') {
m->in_op |= FILE_OPINDIRECT;
@@ -761,6 +984,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,61 +996,85 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
file_magwarn(ms,
"missing ')' in indirect offset");
}
+ EATAB;
+#ifdef ENABLE_CONDITIONALS
+ m->cond = get_cond(l, &l);
+ if (check_cond(ms, m->cond, cont_level) == -1)
+ return -1;
- while (isascii((unsigned char)*l) && isdigit((unsigned char)*l))
- ++l;
EATAB;
+#endif
if (*l == 'u') {
++l;
m->flag |= UNSIGNED;
}
- /* get type, skip it */
- for (i = 0; i < file_nnames; i++) {
- size_t len = strlen(file_names[i]);
- if (strncmp(l, file_names[i], len) == 0) {
- m->type = i;
- l+= len;
- break;
- }
- }
- if (i == file_nnames) {
+ m->type = get_type(l, &l);
+ if (m->type == FILE_INVALID) {
if (ms->flags & MAGIC_CHECK)
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 +1082,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 +1120,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 +1141,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 +1338,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 +1349,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 +1377,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 +1392,66 @@ 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;
+ case '\t':
+ if (action == FILE_COMPILE) {
+ file_magwarn(ms,
+ "escaped tab found, use \\t instead");
+ action++;
+ }
+ /*FALLTHROUGH*/
default:
+ if (action == FILE_COMPILE) {
+ if (isprint((unsigned char)c))
+ file_magwarn(ms,
+ "no need to escape `%c'", c);
+ else
+ file_magwarn(ms,
+ "unknown escape sequence: \\%03o", c);
+ }
+ /*FALLTHROUGH*/
+ /* space, perhaps force people to use \040? */
+ case ' ':
+#if 0
+ /*
+ * Other things people escape, but shouldn't need to,
+ * so we disallow them
+ */
+ case '\'':
+ case '"':
+ case '?':
+#endif
+ /* Relations */
+ case '>':
+ case '<':
+ case '&':
+ case '^':
+ case '=':
+ case '!':
+ /* and baskslash itself */
+ 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 +1460,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 +1479,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 +1526,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 +1552,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 +1577,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 +1841,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);
+ }
}
OpenPOWER on IntegriCloud