diff options
Diffstat (limited to 'contrib/file/softmagic.c')
-rw-r--r-- | contrib/file/softmagic.c | 512 |
1 files changed, 377 insertions, 135 deletions
diff --git a/contrib/file/softmagic.c b/contrib/file/softmagic.c index 1202f72..edcba5e 100644 --- a/contrib/file/softmagic.c +++ b/contrib/file/softmagic.c @@ -39,13 +39,13 @@ #ifndef lint -FILE_RCSID("@(#)$Id: softmagic.c,v 1.72 2004/11/24 17:38:25 christos Exp $") +FILE_RCSID("@(#)$Id: softmagic.c,v 1.78 2006/03/12 22:09:33 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 *, - struct magic *, size_t); + struct magic *, size_t, unsigned int); 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); @@ -115,15 +115,20 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, for (magindex = 0; magindex < nmagic; magindex++) { /* if main entry matches, print it... */ - 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; + int flush = !mget(ms, &p, s, &magic[magindex], nbytes, + cont_level); + if (flush) { + if (magic[magindex].reln == '!') flush = 0; + } else { + switch (mcheck(ms, &p, &magic[magindex])) { + case -1: + return -1; + case 0: + flush++; + break; + default: + break; + } } if (flush) { /* @@ -166,14 +171,18 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, */ cont_level = magic[magindex].cont_level; } + oldoff = magic[magindex].offset; if (magic[magindex].flag & OFFADD) { - oldoff=magic[magindex].offset; - magic[magindex].offset += ms->c.off[cont_level-1]; + magic[magindex].offset += + ms->c.off[cont_level - 1]; } - if (!mget(ms, &p, s, &magic[magindex], nbytes)) + + flush = !mget(ms, &p, s, &magic[magindex], nbytes, + cont_level); + if (flush && magic[magindex].reln != '!') goto done; - switch (mcheck(ms, &p, &magic[magindex])) { + switch (flush ? 1 : mcheck(ms, &p, &magic[magindex])) { case -1: return -1; case 0: @@ -209,9 +218,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, return -1; } done: - if (magic[magindex].flag & OFFADD) { - magic[magindex].offset = oldoff; - } + magic[magindex].offset = oldoff; } firstline = 0; returnval = 1; @@ -265,6 +272,7 @@ mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m) case FILE_LONG: case FILE_BELONG: case FILE_LELONG: + case FILE_MELONG: v = file_signextend(ms, m, p->l); if (file_printf(ms, m->desc, (uint32_t) v) == -1) return -1; @@ -275,10 +283,10 @@ mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m) case FILE_PSTRING: case FILE_BESTRING16: case FILE_LESTRING16: - if (m->reln == '=') { + if (m->reln == '=' || m->reln == '!') { if (file_printf(ms, m->desc, m->value.s) == -1) return -1; - t = m->offset + strlen(m->value.s); + t = m->offset + m->vallen; } else { if (*m->value.s == '\0') { @@ -295,6 +303,7 @@ mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m) case FILE_DATE: case FILE_BEDATE: case FILE_LEDATE: + case FILE_MEDATE: if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1) return -1; t = m->offset + sizeof(time_t); @@ -303,6 +312,7 @@ mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m) case FILE_LDATE: case FILE_BELDATE: case FILE_LELDATE: + case FILE_MELDATE: if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1) return -1; t = m->offset + sizeof(time_t); @@ -312,6 +322,11 @@ mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m) return -1; t = m->offset + strlen(p->s); break; + case FILE_SEARCH: + if (file_printf(ms, m->desc, m->value.s) == -1) + return -1; + t = m->offset + m->vallen; + break; default: file_error(ms, 0, "invalid m->type (%d) in mprint()", m->type); @@ -331,7 +346,7 @@ mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m) switch (m->type) { case FILE_BYTE: if (m->mask) - switch (m->mask_op&0x7F) { + switch (m->mask_op & 0x7F) { case FILE_OPAND: p->b &= m->mask; break; @@ -362,7 +377,7 @@ mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m) return 1; case FILE_SHORT: if (m->mask) - switch (m->mask_op&0x7F) { + switch (m->mask_op & 0x7F) { case FILE_OPAND: p->h &= m->mask; break; @@ -395,7 +410,7 @@ mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m) case FILE_DATE: case FILE_LDATE: if (m->mask) - switch (m->mask_op&0x7F) { + switch (m->mask_op & 0x7F) { case FILE_OPAND: p->l &= m->mask; break; @@ -585,7 +600,43 @@ mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m) if (m->mask_op & FILE_OPINVERSE) p->l = ~p->l; return 1; + case FILE_MELONG: + case FILE_MEDATE: + case FILE_MELDATE: + p->l = (int32_t) + ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2])); + if (m->mask) + switch (m->mask_op&0x7F) { + case FILE_OPAND: + p->l &= m->mask; + break; + case FILE_OPOR: + p->l |= m->mask; + break; + case FILE_OPXOR: + p->l ^= m->mask; + break; + case FILE_OPADD: + p->l += m->mask; + break; + case FILE_OPMINUS: + p->l -= m->mask; + break; + case FILE_OPMULTIPLY: + p->l *= m->mask; + break; + case FILE_OPDIVIDE: + p->l /= m->mask; + break; + case FILE_OPMODULO: + p->l %= m->mask; + break; + } + if (m->mask_op & FILE_OPINVERSE) + p->l = ~p->l; + return 1; case FILE_REGEX: + case FILE_SEARCH: return 1; default: file_error(ms, 0, "invalid type %d in mconvert()", m->type); @@ -612,24 +663,32 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, * 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) { + char *b, *c, *last = NULL; + if (s == NULL) { + p->search.buflen = 0; + p->search.buf = NULL; + return 0; + } + if ((p->search.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++) + 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 char *src = s + offset; - const char *esrc = s + nbytes; + 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) @@ -663,86 +722,88 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, * might even cause problems */ if (nbytes < sizeof(*p)) - (void)memset(((char *)p) + nbytes, '\0', sizeof(*p) - nbytes); + (void)memset(((char *)(void *)p) + nbytes, '\0', + sizeof(*p) - nbytes); return 0; } private int mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s, - struct magic *m, size_t nbytes) + struct magic *m, size_t nbytes, unsigned int cont_level) { uint32_t offset = m->offset; if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes) == -1) return -1; - /* 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) { + int off = m->in_offset; + if (m->in_op & FILE_OPINDIRECT) { + const union VALUETYPE *q = + ((const void *)(s + offset + off)); + switch (m->in_type) { + case FILE_BYTE: + off = q->b; + break; + case FILE_SHORT: + off = q->h; + break; + case FILE_BESHORT: + off = (short)((q->hs[0]<<8)|(q->hs[1])); + break; + case FILE_LESHORT: + off = (short)((q->hs[1]<<8)|(q->hs[0])); + break; + case FILE_LONG: + off = q->l; + break; + case FILE_BELONG: + off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)| + (q->hl[2]<<8)|(q->hl[3])); + break; + case FILE_LELONG: + off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)| + (q->hl[1]<<8)|(q->hl[0])); + break; + case FILE_MELONG: + off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)| + (q->hl[3]<<8)|(q->hl[2])); + break; + } + } switch (m->in_type) { case FILE_BYTE: - if (m->in_offset) { - switch (m->in_op&0x7F) { + if (nbytes < (offset + 1)) return 0; + if (off) { + switch (m->in_op & 0x3F) { case FILE_OPAND: - offset = p->b & m->in_offset; + offset = p->b & off; break; case FILE_OPOR: - offset = p->b | m->in_offset; + offset = p->b | off; break; case FILE_OPXOR: - offset = p->b ^ m->in_offset; + offset = p->b ^ off; break; case FILE_OPADD: - offset = p->b + m->in_offset; + offset = p->b + off; break; case FILE_OPMINUS: - offset = p->b - m->in_offset; + offset = p->b - off; break; case FILE_OPMULTIPLY: - offset = p->b * m->in_offset; + offset = p->b * off; break; case FILE_OPDIVIDE: - offset = p->b / m->in_offset; + offset = p->b / off; break; case FILE_OPMODULO: - offset = p->b % m->in_offset; + offset = p->b % off; break; } } else @@ -751,47 +812,49 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s, offset = ~offset; break; case FILE_BESHORT: - if (m->in_offset) { + if (nbytes < (offset + 2)) + return 0; + if (off) { switch (m->in_op & 0x7F) { case FILE_OPAND: offset = (short)((p->hs[0]<<8)| (p->hs[1])) & - m->in_offset; + off; break; case FILE_OPOR: offset = (short)((p->hs[0]<<8)| (p->hs[1])) | - m->in_offset; + off; break; case FILE_OPXOR: offset = (short)((p->hs[0]<<8)| (p->hs[1])) ^ - m->in_offset; + off; break; case FILE_OPADD: offset = (short)((p->hs[0]<<8)| (p->hs[1])) + - m->in_offset; + off; break; case FILE_OPMINUS: offset = (short)((p->hs[0]<<8)| (p->hs[1])) - - m->in_offset; + off; break; case FILE_OPMULTIPLY: offset = (short)((p->hs[0]<<8)| (p->hs[1])) * - m->in_offset; + off; break; case FILE_OPDIVIDE: offset = (short)((p->hs[0]<<8)| (p->hs[1])) / - m->in_offset; + off; break; case FILE_OPMODULO: offset = (short)((p->hs[0]<<8)| (p->hs[1])) % - m->in_offset; + off; break; } } else @@ -801,47 +864,49 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s, offset = ~offset; break; case FILE_LESHORT: - if (m->in_offset) { + if (nbytes < (offset + 2)) + return 0; + if (off) { switch (m->in_op & 0x7F) { case FILE_OPAND: offset = (short)((p->hs[1]<<8)| (p->hs[0])) & - m->in_offset; + off; break; case FILE_OPOR: offset = (short)((p->hs[1]<<8)| (p->hs[0])) | - m->in_offset; + off; break; case FILE_OPXOR: offset = (short)((p->hs[1]<<8)| (p->hs[0])) ^ - m->in_offset; + off; break; case FILE_OPADD: offset = (short)((p->hs[1]<<8)| (p->hs[0])) + - m->in_offset; + off; break; case FILE_OPMINUS: offset = (short)((p->hs[1]<<8)| (p->hs[0])) - - m->in_offset; + off; break; case FILE_OPMULTIPLY: offset = (short)((p->hs[1]<<8)| (p->hs[0])) * - m->in_offset; + off; break; case FILE_OPDIVIDE: offset = (short)((p->hs[1]<<8)| (p->hs[0])) / - m->in_offset; + off; break; case FILE_OPMODULO: offset = (short)((p->hs[1]<<8)| (p->hs[0])) % - m->in_offset; + off; break; } } else @@ -851,31 +916,33 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s, offset = ~offset; break; case FILE_SHORT: - if (m->in_offset) { + if (nbytes < (offset + 2)) + return 0; + if (off) { switch (m->in_op & 0x7F) { case FILE_OPAND: - offset = p->h & m->in_offset; + offset = p->h & off; break; case FILE_OPOR: - offset = p->h | m->in_offset; + offset = p->h | off; break; case FILE_OPXOR: - offset = p->h ^ m->in_offset; + offset = p->h ^ off; break; case FILE_OPADD: - offset = p->h + m->in_offset; + offset = p->h + off; break; case FILE_OPMINUS: - offset = p->h - m->in_offset; + offset = p->h - off; break; case FILE_OPMULTIPLY: - offset = p->h * m->in_offset; + offset = p->h * off; break; case FILE_OPDIVIDE: - offset = p->h / m->in_offset; + offset = p->h / off; break; case FILE_OPMODULO: - offset = p->h % m->in_offset; + offset = p->h % off; break; } } @@ -885,63 +952,65 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s, offset = ~offset; break; case FILE_BELONG: - if (m->in_offset) { + if (nbytes < (offset + 4)) + return 0; + if (off) { 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; + off; break; case FILE_OPOR: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) | - m->in_offset; + off; break; case FILE_OPXOR: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) ^ - m->in_offset; + off; break; case FILE_OPADD: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) + - m->in_offset; + off; break; case FILE_OPMINUS: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) - - m->in_offset; + off; break; case FILE_OPMULTIPLY: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) * - m->in_offset; + off; break; case FILE_OPDIVIDE: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) / - m->in_offset; + off; break; case FILE_OPMODULO: offset = (int32_t)((p->hl[0]<<24)| (p->hl[1]<<16)| (p->hl[2]<<8)| (p->hl[3])) % - m->in_offset; + off; break; } } else @@ -953,63 +1022,65 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s, offset = ~offset; break; case FILE_LELONG: - if (m->in_offset) { + if (nbytes < (offset + 4)) + return 0; + if (off) { 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; + off; break; case FILE_OPOR: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) | - m->in_offset; + off; break; case FILE_OPXOR: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) ^ - m->in_offset; + off; break; case FILE_OPADD: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) + - m->in_offset; + off; break; case FILE_OPMINUS: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) - - m->in_offset; + off; break; case FILE_OPMULTIPLY: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) * - m->in_offset; + off; break; case FILE_OPDIVIDE: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) / - m->in_offset; + off; break; case FILE_OPMODULO: offset = (int32_t)((p->hl[3]<<24)| (p->hl[2]<<16)| (p->hl[1]<<8)| (p->hl[0])) % - m->in_offset; + off; break; } } else @@ -1020,32 +1091,104 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s, if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; + case FILE_MELONG: + if (nbytes < (offset + 4)) + return 0; + if (off) { + switch (m->in_op & 0x7F) { + case FILE_OPAND: + offset = (int32_t)((p->hl[1]<<24)| + (p->hl[0]<<16)| + (p->hl[3]<<8)| + (p->hl[2])) & + off; + break; + case FILE_OPOR: + offset = (int32_t)((p->hl[1]<<24)| + (p->hl[0]<<16)| + (p->hl[3]<<8)| + (p->hl[2])) | + off; + break; + case FILE_OPXOR: + offset = (int32_t)((p->hl[1]<<24)| + (p->hl[0]<<16)| + (p->hl[3]<<8)| + (p->hl[2])) ^ + off; + break; + case FILE_OPADD: + offset = (int32_t)((p->hl[1]<<24)| + (p->hl[0]<<16)| + (p->hl[3]<<8)| + (p->hl[2])) + + off; + break; + case FILE_OPMINUS: + offset = (int32_t)((p->hl[1]<<24)| + (p->hl[0]<<16)| + (p->hl[3]<<8)| + (p->hl[2])) - + off; + break; + case FILE_OPMULTIPLY: + offset = (int32_t)((p->hl[1]<<24)| + (p->hl[0]<<16)| + (p->hl[3]<<8)| + (p->hl[2])) * + off; + break; + case FILE_OPDIVIDE: + offset = (int32_t)((p->hl[1]<<24)| + (p->hl[0]<<16)| + (p->hl[3]<<8)| + (p->hl[2])) / + off; + break; + case FILE_OPMODULO: + offset = (int32_t)((p->hl[1]<<24)| + (p->hl[0]<<16)| + (p->hl[3]<<8)| + (p->hl[2])) % + off; + break; + } + } else + offset = (int32_t)((p->hl[1]<<24)| + (p->hl[0]<<16)| + (p->hl[3]<<8)| + (p->hl[2])); + if (m->in_op & FILE_OPINVERSE) + offset = ~offset; + break; case FILE_LONG: - if (m->in_offset) { + if (nbytes < (offset + 4)) + return 0; + if (off) { switch (m->in_op & 0x7F) { case FILE_OPAND: - offset = p->l & m->in_offset; + offset = p->l & off; break; case FILE_OPOR: - offset = p->l | m->in_offset; + offset = p->l | off; break; case FILE_OPXOR: - offset = p->l ^ m->in_offset; + offset = p->l ^ off; break; case FILE_OPADD: - offset = p->l + m->in_offset; + offset = p->l + off; break; case FILE_OPMINUS: - offset = p->l - m->in_offset; + offset = p->l - off; break; case FILE_OPMULTIPLY: - offset = p->l * m->in_offset; + offset = p->l * off; break; case FILE_OPDIVIDE: - offset = p->l / m->in_offset; + offset = p->l / off; break; case FILE_OPMODULO: - offset = p->l % m->in_offset; + offset = p->l % off; break; /* case TOOMANYSWITCHBLOCKS: * ugh = p->eye % m->strain; @@ -1062,8 +1205,10 @@ 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) return -1; + m->offset = offset; if ((ms->flags & MAGIC_DEBUG) != 0) { mdebug(offset, (char *)(void *)p, @@ -1071,8 +1216,62 @@ mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s, file_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_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; + default: break; + } + + if (m->type == FILE_SEARCH) { + size_t mlen = 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; + } + (void)memcpy(p->search.buf, s + offset, mlen); + p->search.buf[mlen] = '\0'; + } if (!mconvert(ms, p, m)) - return 0; + return 0; return 1; } @@ -1102,12 +1301,15 @@ mcheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m) 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: v = p->l; break; @@ -1166,19 +1368,59 @@ mcheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m) regex_t rx; char errmsg[512]; - rc = regcomp(&rx, m->value.s, REG_EXTENDED|REG_NOSUB); + if (p->search.buf == NULL) + return 0; + + rc = regcomp(&rx, m->value.s, + REG_EXTENDED|REG_NOSUB|REG_NEWLINE| + ((m->mask & STRING_IGNORE_LOWERCASE) ? REG_ICASE : 0)); if (rc) { - free(p->buf); + 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->buf, 0, 0, 0); + rc = regexec(&rx, p->search.buf, 0, 0, 0); regfree(&rx); - free(p->buf); + free(p->search.buf); + p->search.buf = NULL; return !rc; } } + 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) { + m->offset += range - 1; + break; + } + if (range + slen >= p->search.buflen) + break; + len = slen; + a = (unsigned char*)m->value.s; + b = (unsigned char*)p->search.buf + range; + } + free(p->search.buf); + p->search.buf = NULL; + break; + } default: file_error(ms, 0, "invalid type %d in mcheck()", m->type); return -1; |