Imported Upstream version 5.22 51/75651/1 upstream/5.22
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 21 Jun 2016 01:23:22 +0000 (10:23 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 21 Jun 2016 01:23:48 +0000 (10:23 +0900)
Change-Id: I331769e42f20adada5b7021af4523e67b4d63c42
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
24 files changed:
ChangeLog
README
configure.ac
doc/file.man
doc/libmagic.man
doc/magic.man
magic/Magdir/cafebabe
magic/Magdir/filesystems
magic/Magdir/images
magic/Magdir/jpeg
magic/Magdir/qt [new file with mode: 0644]
magic/Makefile.am
src/apprentice.c
src/compress.c
src/elfclass.h
src/file.c
src/file.h
src/file_opts.h
src/funcs.c
src/getline.c
src/magic.c
src/magic.h.in
src/readelf.c
src/softmagic.c

index 1bc3de9..98cdcc4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2015-01-02  15:15  Christos Zoulas <christos@zoulas.com>
+
+       * release 5.22
+
+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
+       * add note limit, suggested by Alexander Cherepanov
+
+2014-12-16  16:53  Christos Zoulas <christos@zoulas.com>
+       
+       * Bail out on partial pread()'s (Alexander Cherepanov)
+       * Fix incorrect bounds check in file_printable (Alexander Cherepanov)
+
+2014-12-11  20:01  Christos Zoulas <christos@zoulas.com>
+
+       * PR/405: ignore SIGPIPE from uncompress programs
+       * change printable -> file_printable and use it in
+         more places for safety
+       * in ELF, instead of "(uses dynamic libraries)" when PT_INTERP
+         is present print the interpreter name.
+       
 2014-12-10  20:01  Christos Zoulas <christos@zoulas.com>
 
        * release 5.21
@@ -23,6 +49,8 @@
            - reduce the number of recursion levels from 20 to 10
            - preserve error messages in indirect magic handling
 
+       This is tracked as CVE-2014-8116 and CVE-2014-8117
+
 2014-11-12  10:30  Christos Zoulas <christos@zoulas.com>
 
        * fix bogus free in the user buffer case.
diff --git a/README b/README
index 1da02b5..ee0c39e 100644 (file)
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
 ## README for file(1) Command ##
 
-    @(#) $File: README,v 1.46 2013/03/25 14:33:10 christos Exp $
+    @(#) $File: README,v 1.48 2014/03/07 13:55:30 christos Exp $
 
 Mailing List: file@mx.gw.com  
 Mailing List archives: http://mx.gw.com/pipermail/file/  
@@ -25,8 +25,8 @@ A public read-only git repository of the same sources is available at:
 
        https://github.com/file/file
 
-The major changes for 5.x are CDF file parsing, indirect magic, and
-overhaul in mime and ascii encoding handling.
+The major changes for 5.x are CDF file parsing, indirect magic, name/use
+(recursion) and overhaul in mime and ascii encoding handling.
 
 The major feature of 4.x is the refactoring of the code into a library,
 and the re-write of the file command in terms of that library. The library
@@ -67,33 +67,41 @@ in magic(5) format please, to the maintainer, Christos Zoulas.
 COPYING - read this first.  
 README - read this second (you are currently reading this file).  
 INSTALL - read on how to install
-
 src/apprentice.c - parses /etc/magic to learn magic  
+src/asctime_r.c - replacement for OS's that don't have it.  
 src/apptype.c - used for OS/2 specific application type magic  
 src/asprintf.c - replacement for OS's that don't have it.  
 src/ascmagic.c - third & last set of tests, based on hardwired assumptions.  
-src/asctime_r.c - for systems that don't have it.  
-src/asprintf.c - for systems that don't have it.  
-src/cdf.c - parser for Microsoft Compound Document Files  
+src/asctime_r.c - replacement for OS's that don't have it.  
+src/asprintf.c - replacement for OS's that don't have it.  
+src/cdf.[ch] - parser for Microsoft Compound Document Files  
 src/cdf_time.c - time converter for CDF.  
 src/compress.c - handles decompressing files to look inside.  
-src/ctime_r.c - for systems that don't have it.  
+src/ctime_r.c - replacement for OS's that don't have it.  
+src/elfclass.h - common code for elf 32/64.
 src/encoding.c - handles unicode encodings  
 src/file.c - the main program  
 src/file.h - header file  
+src/file_opts.h - list of options
+src/fmtcheck.c - replacement for OS's that don't have it.  
 src/fsmagic.c - first set of tests the program runs, based on filesystem info  
 src/funcs.c - utilility functions  
-src/getopt_long.c - for systems that don't have it.  
-src/getline.c - for systems that don't have it.  
+src/getline.c - replacement for OS's that don't have it.  
+src/getopt_long.c - replacement for OS's that don't have it.  
 src/is_tar.c, tar.h - knows about tarchives (courtesy John Gilmore).  
 src/names.h - header file for ascmagic.c  
+src/magic.h.in - source file for magic.h
 src/magic.c - the libmagic api  
+src/pread.c - replacement for OS's that don't have it.  
 src/print.c - print results, errors, warnings.  
 src/readcdf.c - CDF wrapper.  
 src/readelf.[ch] - Stand-alone elf parsing code.  
 src/softmagic.c - 2nd set of tests, based on /etc/magic  
-src/strlcat.c - for systems that don't have it.  
-src/strlcpy.c - for systems that don't have it.  
+src/mygetopt.h - replacement for OS's that don't have it.  
+src/strcasestr.c - replacement for OS's that don't have it.  
+src/strlcat.c - replacement for OS's that don't have it.  
+src/strlcpy.c - replacement for OS's that don't have it.  
+src/tar.h - tar file definitions
 src/vasprintf.c - for systems that don't have it.  
 doc/file.man - man page for the command  
 doc/magic.man - man page for the magic file, courtesy Guy Harris.
index 23f6f5a..1e2457c 100644 (file)
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-AC_INIT([file],[5.21],[christos@astron.com])
+AC_INIT([file],[5.22],[christos@astron.com])
 AM_INIT_AUTOMAKE([subdir-objects foreign])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 
index 52eb035..07b32db 100644 (file)
@@ -1,5 +1,5 @@
-.\" $File: file.man,v 1.109 2014/11/28 02:35:05 christos Exp $
-.Dd November 27, 2014
+.\" $File: file.man,v 1.110 2014/11/28 02:46:39 christos Exp $
+.Dd December 16, 2014
 .Dt FILE __CSECTION__
 .Os
 .Sh NAME
@@ -310,6 +310,7 @@ Set various parameter limits.
 .It Sy "Name" Ta Sy "Default" Ta Sy "Explanation"
 .It Li indir Ta 15 Ta recursion limit for indirect magic
 .It Li name Ta 30 Ta use count limit for name/use magic
+.It Li elf_notes Ta 256 Ta max ELF notes processed
 .It Li elf_phnum Ta 128 Ta max ELF program sections processed
 .It Li elf_shnum Ta 32768 Ta max ELF sections processed
 .El
index 9fdd208..6f3792e 100644 (file)
@@ -1,4 +1,4 @@
-.\" $File: libmagic.man,v 1.32 2014/11/28 02:35:05 christos Exp $
+.\" $File: libmagic.man,v 1.33 2014/11/28 02:46:39 christos Exp $
 .\"
 .\" Copyright (c) Christos Zoulas 2003.
 .\" All Rights Reserved.
@@ -25,7 +25,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd November 27, 2014
+.Dd December 16, 2014
 .Dt LIBMAGIC 3
 .Os
 .Sh NAME
@@ -284,6 +284,7 @@ library.
 .It Sy "Parameter" Ta Sy "Type" Ta Sy "Default"
 .It Li MAGIC_PARAM_INDIR_MAX Ta size_t Ta 15
 .It Li MAGIC_PARAM_NAME_MAX Ta size_t Ta 30
+.It Li MAGIC_PARAM_ELF_NOTES_MAX Ta size_t Ta 256
 .It Li MAGIC_PARAM_ELF_PHNUM_MAX Ta size_t Ta 128
 .It Li MAGIC_PARAM_ELF_SHNUM_MAX Ta size_t Ta 32768
 .El
@@ -303,12 +304,16 @@ The
 parameter controls the maximum number of calls for name/use.
 .Pp
 The
+.Dv MAGIC_PARAM_NOTES_MAX
+parameter controls how many ELF notes will be processed.
+.Pp
+The
 .Dv MAGIC_PARAM_PHNUM_MAX
-parameter controls how many elf program sections will be processed.
+parameter controls how many ELF program sections will be processed.
 .Pp
 The
 .Dv MAGIC_PARAM_SHNUM_MAX
-parameter controls how many elf sections will be processed.
+parameter controls how many ELF sections will be processed.
 .Pp
 The
 .Fn magic_version
index 66d3b17..86bbda0 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 e0bd528..de0f6d6 100644 (file)
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: cafebabe,v 1.15 2014/03/14 18:47:29 christos Exp $
+# $File: cafebabe,v 1.16 2014/04/30 21:41:02 christos Exp $
 # Cafe Babes unite!
 #
 # Since Java bytecode and Mach-O universal binaries have the same magic number,
@@ -45,7 +45,7 @@
 
 0      name            mach-o          \b [
 >0     use             mach-o-cpu      \b
->&(8.L)        indirect                        \b: 
+>(8.L) indirect                        \b: 
 >0     belong          x               \b]
 
 0      belong          0xcafebabe
index 2075c7d..844784b 100644 (file)
@@ -1,5 +1,5 @@
 #------------------------------------------------------------------------------
-# $File: filesystems,v 1.106 2014/10/23 17:17:09 christos Exp $
+# $File: filesystems,v 1.107 2014/12/03 18:02:52 christos Exp $
 # filesystems:  file(1) magic for different filesystems
 #
 0      name    partid  
 >>(11.s-2)     uleshort        0xAA55          DOS/MBR boot sector
 # for sector sizes with 512 or more Bytes
 >0x1FE         leshort         0xAA55          DOS/MBR boot sector
+
+# keep old DOS/MBR boot sector as dummy for mbr and bootloader displaying
+# only for sector sizes with 512 or more Bytes
+0x1FE          leshort         0xAA55          DOS/MBR boot sector
+#
+# to display information (50) before DOS BPB (strength=70) and after DOS floppy (120) like in old file version
+!:strength +65
 >2             string          OSBS            OS/BS MBR
 # added by Joerg Jenderek at Feb 2013 according to http://thestarman.pcministry.com/asm/mbr/
 # and http://en.wikipedia.org/wiki/Master_Boot_Record
index 92fa314..57dbe8f 100644 (file)
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: images,v 1.96 2014/12/08 16:05:47 christos Exp $
+# $File: images,v 1.101 2015/01/01 04:16:51 christos Exp $
 # images:  file(1) magic for image formats (see also "iff", and "c-lang" for
 # XPM bitmaps)
 #
 # never changed.  The TIFF specification recommends testing for it.
 0      string          MM\x00\x2a      TIFF image data, big-endian
 !:mime image/tiff
->(4.L) use             tiff_ifd
+>(4.L) use             \^tiff_ifd
 0      string          II\x2a\x00      TIFF image data, little-endian
 !:mime image/tiff
 >(4.l) use             tiff_ifd
 >2     use             tiff_entry
 
 0      name            tiff_entry
+# NewSubFileType
+>0     leshort         0xfe
+>>12   use             tiff_entry
 >0     leshort         0x100
 >>4    lelong          1
 >>>12  use             tiff_entry
->>>8   lelong          x               \b, width=%d
+>>>8   leshort         x               \b, width=%d
 >0     leshort         0x101
 >>4    lelong          1
->>>8   lelong          x               \b, height=%d
+>>>8   leshort         x               \b, height=%d
 >>>12  use             tiff_entry
 >0     leshort         0x102
->>8    lelong          x               \b, bps=%d
+>>8    leshort         x               \b, bps=%d
 >>12   use             tiff_entry
 >0     leshort         0x103
 >>4    lelong          1               \b, compression=
->>>8   lelong          1               \bnone
->>>8   lelong          2               \bhuffman
->>>8   lelong          3               \bbi-level group 3
->>>8   lelong          4               \bbi-level group 4
->>>8   lelong          5               \bLZW
->>>8   lelong          6               \bJPEG (old)
->>>8   lelong          7               \bJPEG
->>>8   lelong          8               \bdeflate
->>>8   lelong          9               \bJBIG, ITU-T T.85
->>>8   lelong          0xa             \bJBIG, ITU-T T.43
->>>8   lelong          0x7ffe          \bNeXT RLE 2-bit
->>>8   lelong          0x8005          \bPackBits (Macintosh RLE)
->>>8   lelong          0x8029          \bThunderscan RLE
->>>8   lelong          0x807f          \bRasterPadding (CT or MP)
->>>8   lelong          0x8080          \bRLE (Line Work)
->>>8   lelong          0x8081          \bRLE (High-Res Cont-Tone)
->>>8   lelong          0x8082          \bRLE (Binary Line Work)
->>>8   lelong          0x80b2          \bDeflate (PKZIP)
->>>8   lelong          0x80b3          \bKodak DCS
->>>8   lelong          0x8765          \bJBIG
->>>8   lelong          0x8798          \bJPEG2000
->>>8   lelong          0x8799          \bNikon NEF Compressed
+>>>8   leshort         1               \bnone
+>>>8   leshort         2               \bhuffman
+>>>8   leshort         3               \bbi-level group 3
+>>>8   leshort         4               \bbi-level group 4
+>>>8   leshort         5               \bLZW
+>>>8   leshort         6               \bJPEG (old)
+>>>8   leshort         7               \bJPEG
+>>>8   leshort         8               \bdeflate
+>>>8   leshort         9               \bJBIG, ITU-T T.85
+>>>8   leshort         0xa             \bJBIG, ITU-T T.43
+>>>8   leshort         0x7ffe          \bNeXT RLE 2-bit
+>>>8   leshort         0x8005          \bPackBits (Macintosh RLE)
+>>>8   leshort         0x8029          \bThunderscan RLE
+>>>8   leshort         0x807f          \bRasterPadding (CT or MP)
+>>>8   leshort         0x8080          \bRLE (Line Work)
+>>>8   leshort         0x8081          \bRLE (High-Res Cont-Tone)
+>>>8   leshort         0x8082          \bRLE (Binary Line Work)
+>>>8   leshort         0x80b2          \bDeflate (PKZIP)
+>>>8   leshort         0x80b3          \bKodak DCS
+>>>8   leshort         0x8765          \bJBIG
+>>>8   leshort         0x8798          \bJPEG2000
+>>>8   leshort         0x8799          \bNikon NEF Compressed
 >>>8   default         x       
->>>>8  lelong          x               \b(unknown 0x%x)
+>>>>8  leshort         x               \b(unknown 0x%x)
 >>>12  use             tiff_entry
 >0     leshort         0x106           \b, PhotometricIntepretation=
->>8    lelong          0               \bWhiteIsZero
->>8    lelong          1               \bBlackIsZero
->>8    lelong          2               \bRGB
->>8    lelong          3               \bRGB Palette
->>8    lelong          4               \bTransparency Mask
->>8    lelong          5               \bCMYK
->>8    lelong          6               \bYCbCr
->>8    lelong          8               \bCIELab
->>>8   lelong          x               \b(unknown=0x%x)
+>>8    leshort         0               \bWhiteIsZero
+>>8    leshort         1               \bBlackIsZero
+>>8    leshort         2               \bRGB
+>>8    leshort         3               \bRGB Palette
+>>8    leshort         4               \bTransparency Mask
+>>8    leshort         5               \bCMYK
+>>8    leshort         6               \bYCbCr
+>>8    leshort         8               \bCIELab
+>>>8   leshort         x               \b(unknown=0x%x)
 >>12   use             tiff_entry
 # FillOrder
 >0     leshort         0x10a
 >0     leshort         0x10e
 >>(8.l)        string          x               \b, description=%s
 >>>12  use             tiff_entry
+# Make
+>0     leshort         0x10f
+>>(8.l)        string          x               \b, manufacturer=%s
+>>>12  use             tiff_entry
+# Model
+>0     leshort         0x110
+>>(8.l)        string          x               \b, model=%s
+>>>12  use             tiff_entry
 # StripOffsets
 >0     leshort         0x111
 >>12   use             tiff_entry
-# NewSubFileType
->0     leshort         0xfe
+# Orientation
+>0     leshort         0x112           \b, orientation=
+>>8    leshort         1               \bupper-left
+>>8    leshort         3               \blower-right
+>>8    leshort         6               \bupper-right
+>>8    leshort         8               \blower-left
+>>8    leshort         9               \bundefined
+>>8    default         x
+>>>8   leshort         x               \b[*%d*]
+>>12   use             tiff_entry
+# XResolution
+>0     leshort         0x11a
+>>8    lelong          x               \b, xresolution=%d
+>>12   use             tiff_entry
+# YResolution
+>0     leshort         0x11b
+>>8    lelong          x               \b, yresolution=%d
+>>12   use             tiff_entry
+# ResolutionUnit
+>0     leshort         0x128
+>>8    leshort         x               \b, resolutionunit=%d
+>>12   use             tiff_entry
+# Software
+>0     leshort         0x131
+>>(8.l)        string          x               \b, software=%s
 >>12   use             tiff_entry
 # Datetime
 >0     leshort         0x132
 >>(8.l)        string          x               \b, datetime=%s
->>>12  use             tiff_entry
+>>12   use             tiff_entry
 # HostComputer
 >0     leshort         0x13c
 >>(8.l)        string          x               \b, hostcomputer=%s
->>>12  use             tiff_entry
+>>12   use             tiff_entry
+# WhitePoint
+>0     leshort         0x13e
+>>12   use             tiff_entry
+# PrimaryChromaticities
+>0     leshort         0x13f
+>>12   use             tiff_entry
+# YCbCrCoefficients
+>0     leshort         0x211
+>>12   use             tiff_entry
+# YCbCrPositioning
+>0     leshort         0x213
+>>12   use             tiff_entry
+# ReferenceBlackWhite
+>0     leshort         0x214
+>>12   use             tiff_entry
+# Copyright
+>0     leshort         0x8298
+>>(8.l)        string          x               \b, copyright=%s
+>>12   use             tiff_entry
+# ExifOffset
+>0     leshort         0x8769
+>>12   use             tiff_entry
+# GPS IFD
+>0     leshort         0x8825          \b, GPS-Data
+>>12   use             tiff_entry
+
 #>0    leshort         x               \b, unknown=0x%x
+#>>12  use             tiff_entry
 
 0      string          MM\x00\x2b      Big TIFF image data, big-endian
 !:mime image/tiff
index f3412cd..f32f58a 100644 (file)
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: jpeg,v 1.20 2014/08/05 07:32:31 christos Exp $
+# $File: jpeg,v 1.24 2015/01/01 17:07:34 christos Exp $
 # JPEG images
 # SunOS 5.5.1 had
 #
 # Next, show thumbnail info, if it exists:
 >>18   byte            !0              \b, thumbnail %dx
 >>>19  byte            x               \b%d
-
-# EXIF moved down here to avoid reporting a bogus version number,
-# and EXIF version number printing added.
-#   - Patrik R=E5dman <patrik+file-magic@iki.fi>
->6     string          Exif            \b, EXIF standard
-# Look for EXIF IFD offset in IFD 0, and then look for EXIF version tag in EXIF IFD.
-# All possible combinations of entries have to be enumerated, since no looping
-# is possible. And both endians are possible...
-# The combinations included below are from real-world JPEGs.
-# Little-endian
->>12   string          II              
-# IFD 0 Entry #5:
->>>70  leshort         0x8769          
-# EXIF IFD Entry #1:
->>>>(78.l+14)  leshort 0x9000          
->>>>>(78.l+23) byte    x               %c
->>>>>(78.l+24) byte    x               \b.%c
->>>>>(78.l+25) byte    !0x30           \b%c
-# IFD 0 Entry #9:
->>>118 leshort         0x8769          
-# EXIF IFD Entry #3:
->>>>(126.l+38) leshort 0x9000          
->>>>>(126.l+47)        byte    x               %c
->>>>>(126.l+48)        byte    x               \b.%c
->>>>>(126.l+49)        byte    !0x30           \b%c
-# IFD 0 Entry #10
->>>130 leshort         0x8769          
-# EXIF IFD Entry #3:
->>>>(138.l+38) leshort 0x9000          
->>>>>(138.l+47)        byte    x               %c
->>>>>(138.l+48)        byte    x               \b.%c
->>>>>(138.l+49)        byte    !0x30           \b%c
-# EXIF IFD Entry #4:
->>>>(138.l+50) leshort 0x9000          
->>>>>(138.l+59)        byte    x               %c
->>>>>(138.l+60)        byte    x               \b.%c
->>>>>(138.l+61)        byte    !0x30           \b%c
-# EXIF IFD Entry #5:
->>>>(138.l+62) leshort 0x9000          
->>>>>(138.l+71)        byte    x               %c
->>>>>(138.l+72)        byte    x               \b.%c
->>>>>(138.l+73)        byte    !0x30           \b%c
-# IFD 0 Entry #11
->>>142 leshort         0x8769          
-# EXIF IFD Entry #3:
->>>>(150.l+38) leshort 0x9000          
->>>>>(150.l+47)        byte    x               %c
->>>>>(150.l+48)        byte    x               \b.%c
->>>>>(150.l+49)        byte    !0x30           \b%c
-# EXIF IFD Entry #4:
->>>>(150.l+50) leshort 0x9000          
->>>>>(150.l+59)        byte    x               %c
->>>>>(150.l+60)        byte    x               \b.%c
->>>>>(150.l+61)        byte    !0x30           \b%c
-# EXIF IFD Entry #5:
->>>>(150.l+62) leshort 0x9000          
->>>>>(150.l+71)        byte    x               %c
->>>>>(150.l+72)        byte    x               \b.%c
->>>>>(150.l+73)        byte    !0x30           \b%c
-# Big-endian
->>12   string          MM              
-# IFD 0 Entry #9:
->>>118 beshort         0x8769          
-# EXIF IFD Entry #1:
->>>>(126.L+14) beshort 0x9000          
->>>>>(126.L+23)        byte    x               %c
->>>>>(126.L+24)        byte    x               \b.%c
->>>>>(126.L+25)        byte    !0x30           \b%c
-# EXIF IFD Entry #3:
->>>>(126.L+38) beshort 0x9000          
->>>>>(126.L+47)        byte    x               %c
->>>>>(126.L+48)        byte    x               \b.%c
->>>>>(126.L+49)        byte    !0x30           \b%c
-# IFD 0 Entry #10
->>>130 beshort         0x8769          
-# EXIF IFD Entry #3:
->>>>(138.L+38) beshort 0x9000          
->>>>>(138.L+47)        byte    x               %c
->>>>>(138.L+48)        byte    x               \b.%c
->>>>>(138.L+49)        byte    !0x30           \b%c
-# EXIF IFD Entry #5:
->>>>(138.L+62) beshort 0x9000          
->>>>>(138.L+71)        byte    x               %c
->>>>>(138.L+72)        byte    x               \b.%c
->>>>>(138.L+73)        byte    !0x30           \b%c
-# IFD 0 Entry #11
->>>142 beshort         0x8769          
-# EXIF IFD Entry #4:
->>>>(150.L+50) beshort 0x9000          
->>>>>(150.L+59)        byte    x               %c
->>>>>(150.L+60)        byte    x               \b.%c
->>>>>(150.L+61)        byte    !0x30           \b%c
+>6     string          Exif            \b, Exif standard: [
+>>12   indirect/r      x
+>>12   string          x               \b]
 
 # Jump to the first segment
 >(4.S+4)       use             jpeg_segment
 >0     beshort         0xFFC4
 >>(2.S+2)      use                     jpeg_segment
 
+>0     beshort         0xFFE1          
+#>>(2.S+2)     use                     jpeg_segment
+>>4    string          Exif            \b, Exif Standard: [
+>>>10  indirect/r      x               
+>>>10  string          x               \b]
+
 # Application specific markers
 >0     beshort&0xFFE0  =0xFFE0
 >>(2.S+2)      use                     jpeg_segment
 >0     beshort&0xFFD0  =0xFFD0
 >>(2.S+2)      use                     jpeg_segment
 
+#>0    beshort         x               unknown 0x%x
+#>>(2.S+2)     use                     jpeg_segment
+
 # HSI is Handmade Software's proprietary JPEG encoding scheme
 0      string          hsi1            JPEG image data, HSI proprietary
 
diff --git a/magic/Magdir/qt b/magic/Magdir/qt
new file mode 100644 (file)
index 0000000..f9106a2
--- /dev/null
@@ -0,0 +1,19 @@
+
+#------------------------------------------------------------------------------
+# $File: qt,v 1.1 2014/12/12 16:48:39 christos Exp $
+# qt:  file(1) magic for Qt
+
+# http://doc.qt.io/qt-5/resources.html
+0      string          \<!DOCTYPE\040RCC\>     Qt Resource Collection file
+
+# https://qt.gitorious.org/qt/qtbase/source/\
+# 5367fa356233da4c0f28172a8f817791525f5457:\
+# src/tools/rcc/rcc.cpp#L840
+0      string          qres\0\0                Qt Binary Resource file
+0      search/1024     The\040Resource\040Compiler\040for\040Qt        Qt C-code resource file
+
+# https://qt.gitorious.org/qt/qtbase/source/\
+# 5367fa356233da4c0f28172a8f817791525f5457:\
+# src/corelib/kernel/qtranslator.cpp#L62
+0      string          \x3c\xb8\x64\x18\xca\xef\x9c\x95
+>8     string          \xcd\x21\x1c\xbf\x60\xa1\xbd\xdd        Qt Translation file
index e666cec..8a7320d 100644 (file)
@@ -1,5 +1,5 @@
 #
-# $File: Makefile.am,v 1.99 2014/08/04 06:26:16 christos Exp $
+# $File: Makefile.am,v 1.100 2014/12/10 18:45:43 christos Exp $
 #
 MAGIC_FRAGMENT_BASE = Magdir
 MAGIC_DIR = $(top_srcdir)/magic
@@ -198,6 +198,7 @@ $(MAGIC_FRAGMENT_DIR)/pulsar \
 $(MAGIC_FRAGMENT_DIR)/pwsafe \
 $(MAGIC_FRAGMENT_DIR)/pyramid \
 $(MAGIC_FRAGMENT_DIR)/python \
+$(MAGIC_FRAGMENT_DIR)/qt \
 $(MAGIC_FRAGMENT_DIR)/revision \
 $(MAGIC_FRAGMENT_DIR)/riff \
 $(MAGIC_FRAGMENT_DIR)/rpm \
index 58a27ec..02e081f 100644 (file)
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: apprentice.c,v 1.226 2014/11/28 02:35:05 christos Exp $")
+FILE_RCSID("@(#)$File: apprentice.c,v 1.228 2014/12/16 23:18:40 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -528,6 +528,7 @@ file_ms_alloc(int flags)
        ms->name_max = FILE_NAME_MAX;
        ms->elf_shnum_max = FILE_ELF_SHNUM_MAX;
        ms->elf_phnum_max = FILE_ELF_PHNUM_MAX;
+       ms->elf_notes_max = FILE_ELF_NOTES_MAX;
        return ms;
 free:
        free(ms);
@@ -1604,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
  */
@@ -1873,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 fa9e07a..30be569 100644 (file)
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: compress.c,v 1.74 2014/10/26 20:23:30 christos Exp $")
+FILE_RCSID("@(#)$File: compress.c,v 1.76 2014/12/11 11:47:08 christos Exp $")
 #endif
 
 #include "magic.h"
@@ -45,6 +45,7 @@ FILE_RCSID("@(#)$File: compress.c,v 1.74 2014/10/26 20:23:30 christos Exp $")
 #endif
 #include <string.h>
 #include <errno.h>
+#include <signal.h>
 #if !defined(__MINGW32__) && !defined(WIN32)
 #include <sys/ioctl.h>
 #endif
@@ -103,10 +104,12 @@ file_zmagic(struct magic_set *ms, int fd, const char *name,
        size_t i, nsz;
        int rv = 0;
        int mime = ms->flags & MAGIC_MIME;
+       sig_t osigpipe;
 
        if ((ms->flags & MAGIC_COMPRESS) == 0)
                return 0;
 
+       osigpipe = signal(SIGPIPE, SIG_IGN);
        for (i = 0; i < ncompr; i++) {
                if (nbytes < compr[i].maglen)
                        continue;
@@ -133,6 +136,7 @@ file_zmagic(struct magic_set *ms, int fd, const char *name,
                }
        }
 error:
+       (void)signal(SIGPIPE, osigpipe);
        free(newbuf);
        ms->flags |= MAGIC_COMPRESS;
        return rv;
@@ -508,11 +512,16 @@ err:
                            strerror(errno));
 #endif
                        n = NODATA;
-               } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+               } else if (!WIFEXITED(status)) {
 #ifdef DEBUG
-                       (void)fprintf(stderr, "Child status (0x%x)\n", status);
+                       (void)fprintf(stderr, "Child not exited (0x%x)\n",
+                           status);
+#endif
+               } else if (WEXITSTATUS(status) != 0) {
+#ifdef DEBUG
+                       (void)fprintf(stderr, "Child exited (0x%d)\n",
+                           WEXITSTATUS(status));
 #endif
-                       n = NODATA;
                }
 
                (void) close(fdin[0]);
index e144d11..5360b0b 100644 (file)
        swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA];
 
        type = elf_getu16(swap, elfhdr.e_type);
+       notecount = ms->elf_notes_max;
        switch (type) {
 #ifdef ELFCORE
        case ET_CORE:
                phnum = elf_getu16(swap, elfhdr.e_phnum);
                if (phnum > ms->elf_phnum_max)
-                       return toomany(ms, "program", phnum);
+                       return toomany(ms, "program headers", phnum);
                flags |= FLAGS_IS_CORE;
                if (dophn_core(ms, clazz, swap, fd,
                    (off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
                    (size_t)elf_getu16(swap, elfhdr.e_phentsize),
-                   fsize, &flags) == -1)
+                   fsize, &flags, &notecount) == -1)
                        return -1;
                break;
 #endif
                if (dophn_exec(ms, clazz, swap, fd,
                    (off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
                    (size_t)elf_getu16(swap, elfhdr.e_phentsize),
-                   fsize, &flags, shnum) == -1)
+                   fsize, shnum, &flags, &notecount) == -1)
                        return -1;
                /*FALLTHROUGH*/
        case ET_REL:
                shnum = elf_getu16(swap, elfhdr.e_shnum);
                if (shnum > ms->elf_shnum_max)
-                       return toomany(ms, "section", shnum);
+                       return toomany(ms, "section headers", shnum);
                if (doshn(ms, clazz, swap, fd,
                    (off_t)elf_getu(swap, elfhdr.e_shoff), shnum,
                    (size_t)elf_getu16(swap, elfhdr.e_shentsize),
-                   fsize, &flags, elf_getu16(swap, elfhdr.e_machine),
-                   (int)elf_getu16(swap, elfhdr.e_shstrndx)) == -1)
+                   fsize, elf_getu16(swap, elfhdr.e_machine),
+                   (int)elf_getu16(swap, elfhdr.e_shstrndx),
+                   &flags, &notecount) == -1)
                        return -1;
                break;
 
        default:
                break;
        }
+       if (notecount == 0)
+               return toomany(ms, "notes", ms->elf_notes_max);
        return 1;
index cabd4e1..f1312cf 100644 (file)
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: file.c,v 1.158 2014/11/28 02:35:05 christos Exp $")
+FILE_RCSID("@(#)$File: file.c,v 1.159 2014/11/28 02:46:39 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -125,6 +125,7 @@ private struct {
        { "name",       MAGIC_PARAM_NAME_MAX, 0 },
        { "elf_phnum",  MAGIC_PARAM_ELF_PHNUM_MAX, 0 },
        { "elf_shnum",  MAGIC_PARAM_ELF_SHNUM_MAX, 0 },
+       { "elf_notes",  MAGIC_PARAM_ELF_NOTES_MAX, 0 },
 };
 
 private char *progname;                /* used throughout              */
index d75412f..9a78073 100644 (file)
@@ -27,7 +27,7 @@
  */
 /*
  * file.h - definitions for file(1) program
- * @(#)$File: file.h,v 1.160 2014/11/28 02:46:39 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 {
@@ -407,10 +410,12 @@ struct magic_set {
        uint16_t name_max;
        uint16_t elf_shnum_max;
        uint16_t elf_phnum_max;
+       uint16_t elf_notes_max;
 #define        FILE_INDIR_MAX                  15
 #define        FILE_NAME_MAX                   30
 #define        FILE_ELF_SHNUM_MAX              32768
 #define        FILE_ELF_PHNUM_MAX              128
+#define        FILE_ELF_NOTES_MAX              256
 };
 
 /* Type for Unicode characters */
@@ -476,6 +481,7 @@ protected int file_looks_utf8(const unsigned char *, size_t, unichar *,
     size_t *);
 protected size_t file_pstring_length_size(const struct magic *);
 protected size_t file_pstring_get_length(const struct magic *, const char *);
+protected char * file_printable(char *, size_t, const char *);
 #ifdef __EMX__
 protected int file_os2_apptype(struct magic_set *, const char *, const void *,
     size_t);
index 130ca40..3286ac6 100644 (file)
@@ -46,6 +46,7 @@ OPT('p', "preserve-date", 0, "        preserve access times on files\n")
 OPT('P', "parameter", 0, "            set file engine parameter limits\n"
     "                               indir        15 recursion limit for indirection\n"
     "                               name         30 use limit for name/use magic\n"
+    "                               elf_notes   256 max ELF notes processed\n"
     "                               elf_phnum   128 max ELF prog sections processed\n"
     "                               elf_shnum 32768 max ELF sections processed\n")
 OPT('r', "raw", 0, "                  don't translate unprintable chars to \\ooo\n")
