diff --git a/src/softmagic.c b/src/softmagic.c index 1f02fec..58a1cf7 100644 --- a/ext/fileinfo/libmagic/softmagic.c +++ b/ext/fileinfo/libmagic/softmagic.c @@ -87,6 +87,7 @@ private void cvt_16(union VALUETYPE *, const struct magic *); private void cvt_32(union VALUETYPE *, const struct magic *); private void cvt_64(union VALUETYPE *, const struct magic *); +#define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o))) /* * softmagic - lookup one file in parsed, in-memory copy of database * Passed the name and FILE * of one file to be typed. @@ -1065,6 +1066,7 @@ mget(struct magic_set *ms, const unsigned char *s, { uint32_t offset = ms->offset; uint32_t count = m->str_range; + uint32_t lhs; union VALUETYPE *p = &ms->ms_value; if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1) @@ -1116,7 +1118,7 @@ mget(struct magic_set *ms, const unsigned char *s, } switch (m->in_type) { case FILE_BYTE: - if (nbytes < (offset + 1)) + if (OFFSET_OOB(nbytes, offset, 1)) return 0; if (off) { switch (m->in_op & FILE_OPS_MASK) { @@ -1151,111 +1153,79 @@ mget(struct magic_set *ms, const unsigned char *s, offset = ~offset; break; case FILE_BESHORT: - if (nbytes < (offset + 2)) + if (OFFSET_OOB(nbytes, offset, 2)) return 0; + lhs = (p->hs[0] << 8) | p->hs[1]; if (off) { switch (m->in_op & FILE_OPS_MASK) { case FILE_OPAND: - offset = (short)((p->hs[0]<<8)| - (p->hs[1])) & - off; + offset = lhs & off; break; case FILE_OPOR: - offset = (short)((p->hs[0]<<8)| - (p->hs[1])) | - off; + offset = lhs | off; break; case FILE_OPXOR: - offset = (short)((p->hs[0]<<8)| - (p->hs[1])) ^ - off; + offset = lhs ^ off; break; case FILE_OPADD: - offset = (short)((p->hs[0]<<8)| - (p->hs[1])) + - off; + offset = lhs + off; break; case FILE_OPMINUS: - offset = (short)((p->hs[0]<<8)| - (p->hs[1])) - - off; + offset = lhs - off; break; case FILE_OPMULTIPLY: - offset = (short)((p->hs[0]<<8)| - (p->hs[1])) * - off; + offset = lhs * off; break; case FILE_OPDIVIDE: - offset = (short)((p->hs[0]<<8)| - (p->hs[1])) / - off; + offset = lhs / off; break; case FILE_OPMODULO: - offset = (short)((p->hs[0]<<8)| - (p->hs[1])) % - off; + offset = lhs % off; break; } } else - offset = (short)((p->hs[0]<<8)| - (p->hs[1])); + offset = lhs; if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; case FILE_LESHORT: - if (nbytes < (offset + 2)) + if (OFFSET_OOB(nbytes, offset, 2)) return 0; + lhs = (p->hs[1] << 8) | p->hs[0]; if (off) { switch (m->in_op & FILE_OPS_MASK) { case FILE_OPAND: - offset = (short)((p->hs[1]<<8)| - (p->hs[0])) & - off; + offset = lhs & off; break; case FILE_OPOR: - offset = (short)((p->hs[1]<<8)| - (p->hs[0])) | - off; + offset = lhs | off; break; case FILE_OPXOR: - offset = (short)((p->hs[1]<<8)| - (p->hs[0])) ^ - off; + offset = lhs ^ off; break; case FILE_OPADD: - offset = (short)((p->hs[1]<<8)| - (p->hs[0])) + - off; + offset = lhs + off; break; case FILE_OPMINUS: - offset = (short)((p->hs[1]<<8)| - (p->hs[0])) - - off; + offset = lhs - off; break; case FILE_OPMULTIPLY: - offset = (short)((p->hs[1]<<8)| - (p->hs[0])) * - off; + offset = lhs * off; break; case FILE_OPDIVIDE: - offset = (short)((p->hs[1]<<8)| - (p->hs[0])) / - off; + offset = lhs / off; break; case FILE_OPMODULO: - offset = (short)((p->hs[1]<<8)| - (p->hs[0])) % - off; + offset = lhs % off; break; } } else - offset = (short)((p->hs[1]<<8)| - (p->hs[0])); + offset = lhs; if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; case FILE_SHORT: - if (nbytes < (offset + 2)) + if (OFFSET_OOB(nbytes, offset, 2)) return 0; if (off) { switch (m->in_op & FILE_OPS_MASK) { @@ -1292,218 +1262,119 @@ mget(struct magic_set *ms, const unsigned char *s, break; case FILE_BELONG: case FILE_BEID3: - if (nbytes < (offset + 4)) + if (OFFSET_OOB(nbytes, offset, 4)) return 0; + lhs = (p->hl[0] << 24) | (p->hl[1] << 16) | + (p->hl[2] << 8) | p->hl[3]; if (off) { switch (m->in_op & FILE_OPS_MASK) { case FILE_OPAND: - offset = (int32_t)((p->hl[0]<<24)| - (p->hl[1]<<16)| - (p->hl[2]<<8)| - (p->hl[3])) & - off; + offset = lhs & off; break; case FILE_OPOR: - offset = (int32_t)((p->hl[0]<<24)| - (p->hl[1]<<16)| - (p->hl[2]<<8)| - (p->hl[3])) | - off; + offset = lhs | off; break; case FILE_OPXOR: - offset = (int32_t)((p->hl[0]<<24)| - (p->hl[1]<<16)| - (p->hl[2]<<8)| - (p->hl[3])) ^ - off; + offset = lhs ^ off; break; case FILE_OPADD: - offset = (int32_t)((p->hl[0]<<24)| - (p->hl[1]<<16)| - (p->hl[2]<<8)| - (p->hl[3])) + - off; + offset = lhs + off; break; case FILE_OPMINUS: - offset = (int32_t)((p->hl[0]<<24)| - (p->hl[1]<<16)| - (p->hl[2]<<8)| - (p->hl[3])) - - off; + offset = lhs - off; break; case FILE_OPMULTIPLY: - offset = (int32_t)((p->hl[0]<<24)| - (p->hl[1]<<16)| - (p->hl[2]<<8)| - (p->hl[3])) * - off; + offset = lhs * off; break; case FILE_OPDIVIDE: - offset = (int32_t)((p->hl[0]<<24)| - (p->hl[1]<<16)| - (p->hl[2]<<8)| - (p->hl[3])) / - off; + offset = lhs / off; break; case FILE_OPMODULO: - offset = (int32_t)((p->hl[0]<<24)| - (p->hl[1]<<16)| - (p->hl[2]<<8)| - (p->hl[3])) % - off; + offset = lhs % off; break; } } else - offset = (int32_t)((p->hl[0]<<24)| - (p->hl[1]<<16)| - (p->hl[2]<<8)| - (p->hl[3])); + offset = lhs; if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; case FILE_LELONG: case FILE_LEID3: - if (nbytes < (offset + 4)) + if (OFFSET_OOB(nbytes, offset, 4)) return 0; + lhs = (p->hl[3] << 24) | (p->hl[2] << 16) | + (p->hl[1] << 8) | p->hl[0]; if (off) { switch (m->in_op & FILE_OPS_MASK) { case FILE_OPAND: - offset = (int32_t)((p->hl[3]<<24)| - (p->hl[2]<<16)| - (p->hl[1]<<8)| - (p->hl[0])) & - off; + offset = lhs & off; break; case FILE_OPOR: - offset = (int32_t)((p->hl[3]<<24)| - (p->hl[2]<<16)| - (p->hl[1]<<8)| - (p->hl[0])) | - off; + offset = lhs | off; break; case FILE_OPXOR: - offset = (int32_t)((p->hl[3]<<24)| - (p->hl[2]<<16)| - (p->hl[1]<<8)| - (p->hl[0])) ^ - off; + offset = lhs ^ off; break; case FILE_OPADD: - offset = (int32_t)((p->hl[3]<<24)| - (p->hl[2]<<16)| - (p->hl[1]<<8)| - (p->hl[0])) + - off; + offset = lhs + off; break; case FILE_OPMINUS: - offset = (int32_t)((p->hl[3]<<24)| - (p->hl[2]<<16)| - (p->hl[1]<<8)| - (p->hl[0])) - - off; + offset = lhs - off; break; case FILE_OPMULTIPLY: - offset = (int32_t)((p->hl[3]<<24)| - (p->hl[2]<<16)| - (p->hl[1]<<8)| - (p->hl[0])) * - off; + offset = lhs * off; break; case FILE_OPDIVIDE: - offset = (int32_t)((p->hl[3]<<24)| - (p->hl[2]<<16)| - (p->hl[1]<<8)| - (p->hl[0])) / - off; + offset = lhs / off; break; case FILE_OPMODULO: - offset = (int32_t)((p->hl[3]<<24)| - (p->hl[2]<<16)| - (p->hl[1]<<8)| - (p->hl[0])) % - off; + offset = lhs % off; break; } } else - offset = (int32_t)((p->hl[3]<<24)| - (p->hl[2]<<16)| - (p->hl[1]<<8)| - (p->hl[0])); + offset = lhs; if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; case FILE_MELONG: - if (nbytes < (offset + 4)) + if (OFFSET_OOB(nbytes, offset, 4)) return 0; + lhs = (p->hl[1] << 24) | (p->hl[0] << 16) | + (p->hl[3] << 8) | p->hl[2]; if (off) { switch (m->in_op & FILE_OPS_MASK) { case FILE_OPAND: - offset = (int32_t)((p->hl[1]<<24)| - (p->hl[0]<<16)| - (p->hl[3]<<8)| - (p->hl[2])) & - off; + offset = lhs & off; break; case FILE_OPOR: - offset = (int32_t)((p->hl[1]<<24)| - (p->hl[0]<<16)| - (p->hl[3]<<8)| - (p->hl[2])) | - off; + offset = lhs | off; break; case FILE_OPXOR: - offset = (int32_t)((p->hl[1]<<24)| - (p->hl[0]<<16)| - (p->hl[3]<<8)| - (p->hl[2])) ^ - off; + offset = lhs ^ off; break; case FILE_OPADD: - offset = (int32_t)((p->hl[1]<<24)| - (p->hl[0]<<16)| - (p->hl[3]<<8)| - (p->hl[2])) + - off; + offset = lhs + off; break; case FILE_OPMINUS: - offset = (int32_t)((p->hl[1]<<24)| - (p->hl[0]<<16)| - (p->hl[3]<<8)| - (p->hl[2])) - - off; + offset = lhs - off; break; case FILE_OPMULTIPLY: - offset = (int32_t)((p->hl[1]<<24)| - (p->hl[0]<<16)| - (p->hl[3]<<8)| - (p->hl[2])) * - off; + offset = lhs * off; break; case FILE_OPDIVIDE: - offset = (int32_t)((p->hl[1]<<24)| - (p->hl[0]<<16)| - (p->hl[3]<<8)| - (p->hl[2])) / - off; + offset = lhs / off; break; case FILE_OPMODULO: - offset = (int32_t)((p->hl[1]<<24)| - (p->hl[0]<<16)| - (p->hl[3]<<8)| - (p->hl[2])) % - off; + offset = lhs % off; break; } } else - offset = (int32_t)((p->hl[1]<<24)| - (p->hl[0]<<16)| - (p->hl[3]<<8)| - (p->hl[2])); + offset = lhs; if (m->in_op & FILE_OPINVERSE) offset = ~offset; break; case FILE_LONG: - if (nbytes < (offset + 4)) + if (OFFSET_OOB(nbytes, offset, 4)) return 0; if (off) { switch (m->in_op & FILE_OPS_MASK) { @@ -1570,14 +1441,14 @@ mget(struct magic_set *ms, const unsigned char *s, /* Verify we have enough data to match magic type */ switch (m->type) { case FILE_BYTE: - if (nbytes < (offset + 1)) /* should alway be true */ + if (OFFSET_OOB(nbytes, offset, 1)) return 0; break; case FILE_SHORT: case FILE_BESHORT: case FILE_LESHORT: - if (nbytes < (offset + 2)) + if (OFFSET_OOB(nbytes, offset, 2)) return 0; break; @@ -1596,26 +1467,26 @@ mget(struct magic_set *ms, const unsigned char *s, case FILE_FLOAT: case FILE_BEFLOAT: case FILE_LEFLOAT: - if (nbytes < (offset + 4)) + if (OFFSET_OOB(nbytes, offset, 4)) return 0; break; case FILE_DOUBLE: case FILE_BEDOUBLE: case FILE_LEDOUBLE: - if (nbytes < (offset + 8)) + if (OFFSET_OOB(nbytes, offset, 8)) return 0; break; case FILE_STRING: case FILE_PSTRING: case FILE_SEARCH: - if (nbytes < (offset + m->vallen)) + if (OFFSET_OOB(nbytes, offset, m->vallen)) return 0; break; case FILE_REGEX: - if (nbytes < offset) + if (nbytes < offset) return 0; break; @@ -1623,7 +1494,7 @@ mget(struct magic_set *ms, const unsigned char *s, if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 && file_printf(ms, m->desc) == -1) return -1; - if (nbytes < offset) + if (nbytes < offset) return 0; return file_softmagic(ms, s + offset, nbytes - offset, BINTEST);