]> granicus.if.org Git - file/commitdiff
Add indirect relative offsets; make Exif use them. All other indirect magic
authorChristos Zoulas <christos@zoulas.com>
Thu, 1 Jan 2015 17:07:34 +0000 (17:07 +0000)
committerChristos Zoulas <christos@zoulas.com>
Thu, 1 Jan 2015 17:07:34 +0000 (17:07 +0000)
is absolute by default.

ChangeLog
doc/magic.man
magic/Magdir/jpeg
src/apprentice.c
src/file.h
src/softmagic.c

index 7e501baa3c14b7d2ffa5652b6c2383b66db8ffd9..6552c0a95cbb1af33c23150ef99787546d0527a7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2015-01-01  12:01  Christos Zoulas <christos@zoulas.com>
+
+       * add indirect relative for TIFF/Exif
+
 2014-12-16  18:10  Christos Zoulas <christos@zoulas.com>
        
        * restructure elf note printing to avoid repeated messages
index 66d3b17386085f52b4bd0ada809a86095ea6ab38..86bbda0a7e71112537110fc67266fe8b209e6e22 100644 (file)
@@ -1,5 +1,5 @@
-.\" $File: magic.man,v 1.83 2014/06/03 17:36:13 christos Exp $
-.Dd June 3, 2014
+.\" $File: magic.man,v 1.84 2014/06/03 19:01:34 christos Exp $
+.Dd January 1, 2015
 .Dt MAGIC __FSECTION__
 .Os
 .\" install as magic.4 on USG, magic.5 on V7, Berkeley and Linux systems.
@@ -200,6 +200,11 @@ interpreted as a UNIX-style date, but interpreted as local time rather
 than UTC.
 .It Dv indirect
 Starting at the given offset, consult the magic database again.
+The offset of th
+.Dv indirect
+magic is by default absolute in the file, but one can specify
+.Dv /r
+to indicate that the offset is relative from the beginning of the entry.
 .It Dv name
 Define a
 .Dq named
index 81b0aa6981bc3dd6ee61752638518785930d87a1..48a07f2e838f48fee758d2d21efc1fbdf74ecbef 100644 (file)
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: jpeg,v 1.22 2015/01/01 02:57:40 christos Exp $
+# $File: jpeg,v 1.23 2015/01/01 04:17:41 christos Exp $
 # JPEG images
 # SunOS 5.5.1 had
 #
@@ -32,7 +32,7 @@
 >>18   byte            !0              \b, thumbnail %dx
 >>>19  byte            x               \b%d
 >6     string          Exif            \b, Exif standard: [
->>12   indirect        x
+>>12   indirect/r      x
 >>12   string          x               \b]
 
 # Jump to the first segment
@@ -72,7 +72,7 @@
 >0     beshort         0xFFE1          
 #>>(2.S+2)     use                     jpeg_segment
 >>4    string          Exif            \b, Exif Standard: [
->>>10  indirect        x               
+>>>10  indirect/r      x               
 >>>10  string          x               \b]
 
 # Application specific markers
index ac098263b4a38e71ea3708b51c1ec10f7b048695..02e081fb215dd4bebcf76b598e1b39a807063163 100644 (file)
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: apprentice.c,v 1.227 2014/11/28 02:46:39 christos Exp $")
+FILE_RCSID("@(#)$File: apprentice.c,v 1.228 2014/12/16 23:18:40 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -1605,6 +1605,145 @@ check_cond(struct magic_set *ms, int cond, uint32_t cont_level)
 }
 #endif /* ENABLE_CONDITIONALS */
 
+private int
+parse_indirect_modifier(struct magic_set *ms, struct magic *m, const char **lp)
+{
+       const char *l = *lp;
+
+       while (!isspace((unsigned char)*++l))
+               switch (*l) {
+               case CHAR_INDIRECT_RELATIVE:
+                       m->str_flags |= INDIRECT_RELATIVE;
+                       break;
+               default:
+                       if (ms->flags & MAGIC_CHECK)
+                               file_magwarn(ms, "indirect modifier `%c' "
+                                       "invalid", *l);
+                       *lp = l;
+                       return -1;
+               }
+       *lp = l;
+       return 0;
+}
+
+private void
+parse_op_modifier(struct magic_set *ms, struct magic *m, const char **lp,
+    int op)
+{
+       const char *l = *lp;
+       char *t;
+       uint64_t val;
+
+       ++l;
+       m->mask_op |= op;
+       val = (uint64_t)strtoull(l, &t, 0);
+       l = t;
+       m->num_mask = file_signextend(ms, m, val);
+       eatsize(&l);
+       *lp = l;
+}
+
+private int
+parse_string_modifier(struct magic_set *ms, struct magic *m, const char **lp)
+{
+       const char *l = *lp;
+       char *t;
+       int have_range = 0;
+
+       while (!isspace((unsigned char)*++l)) {
+               switch (*l) {
+               case '0':  case '1':  case '2':
+               case '3':  case '4':  case '5':
+               case '6':  case '7':  case '8':
+               case '9':
+                       if (have_range && (ms->flags & MAGIC_CHECK))
+                               file_magwarn(ms, "multiple ranges");
+                       have_range = 1;
+                       m->str_range = CAST(uint32_t, strtoul(l, &t, 0));
+                       if (m->str_range == 0)
+                               file_magwarn(ms, "zero range");
+                       l = t - 1;
+                       break;
+               case CHAR_COMPACT_WHITESPACE:
+                       m->str_flags |= STRING_COMPACT_WHITESPACE;
+                       break;
+               case CHAR_COMPACT_OPTIONAL_WHITESPACE:
+                       m->str_flags |= STRING_COMPACT_OPTIONAL_WHITESPACE;
+                       break;
+               case CHAR_IGNORE_LOWERCASE:
+                       m->str_flags |= STRING_IGNORE_LOWERCASE;
+                       break;
+               case CHAR_IGNORE_UPPERCASE:
+                       m->str_flags |= STRING_IGNORE_UPPERCASE;
+                       break;
+               case CHAR_REGEX_OFFSET_START:
+                       m->str_flags |= REGEX_OFFSET_START;
+                       break;
+               case CHAR_BINTEST:
+                       m->str_flags |= STRING_BINTEST;
+                       break;
+               case CHAR_TEXTTEST:
+                       m->str_flags |= STRING_TEXTTEST;
+                       break;
+               case CHAR_TRIM:
+                       m->str_flags |= STRING_TRIM;
+                       break;
+               case CHAR_PSTRING_1_LE:
+#define SET_LENGTH(a) m->str_flags = (m->str_flags & ~PSTRING_LEN) | (a)
+                       if (m->type != FILE_PSTRING)
+                               goto bad;
+                       SET_LENGTH(PSTRING_1_LE);
+                       break;
+               case CHAR_PSTRING_2_BE:
+                       if (m->type != FILE_PSTRING)
+                               goto bad;
+                       SET_LENGTH(PSTRING_2_BE);
+                       break;
+               case CHAR_PSTRING_2_LE:
+                       if (m->type != FILE_PSTRING)
+                               goto bad;
+                       SET_LENGTH(PSTRING_2_LE);
+                       break;
+               case CHAR_PSTRING_4_BE:
+                       if (m->type != FILE_PSTRING)
+                               goto bad;
+                       SET_LENGTH(PSTRING_4_BE);
+                       break;
+               case CHAR_PSTRING_4_LE:
+                       switch (m->type) {
+                       case FILE_PSTRING:
+                       case FILE_REGEX:
+                               break;
+                       default:
+                               goto bad;
+                       }
+                       SET_LENGTH(PSTRING_4_LE);
+                       break;
+               case CHAR_PSTRING_LENGTH_INCLUDES_ITSELF:
+                       if (m->type != FILE_PSTRING)
+                               goto bad;
+                       m->str_flags |= PSTRING_LENGTH_INCLUDES_ITSELF;
+                       break;
+               default:
+               bad:
+                       if (ms->flags & MAGIC_CHECK)
+                               file_magwarn(ms, "string modifier `%c' "
+                                       "invalid", *l);
+                       goto out;
+               }
+               /* allow multiple '/' for readability */
+               if (l[1] == '/' && !isspace((unsigned char)l[2]))
+                       l++;
+       }
+       if (string_modifier_check(ms, m) == -1)
+               goto out;
+       *lp = l;
+       return 0;
+out:
+       *lp = l;
+       return -1;
+}
+
 /*
  * parse one line from magic file, put into magic[index++] if valid
  */