index 1df2b8c..b44f562 100644 (file)
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: funcs.c,v 1.76 2014/11/28 02:35:05 christos Exp $")
+FILE_RCSID("@(#)$File: funcs.c,v 1.78 2014/12/11 12:34:24 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -531,3 +531,28 @@ file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb)
        free(pb);
        return rbuf;
 }
+
+/*
+ * convert string to ascii printable format.
+ */
+protected char *
+file_printable(char *buf, size_t bufsiz, const char *str)
+{
+       char *ptr, *eptr;
+       const unsigned char *s = (const unsigned char *)str;
+
+       for (ptr = buf, eptr = ptr + bufsiz - 1; ptr < eptr && *s; s++) {
+               if (isprint(*s)) {
+                       *ptr++ = *s;
+                       continue;
+               }
+               if (ptr >= eptr - 3)
+                       break;
+               *ptr++ = '\\';
+               *ptr++ = ((*s >> 6) & 7) + '0';
+               *ptr++ = ((*s >> 3) & 7) + '0';
+               *ptr++ = ((*s >> 0) & 7) + '0';
+       }
+       *ptr = '\0';
+       return buf;
+}
index ab5e115..b00de01 100644 (file)
@@ -80,7 +80,7 @@ getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
        }
 }
 
-ssize_t
+public ssize_t
 getline(char **buf, size_t *bufsiz, FILE *fp)
 {
        return getdelim(buf, bufsiz, '\n', fp);
index 1edd7f6..0c3371b 100644 (file)
@@ -33,7 +33,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: magic.c,v 1.89 2014/11/28 02:46:39 christos Exp $")
+FILE_RCSID("@(#)$File: magic.c,v 1.90 2014/12/04 15:56:46 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -554,6 +554,9 @@ magic_setparam(struct magic_set *ms, int param, const void *val)
        case MAGIC_PARAM_ELF_SHNUM_MAX:
                ms->elf_shnum_max = *(const size_t *)val;
                return 0;
+       case MAGIC_PARAM_ELF_NOTES_MAX:
+               ms->elf_notes_max = *(const size_t *)val;
+               return 0;
        default:
                errno = EINVAL;
                return -1;
@@ -576,6 +579,9 @@ magic_getparam(struct magic_set *ms, int param, void *val)
        case MAGIC_PARAM_ELF_SHNUM_MAX:
                *(size_t *)val = ms->elf_shnum_max;
                return 0;
+       case MAGIC_PARAM_ELF_NOTES_MAX:
+               *(size_t *)val = ms->elf_notes_max;
+               return 0;
        default:
                errno = EINVAL;
                return -1;
index 856478b..0d4c5ce 100644 (file)
@@ -107,6 +107,7 @@ int magic_errno(magic_t);
 #define MAGIC_PARAM_NAME_MAX           1
 #define MAGIC_PARAM_ELF_PHNUM_MAX      2
 #define MAGIC_PARAM_ELF_SHNUM_MAX      3
+#define MAGIC_PARAM_ELF_NOTES_MAX      4
 
 int magic_setparam(magic_t, int, const void *);
 int magic_getparam(magic_t, int, void *);
index 53a6050..cd1f79d 100644 (file)
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: readelf.c,v 1.110 2014/12/09 02:47:07 christos Exp $")
+FILE_RCSID("@(#)$File: readelf.c,v 1.116 2014/12/16 23:18:40 christos Exp $")
 #endif
 
 #ifdef BUILTIN_ELF
@@ -43,14 +43,14 @@ FILE_RCSID("@(#)$File: readelf.c,v 1.110 2014/12/09 02:47:07 christos Exp $")
 
 #ifdef ELFCORE
 private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t,
-    off_t, int *);
+    off_t, int *, uint16_t *);
 #endif
 private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t,
