]> granicus.if.org Git - file/commitdiff
Add support for signed indirect offsets.
authorChristos Zoulas <christos@zoulas.com>
Wed, 20 Jul 2016 11:27:08 +0000 (11:27 +0000)
committerChristos Zoulas <christos@zoulas.com>
Wed, 20 Jul 2016 11:27:08 +0000 (11:27 +0000)
ChangeLog
doc/magic.man
src/apprentice.c
src/file.h
src/softmagic.c

index 1f30a1f9bfec9e51b6844d1dd251b12b3488459c..61655de5ebdf71aaa663f6a30a2b18c3bc457be9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2016-07-20   7:26  Christos Zoulas <christos@zoulas.com>
+
+       * Add support for signed indirect offsets
+
+2016-07-18   7:41  Christos Zoulas <christos@zoulas.com>
+
+       * cat /dev/null | file - should print empty (Christoph Biedl)
+
 2016-07-05  15:20  Christos Zoulas <christos@zoulas.com>
 
        * Bump string size from 64 to 96.
index fca6f026be0fd2289390402614b5b1bff79bcbe8..fab52e383083695291c70cabe544b4af7442af5c 100644 (file)
@@ -1,5 +1,5 @@
-.\" $File: magic.man,v 1.85 2015/01/01 17:07:34 christos Exp $
-.Dd January 1, 2015
+.\" $File: magic.man,v 1.86 2015/09/08 13:48:44 christos Exp $
+.Dd July 20, 2016
 .Dt MAGIC __FSECTION__
 .Os
 .\" install as magic.4 on USG, magic.5 on V7, Berkeley and Linux systems.
@@ -535,13 +535,18 @@ the file.
 The value at that offset is read, and is used again as an offset
 in the file.
 Indirect offsets are of the form:
-.Em (( x [.[bislBISL]][+\-][ y ]) .
+.Em (( x [[.,][bislBISL]][+\-][ y ]) .
 The value of
 .Em x
 is used as an offset in the file.
 A byte, id3 length, short or long is read at that offset depending on the
 .Em [bislBISLm]
 type specifier.
+The value is treated as signed if
+.Dq ,
+is specified or unsigned if
+.Dq .
+is specified.
 The capitalized types interpret the number as a big endian
 value, whereas the small letter versions interpret the number as a little
 endian value;
index 37d19a21f5c8bd02fbb6ced8f03bf7b3c4fb0479..47879b1fe233f382f250dc7eb1a0bf9fab1dd23d 100644 (file)
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: apprentice.c,v 1.249 2016/05/17 21:43:07 christos Exp $")
+FILE_RCSID("@(#)$File: apprentice.c,v 1.250 2016/07/05 19:20:19 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -1881,10 +1881,13 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
        if (m->flag & INDIR) {
                m->in_type = FILE_LONG;
                m->in_offset = 0;
+               m->in_op = 0;
                /*
-                * read [.lbs][+-]nnnnn)
+                * read [.,lbs][+-]nnnnn)
                 */
-               if (*l == '.') {
+               if (*l == '.' || *l == ',') {
+                       if (*l == ',')
+                               m->in_op |= FILE_OPSIGNED;
                        l++;
                        switch (*l) {
                        case 'l':
@@ -1936,7 +1939,6 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
                        l++;
                }
 
-               m->in_op = 0;
                if (*l == '~') {
                        m->in_op |= FILE_OPINVERSE;
                        l++;
index 6693985b55cbfc95e7cf27060707d947ca287913..1aa9047971a36ef33e9992e53bf55baae6dc66ea 100644 (file)
@@ -27,7 +27,7 @@
  */
 /*
  * file.h - definitions for file(1) program
- * @(#)$File: file.h,v 1.178 2016/03/31 17:51:12 christos Exp $
+ * @(#)$File: file.h,v 1.179 2016/07/05 19:20:19 christos Exp $
  */
 
 #ifndef __file_h__
@@ -275,7 +275,7 @@ struct magic {
 #define                                FILE_OPS_MASK   0x07 /* mask for above ops */
 #define                                FILE_UNUSED_1   0x08
 #define                                FILE_UNUSED_2   0x10
-#define                                FILE_UNUSED_3   0x20
+#define                                FILE_OPSIGNED   0x20
 #define                                FILE_OPINVERSE  0x40
 #define                                FILE_OPINDIRECT 0x80
 
index 6e10b7dbe91c18fe54993a60c9b9f447d5a87b8b..8816aab384fd9ad8d401e8d2f740dba4b81e06f4 100644 (file)
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: softmagic.c,v 1.234 2016/06/13 12:02:06 christos Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.235 2016/06/14 00:22:36 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -63,7 +63,7 @@ private int cvt_16(union VALUETYPE *, const struct magic *);
 private int cvt_32(union VALUETYPE *, const struct magic *);
 private int cvt_64(union VALUETYPE *, const struct magic *);
 
-#define OFFSET_OOB(n, o, i)    ((n) < (o) || (i) > ((n) - (o)))
+#define OFFSET_OOB(n, o, i)    ((n) < (uint32_t)(o) || (i) > ((n) - (o)))
 #define BE64(p) (((uint64_t)(p)->hq[0]<<56)|((uint64_t)(p)->hq[1]<<48)| \
     ((uint64_t)(p)->hq[2]<<40)|((uint64_t)(p)->hq[3]<<32)| \
     ((uint64_t)(p)->hq[4]<<24)|((uint64_t)(p)->hq[5]<<16)| \
@@ -80,6 +80,7 @@ private int cvt_64(union VALUETYPE *, const struct magic *);
      ((uint32_t)(p)->hl[3]<<8)|((uint32_t)(p)->hl[2]))
 #define BE16(p) (((uint16_t)(p)->hs[0]<<8)|((uint16_t)(p)->hs[1]))
 #define LE16(p) (((uint16_t)(p)->hs[1]<<8)|((uint16_t)(p)->hs[0]))
+#define SEXT(s,v,p) ((s)?(intmax_t)(int##v##_t)(p):(intmax_t)(uint##v##_t)(p))
 
 /*
  * softmagic - lookup one file in parsed, in-memory copy of database
@@ -1294,6 +1295,45 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
        return 0;
 }
 
+private uint32_t
+do_ops(struct magic *m, intmax_t lhs, intmax_t off)
+{
+       intmax_t offset;
+       if (off) {
+               switch (m->in_op & FILE_OPS_MASK) {
+               case FILE_OPAND:
+                       offset = lhs & off;
+                       break;
+               case FILE_OPOR:
+                       offset = lhs | off;
+                       break;
+               case FILE_OPXOR:
+                       offset = lhs ^ off;
+                       break;
+               case FILE_OPADD:
+                       offset = lhs + off;
+                       break;
+               case FILE_OPMINUS:
+                       offset = lhs - off;
+                       break;
+               case FILE_OPMULTIPLY:
+                       offset = lhs * off;
+                       break;
+               case FILE_OPDIVIDE:
+                       offset = lhs / off;
+                       break;
+               case FILE_OPMODULO:
+                       offset = lhs % off;
+                       break;
+               }
+       } else
+               offset = lhs;
+       if (m->in_op & FILE_OPINVERSE)
+               offset = ~offset;
+
+       return (uint32_t)offset;
+}
+
 private int
 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,
@@ -1301,7 +1341,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
     int *printed_something, int *need_separator, int *returnval)
 {
        uint32_t offset = ms->offset;
-       uint32_t lhs;
+       intmax_t lhs;
        file_pushbuf_t *pb;
        int rv, oneed_separator, in_type;
        char *rbuf;
@@ -1337,7 +1377,8 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
        }
 
        if (m->flag & INDIR) {
-               int off = m->in_offset;
+               intmax_t off = m->in_offset;
+               const int sgn = m->in_op & FILE_OPSIGNED;
                if (m->in_op & FILE_OPINDIRECT) {
                        const union VALUETYPE *q = CAST(const union VALUETYPE *,
                            ((const void *)(s + offset + off)));
@@ -1345,178 +1386,55 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
                                return 0;
                        switch (cvt_flip(m->in_type, flip)) {
                        case FILE_BYTE:
-                               off = q->b;
+                               off = SEXT(sgn,8,q->b);
                                break;
                        case FILE_SHORT:
-                               off = q->h;
+                               off = SEXT(sgn,16,q->h);
                                break;
                        case FILE_BESHORT:
-                               off = (short)BE16(q);
+                               off = SEXT(sgn,16,BE16(q));
                                break;
                        case FILE_LESHORT:
-                               off = (short)LE16(q);
+                               off = SEXT(sgn,16,LE16(q));
                                break;
                        case FILE_LONG:
-                               off = q->l;
+                               off = SEXT(sgn,32,q->l);
                                break;
                        case FILE_BELONG:
                        case FILE_BEID3:
-                               off = (int32_t)BE32(q);
+                               off = SEXT(sgn,32,BE32(q));
                                break;
                        case FILE_LEID3:
                        case FILE_LELONG:
-                               off = (int32_t)LE32(q);
+                               off = SEXT(sgn,32,LE32(q));
                                break;
                        case FILE_MELONG:
-                               off = (int32_t)ME32(q);
+                               off = SEXT(sgn,32,ME32(q));
                                break;
                        }
                        if ((ms->flags & MAGIC_DEBUG) != 0)
-                               fprintf(stderr, "indirect offs=%u\n", off);
+                               fprintf(stderr, "indirect offs=%jd\n", off);
                }
                switch (in_type = cvt_flip(m->in_type, flip)) {
                case FILE_BYTE:
                        if (OFFSET_OOB(nbytes, offset, 1))
                                return 0;
-                       if (off) {
-                               switch (m->in_op & FILE_OPS_MASK) {
-                               case FILE_OPAND:
-                                       offset = p->b & off;
-                                       break;
-                               case FILE_OPOR:
-                                       offset = p->b | off;
-                                       break;
-                               case FILE_OPXOR:
-                                       offset = p->b ^ off;
-                                       break;
-                               case FILE_OPADD:
-                                       offset = p->b + off;
-                                       break;
-                               case FILE_OPMINUS:
-                                       offset = p->b - off;
-                                       break;
-                               case FILE_OPMULTIPLY:
-                                       offset = p->b * off;
-                                       break;
-                               case FILE_OPDIVIDE:
-                                       offset = p->b / off;
-                                       break;
-                               case FILE_OPMODULO:
-                                       offset = p->b % off;
-                                       break;
-                               }
-                       } else
-                               offset = p->b;
-                       if (m->in_op & FILE_OPINVERSE)
-                               offset = ~offset;
+                       offset = do_ops(m, SEXT(sgn,8,p->b), off);
                        break;
                case FILE_BESHORT:
                        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 = lhs & off;
-                                       break;
-                               case FILE_OPOR:
-                                       offset = lhs | off;
-                                       break;
-                               case FILE_OPXOR:
-                                       offset = lhs ^ off;
-                                       break;
-                               case FILE_OPADD:
-                                       offset = lhs + off;
-                                       break;
-                               case FILE_OPMINUS:
-                                       offset = lhs - off;
-                                       break;
-                               case FILE_OPMULTIPLY:
-                                       offset = lhs * off;
-                                       break;
-                               case FILE_OPDIVIDE:
-                                       offset = lhs / off;
-                                       break;
-                               case FILE_OPMODULO:
-                                       offset = lhs % off;
-                                       break;
-                               }
-                       } else
-                               offset = lhs;
-                       if (m->in_op & FILE_OPINVERSE)
-                               offset = ~offset;
+                       offset = do_ops(m, SEXT(sgn,16,BE16(p)), off);
                        break;
                case FILE_LESHORT:
                        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 = lhs & off;
-                                       break;
-                               case FILE_OPOR:
-                                       offset = lhs | off;
-                                       break;
-                               case FILE_OPXOR:
-                                       offset = lhs ^ off;
-                                       break;
-                               case FILE_OPADD:
-                                       offset = lhs + off;
-                                       break;
-                               case FILE_OPMINUS:
-                                       offset = lhs - off;
-                                       break;
-                               case FILE_OPMULTIPLY:
-                                       offset = lhs * off;
-                                       break;
-                               case FILE_OPDIVIDE:
-                                       offset = lhs / off;
-                                       break;
-                               case FILE_OPMODULO:
-                                       offset = lhs % off;
-                                       break;
-                               }
-                       } else
-                               offset = lhs;
-                       if (m->in_op & FILE_OPINVERSE)
-                               offset = ~offset;
+                       offset = do_ops(m, SEXT(sgn,16,LE16(p)), off);
                        break;
                case FILE_SHORT:
                        if (OFFSET_OOB(nbytes, offset, 2))
                                return 0;
-                       if (off) {
-                               switch (m->in_op & FILE_OPS_MASK) {
-                               case FILE_OPAND:
-                                       offset = p->h & off;
-                                       break;
-                               case FILE_OPOR:
-                                       offset = p->h | off;
-                                       break;
-                               case FILE_OPXOR:
-                                       offset = p->h ^ off;
-                                       break;
-                               case FILE_OPADD:
-                                       offset = p->h + off;
-                                       break;
-                               case FILE_OPMINUS:
-                                       offset = p->h - off;
-                                       break;
-                               case FILE_OPMULTIPLY:
-                                       offset = p->h * off;
-                                       break;
-                               case FILE_OPDIVIDE:
-                                       offset = p->h / off;
-                                       break;
-                               case FILE_OPMODULO:
-                                       offset = p->h % off;
-                                       break;
-                               }
-                       }
-                       else
-                               offset = p->h;
-                       if (m->in_op & FILE_OPINVERSE)
-                               offset = ~offset;
+                       offset = do_ops(m, SEXT(sgn,16,p->h), off);
                        break;
                case FILE_BELONG:
                case FILE_BEID3:
@@ -1524,38 +1442,8 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
                                return 0;
                        lhs = BE32(p);
                        if (in_type == FILE_BEID3)
-                               lhs = cvt_id3(ms, lhs);
-                       if (off) {
-                               switch (m->in_op & FILE_OPS_MASK) {
-                               case FILE_OPAND:
-                                       offset = lhs & off;
-                                       break;
-                               case FILE_OPOR:
-                                       offset = lhs | off;
-                                       break;
-                               case FILE_OPXOR:
-                                       offset = lhs ^ off;
-                                       break;
-                               case FILE_OPADD:
-                                       offset = lhs + off;
-                                       break;
-                               case FILE_OPMINUS:
-                                       offset = lhs - off;
-                                       break;
-                               case FILE_OPMULTIPLY:
-                                       offset = lhs * off;
-                                       break;
-                               case FILE_OPDIVIDE:
-                                       offset = lhs / off;
-                                       break;
-                               case FILE_OPMODULO:
-                                       offset = lhs % off;
-                                       break;
-                               }
-                       } else
-                               offset = lhs;
-                       if (m->in_op & FILE_OPINVERSE)
-                               offset = ~offset;
+                               lhs = cvt_id3(ms, (uint32_t)lhs);
+                       offset = do_ops(m, SEXT(sgn,32,lhs), off);
                        break;
                case FILE_LELONG:
                case FILE_LEID3:
@@ -1563,109 +1451,18 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
                                return 0;
                        lhs = LE32(p);
                        if (in_type == FILE_LEID3)
-                               lhs = cvt_id3(ms, lhs);
-                       if (off) {
-                               switch (m->in_op & FILE_OPS_MASK) {
-                               case FILE_OPAND:
-                                       offset = lhs & off;
-                                       break;
-                               case FILE_OPOR:
-                                       offset = lhs | off;
-                                       break;
-                               case FILE_OPXOR:
-                                       offset = lhs ^ off;
-                                       break;
-                               case FILE_OPADD:
-                                       offset = lhs + off;
-                                       break;
-                               case FILE_OPMINUS:
-                                       offset = lhs - off;
-                                       break;
-                               case FILE_OPMULTIPLY:
-                                       offset = lhs * off;
-                                       break;
-                               case FILE_OPDIVIDE:
-                                       offset = lhs / off;
-                                       break;
-                               case FILE_OPMODULO:
-                                       offset = lhs % off;
-                                       break;
-                               }
-                       } else
-                               offset = lhs;
-                       if (m->in_op & FILE_OPINVERSE)
-                               offset = ~offset;
+                               lhs = cvt_id3(ms, (uint32_t)lhs);
+                       offset = do_ops(m, SEXT(sgn,32,lhs), off);
                        break;
                case FILE_MELONG:
                        if (OFFSET_OOB(nbytes, offset, 4))
                                return 0;
-                       lhs = ME32(p);
-                       if (off) {
-                               switch (m->in_op & FILE_OPS_MASK) {
-                               case FILE_OPAND:
-                                       offset = lhs & off;
-                                       break;
-                               case FILE_OPOR:
-                                       offset = lhs | off;
-                                       break;
-                               case FILE_OPXOR:
-                                       offset = lhs ^ off;
-                                       break;
-                               case FILE_OPADD:
-                                       offset = lhs + off;
-                                       break;
-                               case FILE_OPMINUS:
-                                       offset = lhs - off;
-                                       break;
-                               case FILE_OPMULTIPLY:
-                                       offset = lhs * off;
-                                       break;
-                               case FILE_OPDIVIDE:
-                                       offset = lhs / off;
-                                       break;
-                               case FILE_OPMODULO:
-                                       offset = lhs % off;
-                                       break;
-                               }
-                       } else
-                               offset = lhs;
-                       if (m->in_op & FILE_OPINVERSE)
-                               offset = ~offset;
+                       offset = do_ops(m, SEXT(sgn,32,ME32(p)), off);
                        break;
                case FILE_LONG:
                        if (OFFSET_OOB(nbytes, offset, 4))
                                return 0;
-                       if (off) {
-                               switch (m->in_op & FILE_OPS_MASK) {
-                               case FILE_OPAND:
-                                       offset = p->l & off;
-                                       break;
-                               case FILE_OPOR:
-                                       offset = p->l | off;
-                                       break;
-                               case FILE_OPXOR:
-                                       offset = p->l ^ off;
-                                       break;
-                               case FILE_OPADD:
-                                       offset = p->l + off;
-                                       break;
-                               case FILE_OPMINUS:
-                                       offset = p->l - off;
-                                       break;
-                               case FILE_OPMULTIPLY:
-                                       offset = p->l * off;
-                                       break;
-                               case FILE_OPDIVIDE:
-                                       offset = p->l / off;
-                                       break;
-                               case FILE_OPMODULO:
-                                       offset = p->l % off;
-                                       break;
-                               }
-                       } else
-                               offset = p->l;
-                       if (m->in_op & FILE_OPINVERSE)
-                               offset = ~offset;
+                       offset = do_ops(m, SEXT(sgn,32,p->l), off);
                        break;
                default:
                        break;