@@ -1874,118 +2013,27 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
        m->str_range = 0;
        m->str_flags = m->type == FILE_PSTRING ? PSTRING_1_LE : 0;
        if ((op = get_op(*l)) != -1) {
-               if (!IS_STRING(m->type)) {
-                       uint64_t val;
-                       ++l;
-                       m->mask_op |= op;
-                       val = (uint64_t)strtoull(l, &t, 0);
-                       l = t;
-                       m->num_mask = file_signextend(ms, m, val);
-                       eatsize(&l);
-               }
-               else if (op == FILE_OPDIVIDE) {
-                       int have_range = 0;
-                       while (!isspace((unsigned char)*++l)) {
-                               switch (*l) {
-                               case '0':  case '1':  case '2':
-                               case '3':  case '4':  case '5':
-                               case '6':  case '7':  case '8':
-                               case '9':
-                                       if (have_range &&
-                                           (ms->flags & MAGIC_CHECK))
-                                               file_magwarn(ms,
-                                                   "multiple ranges");
-                                       have_range = 1;
-                                       m->str_range = CAST(uint32_t,
-                                           strtoul(l, &t, 0));
-                                       if (m->str_range == 0)
-                                               file_magwarn(ms,
-                                                   "zero range");
-                                       l = t - 1;
-                                       break;
-                               case CHAR_COMPACT_WHITESPACE:
-                                       m->str_flags |=
-                                           STRING_COMPACT_WHITESPACE;
-                                       break;
-                               case CHAR_COMPACT_OPTIONAL_WHITESPACE:
-                                       m->str_flags |=
-                                           STRING_COMPACT_OPTIONAL_WHITESPACE;
-                                       break;
-                               case CHAR_IGNORE_LOWERCASE:
-                                       m->str_flags |= STRING_IGNORE_LOWERCASE;
-                                       break;
-                               case CHAR_IGNORE_UPPERCASE:
-                                       m->str_flags |= STRING_IGNORE_UPPERCASE;
-                                       break;
-                               case CHAR_REGEX_OFFSET_START:
-                                       m->str_flags |= REGEX_OFFSET_START;
-                                       break;
-                               case CHAR_BINTEST:
-                                       m->str_flags |= STRING_BINTEST;
-                                       break;
-                               case CHAR_TEXTTEST:
-                                       m->str_flags |= STRING_TEXTTEST;
-                                       break;
-                               case CHAR_TRIM:
-                                       m->str_flags |= STRING_TRIM;
-                                       break;
-                               case CHAR_PSTRING_1_LE:
-                                       if (m->type != FILE_PSTRING)
-                                               goto bad;
-                                       m->str_flags = (m->str_flags & ~PSTRING_LEN) | PSTRING_1_LE;
-                                       break;
-                               case CHAR_PSTRING_2_BE:
-                                       if (m->type != FILE_PSTRING)
-                                               goto bad;
-                                       m->str_flags = (m->str_flags & ~PSTRING_LEN) | PSTRING_2_BE;
-                                       break;
-                               case CHAR_PSTRING_2_LE:
-                                       if (m->type != FILE_PSTRING)
-                                               goto bad;
-                                       m->str_flags = (m->str_flags & ~PSTRING_LEN) | PSTRING_2_LE;
-                                       break;
-                               case CHAR_PSTRING_4_BE:
-                                       if (m->type != FILE_PSTRING)
-                                               goto bad;
-                                       m->str_flags = (m->str_flags & ~PSTRING_LEN) | PSTRING_4_BE;
-                                       break;
-                               case CHAR_PSTRING_4_LE:
-                                       switch (m->type) {
-                                       case FILE_PSTRING:
-                                       case FILE_REGEX:
-                                               break;
-                                       default:
-                                               goto bad;
-                                       }
-                                       m->str_flags = (m->str_flags & ~PSTRING_LEN) | PSTRING_4_LE;
-                                       break;
-                               case CHAR_PSTRING_LENGTH_INCLUDES_ITSELF:
-                                       if (m->type != FILE_PSTRING)
-                                               goto bad;
-                                       m->str_flags |= PSTRING_LENGTH_INCLUDES_ITSELF;
-                                       break;
-                               default:
-                               bad:
-                                       if (ms->flags & MAGIC_CHECK)
-                                               file_magwarn(ms,
-                                                   "string extension `%c' "
-                                                   "invalid", *l);
-                                       return -1;
-                               }
-                               /* allow multiple '/' for readability */
-                               if (l[1] == '/' &&
-                                   !isspace((unsigned char)l[2]))
-                                       l++;
+               if (IS_STRING(m->type)) {
+                       int r;
+
+                       if (op != FILE_OPDIVIDE) {
+                               if (ms->flags & MAGIC_CHECK)
+                                       file_magwarn(ms,
+                                           "invalid string/indirect op: "
+                                           "`%c'", *t);
+                               return -1;
                        }
-                       if (string_modifier_check(ms, m) == -1)
+
+                       if (m->type == FILE_INDIRECT)
+                               r = parse_indirect_modifier(ms, m, &l);
+                       else
+                               r = parse_string_modifier(ms, m, &l);
+                       if (r == -1)
                                return -1;
-               }
-               else {
-                       if (ms->flags & MAGIC_CHECK)
-                               file_magwarn(ms, "invalid string op: %c", *t);
-                       return -1;
-               }
+               } else
+                       parse_op_modifier(ms, m, &l, op);
        }
+
        /*
         * We used to set mask to all 1's here, instead let's just not do
         * anything if mask = 0 (unless you have a better idea)
index e977a2c4e95db27745c6525b776885212fab2da8..9a780733524d3944b223b4412ffa3c966b416e5b 100644 (file)
@@ -27,7 +27,7 @@
  */
 /*
  * file.h - definitions for file(1) program
- * @(#)$File: file.h,v 1.162 2014/12/11 12:34:24 christos Exp $
+ * @(#)$File: file.h,v 1.163 2014/12/16 23:18:40 christos Exp $
  */
 
 #ifndef __file_h__
@@ -234,6 +234,7 @@ struct magic {
         (t) == FILE_LESTRING16 || \
         (t) == FILE_REGEX || \
         (t) == FILE_SEARCH || \
+        (t) == FILE_INDIRECT || \
         (t) == FILE_NAME || \
         (t) == FILE_USE)
 
@@ -346,6 +347,8 @@ struct magic {
 #define STRING_IGNORE_CASE             (STRING_IGNORE_LOWERCASE|STRING_IGNORE_UPPERCASE)
 #define STRING_DEFAULT_RANGE           100
 
+#define        INDIRECT_RELATIVE                       BIT(0)
+#define        CHAR_INDIRECT_RELATIVE                  'r'
 
 /* list of magic entries */
 struct mlist {
index 0bdfb377aece346906101c49035729ec32c1cc64..29be5f9b10c52c0424a0259d2c7aa8acee3bf7cc 100644 (file)
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: softmagic.c,v 1.204 2014/12/11 12:34:24 christos Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.205 2015/01/01 04:12:23 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -1665,7 +1665,8 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
                break;
 
        case FILE_INDIRECT:
-               offset += o;
+               if (m->str_flags & INDIRECT_RELATIVE)
+                       offset += o;
                if (offset == 0)
                        return 0;