-    off_t, int *, int);
+    off_t, int, int *, uint16_t *);
 private int doshn(struct magic_set *, int, int, int, off_t, int, size_t,
-    off_t, int *, int, int);
+    off_t, int, int, int *, uint16_t *);
 private size_t donote(struct magic_set *, void *, size_t, size_t, int,
-    int, size_t, int *);
+    int, size_t, int *, uint16_t *);
 
 #define        ELF_ALIGN(a)    ((((a) + align - 1) / align) * align)
 
@@ -67,7 +67,7 @@ private uint64_t getu64(int, uint64_t);
 private int
 toomany(struct magic_set *ms, const char *name, uint16_t num)
 {
-       if (file_printf(ms, ", too many %s header sections (%u)", name, num
+       if (file_printf(ms, ", too many %s (%u)", name, num
            ) == -1)
                return -1;
        return 0;
@@ -293,15 +293,19 @@ private const char os_style_names[][8] = {
        "NetBSD",
 };
 
-#define FLAGS_DID_CORE         0x01
-#define FLAGS_DID_NOTE         0x02
-#define FLAGS_DID_BUILD_ID     0x04
-#define FLAGS_DID_CORE_STYLE   0x08
-#define FLAGS_IS_CORE          0x10
+#define FLAGS_DID_CORE                 0x001
+#define FLAGS_DID_OS_NOTE              0x002
+#define FLAGS_DID_BUILD_ID             0x004
+#define FLAGS_DID_CORE_STYLE           0x008
+#define FLAGS_DID_NETBSD_PAX           0x010
+#define FLAGS_DID_NETBSD_MARCH         0x020
+#define FLAGS_DID_NETBSD_CMODEL                0x040
+#define FLAGS_DID_NETBSD_UNKNOWN       0x080
+#define FLAGS_IS_CORE                  0x100
 
 private int
 dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
-    int num, size_t size, off_t fsize, int *flags)
+    int num, size_t size, off_t fsize, int *flags, uint16_t *notecount)
 {
        Elf32_Phdr ph32;
        Elf64_Phdr ph64;
@@ -319,7 +323,7 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
         * Loop through all the program headers.
         */
        for ( ; num; num--) {
-               if (pread(fd, xph_addr, xph_sizeof, off) == -1) {
+               if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) {
                        file_badread(ms);
                        return -1;
                }
@@ -347,7 +351,7 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
                        if (offset >= (size_t)bufsize)
                                break;
                        offset = donote(ms, nbuf, offset, (size_t)bufsize,
-                           clazz, swap, 4, flags);
+                           clazz, swap, 4, flags, notecount);
                        if (offset == 0)
                                break;
 
@@ -477,132 +481,127 @@ do_note_freebsd_version(struct magic_set *ms, int swap, void *v)
        }
 }
 
-private size_t
-donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
-    int clazz, int swap, size_t align, int *flags)
+private int
+do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
+    int swap __attribute__((__unused__)), uint32_t namesz, uint32_t descsz,
+    size_t noff, size_t doff, int *flags)
 {
-       Elf32_Nhdr nh32;
-       Elf64_Nhdr nh64;
-       size_t noff, doff;
-#ifdef ELFCORE
-       int os_style = -1;
-#endif
-       uint32_t namesz, descsz;
-       unsigned char *nbuf = CAST(unsigned char *, vbuf);
-
-       if (xnh_sizeof + offset > size) {
-               /*
-                * We're out of note headers.
-                */
-               return xnh_sizeof + offset;
-       }
-
-       (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
-       offset += xnh_sizeof;
-
-       namesz = xnh_namesz;
-       descsz = xnh_descsz;
-       if ((namesz == 0) && (descsz == 0)) {
-               /*
-                * We're out of note headers.
-                */
-               return (offset >= size) ? offset : size;
-       }
-
-       if (namesz & 0x80000000) {
-           (void)file_printf(ms, ", bad note name size 0x%lx",
-               (unsigned long)namesz);
-           return 0;
-       }
-
-       if (descsz & 0x80000000) {
-           (void)file_printf(ms, ", bad note description size 0x%lx",
-               (unsigned long)descsz);
-           return 0;
-       }
-
-
-       noff = offset;
-       doff = ELF_ALIGN(offset + namesz);
-
-       if (offset + namesz > size) {
-               /*
-                * We're past the end of the buffer.
-                */
-               return doff;
-       }
-
-       offset = ELF_ALIGN(doff + descsz);
-       if (doff + descsz > size) {
-               /*
-                * We're past the end of the buffer.
-                */
-               return (offset >= size) ? offset : size;
+       if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
+           type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) {
+               uint8_t desc[20];
+               uint32_t i;
+               *flags |= FLAGS_DID_BUILD_ID;
+               if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" :
+                   "sha1") == -1)
+                       return 1;
+               (void)memcpy(desc, &nbuf[doff], descsz);
+               for (i = 0; i < descsz; i++)
+                   if (file_printf(ms, "%02x", desc[i]) == -1)
+                       return 1;
+               return 1;
        }
+       return 0;
+}
 
-       if ((*flags & (FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID)) ==
-           (FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID))
-               goto core;
-
+private int
+do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
+    int swap, uint32_t namesz, uint32_t descsz,
+    size_t noff, size_t doff, int *flags)
+{
        if (namesz == 5 && strcmp((char *)&nbuf[noff], "SuSE") == 0 &&
-           xnh_type == NT_GNU_VERSION && descsz == 2) {
+           type == NT_GNU_VERSION && descsz == 2) {
+           *flags |= FLAGS_DID_OS_NOTE;
            file_printf(ms, ", for SuSE %d.%d", nbuf[doff], nbuf[doff + 1]);
+           return 1;
        }
+
        if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
-           xnh_type == NT_GNU_VERSION && descsz == 16) {
+           type == NT_GNU_VERSION && descsz == 16) {
                uint32_t desc[4];
                (void)memcpy(desc, &nbuf[doff], sizeof(desc));
 
+               *flags |= FLAGS_DID_OS_NOTE;
                if (file_printf(ms, ", for GNU/") == -1)
-                       return size;
+                       return 1;
                switch (elf_getu32(swap, desc[0])) {
                case GNU_OS_LINUX:
                        if (file_printf(ms, "Linux") == -1)
-                               return size;
+                               return 1;
                        break;
                case GNU_OS_HURD:
                        if (file_printf(ms, "Hurd") == -1)
-                               return size;
+                               return 1;
                        break;
                case GNU_OS_SOLARIS:
                        if (file_printf(ms, "Solaris") == -1)
-                               return size;
+                               return 1;
                        break;
                case GNU_OS_KFREEBSD:
                        if (file_printf(ms, "kFreeBSD") == -1)
-                               return size;
+                               return 1;
                        break;
                case GNU_OS_KNETBSD:
                        if (file_printf(ms, "kNetBSD") == -1)
-                               return size;
+                               return 1;
                        break;
                default:
                        if (file_printf(ms, "<unknown>") == -1)
-                               return size
+                               return 1
                }
                if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]),
                    elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1)
-                       return size;
-               *flags |= FLAGS_DID_NOTE;
-               return size;
+                       return 1;
+               return 1;
        }
 
-       if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
-           xnh_type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) {
-           uint8_t desc[20];
-           uint32_t i;
-           if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" :
-               "sha1") == -1)
-                   return size;
-           (void)memcpy(desc, &nbuf[doff], descsz);
-           for (i = 0; i < descsz; i++)
-               if (file_printf(ms, "%02x", desc[i]) == -1)
-                   return size;
-           *flags |= FLAGS_DID_BUILD_ID;
+       if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) {
+               if (type == NT_NETBSD_VERSION && descsz == 4) {
+                       *flags |= FLAGS_DID_OS_NOTE;
+                       do_note_netbsd_version(ms, swap, &nbuf[doff]);
+                       return 1;
+               }
+       }
+
+       if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) {
+               if (type == NT_FREEBSD_VERSION && descsz == 4) {
+                       *flags |= FLAGS_DID_OS_NOTE;
+                       do_note_freebsd_version(ms, swap, &nbuf[doff]);
+                       return 1;
+               }
+       }
+
+       if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 &&
+           type == NT_OPENBSD_VERSION && descsz == 4) {
+               *flags |= FLAGS_DID_OS_NOTE;
+               if (file_printf(ms, ", for OpenBSD") == -1)
+                       return 1;
+               /* Content of note is always 0 */
+               return 1;
+       }
+
+       if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 &&
+           type == NT_DRAGONFLY_VERSION && descsz == 4) {
+               uint32_t desc;
+               *flags |= FLAGS_DID_OS_NOTE;
+               if (file_printf(ms, ", for DragonFly") == -1)
+                       return 1;
+               (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
+               desc = elf_getu32(swap, desc);
+               if (file_printf(ms, " %d.%d.%d", desc / 100000,
+                   desc / 10000 % 10, desc % 10000) == -1)
+                       return 1;
+               return 1;
        }
+       return 0;
+}
 
+private int
+do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
+    int swap, uint32_t namesz, uint32_t descsz,
+    size_t noff, size_t doff, int *flags)
+{
        if (namesz == 4 && strcmp((char *)&nbuf[noff], "PaX") == 0 &&
-           xnh_type == NT_NETBSD_PAX && descsz == 4) {
+           type == NT_NETBSD_PAX && descsz == 4) {
                static const char *pax[] = {
                    "+mprotect",
                    "-mprotect",
@@ -615,80 +614,32 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
                size_t i;
                int did = 0;
 
+               *flags |= FLAGS_DID_NETBSD_PAX;
                (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
                desc = elf_getu32(swap, desc);
 
                if (desc && file_printf(ms, ", PaX: ") == -1)
-                       return size;
+                       return 1;
 
                for (i = 0; i < __arraycount(pax); i++) {
                        if (((1 << i) & desc) == 0)
                                continue;
                        if (file_printf(ms, "%s%s", did++ ? "," : "",
                            pax[i]) == -1)
-                               return size;
+                               return 1;
                }
+               return 1;
        }
+       return 0;
+}
 
-       if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) {
-               switch (xnh_type) {
-               case NT_NETBSD_VERSION:
-                       if (descsz == 4) {
-                               do_note_netbsd_version(ms, swap, &nbuf[doff]);
-                               *flags |= FLAGS_DID_NOTE;
-                               return size;
-                       }
-                       break;
-               case NT_NETBSD_MARCH:
-                       if (file_printf(ms, ", compiled for: %.*s", (int)descsz,
-                           (const char *)&nbuf[doff]) == -1)
-                               return size;
-                       break;
-               case NT_NETBSD_CMODEL:
-                       if (file_printf(ms, ", compiler model: %.*s",
-                           (int)descsz, (const char *)&nbuf[doff]) == -1)
-                               return size;
-                       break;
-               default:
-                       if (file_printf(ms, ", note=%u", xnh_type) == -1)
-                               return size;
-                       break;
-               }
-               return size;
-       }
-
-       if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) {
-               if (xnh_type == NT_FREEBSD_VERSION && descsz == 4) {
-                       do_note_freebsd_version(ms, swap, &nbuf[doff]);
-                       *flags |= FLAGS_DID_NOTE;
-                       return size;
-               }
-       }
-
-       if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 &&
-           xnh_type == NT_OPENBSD_VERSION && descsz == 4) {
-               if (file_printf(ms, ", for OpenBSD") == -1)
-                       return size;
-               /* Content of note is always 0 */
-               *flags |= FLAGS_DID_NOTE;
-               return size;
-       }
-
-       if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 &&
-           xnh_type == NT_DRAGONFLY_VERSION && descsz == 4) {
-               uint32_t desc;
-               if (file_printf(ms, ", for DragonFly") == -1)
-                       return size;
-               (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
-               desc = elf_getu32(swap, desc);
-               if (file_printf(ms, " %d.%d.%d", desc / 100000,
-                   desc / 10000 % 10, desc % 10000) == -1)
-                       return size;
-               *flags |= FLAGS_DID_NOTE;
-               return size;
-       }
-
-core:
+private int
+do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
+    int swap, uint32_t namesz, uint32_t descsz,
+    size_t noff, size_t doff, int *flags, size_t size, int clazz)
+{
+#ifdef ELFCORE
+       int os_style = -1;
        /*
         * Sigh.  The 2.0.36 kernel in Debian 2.1, at
         * least, doesn't correctly implement name
@@ -717,20 +668,17 @@ core:
                os_style = OS_STYLE_NETBSD;
        }
 
-#ifdef ELFCORE
-       if ((*flags & FLAGS_DID_CORE) != 0)
-               return size;
-
        if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) {
                if (file_printf(ms, ", %s-style", os_style_names[os_style])
                    == -1)
-                       return size;
+                       return 1;
                *flags |= FLAGS_DID_CORE_STYLE;
        }
 
        switch (os_style) {
        case OS_STYLE_NETBSD:
-               if (xnh_type == NT_NETBSD_CORE_PROCINFO) {
+               if (type == NT_NETBSD_CORE_PROCINFO) {
+                       char sbuf[512];
                        uint32_t signo;
                        /*
                         * Extract the program name.  It is at
@@ -738,8 +686,9 @@ core:
                         * including the terminating NUL.
                         */
                        if (file_printf(ms, ", from '%.31s'",
-                           &nbuf[doff + 0x7c]) == -1)
-                               return size;
+                           file_printable(sbuf, sizeof(sbuf),
+                           (const char *)&nbuf[doff + 0x7c])) == -1)
+                               return 1;
                        
                        /*
                         * Extract the signal number.  It is at
@@ -749,14 +698,14 @@ core:
                            sizeof(signo));
                        if (file_printf(ms, " (signal %u)",
                            elf_getu32(swap, signo)) == -1)
-                               return size;
+                               return 1;
                        *flags |= FLAGS_DID_CORE;
-                       return size;
+                       return 1;
                }
                break;
 
        default:
-               if (xnh_type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
+               if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
                        size_t i, j;
                        unsigned char c;
                        /*
@@ -824,7 +773,7 @@ core:
                                 * Try next offsets, in case this match is
                                 * in the middle of a string.
                                 */
