+--- rpm-4.4.1/file/src/file.h.orig 2005-01-03 00:11:30.000000000 +0100
++++ rpm-4.4.1/file/src/file.h 2005-07-19 19:22:21.264100296 +0200
+@@ -27,7 +27,7 @@
+ */
+ /*
+ * file.h - definitions for file(1) program
+- * @(#)$Id$
++ * @(#)$Id$
+ */
+
+ #ifndef __file_h__
+@@ -65,9 +65,9 @@
+ #define public
+
+ #ifndef HOWMANY
+-# define HOWMANY 65536 /* how much of the file to look at */
++# define HOWMANY (256 * 1024) /* how much of the file to look at */
+ #endif
+-#define MAXMAGIS 4096 /* max entries in /etc/magic */
++#define MAXMAGIS 8192 /* max entries in /etc/magic */
+ #define MAXDESC 64 /* max leng of text description */
+ #define MAXstring 32 /* max leng of "string" types */
+
+@@ -87,6 +87,7 @@
+ #define INDIR 1 /* if '>(...)' appears, */
+ #define UNSIGNED 2 /* comparison is unsigned */
+ #define OFFADD 4 /* if '>&' appears, */
++#define INDIROFFADD 8 /* if '>&(' appears, */
+ /* Word 2 */
+ uint8_t reln; /* relation (0=eq, '>'=gt, etc) */
+ uint8_t vallen; /* length of string value, if any */
+@@ -110,6 +111,7 @@
+ #define FILE_REGEX 17
+ #define FILE_BESTRING16 18
+ #define FILE_LESTRING16 19
++#define FILE_SEARCH 20
+
+ #define FILE_FORMAT_NAME \
+ /* 0 */ "invalid 0", \
+@@ -121,7 +123,7 @@
+ /* 6 */ "date", \
+ /* 7 */ "beshort", \
+ /* 8 */ "belong", \
+-/* 9 */ "bedate" \
++/* 9 */ "bedate", \
+ /* 10 */ "leshort", \
+ /* 11 */ "lelong", \
+ /* 12 */ "ledate", \
+@@ -131,7 +133,8 @@
+ /* 16 */ "leldate", \
+ /* 17 */ "regex", \
+ /* 18 */ "bestring16", \
+-/* 19 */ "lestring16",
++/* 19 */ "lestring16", \
++/* 20 */ "search",
+
+ #define FILE_FMT_NUM "cduxXi"
+ #define FILE_FMT_STR "s"
+@@ -156,7 +159,8 @@
+ /* 16 */ FILE_FMT_STR, \
+ /* 17 */ FILE_FMT_STR, \
+ /* 18 */ FILE_FMT_STR, \
+-/* 19 */ FILE_FMT_STR,
++/* 19 */ FILE_FMT_STR, \
++/* 20 */ FILE_FMT_STR,
+
+ /* Word 3 */
+ uint8_t in_op; /* operator for indirection */
+@@ -172,11 +176,12 @@
+ #define FILE_OPMULTIPLY 5
+ #define FILE_OPDIVIDE 6
+ #define FILE_OPMODULO 7
+-#define FILE_OPINVERSE 0x80
++#define FILE_OPINVERSE 0x40
++#define FILE_OPINDIRECT 0x80
+ /* Word 4 */
+ uint32_t offset; /* offset to magic number */
+ /* Word 5 */
+- uint32_t in_offset; /* offset from indirection */
++ int32_t in_offset; /* offset from indirection */
+ /* Word 6 */
+ uint32_t mask; /* mask before comparison with value */
+ /* Word 7 */
+--- rpm-4.4.1/file/src/softmagic.c.orig 2005-01-26 04:39:56.000000000 +0100
++++ rpm-4.4.1/file/src/softmagic.c 2005-07-19 18:50:47.923931752 +0200
+@@ -39,7 +39,7 @@
+
+
+ #ifndef lint
+-FILE_RCSID("@(#)$Id$")
++FILE_RCSID("@(#)$Id$")
+ #endif /* lint */
+
+ private int match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
+@@ -47,7 +47,7 @@
+ /*@globals fileSystem @*/
+ /*@modifies ms, magic, fileSystem @*/;
+ 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, int i)
+ /*@globals fileSystem @*/
+ /*@modifies ms, p, m, fileSystem @*/;
+ private int mcheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
+@@ -128,15 +128,20 @@
+
+ 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++;
+- /*@switchbreak@*/ break;
+- default:
+- /*@switchbreak@*/ 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++;
++ /*@switchbreak@*/ break;
++ default:
++ /*@switchbreak@*/ break;
++ }
+ }
+ if (flush) {
+ /*
+@@ -179,14 +184,18 @@
+ */
+ 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:
+@@ -222,9 +231,7 @@
+ return -1;
+ }
+ done:
+- if (magic[magindex].flag & OFFADD) {
+- magic[magindex].offset = oldoff;
+- }
++ magic[magindex].offset = oldoff;
+ }
+ firstline = 0;
+ returnval = 1;
+@@ -288,10 +295,10 @@
+ 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') {
+@@ -325,6 +332,11 @@
+ 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);
+@@ -344,7 +356,7 @@
+ 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;
+ /*@innerbreak@*/ break;
+@@ -375,7 +387,7 @@
+ 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;
+ /*@innerbreak@*/ break;
+@@ -408,7 +420,7 @@
+ 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;
+ /*@innerbreak@*/ break;
+@@ -599,6 +611,7 @@
+ 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);
+@@ -625,15 +638,17 @@
+ * offset is interpreted as last line to search,
+ * (starting at 1), not as bytes-from start-of-file
+ */
+- unsigned char *b, *last = NULL;
++ char *b, *c, *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++)
++ for (b = p->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';
+ return 0;
+@@ -682,80 +697,77 @@
+
+ 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, 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 union VALUETYPE *)(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;
++ }
++ }
+ 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;
+ /*@innerbreak@*/ break;
+ case FILE_OPOR:
+- offset = p->b | m->in_offset;
++ offset = p->b | off;
+ /*@innerbreak@*/ break;
+ case FILE_OPXOR:
+- offset = p->b ^ m->in_offset;
++ offset = p->b ^ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPADD:
+- offset = p->b + m->in_offset;
++ offset = p->b + off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMINUS:
+- offset = p->b - m->in_offset;
++ offset = p->b - off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMULTIPLY:
+- offset = p->b * m->in_offset;
++ offset = p->b * off;
+ /*@innerbreak@*/ break;
+ case FILE_OPDIVIDE:
+- offset = p->b / m->in_offset;
++ offset = p->b / off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMODULO:
+- offset = p->b % m->in_offset;
++ offset = p->b % off;
+ /*@innerbreak@*/ break;
+ }
+ } else
+@@ -764,47 +776,49 @@
+ 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;
+ /*@innerbreak@*/ break;
+ case FILE_OPOR:
+ offset = (short)((p->hs[0]<<8)|
+ (p->hs[1])) |
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPXOR:
+ offset = (short)((p->hs[0]<<8)|
+ (p->hs[1])) ^
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPADD:
+ offset = (short)((p->hs[0]<<8)|
+ (p->hs[1])) +
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMINUS:
+ offset = (short)((p->hs[0]<<8)|
+ (p->hs[1])) -
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMULTIPLY:
+ offset = (short)((p->hs[0]<<8)|
+ (p->hs[1])) *
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPDIVIDE:
+ offset = (short)((p->hs[0]<<8)|
+ (p->hs[1])) /
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMODULO:
+ offset = (short)((p->hs[0]<<8)|
+ (p->hs[1])) %
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ }
+ } else
+@@ -814,47 +828,49 @@
+ 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;
+ /*@innerbreak@*/ break;
+ case FILE_OPOR:
+ offset = (short)((p->hs[1]<<8)|
+ (p->hs[0])) |
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPXOR:
+ offset = (short)((p->hs[1]<<8)|
+ (p->hs[0])) ^
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPADD:
+ offset = (short)((p->hs[1]<<8)|
+ (p->hs[0])) +
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMINUS:
+ offset = (short)((p->hs[1]<<8)|
+ (p->hs[0])) -
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMULTIPLY:
+ offset = (short)((p->hs[1]<<8)|
+ (p->hs[0])) *
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPDIVIDE:
+ offset = (short)((p->hs[1]<<8)|
+ (p->hs[0])) /
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMODULO:
+ offset = (short)((p->hs[1]<<8)|
+ (p->hs[0])) %
+- m->in_offset;
++ off;
+ /*@innerbreak@*/ break;
+ }
+ } else
+@@ -864,31 +880,33 @@
+ 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;
+ /*@innerbreak@*/ break;
+ case FILE_OPOR:
+- offset = p->h | m->in_offset;
++ offset = p->h | off;
+ /*@innerbreak@*/ break;
+ case FILE_OPXOR:
+- offset = p->h ^ m->in_offset;
++ offset = p->h ^ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPADD:
+- offset = p->h + m->in_offset;
++ offset = p->h + off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMINUS:
+- offset = p->h - m->in_offset;
++ offset = p->h - off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMULTIPLY:
+- offset = p->h * m->in_offset;
++ offset = p->h * off;
+ /*@innerbreak@*/ break;
+ case FILE_OPDIVIDE:
+- offset = p->h / m->in_offset;
++ offset = p->h / off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMODULO:
+- offset = p->h % m->in_offset;
++ offset = p->h % off;
+ /*@innerbreak@*/ break;
+ }
+ }
+@@ -898,63 +916,65 @@
+ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ break;
+ }
+ } else
+@@ -966,63 +986,65 @@
+ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ 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;
+ /*@innerbreak@*/ break;
+ }
+ } else
+@@ -1034,31 +1056,33 @@
+ 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;
+ /*@innerbreak@*/ break;
+ case FILE_OPOR:
+- offset = p->l | m->in_offset;
++ offset = p->l | off;
+ /*@innerbreak@*/ break;
+ case FILE_OPXOR:
+- offset = p->l ^ m->in_offset;
++ offset = p->l ^ off;
+ /*@innerbreak@*/ break;
+ case FILE_OPADD:
+- offset = p->l + m->in_offset;
++ offset = p->l + off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMINUS:
+- offset = p->l - m->in_offset;
++ offset = p->l - off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMULTIPLY:
+- offset = p->l * m->in_offset;
++ offset = p->l * off;
+ /*@innerbreak@*/ break;
+ case FILE_OPDIVIDE:
+- offset = p->l / m->in_offset;
++ offset = p->l / off;
+ /*@innerbreak@*/ break;
+ case FILE_OPMODULO:
+- offset = p->l % m->in_offset;
++ offset = p->l % off;
+ /*@innerbreak@*/ break;
+ /* case TOOMANYSWITCHBLOCKS:
+ * ugh = p->eye % m->strain;
+@@ -1075,8 +1099,10 @@
+ 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,
+@@ -1084,8 +1110,53 @@
+ 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_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:
++ case FILE_SEARCH:
++ if (nbytes < (offset + m->vallen))
++ return 0;
++ break;
++ default: break;
++ }
++
++ if (m->type == FILE_SEARCH) {
++ p->buf = malloc(m->mask + m->vallen);
++ if (p->buf == NULL) {
++ file_error(ms, errno, "Cannot allocate search buffer");
++ return 0;
++ }
++ (void)memcpy(p->buf, s + offset, m->mask + m->vallen);
++ }
+ if (!mconvert(ms, p, m))
+- return 0;
++ return 0;
+ return 1;
+ }
+
+@@ -1179,7 +1250,9 @@
+ regex_t rx;
+ char errmsg[512];
+
+- rc = regcomp(&rx, m->value.s, REG_EXTENDED|REG_NOSUB);
++ 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);
+ regerror(rc, &rx, errmsg, sizeof(errmsg));
+@@ -1194,6 +1267,31 @@
+ 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->buf;
++ int len = m->vallen;
++ int range = 0;
++ l = 0;
++ v = 0;
++ while (++range <= m->mask) {
++ while (len-- > 0 && (v = *b++ - *a++) == 0)
++ continue;
++ if (!v) {
++ m->offset += range-1;
++ break;
++ }
++ len = m->vallen;
++ a = (unsigned char*)m->value.s;
++ b = (unsigned char*)p->buf + range;
++ }
++ free(p->buf);
++ break;
++ }
+ default:
+ file_error(ms, 0, "invalid type %d in mcheck()", m->type);
+ return -1;