diff options
Diffstat (limited to 'contrib/file/softmagic.c')
-rw-r--r-- | contrib/file/softmagic.c | 861 |
1 files changed, 487 insertions, 374 deletions
diff --git a/contrib/file/softmagic.c b/contrib/file/softmagic.c index d1ef94d..4e063b9 100644 --- a/contrib/file/softmagic.c +++ b/contrib/file/softmagic.c @@ -1,31 +1,41 @@ /* + * Copyright (c) Ian F. Darwin 1986-1995. + * Software written by Ian F. Darwin and others; + * maintained 1995-present by Christos Zoulas and others. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Ian F. Darwin and others. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* * softmagic - interpret variable magic from MAGIC - * - * Copyright (c) Ian F. Darwin, 1987. - * Written by Ian F. Darwin. - * - * This software is not subject to any license of the American Telephone - * and Telegraph Company or of the Regents of the University of California. - * - * Permission is granted to anyone to use this software for any purpose on - * any computer system, and to alter it and redistribute it freely, subject - * to the following restrictions: - * - * 1. The author is not responsible for the consequences of use of this - * software, no matter how awful, even if they arise from flaws in it. - * - * 2. The origin of this software must not be misrepresented, either by - * explicit claim or by omission. Since few users ever read sources, - * credits must appear in the documentation. - * - * 3. Altered versions must be plainly marked as such, and must not be - * misrepresented as being the original software. Since few users - * ever read sources, credits must appear in the documentation. - * - * 4. This notice may not be removed or altered. */ #include "file.h" +#include "magic.h" #include <string.h> #include <ctype.h> #include <stdlib.h> @@ -34,17 +44,18 @@ #ifndef lint -FILE_RCSID("@(#)$Id: softmagic.c,v 1.54 2003/02/25 13:04:32 christos Exp $") +FILE_RCSID("@(#)$Id: softmagic.c,v 1.66 2004/07/24 20:38:56 christos Exp $") #endif /* lint */ -static int match(struct magic *, uint32_t, unsigned char *, int); -static int mget(union VALUETYPE *, unsigned char *, struct magic *, int); -static int mcheck(union VALUETYPE *, struct magic *); -static int32_t mprint(union VALUETYPE *, struct magic *); -static void mdebug(int32_t, char *, int); -static int mconvert(union VALUETYPE *, struct magic *); - -extern int kflag; +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 *, + struct magic *, size_t); +private int mcheck(struct magic_set *, union VALUETYPE *, struct magic *); +private int32_t mprint(struct magic_set *, union VALUETYPE *, struct magic *); +private void mdebug(uint32_t, const char *, size_t); +private int mconvert(struct magic_set *, union VALUETYPE *, struct magic *); +private int check_mem(struct magic_set *, unsigned int); /* * softmagic - lookup one file in database @@ -52,13 +63,12 @@ extern int kflag; * Passed the name and FILE * of one file to be typed. */ /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */ -int -softmagic(unsigned char *buf, int nbytes) +protected int +file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes) { struct mlist *ml; - - for (ml = mlist.next; ml != &mlist; ml = ml->next) - if (match(ml->magic, ml->nmagic, buf, nbytes)) + for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next) + if (match(ms, ml->magic, ml->nmagic, buf, nbytes)) return 1; return 0; @@ -91,44 +101,53 @@ softmagic(unsigned char *buf, int nbytes) * If a continuation matches, we bump the current continuation level * so that higher-level continuations are processed. */ -static int -match(struct magic *magic, uint32_t nmagic, unsigned char *s, int nbytes) +private int +match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, + const unsigned char *s, size_t nbytes) { - int magindex = 0; - int cont_level = 0; + uint32_t magindex = 0; + unsigned int cont_level = 0; int need_separator = 0; union VALUETYPE p; - static int32_t *tmpoff = NULL; - static size_t tmplen = 0; 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 */ - if (tmpoff == NULL) - if ((tmpoff = (int32_t *) malloc( - (tmplen = 20) * sizeof(*tmpoff))) == NULL) - error("out of memory\n"); + if (check_mem(ms, cont_level) == -1) + return -1; for (magindex = 0; magindex < nmagic; magindex++) { /* if main entry matches, print it... */ - if (!mget(&p, s, &magic[magindex], nbytes) || - !mcheck(&p, &magic[magindex])) { - /* - * main entry didn't match, - * flush its continuations - */ - while (magindex < nmagic && - magic[magindex + 1].cont_level != 0) - magindex++; - continue; + int flush = !mget(ms, &p, s, &magic[magindex], nbytes); + switch (mcheck(ms, &p, &magic[magindex])) { + case -1: + return -1; + case 0: + flush++; + break; + default: + break; + } + if (flush) { + /* + * main entry didn't match, + * flush its continuations + */ + while (magindex < nmagic - 1 && + magic[magindex + 1].cont_level != 0) + magindex++; + continue; } - if (! firstline) { /* we found another match */ + if (!firstline) { /* we found another match */ /* put a newline and '-' to do some simple formatting*/ - printf("\n- "); + if (file_printf(ms, "\n- ") == -1) + return -1; } - tmpoff[cont_level] = mprint(&p, &magic[magindex]); + if ((ms->c.off[cont_level] = mprint(ms, &p, &magic[magindex])) + == -1) + return -1; /* * If we printed something, we'll need to print * a blank before we print something else. @@ -136,107 +155,130 @@ match(struct magic *magic, uint32_t nmagic, unsigned char *s, int nbytes) if (magic[magindex].desc[0]) need_separator = 1; /* and any continuations that match */ - if (++cont_level >= tmplen) - if ((tmpoff = (int32_t *) realloc(tmpoff, - (tmplen += 20) * sizeof(*tmpoff))) == NULL) - error("out of memory\n"); + if (check_mem(ms, ++cont_level) == -1) + return -1; + while (magic[magindex+1].cont_level != 0 && ++magindex < nmagic) { - if (cont_level >= magic[magindex].cont_level) { - if (cont_level > magic[magindex].cont_level) { - /* - * We're at the end of the level - * "cont_level" continuations. - */ - cont_level = magic[magindex].cont_level; - } - if (magic[magindex].flag & OFFADD) { - oldoff=magic[magindex].offset; - magic[magindex].offset += - tmpoff[cont_level-1]; + if (cont_level < magic[magindex].cont_level) + continue; + if (cont_level > magic[magindex].cont_level) { + /* + * We're at the end of the level + * "cont_level" continuations. + */ + cont_level = magic[magindex].cont_level; + } + if (magic[magindex].flag & OFFADD) { + oldoff=magic[magindex].offset; + magic[magindex].offset += ms->c.off[cont_level-1]; + } + if (!mget(ms, &p, s, &magic[magindex], nbytes)) + goto done; + + switch (mcheck(ms, &p, &magic[magindex])) { + case -1: + return -1; + case 0: + break; + default: + /* + * 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')) { + if (file_printf(ms, " ") == -1) + return -1; + need_separator = 0; } - if (mget(&p, s, &magic[magindex], nbytes) && - mcheck(&p, &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; - } - tmpoff[cont_level] = - mprint(&p, &magic[magindex]); - if (magic[magindex].desc[0]) - need_separator = 1; + if ((ms->c.off[cont_level] = mprint(ms, &p, + &magic[magindex])) == -1) + return -1; + if (magic[magindex].desc[0]) + need_separator = 1; - /* - * If we see any continuations - * at a higher level, - * process them. - */ - if (++cont_level >= tmplen) - if ((tmpoff = - (int32_t *) realloc(tmpoff, - (tmplen += 20) - * sizeof(*tmpoff))) == NULL) - error("out of memory\n"); - } - if (magic[magindex].flag & OFFADD) { - magic[magindex].offset = oldoff; - } + /* + * If we see any continuations + * at a higher level, + * process them. + */ + if (check_mem(ms, ++cont_level) == -1) + return -1; + } +done: + if (magic[magindex].flag & OFFADD) { + magic[magindex].offset = oldoff; } } firstline = 0; returnval = 1; - if (!kflag) { + if ((ms->flags & MAGIC_CONTINUE) == 0) { return 1; /* don't keep searching */ } } return returnval; /* This is hit if -k is set or there is no match */ } -static int32_t -mprint(union VALUETYPE *p, struct magic *m) +private int +check_mem(struct magic_set *ms, unsigned int level) +{ + size_t len; + + 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) + return 0; + file_oomem(ms); + return -1; +} + +private int32_t +mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m) { uint32_t v; int32_t t=0 ; switch (m->type) { - case BYTE: - v = signextend(m, p->b); - (void) printf(m->desc, (unsigned char) v); + case FILE_BYTE: + v = file_signextend(ms, m, (size_t)p->b); + if (file_printf(ms, m->desc, (unsigned char) v) == -1) + return -1; t = m->offset + sizeof(char); break; - case SHORT: - case BESHORT: - case LESHORT: - v = signextend(m, p->h); - (void) printf(m->desc, (unsigned short) v); + case FILE_SHORT: + case FILE_BESHORT: + case FILE_LESHORT: + v = file_signextend(ms, m, (size_t)p->h); + if (file_printf(ms, m->desc, (unsigned short) v) == -1) + return -1; t = m->offset + sizeof(short); break; - case LONG: - case BELONG: - case LELONG: - v = signextend(m, p->l); - (void) printf(m->desc, (uint32_t) v); + case FILE_LONG: + case FILE_BELONG: + case FILE_LELONG: + v = file_signextend(ms, m, p->l); + if (file_printf(ms, m->desc, (uint32_t) v) == -1) + return -1; t = m->offset + sizeof(int32_t); break; - case STRING: - case PSTRING: + case FILE_STRING: + case FILE_PSTRING: if (m->reln == '=') { - (void) printf(m->desc, m->value.s); + if (file_printf(ms, m->desc, m->value.s) == -1) + return -1; t = m->offset + strlen(m->value.s); } else { @@ -245,32 +287,36 @@ mprint(union VALUETYPE *p, struct magic *m) if (cp) *cp = '\0'; } - (void) printf(m->desc, p->s); + if (file_printf(ms, m->desc, p->s) == -1) + return -1; t = m->offset + strlen(p->s); } break; - case DATE: - case BEDATE: - case LEDATE: - (void) printf(m->desc, fmttime(p->l, 1)); + case FILE_DATE: + case FILE_BEDATE: + case FILE_LEDATE: + if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1) + return -1; t = m->offset + sizeof(time_t); break; - case LDATE: - case BELDATE: - case LELDATE: - (void) printf(m->desc, fmttime(p->l, 0)); + case FILE_LDATE: + case FILE_BELDATE: + case FILE_LELDATE: + if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1) + return -1; t = m->offset + sizeof(time_t); break; - case REGEX: - (void) printf(m->desc, p->s); + case FILE_REGEX: + if (file_printf(ms, m->desc, p->s) == -1) + return -1; t = m->offset + strlen(p->s); break; default: - error("invalid m->type (%d) in mprint().\n", m->type); - /*NOTREACHED*/ + file_error(ms, 0, "invalid m->type (%d) in mprint()", m->type); + return -1; } return(t); } @@ -280,106 +326,106 @@ mprint(union VALUETYPE *p, struct magic *m) * While we're here, let's apply the mask operation * (unless you have a better idea) */ -static int -mconvert(union VALUETYPE *p, struct magic *m) +private int +mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m) { switch (m->type) { - case BYTE: + case FILE_BYTE: if (m->mask) switch (m->mask_op&0x7F) { - case OPAND: + case FILE_OPAND: p->b &= m->mask; break; - case OPOR: + case FILE_OPOR: p->b |= m->mask; break; - case OPXOR: + case FILE_OPXOR: p->b ^= m->mask; break; - case OPADD: + case FILE_OPADD: p->b += m->mask; break; - case OPMINUS: + case FILE_OPMINUS: p->b -= m->mask; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: p->b *= m->mask; break; - case OPDIVIDE: + case FILE_OPDIVIDE: p->b /= m->mask; break; - case OPMODULO: + case FILE_OPMODULO: p->b %= m->mask; break; } - if (m->mask_op & OPINVERSE) + if (m->mask_op & FILE_OPINVERSE) p->b = ~p->b; return 1; - case SHORT: + case FILE_SHORT: if (m->mask) switch (m->mask_op&0x7F) { - case OPAND: + case FILE_OPAND: p->h &= m->mask; break; - case OPOR: + case FILE_OPOR: p->h |= m->mask; break; - case OPXOR: + case FILE_OPXOR: p->h ^= m->mask; break; - case OPADD: + case FILE_OPADD: p->h += m->mask; break; - case OPMINUS: + case FILE_OPMINUS: p->h -= m->mask; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: p->h *= m->mask; break; - case OPDIVIDE: + case FILE_OPDIVIDE: p->h /= m->mask; break; - case OPMODULO: + case FILE_OPMODULO: p->h %= m->mask; break; } - if (m->mask_op & OPINVERSE) + if (m->mask_op & FILE_OPINVERSE) p->h = ~p->h; return 1; - case LONG: - case DATE: - case LDATE: + case FILE_LONG: + case FILE_DATE: + case FILE_LDATE: if (m->mask) switch (m->mask_op&0x7F) { - case OPAND: + case FILE_OPAND: p->l &= m->mask; break; - case OPOR: + case FILE_OPOR: p->l |= m->mask; break; - case OPXOR: + case FILE_OPXOR: p->l ^= m->mask; break; - case OPADD: + case FILE_OPADD: p->l += m->mask; break; - case OPMINUS: + case FILE_OPMINUS: p->l -= m->mask; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: p->l *= m->mask; break; - case OPDIVIDE: + case FILE_OPDIVIDE: p->l /= m->mask; break; - case OPMODULO: + case FILE_OPMODULO: p->l %= m->mask; break; } - if (m->mask_op & OPINVERSE) + if (m->mask_op & FILE_OPINVERSE) p->l = ~p->l; return 1; - case STRING: + case FILE_STRING: { int n; @@ -390,10 +436,10 @@ mconvert(union VALUETYPE *p, struct magic *m) p->s[n] = '\0'; return 1; } - case PSTRING: + case FILE_PSTRING: { char *ptr1 = p->s, *ptr2 = ptr1 + 1; - int n = *p->s; + unsigned int n = *p->s; if (n >= sizeof(p->s)) n = sizeof(p->s) - 1; while (n--) @@ -404,175 +450,180 @@ mconvert(union VALUETYPE *p, struct magic *m) p->s[n] = '\0'; return 1; } - case BESHORT: + case FILE_BESHORT: p->h = (short)((p->hs[0]<<8)|(p->hs[1])); if (m->mask) switch (m->mask_op&0x7F) { - case OPAND: + case FILE_OPAND: p->h &= m->mask; break; - case OPOR: + case FILE_OPOR: p->h |= m->mask; break; - case OPXOR: + case FILE_OPXOR: p->h ^= m->mask; break; - case OPADD: + case FILE_OPADD: p->h += m->mask; break; - case OPMINUS: + case FILE_OPMINUS: p->h -= m->mask; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: p->h *= m->mask; break; - case OPDIVIDE: + case FILE_OPDIVIDE: p->h /= m->mask; break; - case OPMODULO: + case FILE_OPMODULO: p->h %= m->mask; break; } - if (m->mask_op & OPINVERSE) + if (m->mask_op & FILE_OPINVERSE) p->h = ~p->h; return 1; - case BELONG: - case BEDATE: - case BELDATE: + case FILE_BELONG: + case FILE_BEDATE: + case FILE_BELDATE: p->l = (int32_t) ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3])); if (m->mask) switch (m->mask_op&0x7F) { - case OPAND: + case FILE_OPAND: p->l &= m->mask; break; - case OPOR: + case FILE_OPOR: p->l |= m->mask; break; - case OPXOR: + case FILE_OPXOR: p->l ^= m->mask; break; - case OPADD: + case FILE_OPADD: p->l += m->mask; break; - case OPMINUS: + case FILE_OPMINUS: p->l -= m->mask; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: p->l *= m->mask; break; - case OPDIVIDE: + case FILE_OPDIVIDE: p->l /= m->mask; break; - case OPMODULO: + case FILE_OPMODULO: p->l %= m->mask; break; } - if (m->mask_op & OPINVERSE) + if (m->mask_op & FILE_OPINVERSE) p->l = ~p->l; return 1; - case LESHORT: + case FILE_LESHORT: p->h = (short)((p->hs[1]<<8)|(p->hs[0])); if (m->mask) switch (m->mask_op&0x7F) { - case OPAND: + case FILE_OPAND: p->h &= m->mask; break; - case OPOR: + case FILE_OPOR: p->h |= m->mask; break; - case OPXOR: + case FILE_OPXOR: p->h ^= m->mask; break; - case OPADD: + case FILE_OPADD: p->h += m->mask; break; - case OPMINUS: + case FILE_OPMINUS: p->h -= m->mask; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: p->h *= m->mask; break; - case OPDIVIDE: + case FILE_OPDIVIDE: p->h /= m->mask; break; - case OPMODULO: + case FILE_OPMODULO: p->h %= m->mask; break; } - if (m->mask_op & OPINVERSE) + if (m->mask_op & FILE_OPINVERSE) p->h = ~p->h; return 1; - case LELONG: - case LEDATE: - case LELDATE: + case FILE_LELONG: + case FILE_LEDATE: + case FILE_LELDATE: p->l = (int32_t) ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0])); if (m->mask) switch (m->mask_op&0x7F) { - case OPAND: + case FILE_OPAND: p->l &= m->mask; break; - case OPOR: + case FILE_OPOR: p->l |= m->mask; break; - case OPXOR: + case FILE_OPXOR: p->l ^= m->mask; break; - case OPADD: + case FILE_OPADD: p->l += m->mask; break; - case OPMINUS: + case FILE_OPMINUS: p->l -= m->mask; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: p->l *= m->mask; break; - case OPDIVIDE: + case FILE_OPDIVIDE: p->l /= m->mask; break; - case OPMODULO: + case FILE_OPMODULO: p->l %= m->mask; break; } - if (m->mask_op & OPINVERSE) + if (m->mask_op & FILE_OPINVERSE) p->l = ~p->l; return 1; - case REGEX: + case FILE_REGEX: return 1; default: - error("invalid type %d in mconvert().\n", m->type); + file_error(ms, 0, "invalid type %d in mconvert()", m->type); return 0; } } -static void -mdebug(int32_t offset, char *str, int len) +private void +mdebug(uint32_t offset, const char *str, size_t len) { (void) fprintf(stderr, "mget @%d: ", offset); - showstr(stderr, (char *) str, len); + file_showstr(stderr, str, len); (void) fputc('\n', stderr); (void) fputc('\n', stderr); } -static int -mget(union VALUETYPE *p, unsigned char *s, struct magic *m, int nbytes) +private int +mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s, + struct magic *m, size_t nbytes) { - int32_t offset = m->offset; + uint32_t offset = m->offset; - if (m->type == REGEX) { - /* - * offset is interpreted as last line to search, - * (starting at 1), not as bytes-from start-of-file - */ - unsigned char *last = NULL; - p->buf = (char *)s; - for (; offset && (s = (unsigned char *)strchr(s, '\n')) != NULL; - offset--, s++) - last = s; - if (last != NULL) - *last = '\0'; + if (m->type == FILE_REGEX) { + /* + * offset is interpreted as last line to search, + * (starting at 1), not as bytes-from start-of-file + */ + unsigned char *b, *last = NULL; + if ((p->buf = strdup((const char *)s)) == NULL) { + file_oomem(ms); + return -1; + } + for (b = (unsigned char *)p->buf; offset && + (b = (unsigned char *)strchr((char *)b, '\n')) != NULL; + offset--, s++) + last = b; + if (last != NULL) + *last = '\0'; } else if (offset + sizeof(union VALUETYPE) <= nbytes) memcpy(p, s + offset, sizeof(union VALUETYPE)); else { @@ -580,228 +631,272 @@ mget(union VALUETYPE *p, unsigned char *s, struct magic *m, int nbytes) * the usefulness of padding with zeroes eludes me, it * might even cause problems */ - int32_t have = nbytes - offset; memset(p, 0, sizeof(union VALUETYPE)); - if (have > 0) - memcpy(p, s + offset, have); + if (offset < nbytes) + memcpy(p, s + offset, nbytes - offset); } - if (debug) { - mdebug(offset, (char *) p, sizeof(union VALUETYPE)); - mdump(m); + /* 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_LONG: + case FILE_BELONG: + case FILE_LELONG: + case FILE_DATE: + case FILE_BEDATE: + case FILE_LEDATE: + case FILE_LDATE: + case FILE_BELDATE: + case FILE_LELDATE: + if (nbytes < (offset + 4)) + return 0; + break; + + case FILE_STRING: + case FILE_PSTRING: + if (nbytes < (offset + m->vallen)) + return 0; + break; + } + + if ((ms->flags & MAGIC_DEBUG) != 0) { + mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE)); + file_mdump(m); } if (m->flag & INDIR) { switch (m->in_type) { - case BYTE: - if (m->in_offset) + case FILE_BYTE: + if (m->in_offset) { switch (m->in_op&0x7F) { - case OPAND: + case FILE_OPAND: offset = p->b & m->in_offset; break; - case OPOR: + case FILE_OPOR: offset = p->b | m->in_offset; break; - case OPXOR: + case FILE_OPXOR: offset = p->b ^ m->in_offset; break; - case OPADD: + case FILE_OPADD: offset = p->b + m->in_offset; break; - case OPMINUS: + case FILE_OPMINUS: offset = p->b - m->in_offset; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: offset = p->b * m->in_offset; break; - case OPDIVIDE: + case FILE_OPDIVIDE: offset = p->b / m->in_offset; break; - case OPMODULO: + case FILE_OPMODULO: offset = p->b % m->in_offset; break; } - if (m->in_op & OPINVERSE) + } else + offset = p->b; + if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; - case BESHORT: - if (m->in_offset) - switch (m->in_op&0x7F) { - case OPAND: + case FILE_BESHORT: + if (m->in_offset) { + switch (m->in_op & 0x7F) { + case FILE_OPAND: offset = (short)((p->hs[0]<<8)| (p->hs[1])) & m->in_offset; break; - case OPOR: + case FILE_OPOR: offset = (short)((p->hs[0]<<8)| (p->hs[1])) | m->in_offset; break; - case OPXOR: + case FILE_OPXOR: offset = (short)((p->hs[0]<<8)| (p->hs[1])) ^ m->in_offset; break; - case OPADD: + case FILE_OPADD: offset = (short)((p->hs[0]<<8)| (p->hs[1])) + m->in_offset; break; - case OPMINUS: + case FILE_OPMINUS: offset = (short)((p->hs[0]<<8)| (p->hs[1])) - m->in_offset; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: offset = (short)((p->hs[0]<<8)| (p->hs[1])) * m->in_offset; break; - case OPDIVIDE: + case FILE_OPDIVIDE: offset = (short)((p->hs[0]<<8)| (p->hs[1])) / m->in_offset; break; - case OPMODULO: + case FILE_OPMODULO: offset = (short)((p->hs[0]<<8)| (p->hs[1])) % m->in_offset; break; } - if (m->in_op & OPINVERSE) + } else + offset = (short)((p->hs[0]<<8)| + (p->hs[1])); + if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; - case LESHORT: - if (m->in_offset) - switch (m->in_op&0x7F) { - case OPAND: + case FILE_LESHORT: + if (m->in_offset) { + switch (m->in_op & 0x7F) { + case FILE_OPAND: offset = (short)((p->hs[1]<<8)| (p->hs[0])) & m->in_offset; break; - case OPOR: + case FILE_OPOR: offset = (short)((p->hs[1]<<8)| (p->hs[0])) | m->in_offset; break; - case OPXOR: + case FILE_OPXOR: offset = (short)((p->hs[1]<<8)| (p->hs[0])) ^ m->in_offset; break; - case OPADD: + case FILE_OPADD: offset = (short)((p->hs[1]<<8)| (p->hs[0])) + m->in_offset; break; - case OPMINUS: + case FILE_OPMINUS: offset = (short)((p->hs[1]<<8)| (p->hs[0])) - m->in_offset; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: offset = (short)((p->hs[1]<<8)| (p->hs[0])) * m->in_offset; break; - case OPDIVIDE: + case FILE_OPDIVIDE: offset = (short)((p->hs[1]<<8)| (p->hs[0])) / m->in_offset; break; - case OPMODULO: + case FILE_OPMODULO: offset = (short)((p->hs[1]<<8)| (p->hs[0])) % m->in_offset; break; } - if (m->in_op & OPINVERSE) + } else + offset = (short)((p->hs[1]<<8)| + (p->hs[0])); + if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; - case SHORT: - if (m->in_offset) - switch (m->in_op&0x7F) { - case OPAND: + case FILE_SHORT: + if (m->in_offset) { + switch (m->in_op & 0x7F) { + case FILE_OPAND: offset = p->h & m->in_offset; break; - case OPOR: + case FILE_OPOR: offset = p->h | m->in_offset; break; - case OPXOR: + case FILE_OPXOR: offset = p->h ^ m->in_offset; break; - case OPADD: + case FILE_OPADD: offset = p->h + m->in_offset; break; - case OPMINUS: + case FILE_OPMINUS: offset = p->h - m->in_offset; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: offset = p->h * m->in_offset; break; - case OPDIVIDE: + case FILE_OPDIVIDE: offset = p->h / m->in_offset; break; - case OPMODULO: + case FILE_OPMODULO: offset = p->h % m->in_offset; break; } - if (m->in_op & OPINVERSE) + } + else + offset = p->h; + if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; - case BELONG: - if (m->in_offset) - switch (m->in_op&0x7F) { - case OPAND: + case FILE_BELONG: + if (m->in_offset) { + switch (m->in_op & 0x7F) { + case FILE_OPAND: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) & m->in_offset; break; - case OPOR: + case FILE_OPOR: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) | m->in_offset; break; - case OPXOR: + case FILE_OPXOR: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) ^ m->in_offset; break; - case OPADD: + case FILE_OPADD: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) + m->in_offset; break; - case OPMINUS: + case FILE_OPMINUS: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) - m->in_offset; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) * m->in_offset; break; - case OPDIVIDE: + case FILE_OPDIVIDE: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) / m->in_offset; break; - case OPMODULO: + case FILE_OPMODULO: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| @@ -809,62 +904,67 @@ mget(union VALUETYPE *p, unsigned char *s, struct magic *m, int nbytes) m->in_offset; break; } - if (m->in_op & OPINVERSE) + } else + offset = (int32_t)((p->hl[0]<<24)| + (p->hl[1]<<16)| + (p->hl[2]<<8)| + (p->hl[3])); + if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; - case LELONG: - if (m->in_offset) - switch (m->in_op&0x7F) { - case OPAND: + case FILE_LELONG: + if (m->in_offset) { + switch (m->in_op & 0x7F) { + case FILE_OPAND: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) & m->in_offset; break; - case OPOR: + case FILE_OPOR: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) | m->in_offset; break; - case OPXOR: + case FILE_OPXOR: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) ^ m->in_offset; break; - case OPADD: + case FILE_OPADD: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) + m->in_offset; break; - case OPMINUS: + case FILE_OPMINUS: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) - m->in_offset; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) * m->in_offset; break; - case OPDIVIDE: + case FILE_OPDIVIDE: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) / m->in_offset; break; - case OPMODULO: + case FILE_OPMODULO: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| @@ -872,34 +972,39 @@ mget(union VALUETYPE *p, unsigned char *s, struct magic *m, int nbytes) m->in_offset; break; } - if (m->in_op & OPINVERSE) + } else + offset = (int32_t)((p->hl[3]<<24)| + (p->hl[2]<<16)| + (p->hl[1]<<8)| + (p->hl[0])); + if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; - case LONG: - if (m->in_offset) - switch (m->in_op&0x7F) { - case OPAND: + case FILE_LONG: + if (m->in_offset) { + switch (m->in_op & 0x7F) { + case FILE_OPAND: offset = p->l & m->in_offset; break; - case OPOR: + case FILE_OPOR: offset = p->l | m->in_offset; break; - case OPXOR: + case FILE_OPXOR: offset = p->l ^ m->in_offset; break; - case OPADD: + case FILE_OPADD: offset = p->l + m->in_offset; break; - case OPMINUS: + case FILE_OPMINUS: offset = p->l - m->in_offset; break; - case OPMULTIPLY: + case FILE_OPMULTIPLY: offset = p->l * m->in_offset; break; - case OPDIVIDE: + case FILE_OPDIVIDE: offset = p->l / m->in_offset; break; - case OPMODULO: + case FILE_OPMODULO: offset = p->l % m->in_offset; break; /* case TOOMANYSWITCHBLOCKS: @@ -910,64 +1015,67 @@ mget(union VALUETYPE *p, unsigned char *s, struct magic *m, int nbytes) * sleep; */ } - if (m->in_op & OPINVERSE) + } else + offset = p->l; + if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; } - if (offset + sizeof(union VALUETYPE) > nbytes) + if (nbytes < sizeof(union VALUETYPE) || + nbytes - sizeof(union VALUETYPE) < offset) return 0; memcpy(p, s + offset, sizeof(union VALUETYPE)); - if (debug) { - mdebug(offset, (char *) p, sizeof(union VALUETYPE)); - mdump(m); + if ((ms->flags & MAGIC_DEBUG) != 0) { + mdebug(offset, (char *)(void *)p, + sizeof(union VALUETYPE)); + file_mdump(m); } } - if (!mconvert(p, m)) + if (!mconvert(ms, p, m)) return 0; return 1; } -static int -mcheck(union VALUETYPE *p, struct magic *m) +private int +mcheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m) { uint32_t l = m->value.l; uint32_t v; int matched; if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) { - fprintf(stderr, "BOINK"); return 1; } switch (m->type) { - case BYTE: + case FILE_BYTE: v = p->b; break; - case SHORT: - case BESHORT: - case LESHORT: + case FILE_SHORT: + case FILE_BESHORT: + case FILE_LESHORT: v = p->h; break; - case LONG: - case BELONG: - case LELONG: - case DATE: - case BEDATE: - case LEDATE: - case LDATE: - case BELDATE: - case LELDATE: + case FILE_LONG: + case FILE_BELONG: + case FILE_LELONG: + case FILE_DATE: + case FILE_BEDATE: + case FILE_LEDATE: + case FILE_LDATE: + case FILE_BELDATE: + case FILE_LELDATE: v = p->l; break; - case STRING: - case PSTRING: + case FILE_STRING: + case FILE_PSTRING: { /* * What we want here is: @@ -1013,7 +1121,7 @@ mcheck(union VALUETYPE *p, struct magic *m) } break; } - case REGEX: + case FILE_REGEX: { int rc; regex_t rx; @@ -1021,38 +1129,42 @@ mcheck(union VALUETYPE *p, struct magic *m) rc = regcomp(&rx, m->value.s, REG_EXTENDED|REG_NOSUB); if (rc) { + free(p->buf); regerror(rc, &rx, errmsg, sizeof(errmsg)); - error("regex error %d, (%s)\n", rc, errmsg); + file_error(ms, 0, "regex error %d, (%s)", rc, errmsg); + return -1; } else { rc = regexec(&rx, p->buf, 0, 0, 0); + regfree(&rx); + free(p->buf); return !rc; } } default: - error("invalid type %d in mcheck().\n", m->type); - return 0;/*NOTREACHED*/ + file_error(ms, 0, "invalid type %d in mcheck()", m->type); + return -1; } - if(m->type != STRING && m->type != PSTRING) - v = signextend(m, v); + if (m->type != FILE_STRING && m->type != FILE_PSTRING) + v = file_signextend(ms, m, v); switch (m->reln) { case 'x': - if (debug) + if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%u == *any* = 1\n", v); matched = 1; break; case '!': matched = v != l; - if (debug) + if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%u != %u = %d\n", v, l, matched); break; case '=': matched = v == l; - if (debug) + if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%u == %u = %d\n", v, l, matched); break; @@ -1060,13 +1172,13 @@ mcheck(union VALUETYPE *p, struct magic *m) case '>': if (m->flag & UNSIGNED) { matched = v > l; - if (debug) + if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%u > %u = %d\n", v, l, matched); } else { matched = (int32_t) v > (int32_t) l; - if (debug) + if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%d > %d = %d\n", v, l, matched); } @@ -1075,13 +1187,13 @@ mcheck(union VALUETYPE *p, struct magic *m) case '<': if (m->flag & UNSIGNED) { matched = v < l; - if (debug) + if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%u < %u = %d\n", v, l, matched); } else { matched = (int32_t) v < (int32_t) l; - if (debug) + if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%d < %d = %d\n", v, l, matched); } @@ -1089,22 +1201,23 @@ mcheck(union VALUETYPE *p, struct magic *m) case '&': matched = (v & l) == l; - if (debug) + if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "((%x & %x) == %x) = %d\n", v, l, l, matched); break; case '^': matched = (v & l) != l; - if (debug) + if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "((%x & %x) != %x) = %d\n", v, l, l, matched); break; default: matched = 0; - error("mcheck: can't happen: invalid relation %d.\n", m->reln); - break;/*NOTREACHED*/ + file_error(ms, 0, "cannot happen: invalid relation `%c'", + m->reln); + return -1; } return matched; |