-                               for (k = i + 1 ; k < NOFFSETS ; k++) {
+                               for (k = i + 1 ; k < NOFFSETS; k++) {
                                        size_t no;
                                        int adjust = 1;
                                        if (prpsoffsets(k) >= prpsoffsets(i))
@@ -849,9 +798,9 @@ core:
                                        cp--;
                                if (file_printf(ms, ", from '%.*s'",
                                    (int)(cp - cname), cname) == -1)
-                                       return size;
+                                       return 1;
                                *flags |= FLAGS_DID_CORE;
-                               return size;
+                               return 1;
 
                        tryanother:
                                ;
@@ -860,6 +809,129 @@ core:
                break;
        }
 #endif
+       return 0;
+}
+
+private size_t
+donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
+    int clazz, int swap, size_t align, int *flags, uint16_t *notecount)
+{
+       Elf32_Nhdr nh32;
+       Elf64_Nhdr nh64;
+       size_t noff, doff;
+       uint32_t namesz, descsz;
+       unsigned char *nbuf = CAST(unsigned char *, vbuf);
+
+       if (*notecount == 0)
+               return 0;
+       --*notecount;
+
+       if (xnh_sizeof + offset > size) {
+               /*
+                * We're out of note headers.
+                */
+               return xnh_sizeof + offset;
+       }
+
+       (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
+       offset += xnh_sizeof;
+
+       namesz = xnh_namesz;
+       descsz = xnh_descsz;
+       if ((namesz == 0) && (descsz == 0)) {
+               /*
+                * We're out of note headers.
+                */
+               return (offset >= size) ? offset : size;
+       }
+
+       if (namesz & 0x80000000) {
+           (void)file_printf(ms, ", bad note name size 0x%lx",
+               (unsigned long)namesz);
+           return 0;
+       }
+
+       if (descsz & 0x80000000) {
+           (void)file_printf(ms, ", bad note description size 0x%lx",
+               (unsigned long)descsz);
+           return 0;
+       }
+
+       noff = offset;
+       doff = ELF_ALIGN(offset + namesz);
+
+       if (offset + namesz > size) {
+               /*
+                * We're past the end of the buffer.
+                */
+               return doff;
+       }
+
+       offset = ELF_ALIGN(doff + descsz);
+       if (doff + descsz > size) {
+               /*
+                * We're past the end of the buffer.
+                */
+               return (offset >= size) ? offset : size;
+       }
+
+       if ((*flags & FLAGS_DID_OS_NOTE) == 0) {
+               if (do_os_note(ms, nbuf, xnh_type, swap,
+                   namesz, descsz, noff, doff, flags))
+                       return size;
+       }
+
+       if ((*flags & FLAGS_DID_BUILD_ID) == 0) {
+               if (do_bid_note(ms, nbuf, xnh_type, swap,
+                   namesz, descsz, noff, doff, flags))
+                       return size;
+       }
+               
+       if ((*flags & FLAGS_DID_NETBSD_PAX) == 0) {
+               if (do_pax_note(ms, nbuf, xnh_type, swap,
+                   namesz, descsz, noff, doff, flags))
+                       return size;
+       }
+
+       if ((*flags & FLAGS_DID_CORE) == 0) {
+               if (do_core_note(ms, nbuf, xnh_type, swap,
+                   namesz, descsz, noff, doff, flags, size, clazz))
+                       return size;
+       }
+
+       if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) {
+               if (descsz > 100)
+                       descsz = 100;
+               switch (xnh_type) {
+               case NT_NETBSD_VERSION:
+                       return size;
+               case NT_NETBSD_MARCH:
+                       if (*flags & FLAGS_DID_NETBSD_MARCH)
+                               return size;
+                       *flags |= FLAGS_DID_NETBSD_MARCH;
+                       if (file_printf(ms, ", compiled for: %.*s",
+                           (int)descsz, (const char *)&nbuf[doff]) == -1)
+                               return size;
+                       break;
+               case NT_NETBSD_CMODEL:
+                       if (*flags & FLAGS_DID_NETBSD_CMODEL)
+                               return size;
+                       *flags |= FLAGS_DID_NETBSD_CMODEL;
+                       if (file_printf(ms, ", compiler model: %.*s",
+                           (int)descsz, (const char *)&nbuf[doff]) == -1)
+                               return size;
+                       break;
+               default:
+                       if (*flags & FLAGS_DID_NETBSD_UNKNOWN)
+                               return size;
+                       *flags |= FLAGS_DID_NETBSD_UNKNOWN;
+                       if (file_printf(ms, ", note=%u", xnh_type) == -1)
+                               return size;
+                       break;
+               }
+               return size;
+       }
+
        return offset;
 }
 
@@ -915,7 +987,8 @@ static const cap_desc_t cap_desc_386[] = {
 
 private int
 doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
-    size_t size, off_t fsize, int *flags, int mach, int strtab)
+    size_t size, off_t fsize, int mach, int strtab, int *flags,
+    uint16_t *notecount)
 {
        Elf32_Shdr sh32;
        Elf64_Shdr sh64;
@@ -926,6 +999,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
        uint64_t cap_hw1 = 0;   /* SunOS 5.x hardware capabilites */
        uint64_t cap_sf1 = 0;   /* SunOS 5.x software capabilites */
        char name[50];
+       ssize_t namesize;
 
        if (size != xsh_sizeof) {
                if (file_printf(ms, ", corrupted section header size") == -1)
@@ -934,7 +1008,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
        }
 
        /* Read offset of name section to be able to read section names later */
-       if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) == -1) {
+       if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) < (ssize_t)xsh_sizeof) {
                file_badread(ms);
                return -1;
        }
@@ -942,15 +1016,15 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
 
        for ( ; num; num--) {
                /* Read the name of this section. */
-               if (pread(fd, name, sizeof(name), name_off + xsh_name) == -1) {
+               if ((namesize = pread(fd, name, sizeof(name) - 1, name_off + xsh_name)) == -1) {
                        file_badread(ms);
                        return -1;
                }
-               name[sizeof(name) - 1] = '\0';
+               name[namesize] = '\0';
                if (strcmp(name, ".debug_info") == 0)
                        stripped = 0;
 
-               if (pread(fd, xsh_addr, xsh_sizeof, off) == -1) {
+               if (pread(fd, xsh_addr, xsh_sizeof, off) < (ssize_t)xsh_sizeof) {
                        file_badread(ms);
                        return -1;
                }
@@ -980,7 +1054,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
                                    " for note");
                                return -1;
                        }
-                       if (pread(fd, nbuf, xsh_size, xsh_offset) == -1) {
+                       if (pread(fd, nbuf, xsh_size, xsh_offset) < (ssize_t)xsh_size) {
                                file_badread(ms);
                                free(nbuf);
                                return -1;
@@ -991,7 +1065,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
                                if (noff >= (off_t)xsh_size)
                                        break;
                                noff = donote(ms, nbuf, (size_t)noff,
-                                   xsh_size, clazz, swap, 4, flags);
+                                   xsh_size, clazz, swap, 4, flags, notecount);
                                if (noff == 0)
                                        break;
                        }
@@ -1158,13 +1232,15 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
  */
 private int
 dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
-    int num, size_t size, off_t fsize, int *flags, int sh_num)
+    int num, size_t size, off_t fsize, int sh_num, int *flags,
+    uint16_t *notecount)
 {
        Elf32_Phdr ph32;
        Elf64_Phdr ph64;
        const char *linking_style = "statically";
-       const char *shared_libraries = "";
+       const char *interp = "";
        unsigned char nbuf[BUFSIZ];
+       char ibuf[BUFSIZ];
        ssize_t bufsize;
        size_t offset, align, len;
        
@@ -1175,20 +1251,40 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
        }
 
        for ( ; num; num--) {
-               if (pread(fd, xph_addr, xph_sizeof, off) == -1) {
+               if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) {
                        file_badread(ms);
                        return -1;
                }
 
                off += size;
+               bufsize = 0;
+               align = 4;
 
                /* Things we can determine before we seek */
                switch (xph_type) {
                case PT_DYNAMIC:
                        linking_style = "dynamically";
                        break;
+               case PT_NOTE:
+                       if (sh_num)     /* Did this through section headers */
+                               continue;
+                       if (((align = xph_align) & 0x80000000UL) != 0 ||
+                           align < 4) {
+                               if (file_printf(ms, 
+                                   ", invalid note alignment 0x%lx",
+                                   (unsigned long)align) == -1)
+                                       return -1;
+                               align = 4;
+                       }
+                       /*FALLTHROUGH*/
                case PT_INTERP:
-                       shared_libraries = " (uses shared libs)";
+                       len = xph_filesz < sizeof(nbuf) ? xph_filesz
+                           : sizeof(nbuf);
+                       bufsize = pread(fd, nbuf, len, xph_offset);
+                       if (bufsize == -1) {
+                               file_badread(ms);
+                               return -1;
+                       }
                        break;
                default:
                        if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
@@ -1200,35 +1296,25 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
 
                /* Things we can determine when we seek */
                switch (xph_type) {
+               case PT_INTERP:
+                       if (bufsize && nbuf[0]) {
+                               nbuf[bufsize - 1] = '\0';
+                               interp = (const char *)nbuf;
+                       } else
+                               interp = "*empty*";
+                       break;
                case PT_NOTE:
-                       if (((align = xph_align) & 0x80000000UL) != 0 ||
-                           align < 4) {
-                               if (file_printf(ms, 
-                                   ", invalid note alignment 0x%lx",
-                                   (unsigned long)align) == -1)
-                                       return -1;
-                               align = 4;
-                       }
-                       if (sh_num)
-                               break;
                        /*
                         * This is a PT_NOTE section; loop through all the notes
                         * in the section.
                         */
-                       len = xph_filesz < sizeof(nbuf) ? xph_filesz
-                           : sizeof(nbuf);
-                       bufsize = pread(fd, nbuf, len, xph_offset);
-                       if (bufsize == -1) {
-                               file_badread(ms);
-                               return -1;
-                       }
                        offset = 0;
                        for (;;) {
                                if (offset >= (size_t)bufsize)
                                        break;
                                offset = donote(ms, nbuf, offset,
                                    (size_t)bufsize, clazz, swap, align,
-                                   flags);
+                                   flags, notecount);
                                if (offset == 0)
                                        break;
                        }
@@ -1237,9 +1323,13 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
                        break;
                }
        }
-       if (file_printf(ms, ", %s linked%s", linking_style, shared_libraries)
+       if (file_printf(ms, ", %s linked", linking_style)
            == -1)
-           return -1;
+               return -1;
+       if (interp[0])
+               if (file_printf(ms, ", interpreter %s",
+                   file_printable(ibuf, sizeof(ibuf), interp)) == -1)
+                       return -1;
        return 0;
 }
 
@@ -1259,7 +1349,7 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
        int flags = 0;
        Elf32_Ehdr elf32hdr;
        Elf64_Ehdr elf64hdr;
-       uint16_t type, phnum, shnum;
+       uint16_t type, phnum, shnum, notecount;
 
        if (ms->flags & (MAGIC_MIME|MAGIC_APPLE))
                return 0;
index 0c36cd8..29be5f9 100644 (file)
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef        lint
-FILE_RCSID("@(#)$File: softmagic.c,v 1.202 2014/11/28 02:46:39 christos Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.205 2015/01/01 04:12:23 christos Exp $")
 #endif /* lint */
 
 #include "magic.h"
@@ -404,28 +404,6 @@ strndup(const char *str, size_t n)
 }
 #endif /* HAVE_STRNDUP */
 
-static char *
-printable(char *buf, size_t bufsiz, const char *str)
-{
-       char *ptr, *eptr;
-       const unsigned char *s = (const unsigned char *)str;
-
-       for (ptr = buf, eptr = ptr + bufsiz - 1; ptr < eptr && *s; s++) {
-               if (isprint(*s)) {
-                       *ptr++ = *s;
-                       continue;
-               }
-               if (ptr >= eptr + 4)
-                       break;
-               *ptr++ = '\\';
-               *ptr++ = ((*s >> 6) & 7) + '0';
-               *ptr++ = ((*s >> 3) & 7) + '0';
-               *ptr++ = ((*s >> 0) & 7) + '0';
-       }
-       *ptr = '\0';
-       return buf;
-}
-
 private int32_t
 mprint(struct magic_set *ms, struct magic *m)
 {
@@ -433,7 +411,7 @@ mprint(struct magic_set *ms, struct magic *m)
        float vf;
        double vd;
        int64_t t = 0;
-       char buf[128], tbuf[26];
+       char buf[128], tbuf[26], sbuf[512];
        union VALUETYPE *p = &ms->ms_value;
 
        switch (m->type) {
@@ -527,12 +505,13 @@ mprint(struct magic_set *ms, struct magic *m)
        case FILE_BESTRING16:
        case FILE_LESTRING16:
                if (m->reln == '=' || m->reln == '!') {
-                       if (file_printf(ms, F(ms, m, "%s"), m->value.s) == -1)
+                       if (file_printf(ms, F(ms, m, "%s"), 
+                           file_printable(sbuf, sizeof(sbuf), m->value.s))
+                           == -1)
                                return -1;
                        t = ms->offset + m->vallen;
                }
                else {
-                       char sbuf[512];
                        char *str = p->s;
 
                        /* compute t before we mangle the string? */
@@ -555,7 +534,7 @@ mprint(struct magic_set *ms, struct magic *m)
                        }
 
                        if (file_printf(ms, F(ms, m, "%s"),
-                           printable(sbuf, sizeof(sbuf), str)) == -1)
+                           file_printable(sbuf, sizeof(sbuf), str)) == -1)
                                return -1;
 
                        if (m->type == FILE_PSTRING)
@@ -659,7 +638,8 @@ mprint(struct magic_set *ms, struct magic *m)
                        file_oomem(ms, ms->search.rm_len);
                        return -1;
                }
-               rval = file_printf(ms, F(ms, m, "%s"), cp);
+               rval = file_printf(ms, F(ms, m, "%s"),
+                   file_printable(sbuf, sizeof(sbuf), cp));
                free(cp);
 
                if (rval == -1)
@@ -673,7 +653,8 @@ mprint(struct magic_set *ms, struct magic *m)
        }
 
        case FILE_SEARCH:
-               if (file_printf(ms, F(ms, m, "%s"), m->value.s) == -1)
+               if (file_printf(ms, F(ms, m, "%s"),
+                   file_printable(sbuf, sizeof(sbuf), m->value.s)) == -1)
                        return -1;
                if ((m->str_flags & REGEX_OFFSET_START))
                        t = ms->search.offset;
@@ -1684,6 +1665,8 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
                break;
 
        case FILE_INDIRECT:
+               if (m->str_flags & INDIRECT_RELATIVE)
+                       offset += o;
                if (offset == 0)
                        return 0;