Fix numerous sign-extension problems, and add support for explicitly unsigned
comparisons.
This commit is contained in:
parent
9fc3df91d1
commit
ab61bc03f0
@ -26,7 +26,7 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$Id: apprentice.c,v 1.3 1993/08/01 18:16:26 mycroft Exp $";
|
||||
static char rcsid[] = "$Id: apprentice.c,v 1.4 1993/11/03 04:04:21 mycroft Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
@ -43,6 +43,7 @@ static int getvalue __P((struct magic *, char **));
|
||||
static int hextoint __P((int));
|
||||
static char *getstr __P((char *, char *, int, int *));
|
||||
static int parse __P((char *, int *, int));
|
||||
extern unsigned long signextend __P((struct magic *, unsigned long));
|
||||
|
||||
static int maxmagic = 0;
|
||||
|
||||
@ -75,10 +76,6 @@ int check; /* non-zero? checking-only run. */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* parse it */
|
||||
if (check) /* print silly verbose header for USG compat. */
|
||||
(void) printf("cont\toffset\ttype\topcode\tmask\tvalue\tdesc\n");
|
||||
|
||||
for (lineno = 1;fgets(line, BUFSIZ, f) != NULL; lineno++) {
|
||||
if (line[0]=='#') /* comment, do not parse */
|
||||
continue;
|
||||
@ -93,6 +90,45 @@ int check; /* non-zero? checking-only run. */
|
||||
return errs ? -1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* extend the sign bit if the comparison is to be signed
|
||||
*/
|
||||
unsigned long
|
||||
signextend(m, v)
|
||||
struct magic *m;
|
||||
unsigned long v;
|
||||
{
|
||||
if (!(m->flag & UNSIGNED))
|
||||
switch(m->type) {
|
||||
/*
|
||||
* Do not remove the casts below. They are
|
||||
* vital. When later compared with the data,
|
||||
* the sign extension must have happened.
|
||||
*/
|
||||
case BYTE:
|
||||
v = (char) v;
|
||||
break;
|
||||
case SHORT:
|
||||
case BESHORT:
|
||||
case LESHORT:
|
||||
v = (short) v;
|
||||
break;
|
||||
case DATE:
|
||||
case BEDATE:
|
||||
case LEDATE:
|
||||
case LONG:
|
||||
case BELONG:
|
||||
case LELONG:
|
||||
v = (long) v;
|
||||
break;
|
||||
default:
|
||||
magwarn("can't happen: m->type=%d\n",
|
||||
m->type);
|
||||
return -1;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* parse one line from magic file, put into magic[index++] if valid
|
||||
*/
|
||||
@ -188,6 +224,11 @@ int *ndx, check;
|
||||
#define NLELONG 6
|
||||
#define NLEDATE 6
|
||||
|
||||
if (*l == 'u') {
|
||||
++l;
|
||||
m->flag |= UNSIGNED;
|
||||
}
|
||||
|
||||
/* get type, skip it */
|
||||
if (strncmp(l, "byte", NBYTE)==0) {
|
||||
m->type = BYTE;
|
||||
@ -229,7 +270,8 @@ int *ndx, check;
|
||||
/* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */
|
||||
if (*l == '&') {
|
||||
++l;
|
||||
m->mask = strtol(l, &l, 0);
|
||||
m->mask = signextend(m, strtol(l, &l, 0));
|
||||
m->flag |= MASK;
|
||||
} else
|
||||
m->mask = 0L;
|
||||
EATAB;
|
||||
@ -310,36 +352,9 @@ char **p;
|
||||
if (m->type == STRING) {
|
||||
*p = getstr(*p, m->value.s, sizeof(m->value.s), &slen);
|
||||
m->vallen = slen;
|
||||
} else {
|
||||
if (m->reln != 'x') {
|
||||
switch(m->type) {
|
||||
/*
|
||||
* Do not remove the casts below. They are vital.
|
||||
* When later compared with the data, the sign
|
||||
* extension must have happened.
|
||||
*/
|
||||
case BYTE:
|
||||
m->value.l = (char) strtol(*p,p,0);
|
||||
break;
|
||||
case SHORT:
|
||||
case BESHORT:
|
||||
case LESHORT:
|
||||
m->value.l = (short) strtol(*p,p,0);
|
||||
break;
|
||||
case DATE:
|
||||
case BEDATE:
|
||||
case LEDATE:
|
||||
case LONG:
|
||||
case BELONG:
|
||||
case LELONG:
|
||||
m->value.l = (long) strtol(*p,p,0);
|
||||
break;
|
||||
default:
|
||||
magwarn("can't happen: m->type=%d\n", m->type);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (m->reln != 'x')
|
||||
m->value.l = signextend(m, strtol(*p, p, 0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* file.h - definitions for file(1) program
|
||||
*
|
||||
* $Id: file.h,v 1.3 1993/08/01 18:16:29 mycroft Exp $
|
||||
* $Id: file.h,v 1.4 1993/11/03 04:04:19 mycroft Exp $
|
||||
*
|
||||
* Copyright (c) Ian F. Darwin, 1987.
|
||||
* Written by Ian F. Darwin.
|
||||
@ -35,13 +35,14 @@
|
||||
struct magic {
|
||||
short flag;
|
||||
#define INDIR 1 /* if '>(...)' appears, */
|
||||
#define UNSIGNED 2 /* comparison is unsigned */
|
||||
#define MASK 4 /* this is a masked op, like & v1 = v2 */
|
||||
short cont_level; /* level of ">" */
|
||||
struct {
|
||||
char type; /* byte short long */
|
||||
long offset; /* offset from indirection */
|
||||
} in;
|
||||
long offset; /* offset to magic number */
|
||||
#define MASK 0200 /* this is a masked op, like & v1 = v2 */
|
||||
unsigned char reln; /* relation (0=eq, '>'=gt, etc) */
|
||||
char type; /* int, short, long or string. */
|
||||
char vallen; /* length of string value, if any */
|
||||
@ -57,14 +58,14 @@ struct magic {
|
||||
#define LELONG 11
|
||||
#define LEDATE 12
|
||||
union VALUETYPE {
|
||||
char b;
|
||||
short h;
|
||||
long l;
|
||||
unsigned char b;
|
||||
unsigned short h;
|
||||
unsigned long l;
|
||||
char s[MAXstring];
|
||||
unsigned char hs[2]; /* 2 bytes of a fixed-endian "short" */
|
||||
unsigned char hl[4]; /* 2 bytes of a fixed-endian "long" */
|
||||
} value; /* either number or string */
|
||||
long mask; /* mask before comparison with value */
|
||||
unsigned long mask; /* mask before comparison with value */
|
||||
char nospflag; /* supress space character */
|
||||
char desc[MAXDESC]; /* description */
|
||||
};
|
||||
|
@ -26,7 +26,7 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$Id: print.c,v 1.4 1993/08/06 01:47:19 deraadt Exp $";
|
||||
static char rcsid[] = "$Id: print.c,v 1.5 1993/11/03 04:04:20 mycroft Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
@ -45,31 +45,27 @@ void
|
||||
mdump(m)
|
||||
struct magic *m;
|
||||
{
|
||||
static char *offs[] = { "absolute", "offset",
|
||||
"indirect", "indirect-offset" };
|
||||
static char *typ[] = { "invalid", "byte", "short", "invalid",
|
||||
"long", "string", "date", "beshort",
|
||||
"belong", "bedate", "leshort", "lelong",
|
||||
"ledate" };
|
||||
(void) fprintf(stderr, "[%s,%d,%s,%s%c,",
|
||||
(m->flag >= 0 && m->flag < 4 ? offs[m->flag]: "*bad*"),
|
||||
m->offset,
|
||||
(m->type >= 0 && m->type < 13 ?
|
||||
typ[(unsigned char) m->type] : "*bad*"),
|
||||
m->reln & MASK ? "&" : "",
|
||||
m->reln & ~MASK);
|
||||
printf(">>>>>>>>%d" + 8 - m->cont_level, m->offset);
|
||||
if (m->flag & INDIR)
|
||||
(void) fprintf(stderr, "(%s,%d)",
|
||||
(m->in.type >= 0 &&
|
||||
m->in.type < 6 ? typ[(unsigned char) m->in.type] : "*bad*"),
|
||||
printf("(%s,%d)",
|
||||
(m->in.type >= 0 && m->in.type < 6 ?
|
||||
typ[(unsigned char) m->in.type] : "*bad*"),
|
||||
m->in.offset);
|
||||
|
||||
printf(" %s%s", m->flag & UNSIGNED ? "u" : "",
|
||||
(m->type >= 0 && m->type < 13 ?
|
||||
typ[(unsigned char) m->type] : "*bad*"));
|
||||
if (m->flag & MASK)
|
||||
printf("&%d", m->mask);
|
||||
printf(" %c", m->reln);
|
||||
if (m->type == STRING)
|
||||
showstr(m->value.s);
|
||||
else
|
||||
(void) fprintf(stderr, "%d",m->value.l);
|
||||
(void) fprintf(stderr, ",%s", m->desc);
|
||||
(void) fputs("]\n", stderr);
|
||||
printf("%d", m->value.l);
|
||||
printf(" %s\n", m->desc);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -26,7 +26,7 @@
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$Id: softmagic.c,v 1.4 1993/08/06 01:47:19 deraadt Exp $";
|
||||
static char rcsid[] = "$Id: softmagic.c,v 1.5 1993/11/03 04:04:22 mycroft Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
@ -38,7 +38,10 @@ static char rcsid[] = "$Id: softmagic.c,v 1.4 1993/08/06 01:47:19 deraadt Exp $"
|
||||
|
||||
static int match __P((unsigned char *));
|
||||
static int mcheck __P((unsigned char *, struct magic *));
|
||||
static void mprint __P((struct magic *, unsigned char *));
|
||||
static void mprint __P((unsigned char *, struct magic *, unsigned long));
|
||||
extern unsigned long signextend __P((struct magic *, unsigned long));
|
||||
|
||||
static int need_separator;
|
||||
|
||||
/*
|
||||
* softmagic - lookup one file in database
|
||||
@ -90,18 +93,11 @@ unsigned char *s;
|
||||
{
|
||||
int magindex = 0;
|
||||
int cont_level = 0;
|
||||
int need_separator = 0;
|
||||
|
||||
while (magindex < nmagic) {
|
||||
/* if main entry matches, print it... */
|
||||
need_separator = 0;
|
||||
if (mcheck(s, &magic[magindex])) {
|
||||
mprint(&magic[magindex],s);
|
||||
/*
|
||||
* If we printed something, we'll need to print
|
||||
* a blank before we print something else.
|
||||
*/
|
||||
if (magic[magindex].desc[0])
|
||||
need_separator = 1;
|
||||
/* and any continuations that match */
|
||||
cont_level++;
|
||||
while (magic[magindex+1].cont_level != 0 &&
|
||||
@ -122,24 +118,6 @@ unsigned char *s;
|
||||
if (mcheck(s, &magic[magindex])) {
|
||||
/*
|
||||
* This continuation matched.
|
||||
* Print its message, with
|
||||
* a blank before it if
|
||||
* the previous item printed
|
||||
* and this item isn't empty.
|
||||
*/
|
||||
/* space if previous printed */
|
||||
if (need_separator
|
||||
&& (magic[magindex].nospflag == 0)
|
||||
&& (magic[magindex].desc[0] != '\0')
|
||||
) {
|
||||
(void) putchar(' ');
|
||||
need_separator = 0;
|
||||
}
|
||||
mprint(&magic[magindex],s);
|
||||
if (magic[magindex].desc[0])
|
||||
need_separator = 1;
|
||||
|
||||
/*
|
||||
* If we see any continuations
|
||||
* at a higher level,
|
||||
* process them.
|
||||
@ -162,49 +140,29 @@ unsigned char *s;
|
||||
}
|
||||
|
||||
static void
|
||||
mprint(m, s)
|
||||
struct magic *m;
|
||||
mprint(s, m, v)
|
||||
unsigned char *s;
|
||||
struct magic *m;
|
||||
unsigned long v;
|
||||
{
|
||||
register union VALUETYPE *p = (union VALUETYPE *)(s+m->offset);
|
||||
char *pp, *rt;
|
||||
|
||||
/* correct byte order dependancies */
|
||||
switch (m->type) {
|
||||
case BESHORT:
|
||||
p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
|
||||
break;
|
||||
case BELONG:
|
||||
case BEDATE:
|
||||
p->l = (long)
|
||||
((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
|
||||
break;
|
||||
case LESHORT:
|
||||
p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
|
||||
break;
|
||||
case LELONG:
|
||||
case LEDATE:
|
||||
p->l = (long)
|
||||
((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
|
||||
break;
|
||||
if (m->desc[0]) {
|
||||
if (need_separator && !m->nospflag)
|
||||
(void) putchar(' ');
|
||||
need_separator = 1;
|
||||
}
|
||||
|
||||
switch (m->type) {
|
||||
case BYTE:
|
||||
(void) printf(m->desc,
|
||||
(m->reln & MASK) ? p->b & m->mask : p->b);
|
||||
break;
|
||||
case SHORT:
|
||||
case BESHORT:
|
||||
case LESHORT:
|
||||
(void) printf(m->desc,
|
||||
(m->reln & MASK) ? p->h & m->mask : p->h);
|
||||
break;
|
||||
case LONG:
|
||||
case BELONG:
|
||||
case LELONG:
|
||||
(void) printf(m->desc,
|
||||
(m->reln & MASK) ? p->l & m->mask : p->l);
|
||||
(void) printf(m->desc, v);
|
||||
break;
|
||||
case STRING:
|
||||
if ((rt=strchr(p->s, '\n')) != NULL)
|
||||
@ -216,7 +174,7 @@ unsigned char *s;
|
||||
case DATE:
|
||||
case BEDATE:
|
||||
case LEDATE:
|
||||
pp = ctime((time_t*) &p->l);
|
||||
pp = ctime((time_t*) &v);
|
||||
if ((rt = strchr(pp, '\n')) != NULL)
|
||||
*rt = '\0';
|
||||
(void) printf(m->desc, pp);
|
||||
@ -235,19 +193,21 @@ unsigned char *s;
|
||||
struct magic *m;
|
||||
{
|
||||
register union VALUETYPE *p = (union VALUETYPE *)(s+m->offset);
|
||||
register long l = m->value.l;
|
||||
register long mask = m->mask;
|
||||
register long v;
|
||||
register unsigned long l = m->value.l;
|
||||
register unsigned long v;
|
||||
register int matched;
|
||||
|
||||
if (debug) {
|
||||
(void) printf("mcheck: %10.10s ", s);
|
||||
mdump(m);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
|
||||
printf("BOINK");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (m->type) {
|
||||
case BYTE:
|
||||
@ -276,19 +236,19 @@ struct magic *m;
|
||||
}
|
||||
break;
|
||||
case BESHORT:
|
||||
v = (short)((p->hs[0]<<8)|(p->hs[1]));
|
||||
v = (unsigned short)((p->hs[0]<<8)|(p->hs[1]));
|
||||
break;
|
||||
case BELONG:
|
||||
case BEDATE:
|
||||
v = (long)
|
||||
v = (unsigned long)
|
||||
((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
|
||||
break;
|
||||
case LESHORT:
|
||||
v = (short)((p->hs[1]<<8)|(p->hs[0]));
|
||||
v = (unsigned short)((p->hs[1]<<8)|(p->hs[0]));
|
||||
break;
|
||||
case LELONG:
|
||||
case LEDATE:
|
||||
v = (long)
|
||||
v = (unsigned long)
|
||||
((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
|
||||
break;
|
||||
default:
|
||||
@ -296,32 +256,40 @@ struct magic *m;
|
||||
return -1;/*NOTREACHED*/
|
||||
}
|
||||
|
||||
if (m->mask != 0L)
|
||||
v = signextend(m, v);
|
||||
|
||||
if (m->flag & MASK)
|
||||
v &= m->mask;
|
||||
|
||||
switch (m->reln) {
|
||||
case 'x':
|
||||
return 1;
|
||||
matched = 1; break;
|
||||
case '!':
|
||||
return v != l;
|
||||
matched = v != l; break;
|
||||
case '=':
|
||||
return v == l;
|
||||
matched = v == l; break;
|
||||
case '>':
|
||||
return v > l;
|
||||
if (m->flag & UNSIGNED)
|
||||
matched = v > l;
|
||||
else
|
||||
matched = (long)v > (long)l;
|
||||
break;
|
||||
case '<':
|
||||
return v < l;
|
||||
if (m->flag & UNSIGNED)
|
||||
matched = v < l;
|
||||
else
|
||||
matched = (long)v < (long)l;
|
||||
break;
|
||||
case '&':
|
||||
return (v & l) == l;
|
||||
matched = (v & l) == l; break;
|
||||
case '^':
|
||||
return (v & l) != l;
|
||||
case MASK | '=':
|
||||
return (v & mask) == l;
|
||||
case MASK | '>':
|
||||
return (v & mask) > l;
|
||||
case MASK | '<':
|
||||
return (v & mask) < l;
|
||||
matched = (v & l) != l; break;
|
||||
default:
|
||||
error("mcheck: can't happen: invalid relation %d.\n", m->reln);
|
||||
return -1;/*NOTREACHED*/
|
||||
}
|
||||
|
||||
if (matched)
|
||||
mprint(s, m, v);
|
||||
return matched;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user