--- embedaddon/php/ext/fileinfo/libmagic/softmagic.c 2012/02/21 23:47:56 1.1.1.1 +++ embedaddon/php/ext/fileinfo/libmagic/softmagic.c 2013/07/22 01:31:50 1.1.1.3 @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: softmagic.c,v 1.135 2009/03/27 22:42:49 christos Exp $") +FILE_RCSID("@(#)$File: softmagic.c,v 1.165 2013/03/07 02:22:24 christos Exp $") #endif /* lint */ #include "magic.h" @@ -48,16 +48,18 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.135 2009/03/27 private int match(struct magic_set *, struct magic *, uint32_t, - const unsigned char *, size_t, int); + const unsigned char *, size_t, size_t, int, int, int, int, int *, int *, + int *); private int mget(struct magic_set *, const unsigned char *, - struct magic *, size_t, unsigned int); + struct magic *, size_t, size_t, unsigned int, int, int, int, int, int *, + int *, int *); private int magiccheck(struct magic_set *, struct magic *); private int32_t mprint(struct magic_set *, struct magic *); private int32_t moffset(struct magic_set *, struct magic *); private void mdebug(uint32_t, const char *, size_t); private int mcopy(struct magic_set *, union VALUETYPE *, int, int, const unsigned char *, uint32_t, size_t, size_t); -private int mconvert(struct magic_set *, struct magic *); +private int mconvert(struct magic_set *, struct magic *, int); private int print_sep(struct magic_set *, int); private int handle_annotation(struct magic_set *, struct magic *); private void cvt_8(union VALUETYPE *, const struct magic *); @@ -71,12 +73,15 @@ private void cvt_64(union VALUETYPE *, const struct ma */ /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */ protected int -file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes, int mode) +file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes, + int mode, int text) { struct mlist *ml; - int rv; - for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next) - if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, mode)) != 0) + int rv, printed_something = 0, need_separator = 0; + for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next) + if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode, + text, 0, 0, &printed_something, &need_separator, + NULL)) != 0) return rv; return 0; @@ -111,16 +116,19 @@ file_softmagic(struct magic_set *ms, const unsigned ch */ private int match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, - const unsigned char *s, size_t nbytes, int mode) + const unsigned char *s, size_t nbytes, size_t offset, int mode, int text, + int flip, int recursion_level, int *printed_something, int *need_separator, + int *returnval) { uint32_t magindex = 0; unsigned int cont_level = 0; - int need_separator = 0; - int returnval = 0, e; /* if a match is found it is set to 1*/ + int returnvalv = 0, e; /* if a match is found it is set to 1*/ int firstline = 1; /* a flag to print X\n X\n- X */ - int printed_something = 0; int print = (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0; + if (returnval == NULL) + returnval = &returnvalv; + if (file_check_mem(ms, cont_level) == -1) return -1; @@ -128,11 +136,17 @@ match(struct magic_set *ms, struct magic *magic, uint3 int flush = 0; struct magic *m = &magic[magindex]; - if ((m->flag & BINTEST) != mode) { + if (m->type != FILE_NAME) + if ((IS_LIBMAGIC_STRING(m->type) && +#define FLT (STRING_BINTEST | STRING_TEXTTEST) + ((text && (m->str_flags & FLT) == STRING_BINTEST) || + (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) || + (m->flag & mode) != mode) { /* Skip sub-tests */ - while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) { - magindex++; - } + while (magindex + 1 < nmagic && + magic[magindex + 1].cont_level != 0 && + ++magindex) + continue; continue; /* Skip to next top-level test*/ } @@ -140,7 +154,9 @@ match(struct magic_set *ms, struct magic *magic, uint3 ms->line = m->lineno; /* if main entry matches, print it... */ - switch (mget(ms, s, m, nbytes, cont_level)) { + switch (mget(ms, s, m, nbytes, offset, cont_level, mode, text, + flip, recursion_level + 1, printed_something, + need_separator, returnval)) { case -1: return -1; case 0: @@ -148,8 +164,8 @@ match(struct magic_set *ms, struct magic *magic, uint3 break; default: if (m->type == FILE_INDIRECT) - returnval = 1; - + *returnval = 1; + switch (magiccheck(ms, m)) { case -1: return -1; @@ -167,21 +183,23 @@ match(struct magic_set *ms, struct magic *magic, uint3 * main entry didn't match, * flush its continuations */ - while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) { + while (magindex < nmagic - 1 && + magic[magindex + 1].cont_level != 0) magindex++; - } continue; } + if ((e = handle_annotation(ms, m)) != 0) { + *returnval = 1; + return e; + } /* * If we are going to print something, we'll need to print * a blank before we print something else. */ if (*m->desc) { - need_separator = 1; - printed_something = 1; - if ((e = handle_annotation(ms, m)) != 0) - return e; + *need_separator = 1; + *printed_something = 1; if (print_sep(ms, firstline) == -1) return -1; } @@ -196,8 +214,8 @@ match(struct magic_set *ms, struct magic *magic, uint3 if (file_check_mem(ms, ++cont_level) == -1) return -1; - while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) { - magindex++; + while (magindex + 1 < nmagic && magic[magindex+1].cont_level != 0 && + ++magindex) { m = &magic[magindex]; ms->line = m->lineno; /* for messages */ @@ -212,7 +230,8 @@ match(struct magic_set *ms, struct magic *magic, uint3 } ms->offset = m->offset; if (m->flag & OFFADD) { - ms->offset += ms->c.li[cont_level - 1].off; + ms->offset += + ms->c.li[cont_level - 1].off; } #ifdef ENABLE_CONDITIONALS @@ -222,7 +241,9 @@ match(struct magic_set *ms, struct magic *magic, uint3 continue; } #endif - switch (mget(ms, s, m, nbytes, cont_level)) { + switch (mget(ms, s, m, nbytes, offset, cont_level, mode, + text, flip, recursion_level + 1, printed_something, + need_separator, returnval)) { case -1: return -1; case 0: @@ -232,7 +253,7 @@ match(struct magic_set *ms, struct magic *magic, uint3 break; default: if (m->type == FILE_INDIRECT) - returnval = 1; + *returnval = 1; flush = 0; break; } @@ -255,15 +276,17 @@ match(struct magic_set *ms, struct magic *magic, uint3 ms->c.li[cont_level].got_match = 0; break; } + if ((e = handle_annotation(ms, m)) != 0) { + *returnval = 1; + return e; + } /* * If we are going to print something, * make sure that we have a separator first. */ if (*m->desc) { - if ((e = handle_annotation(ms, m)) != 0) - return e; - if (!printed_something) { - printed_something = 1; + if (!*printed_something) { + *printed_something = 1; if (print_sep(ms, firstline) == -1) return -1; @@ -276,13 +299,13 @@ match(struct magic_set *ms, struct magic *magic, uint3 * this item isn't empty. */ /* space if previous printed */ - if (need_separator + if (*need_separator && ((m->flag & NOSPACE) == 0) && *m->desc) { if (print && file_printf(ms, " ") == -1) return -1; - need_separator = 0; + *need_separator = 0; } if (print && mprint(ms, m) == -1) return -1; @@ -290,7 +313,7 @@ match(struct magic_set *ms, struct magic *magic, uint3 ms->c.li[cont_level].off = moffset(ms, m); if (*m->desc) - need_separator = 1; + *need_separator = 1; /* * If we see any continuations @@ -302,16 +325,16 @@ match(struct magic_set *ms, struct magic *magic, uint3 break; } } - if (printed_something) { + if (*printed_something) { firstline = 0; if (print) - returnval = 1; + *returnval = 1; } - if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) { - return returnval; /* don't keep searching */ + if ((ms->flags & MAGIC_CONTINUE) == 0 && *printed_something) { + return *returnval; /* don't keep searching */ } } - return returnval; /* This is hit if -k is set or there is no match */ + return *returnval; /* This is hit if -k is set or there is no match */ } private int @@ -340,7 +363,7 @@ mprint(struct magic_set *ms, struct magic *m) float vf; double vd; int64_t t = 0; - char buf[128]; + char buf[128], tbuf[26]; union VALUETYPE *p = &ms->ms_value; switch (m->type) { @@ -425,13 +448,32 @@ mprint(struct magic_set *ms, struct magic *m) t = ms->offset + m->vallen; } else { + char *str = p->s; + + /* compute t before we mangle the string? */ + t = ms->offset + strlen(str); + if (*m->value.s == '\0') - p->s[strcspn(p->s, "\n")] = '\0'; - if (file_printf(ms, m->desc, p->s) == -1) + str[strcspn(str, "\n")] = '\0'; + + if (m->str_flags & STRING_TRIM) { + char *last; + while (isspace((unsigned char)*str)) + str++; + last = str; + while (*last) + last++; + --last; + while (isspace((unsigned char)*last)) + last--; + *++last = '\0'; + } + + if (file_printf(ms, m->desc, str) == -1) return -1; - t = ms->offset + strlen(p->s); + if (m->type == FILE_PSTRING) - t++; + t += file_pstring_length_size(m); } break; @@ -439,25 +481,26 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_BEDATE: case FILE_LEDATE: case FILE_MEDATE: - if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1) + if (file_printf(ms, m->desc, file_fmttime(p->l, FILE_T_LOCAL, + tbuf)) == -1) return -1; - t = ms->offset + sizeof(time_t); + t = ms->offset + sizeof(uint32_t); break; case FILE_LDATE: case FILE_BELDATE: case FILE_LELDATE: case FILE_MELDATE: - if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1) + if (file_printf(ms, m->desc, file_fmttime(p->l, 0, tbuf)) == -1) return -1; - t = ms->offset + sizeof(time_t); + t = ms->offset + sizeof(uint32_t); break; case FILE_QDATE: case FILE_BEQDATE: case FILE_LEQDATE: - if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, - 1)) == -1) + if (file_printf(ms, m->desc, file_fmttime(p->q, FILE_T_LOCAL, + tbuf)) == -1) return -1; t = ms->offset + sizeof(uint64_t); break; @@ -465,12 +508,20 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_QLDATE: case FILE_BEQLDATE: case FILE_LEQLDATE: - if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, - 0)) == -1) + if (file_printf(ms, m->desc, file_fmttime(p->q, 0, tbuf)) == -1) return -1; t = ms->offset + sizeof(uint64_t); break; + case FILE_QWDATE: + case FILE_BEQWDATE: + case FILE_LEQWDATE: + if (file_printf(ms, m->desc, file_fmttime(p->q, FILE_T_WINDOWS, + tbuf)) == -1) + return -1; + t = ms->offset + sizeof(uint64_t); + break; + case FILE_FLOAT: case FILE_BEFLOAT: case FILE_LEFLOAT: @@ -516,7 +567,10 @@ mprint(struct magic_set *ms, struct magic *m) int rval; cp = estrndup((const char *)ms->search.s, ms->search.rm_len); - + if (cp == NULL) { + file_oomem(ms, ms->search.rm_len); + return -1; + } rval = file_printf(ms, m->desc, cp); efree(cp); @@ -546,6 +600,8 @@ mprint(struct magic_set *ms, struct magic *m) break; case FILE_INDIRECT: + case FILE_USE: + case FILE_NAME: t = ms->offset; break; @@ -561,23 +617,23 @@ moffset(struct magic_set *ms, struct magic *m) { switch (m->type) { case FILE_BYTE: - return ms->offset + sizeof(char); + return CAST(int32_t, (ms->offset + sizeof(char))); case FILE_SHORT: case FILE_BESHORT: case FILE_LESHORT: - return ms->offset + sizeof(short); + return CAST(int32_t, (ms->offset + sizeof(short))); case FILE_LONG: case FILE_BELONG: case FILE_LELONG: case FILE_MELONG: - return ms->offset + sizeof(int32_t); + return CAST(int32_t, (ms->offset + sizeof(int32_t))); case FILE_QUAD: case FILE_BEQUAD: case FILE_LEQUAD: - return ms->offset + sizeof(int64_t); + return CAST(int32_t, (ms->offset + sizeof(int64_t))); case FILE_STRING: case FILE_PSTRING: @@ -591,9 +647,9 @@ moffset(struct magic_set *ms, struct magic *m) if (*m->value.s == '\0') p->s[strcspn(p->s, "\n")] = '\0'; - t = ms->offset + strlen(p->s); + t = CAST(uint32_t, (ms->offset + strlen(p->s))); if (m->type == FILE_PSTRING) - t++; + t += (uint32_t)file_pstring_length_size(m); return t; } @@ -601,46 +657,46 @@ moffset(struct magic_set *ms, struct magic *m) case FILE_BEDATE: case FILE_LEDATE: case FILE_MEDATE: - return ms->offset + sizeof(time_t); + return CAST(int32_t, (ms->offset + sizeof(uint32_t))); case FILE_LDATE: case FILE_BELDATE: case FILE_LELDATE: case FILE_MELDATE: - return ms->offset + sizeof(time_t); + return CAST(int32_t, (ms->offset + sizeof(uint32_t))); case FILE_QDATE: case FILE_BEQDATE: case FILE_LEQDATE: - return ms->offset + sizeof(uint64_t); + return CAST(int32_t, (ms->offset + sizeof(uint64_t))); case FILE_QLDATE: case FILE_BEQLDATE: case FILE_LEQLDATE: - return ms->offset + sizeof(uint64_t); + return CAST(int32_t, (ms->offset + sizeof(uint64_t))); case FILE_FLOAT: case FILE_BEFLOAT: case FILE_LEFLOAT: - return ms->offset + sizeof(float); + return CAST(int32_t, (ms->offset + sizeof(float))); case FILE_DOUBLE: case FILE_BEDOUBLE: case FILE_LEDOUBLE: - return ms->offset + sizeof(double); - break; + return CAST(int32_t, (ms->offset + sizeof(double))); case FILE_REGEX: if ((m->str_flags & REGEX_OFFSET_START) != 0) - return ms->search.offset; + return CAST(int32_t, ms->search.offset); else - return ms->search.offset + ms->search.rm_len; + return CAST(int32_t, (ms->search.offset + + ms->search.rm_len)); case FILE_SEARCH: if ((m->str_flags & REGEX_OFFSET_START) != 0) - return ms->search.offset; + return CAST(int32_t, ms->search.offset); else - return ms->search.offset + m->vallen; + return CAST(int32_t, (ms->search.offset + m->vallen)); case FILE_DEFAULT: return ms->offset; @@ -653,6 +709,56 @@ moffset(struct magic_set *ms, struct magic *m) } } +private int +cvt_flip(int type, int flip) +{ + if (flip == 0) + return type; + switch (type) { + case FILE_BESHORT: + return FILE_LESHORT; + case FILE_BELONG: + return FILE_LELONG; + case FILE_BEDATE: + return FILE_LEDATE; + case FILE_BELDATE: + return FILE_LELDATE; + case FILE_BEQUAD: + return FILE_LEQUAD; + case FILE_BEQDATE: + return FILE_LEQDATE; + case FILE_BEQLDATE: + return FILE_LEQLDATE; + case FILE_BEQWDATE: + return FILE_LEQWDATE; + case FILE_LESHORT: + return FILE_BESHORT; + case FILE_LELONG: + return FILE_BELONG; + case FILE_LEDATE: + return FILE_BEDATE; + case FILE_LELDATE: + return FILE_BELDATE; + case FILE_LEQUAD: + return FILE_BEQUAD; + case FILE_LEQDATE: + return FILE_BEQDATE; + case FILE_LEQLDATE: + return FILE_BEQLDATE; + case FILE_LEQWDATE: + return FILE_BEQWDATE; + case FILE_BEFLOAT: + return FILE_LEFLOAT; + case FILE_LEFLOAT: + return FILE_BEFLOAT; + case FILE_BEDOUBLE: + return FILE_LEDOUBLE; + case FILE_LEDOUBLE: + return FILE_BEDOUBLE; + default: + return type; + } +} #define DO_CVT(fld, cast) \ if (m->num_mask) \ switch (m->mask_op & FILE_OPS_MASK) { \ @@ -743,11 +849,11 @@ cvt_double(union VALUETYPE *p, const struct magic *m) * (unless you have a better idea) */ private int -mconvert(struct magic_set *ms, struct magic *m) +mconvert(struct magic_set *ms, struct magic *m, int flip) { union VALUETYPE *p = &ms->ms_value; - switch (m->type) { + switch (cvt_flip(m->type, flip)) { case FILE_BYTE: cvt_8(p, m); return 1; @@ -762,6 +868,7 @@ mconvert(struct magic_set *ms, struct magic *m) case FILE_QUAD: case FILE_QDATE: case FILE_QLDATE: + case FILE_QWDATE: cvt_64(p, m); return 1; case FILE_STRING: @@ -769,28 +876,16 @@ mconvert(struct magic_set *ms, struct magic *m) case FILE_LESTRING16: { /* Null terminate and eat *trailing* return */ p->s[sizeof(p->s) - 1] = '\0'; -#if 0 - /* Why? breaks magic numbers that end with \xa */ - len = strlen(p->s); - if (len-- && p->s[len] == '\n') - p->s[len] = '\0'; -#endif return 1; } case FILE_PSTRING: { - char *ptr1 = p->s, *ptr2 = ptr1 + 1; - size_t len = *p->s; + char *ptr1 = p->s, *ptr2 = ptr1 + file_pstring_length_size(m); + size_t len = file_pstring_get_length(m, ptr1); if (len >= sizeof(p->s)) len = sizeof(p->s) - 1; while (len--) *ptr1++ = *ptr2++; *ptr1 = '\0'; -#if 0 - /* Why? breaks magic numbers that end with \xa */ - len = strlen(p->s); - if (len-- && p->s[len] == '\n') - p->s[len] = '\0'; -#endif return 1; } case FILE_BESHORT: @@ -807,6 +902,7 @@ mconvert(struct magic_set *ms, struct magic *m) case FILE_BEQUAD: case FILE_BEQDATE: case FILE_BEQLDATE: + case FILE_BEQWDATE: p->q = (uint64_t) (((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)| ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)| @@ -828,6 +924,7 @@ mconvert(struct magic_set *ms, struct magic *m) case FILE_LEQUAD: case FILE_LEQDATE: case FILE_LEQLDATE: + case FILE_LEQWDATE: p->q = (uint64_t) (((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)| ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)| @@ -875,6 +972,8 @@ mconvert(struct magic_set *ms, struct magic *m) case FILE_REGEX: case FILE_SEARCH: case FILE_DEFAULT: + case FILE_NAME: + case FILE_USE: return 1; default: file_magerror(ms, "invalid type %d in mconvert()", m->type); @@ -886,7 +985,7 @@ mconvert(struct magic_set *ms, struct magic *m) private void mdebug(uint32_t offset, const char *str, size_t len) { - (void) fprintf(stderr, "mget @%d: ", offset); + (void) fprintf(stderr, "mget/%zu @%d: ", len, offset); file_showstr(stderr, str, len); (void) fputc('\n', stderr); (void) fputc('\n', stderr); @@ -903,7 +1002,7 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int ty if (indir == 0) { switch (type) { case FILE_SEARCH: - ms->search.s = (const char *)s + offset; + ms->search.s = RCAST(const char *, s) + offset; ms->search.s_len = nbytes - offset; ms->search.offset = offset; return 0; @@ -921,18 +1020,21 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int ty ms->search.s = NULL; return 0; } - buf = (const char *)s + offset; - end = last = (const char *)s + nbytes; + buf = RCAST(const char *, s) + offset; + end = last = RCAST(const char *, s) + nbytes; /* mget() guarantees buf <= last */ - for (lines = linecnt, b = buf; - lines && ((b = memchr(c = b, '\n', end - b)) || (b = memchr(c, '\r', end - c))); + for (lines = linecnt, b = buf; lines && b < end && + ((b = CAST(const char *, + memchr(c = b, '\n', CAST(size_t, (end - b))))) + || (b = CAST(const char *, + memchr(c, '\r', CAST(size_t, (end - c)))))); lines--, b++) { last = b; if (b[0] == '\r' && b[1] == '\n') b++; } if (lines) - last = (const char *)s + nbytes; + last = RCAST(const char *, s) + nbytes; ms->search.s = buf; ms->search.s_len = last - buf; @@ -950,8 +1052,8 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int ty if (type == FILE_BESTRING16) src++; - /* check for pointer overflow */ - if (src < s) { + /* check that offset is within range */ + if (offset >= nbytes) { file_magerror(ms, "invalid offset %u in mcopy()", offset); return -1; @@ -1000,26 +1102,40 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int ty } private int -mget(struct magic_set *ms, const unsigned char *s, - struct magic *m, size_t nbytes, unsigned int cont_level) +mget(struct magic_set *ms, const unsigned char *s, struct magic *m, + size_t nbytes, size_t o, unsigned int cont_level, int mode, int text, + int flip, int recursion_level, int *printed_something, + int *need_separator, int *returnval) { - uint32_t offset = ms->offset; + uint32_t soffset, offset = ms->offset; uint32_t count = m->str_range; + int rv, oneed_separator; + char *sbuf, *rbuf; union VALUETYPE *p = &ms->ms_value; + struct mlist ml; - if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1) + if (recursion_level >= 20) { + file_error(ms, 0, "recursion nesting exceeded"); return -1; + } + if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o), + (uint32_t)nbytes, count) == -1) + return -1; + if ((ms->flags & MAGIC_DEBUG) != 0) { + fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%zu, " + "nbytes=%zu, count=%u)\n", m->type, m->flag, offset, o, + nbytes, count); mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE)); } 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) { + const union VALUETYPE *q = CAST(const union VALUETYPE *, + ((const void *)(s + offset + off))); + switch (cvt_flip(m->in_type, flip)) { case FILE_BYTE: off = q->b; break; @@ -1050,8 +1166,10 @@ mget(struct magic_set *ms, const unsigned char *s, (q->hl[3]<<8)|(q->hl[2])); break; } + if ((ms->flags & MAGIC_DEBUG) != 0) + fprintf(stderr, "indirect offs=%u\n", off); } - switch (m->in_type) { + switch (cvt_flip(m->in_type, flip)) { case FILE_BYTE: if (nbytes < (offset + 1)) return 0; @@ -1476,7 +1594,7 @@ mget(struct magic_set *ms, const unsigned char *s, break; } - switch (m->in_type) { + switch (cvt_flip(m->in_type, flip)) { case FILE_LEID3: case FILE_BEID3: offset = ((((offset >> 0) & 0x7f) << 0) | @@ -1490,6 +1608,14 @@ mget(struct magic_set *ms, const unsigned char *s, if (m->flag & INDIROFFADD) { offset += ms->c.li[cont_level-1].off; + if (offset == 0) { + if ((ms->flags & MAGIC_DEBUG) != 0) + fprintf(stderr, + "indirect *zero* offset\n"); + return 0; + } + if ((ms->flags & MAGIC_DEBUG) != 0) + fprintf(stderr, "indirect +offs=%u\n", offset); } if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1) return -1; @@ -1554,19 +1680,61 @@ mget(struct magic_set *ms, const unsigned char *s, break; case FILE_INDIRECT: + if (nbytes < offset) + return 0; + sbuf = ms->o.buf; + soffset = ms->offset; + ms->o.buf = NULL; + ms->offset = 0; + rv = file_softmagic(ms, s + offset, nbytes - offset, + BINTEST, text); + if ((ms->flags & MAGIC_DEBUG) != 0) + fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv); + rbuf = ms->o.buf; + ms->o.buf = sbuf; + ms->offset = soffset; + if (rv == 1) { if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 && - file_printf(ms, m->desc) == -1) + file_printf(ms, m->desc, offset) == -1) return -1; + if (file_printf(ms, "%s", rbuf) == -1) + return -1; + efree(rbuf); + } + return rv; + + case FILE_USE: if (nbytes < offset) return 0; - return file_softmagic(ms, s + offset, nbytes - offset, - BINTEST); + sbuf = m->value.s; + if (*sbuf == '^') { + sbuf++; + flip = !flip; + } + if (file_magicfind(ms, sbuf, &ml) == -1) { + file_error(ms, 0, "cannot find entry `%s'", sbuf); + return -1; + } + oneed_separator = *need_separator; + if (m->flag & NOSPACE) + *need_separator = 0; + rv = match(ms, ml.magic, ml.nmagic, s, nbytes, offset + o, + mode, text, flip, recursion_level, printed_something, + need_separator, returnval); + if (rv != 1) + *need_separator = oneed_separator; + return rv; + + case FILE_NAME: + if (file_printf(ms, "%s", m->desc) == -1) + return -1; + return 1; case FILE_DEFAULT: /* nothing to check */ default: break; } - if (!mconvert(ms, m)) + if (!mconvert(ms, m, flip)) return 0; return 1; } @@ -1606,19 +1774,20 @@ file_strncmp(const char *s1, const char *s2, size_t le if ((v = toupper(*b++) - *a++) != '\0') break; } - else if ((flags & STRING_COMPACT_BLANK) && + else if ((flags & STRING_COMPACT_WHITESPACE) && isspace(*a)) { a++; if (isspace(*b++)) { - while (isspace(*b)) - b++; + if (!isspace(*a)) + while (isspace(*b)) + b++; } else { v = 1; break; } } - else if ((flags & STRING_COMPACT_OPTIONAL_BLANK) && + else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) && isspace(*a)) { a++; while (isspace(*b)) @@ -1645,7 +1814,7 @@ file_strncmp16(const char *a, const char *b, size_t le return file_strncmp(a, b, len, flags); } -private void +public void convert_libmagic_pattern(zval *pattern, int options) { int i, j=0; @@ -1657,29 +1826,6 @@ convert_libmagic_pattern(zval *pattern, int options) for (i=0; iq; break; @@ -1876,11 +2025,8 @@ magiccheck(struct magic_set *ms, struct magic *m) convert_libmagic_pattern(pattern, options); -#if (PHP_MAJOR_VERSION < 6) + l = v = 0; if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(pattern), Z_STRLEN_P(pattern) TSRMLS_CC)) == NULL) { -#else - if ((pce = pcre_get_compiled_regex_cache(IS_STRING, Z_STRVAL_P(pattern), Z_STRLEN_P(pattern) TSRMLS_CC)) == NULL) { -#endif zval_dtor(pattern); FREE_ZVAL(pattern); return -1; @@ -1897,11 +2043,7 @@ magiccheck(struct magic_set *ms, struct magic *m) haystack = estrndup(ms->search.s, ms->search.s_len); /* match v = 0, no match v = 1 */ -#if (PHP_MAJOR_VERSION < 6) php_pcre_match_impl(pce, haystack, ms->search.s_len, retval, subpats, 1, 1, PREG_OFFSET_CAPTURE, 0 TSRMLS_CC); -#else - php_pcre_match_impl(pce, IS_STRING, haystack, ms->search.s_len, retval, subpats, 1, 1, PREG_OFFSET_CAPTURE, 0 TSRMLS_CC); -#endif /* Free haystack */ efree(haystack); @@ -2015,6 +2157,8 @@ magiccheck(struct magic_set *ms, struct magic *m) break; } case FILE_INDIRECT: + case FILE_USE: + case FILE_NAME: return 1; default: file_magerror(ms, "invalid type %d in magiccheck()", m->type); @@ -2026,40 +2170,42 @@ magiccheck(struct magic_set *ms, struct magic *m) switch (m->reln) { case 'x': if ((ms->flags & MAGIC_DEBUG) != 0) - (void) fprintf(stderr, "%llu == *any* = 1\n", - (uint64_t)v); + (void) fprintf(stderr, "%" INT64_T_FORMAT + "u == *any* = 1\n", (unsigned long long)v); matched = 1; break; case '!': matched = v != l; if ((ms->flags & MAGIC_DEBUG) != 0) - (void) fprintf(stderr, "%llu != %llu = %d\n", - (uint64_t)v, (uint64_t)l, - matched); + (void) fprintf(stderr, "%" INT64_T_FORMAT "u != %" + INT64_T_FORMAT "u = %d\n", (unsigned long long)v, + (unsigned long long)l, matched); break; case '=': matched = v == l; if ((ms->flags & MAGIC_DEBUG) != 0) - (void) fprintf(stderr, "%llu == %llu = %d\n", - (uint64_t)v, (uint64_t)l, - matched); + (void) fprintf(stderr, "%" INT64_T_FORMAT "u == %" + INT64_T_FORMAT "u = %d\n", (unsigned long long)v, + (unsigned long long)l, matched); break; case '>': if (m->flag & UNSIGNED) { matched = v > l; if ((ms->flags & MAGIC_DEBUG) != 0) - (void) fprintf(stderr, "%llu > %llu = %d\n", - (uint64_t)v, - (uint64_t)l, matched); + (void) fprintf(stderr, "%" INT64_T_FORMAT + "u > %" INT64_T_FORMAT "u = %d\n", + (unsigned long long)v, + (unsigned long long)l, matched); } else { matched = (int64_t) v > (int64_t) l; if ((ms->flags & MAGIC_DEBUG) != 0) - (void) fprintf(stderr, "%lld > %lld = %d\n", - (uint64_t)v, (uint64_t)l, matched); + (void) fprintf(stderr, "%" INT64_T_FORMAT + "d > %" INT64_T_FORMAT "d = %d\n", + (long long)v, (long long)l, matched); } break; @@ -2067,32 +2213,38 @@ magiccheck(struct magic_set *ms, struct magic *m) if (m->flag & UNSIGNED) { matched = v < l; if ((ms->flags & MAGIC_DEBUG) != 0) - (void) fprintf(stderr, "%llu < %llu = %d\n", - (uint64_t)v, - (uint64_t)l, matched); + (void) fprintf(stderr, "%" INT64_T_FORMAT + "u < %" INT64_T_FORMAT "u = %d\n", + (unsigned long long)v, + (unsigned long long)l, matched); } else { matched = (int64_t) v < (int64_t) l; if ((ms->flags & MAGIC_DEBUG) != 0) - (void) fprintf(stderr, "%lld < %lld = %d\n", - (int64_t)v, (int64_t)l, matched); + (void) fprintf(stderr, "%" INT64_T_FORMAT + "d < %" INT64_T_FORMAT "d = %d\n", + (long long)v, (long long)l, matched); } break; case '&': matched = (v & l) == l; if ((ms->flags & MAGIC_DEBUG) != 0) - (void) fprintf(stderr, "((%llx & %llx) == %llx) = %d\n", - (uint64_t)v, (uint64_t)l, - (uint64_t)l, matched); + (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" + INT64_T_FORMAT "x) == %" INT64_T_FORMAT + "x) = %d\n", (unsigned long long)v, + (unsigned long long)l, (unsigned long long)l, + matched); break; case '^': matched = (v & l) != l; if ((ms->flags & MAGIC_DEBUG) != 0) - (void) fprintf(stderr, "((%llx & %llx) != %llx) = %d\n", - (uint64_t)v, (uint64_t)l, - (uint64_t)l, matched); + (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" + INT64_T_FORMAT "x) != %" INT64_T_FORMAT + "x) = %d\n", (unsigned long long)v, + (unsigned long long)l, (unsigned long long)l, + matched); break; default: