From bfe9001b2fa70d536a5db9d5da04faebf69c0323 Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Tue, 21 Jun 2016 10:27:45 +0900 Subject: [PATCH] Imported Upstream version 5.27 Change-Id: Ic85690306751868ae3ddb56ec1c95f1985f17683 Signed-off-by: DongHun Kwak --- .travis.yml | 12 ++++- ChangeLog | 15 +++++- configure.ac | 2 +- magic/Magdir/archive | 10 +++- magic/Magdir/commands | 4 +- magic/Magdir/console | 4 +- magic/Magdir/os2 | 4 +- magic/Magdir/xenix | 23 ++++++++- src/ascmagic.c | 12 ++--- src/cdf.c | 125 ++++++++++++++++++++++++++++----------------- src/cdf.h | 3 +- src/compress.c | 36 ++++++++----- src/der.c | 9 +++- src/magic.c | 12 +++-- src/magic.h.in | 1 + src/readcdf.c | 4 +- src/softmagic.c | 64 +++++++++++++++-------- tests/CVE-2014-1943.result | 2 +- tests/Makefile.am | 2 +- tests/fit-map-data.result | 2 +- 20 files changed, 229 insertions(+), 117 deletions(-) diff --git a/.travis.yml b/.travis.yml index 429362f..5282385 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,19 @@ # $File$ + language: c + +os: + - linux + - osx + compiler: - gcc - clang + before_install: - - sudo apt-get update -qq - - sudo apt-get install -qq automake libtool make python zlib1g-dev + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq; fi + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install -qq automake libtool make python zlib1g-dev; fi + script: - autoreconf -f -i - ./configure --disable-silent-rules diff --git a/ChangeLog b/ChangeLog index 9a28e5c..7554254 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,19 @@ +2016-05-13 12:00 Christos Zoulas + + * release 5.27 + +2016-04-18 9:35 Christos Zoulas + + * Errors comparing DER entries or computing offsets + are just indications of malformed non-DER files. + Don't print them. + * Offset comparison was off-by-one. + * Fix compression code (Werner Fink) + * Put new bytes constant in the right file (not the generated one) + 2016-04-16 18:34 Christos Zoulas - * release 5.25 + * release 5.26 2016-03-31 13:50 Christos Zoulas diff --git a/configure.ac b/configure.ac index 676c0fb..3c5f922 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT([file],[5.26],[christos@astron.com]) +AC_INIT([file],[5.27],[christos@astron.com]) AM_INIT_AUTOMAKE([subdir-objects foreign]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) diff --git a/magic/Magdir/archive b/magic/Magdir/archive index 06d7a3a..22f4ebb 100644 --- a/magic/Magdir/archive +++ b/magic/Magdir/archive @@ -1,5 +1,5 @@ #------------------------------------------------------------------------------ -# $File: archive,v 1.101 2016/01/08 00:41:02 christos Exp $ +# $File: archive,v 1.102 2016/01/11 20:59:24 christos Exp $ # archive: file(1) magic for archive formats (see also "msdos" for self- # extracting compressed archives) # @@ -891,6 +891,14 @@ >(26.s+30) leshort 0xcafe Java archive data (JAR) !:mime application/java-archive +# iOS App +>(26.s+30) leshort !0xcafe +>>26 string !\x8\0\0\0mimetype +>>>30 string Payload/ +>>>>38 search/64 .app/ iOS App +!:mime application/x-ios-app + + # Generic zip archives (Greg Roelofs, c/o zip-bugs@wkuvx1.wku.edu) # Next line excludes specialized formats: >(26.s+30) leshort !0xcafe diff --git a/magic/Magdir/commands b/magic/Magdir/commands index 95109f3..fddb764 100644 --- a/magic/Magdir/commands +++ b/magic/Magdir/commands @@ -1,6 +1,6 @@ #------------------------------------------------------------------------------ -# $File: commands,v 1.52 2015/06/04 19:16:55 christos Exp $ +# $File: commands,v 1.53 2016/02/23 12:35:20 christos Exp $ # commands: file(1) magic for various shells and interpreters # #0 string/w : shell archive or script for antique kernel text @@ -101,7 +101,7 @@ 0 string =5 regex [\ \n] >>6 string /*\ Smarty\ version Smarty compiled template ->24 regex [0-9.]+ \b, version %s +>>>24 regex [0-9.]+ \b, version %s !:mime text/x-php 0 string Zend\x00 PHP script Zend Optimizer data diff --git a/magic/Magdir/console b/magic/Magdir/console index ed69f43..9448223 100644 --- a/magic/Magdir/console +++ b/magic/Magdir/console @@ -1,6 +1,6 @@ #------------------------------------------------------------------------------ -# $File: console,v 1.23 2016/03/17 20:53:09 christos Exp $ +# $File: console,v 1.24 2016/03/23 15:29:20 christos Exp $ # Console game magic # Toby Deshane @@ -53,7 +53,7 @@ # so most of the data isn't easily parseable. # 0 string UNIF -4 lelong <16 UNIF v%d format NES ROM image +>4 lelong <16 UNIF v%d format NES ROM image #------------------------------------------------------------------------------ # gameboy: file(1) magic for the Nintendo (Color) Gameboy raw ROM format diff --git a/magic/Magdir/os2 b/magic/Magdir/os2 index e856856..d66ba49 100644 --- a/magic/Magdir/os2 +++ b/magic/Magdir/os2 @@ -1,12 +1,12 @@ #------------------------------------------------------------------------------ -# $File: os2,v 1.7 2009/09/19 16:28:11 christos Exp $ +# $File: os2,v 1.8 2015/01/05 00:17:13 christos Exp $ # os2: file(1) magic for OS/2 files # # Provided 1998/08/22 by # David Mediavilla -1 search/1 InternetShortcut MS Windows 95 Internet shortcut text +1 search/100 InternetShortcut MS Windows 95 Internet shortcut text >17 search/100 URL= (URL=< >>&0 string x \b%s>) diff --git a/magic/Magdir/xenix b/magic/Magdir/xenix index 38e1e3c..ca5eaae 100644 --- a/magic/Magdir/xenix +++ b/magic/Magdir/xenix @@ -1,6 +1,6 @@ #------------------------------------------------------------------------------ -# $File$ +# $File: xenix,v 1.9 2009/09/19 16:28:13 christos Exp $ # xenix: file(1) magic for Microsoft Xenix # # "Middle model" stuff, and "Xenix 8086 relocatable or 80286 small @@ -12,7 +12,26 @@ # XXX - "x.out" collides with PDP-11 archives # 0 string core core file (Xenix) -0 byte 0x80 8086 relocatable (Microsoft) +# URL: http://www.polarhome.com/service/man/?qf=86rel&tf=2&of=Xenix +# Reference: http://www.azillionmonkeys.com/qed/Omfg.pdf +# Update: Joerg Jenderek +# recordtype~TranslatorHEADerRecord +0 byte 0x80 +# GRR: line above is too general as it catches also Extensible storage engine DataBase +# skip examples like GENA.SND Switch.Snd by looking for record length maximal 1024-3 +>1 uleshort <1022 +# skip examples like GAME.PICTURE Strange.Pic by looking for positiv record length +>>1 uleshort >0 +# skip examples like Xtable.Data FRACTAL.GEN SHR.VIEW by looking for positiv string length +>>>3 ubyte >0 +# skip examples like OMBRE.6 with "UUUUUU" by looking for filename like "hello.c" +>>>>4 regex [a-zA-Z_/]{1,8}[.] 8086 relocatable (Microsoft) +#!:mime application/octet-stream +!:mime application/x-object +!:ext o/a +>>>>>3 pstring x \b, "%s" +# checksum +#>>>>>(3.b+4) ubyte x \b, checksum 0x%2.2x 0 leshort 0xff65 x.out >2 string __.SYMDEF randomized >0 byte x archive diff --git a/src/ascmagic.c b/src/ascmagic.c index 4b379fb..586f16e 100644 --- a/src/ascmagic.c +++ b/src/ascmagic.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: ascmagic.c,v 1.93 2016/03/21 15:56:53 christos Exp $") +FILE_RCSID("@(#)$File: ascmagic.c,v 1.94 2016/03/31 17:51:12 christos Exp $") #endif /* lint */ #include "magic.h" @@ -79,9 +79,6 @@ file_ascmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes, const char *code_mime = NULL; const char *type = NULL; - if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) - return 0; - nbytes = trim_nuls(buf, nbytes); /* If file doesn't look like any sort of text, give up. */ @@ -123,9 +120,6 @@ file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf, size_t last_line_end = (size_t)-1; int has_long_lines = 0; - if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) - return 0; - nbytes = trim_nuls(buf, nbytes); /* If we have fewer than 2 bytes, give up. */ @@ -150,7 +144,11 @@ file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf, (size_t)(utf8_end - utf8_buf), NULL, NULL, TEXTTEST, text)) == 0) rv = -1; + if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))) + return rv == -1 ? 0 : 1; } + if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))) + return 0; /* Now try to discover other details about the file. */ for (i = 0; i < ulen; i++) { diff --git a/src/cdf.c b/src/cdf.c index 9489f39..3f53d8a 100644 --- a/src/cdf.c +++ b/src/cdf.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: cdf.c,v 1.75 2015/02/27 21:16:55 christos Exp $") +FILE_RCSID("@(#)$File: cdf.c,v 1.79 2016/04/26 12:37:34 christos Exp $") #endif #include @@ -267,13 +267,32 @@ cdf_unpack_dir(cdf_directory_t *d, char *buf) } static int +cdf_zero_stream(cdf_stream_t *scn) +{ + scn->sst_len = 0; + scn->sst_dirlen = 0; + scn->sst_ss = 0; + free(scn->sst_tab); + scn->sst_tab = NULL; + return -1; +} + +static size_t +cdf_check_stream(const cdf_stream_t *sst, const cdf_header_t *h) +{ + size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ? + CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h); + assert(ss == sst->sst_ss); + return sst->sst_ss; +} + +static int cdf_check_stream_offset(const cdf_stream_t *sst, const cdf_header_t *h, const void *p, size_t tail, int line) { const char *b = (const char *)sst->sst_tab; const char *e = ((const char *)p) + tail; - size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ? - CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h); + size_t ss = cdf_check_stream(sst, h); /*LINTED*/(void)&line; if (e >= b && (size_t)(e - b) <= ss * sst->sst_len) return 0; @@ -290,10 +309,8 @@ cdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len) { size_t siz = (size_t)off + len; - if ((off_t)(off + len) != (off_t)siz) { - errno = EINVAL; - return -1; - } + if ((off_t)(off + len) != (off_t)siz) + goto out; if (info->i_buf != NULL && info->i_len >= siz) { (void)memcpy(buf, &info->i_buf[off], len); @@ -301,12 +318,15 @@ cdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len) } if (info->i_fd == -1) - return -1; + goto out; if (pread(info->i_fd, buf, len, off) != (ssize_t)len) return -1; return (ssize_t)len; +out: + errno = EINVAL; + return -1; } int @@ -363,11 +383,14 @@ cdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs, DPRINTF(("Out of bounds read %" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", pos + len, CDF_SEC_SIZE(h) * sst->sst_len)); - return -1; + goto out; } (void)memcpy(((char *)buf) + offs, ((const char *)sst->sst_tab) + pos, len); return len; +out: + errno = EFTYPE; + return -1; } /* @@ -421,8 +444,7 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat) goto out; if (j >= CDF_LOOP_LIMIT) { DPRINTF(("Reading master sector loop limit")); - errno = EFTYPE; - goto out2; + goto out3; } if (cdf_read_sector(info, msa, 0, ss, h, mid) != (ssize_t)ss) { DPRINTF(("Reading master sector %d", mid)); @@ -435,8 +457,7 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat) if (i >= sat->sat_len) { DPRINTF(("Out of bounds reading MSA %" SIZE_T_FORMAT "u >= %" SIZE_T_FORMAT "u", i, sat->sat_len)); - errno = EFTYPE; - goto out2; + goto out3; } if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, sec) != (ssize_t)ss) { @@ -451,6 +472,8 @@ out: sat->sat_len = i; free(msa); return 0; +out3: + errno = EFTYPE; out2: free(msa); out1: @@ -476,23 +499,24 @@ cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size) DPRINTF((" %d", sid)); if (j >= CDF_LOOP_LIMIT) { DPRINTF(("Counting chain loop limit")); - errno = EFTYPE; - return (size_t)-1; + goto out; } if (sid >= maxsector) { DPRINTF(("Sector %d >= %d\n", sid, maxsector)); - errno = EFTYPE; - return (size_t)-1; + goto out; } sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); } if (i == 0) { DPRINTF((" none, sid: %d\n", sid)); - return (size_t)-1; + goto out; } DPRINTF(("\n")); return i; +out: + errno = EFTYPE; + return (size_t)-1; } int @@ -501,27 +525,27 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, { size_t ss = CDF_SEC_SIZE(h), i, j; ssize_t nr; + scn->sst_tab = NULL; scn->sst_len = cdf_count_chain(sat, sid, ss); scn->sst_dirlen = len; + scn->sst_ss = ss; if (scn->sst_len == (size_t)-1) - return -1; + goto out; scn->sst_tab = calloc(scn->sst_len, ss); if (scn->sst_tab == NULL) - return -1; + return cdf_zero_stream(scn); for (j = i = 0; sid >= 0; i++, j++) { if (j >= CDF_LOOP_LIMIT) { DPRINTF(("Read long sector chain loop limit")); - errno = EFTYPE; goto out; } if (i >= scn->sst_len) { DPRINTF(("Out of bounds reading long sector chain " "%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", i, scn->sst_len)); - errno = EFTYPE; goto out; } if ((nr = cdf_read_sector(info, scn->sst_tab, i * ss, ss, h, @@ -537,8 +561,8 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, } return 0; out: - free(scn->sst_tab); - return -1; + errno = EFTYPE; + return cdf_zero_stream(scn); } int @@ -547,27 +571,27 @@ cdf_read_short_sector_chain(const cdf_header_t *h, cdf_secid_t sid, size_t len, cdf_stream_t *scn) { size_t ss = CDF_SHORT_SEC_SIZE(h), i, j; - scn->sst_len = cdf_count_chain(ssat, sid, CDF_SEC_SIZE(h)); + scn->sst_tab = NULL; + scn->sst_len = cdf_count_chain(ssat, sid, ss); scn->sst_dirlen = len; + scn->sst_ss = ss; if (sst->sst_tab == NULL || scn->sst_len == (size_t)-1) - return -1; + goto out; scn->sst_tab = calloc(scn->sst_len, ss); if (scn->sst_tab == NULL) - return -1; + return cdf_zero_stream(scn); for (j = i = 0; sid >= 0; i++, j++) { if (j >= CDF_LOOP_LIMIT) { DPRINTF(("Read short sector chain loop limit")); - errno = EFTYPE; goto out; } if (i >= scn->sst_len) { DPRINTF(("Out of bounds reading short sector chain " "%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", i, scn->sst_len)); - errno = EFTYPE; goto out; } if (cdf_read_short_sector(sst, scn->sst_tab, i * ss, ss, h, @@ -579,8 +603,8 @@ cdf_read_short_sector_chain(const cdf_header_t *h, } return 0; out: - free(scn->sst_tab); - return -1; + errno = EFTYPE; + return cdf_zero_stream(scn); } int @@ -625,7 +649,6 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, for (j = i = 0; i < ns; i++, j++) { if (j >= CDF_LOOP_LIMIT) { DPRINTF(("Read dir loop limit")); - errno = EFTYPE; goto out; } if (cdf_read_sector(info, buf, 0, ss, h, sid) != (ssize_t)ss) { @@ -646,6 +669,7 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, out: free(dir->dir_tab); free(buf); + errno = EFTYPE; return -1; } @@ -658,36 +682,37 @@ cdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h, size_t ss = CDF_SEC_SIZE(h); cdf_secid_t sid = h->h_secid_first_sector_in_short_sat; + ssat->sat_tab = NULL; ssat->sat_len = cdf_count_chain(sat, sid, CDF_SEC_SIZE(h)); if (ssat->sat_len == (size_t)-1) - return -1; + goto out; ssat->sat_tab = CAST(cdf_secid_t *, calloc(ssat->sat_len, ss)); if (ssat->sat_tab == NULL) - return -1; + goto out1; for (j = i = 0; sid >= 0; i++, j++) { if (j >= CDF_LOOP_LIMIT) { DPRINTF(("Read short sat sector loop limit")); - errno = EFTYPE; goto out; } if (i >= ssat->sat_len) { DPRINTF(("Out of bounds reading short sector chain " "%" SIZE_T_FORMAT "u > %" SIZE_T_FORMAT "u\n", i, ssat->sat_len)); - errno = EFTYPE; goto out; } if (cdf_read_sector(info, ssat->sat_tab, i * ss, ss, h, sid) != (ssize_t)ss) { DPRINTF(("Reading short sat sector %d", sid)); - goto out; + goto out1; } sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); } return 0; out: + errno = EFTYPE; +out1: free(ssat->sat_tab); return -1; } @@ -715,13 +740,13 @@ cdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h, if (d->d_stream_first_sector < 0) goto out; - return cdf_read_long_sector_chain(info, h, sat, + return cdf_read_long_sector_chain(info, h, sat, d->d_stream_first_sector, d->d_size, scn); out: scn->sst_tab = NULL; - scn->sst_len = 0; - scn->sst_dirlen = 0; - return 0; + (void)cdf_zero_stream(scn); + errno = EFTYPE; + return -1; } static int @@ -750,8 +775,10 @@ cdf_read_user_stream(const cdf_info_t *info, const cdf_header_t *h, const cdf_directory_t *d; int i = cdf_find_stream(dir, name, CDF_DIR_TYPE_USER_STREAM); - if (i <= 0) + if (i <= 0) { + memset(scn, 0, sizeof(*scn)); return -1; + } d = &dir->dir_tab[i - 1]; return cdf_read_sector_chain(info, h, sat, ssat, sst, @@ -824,7 +851,7 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h, malloc(*maxcount * sizeof(*inp))); } if (inp == NULL) - goto out; + goto out1; *info = inp; inp += *count; *count += sh.sh_properties; @@ -931,7 +958,7 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h, inp = CAST(cdf_property_info_t *, realloc(*info, *maxcount * sizeof(*inp))); if (inp == NULL) - goto out; + goto out1; *info = inp; inp = *info + nelem; } @@ -976,6 +1003,8 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h, } return 0; out: + errno = EFTYPE; +out1: free(*info); return -1; } @@ -1022,8 +1051,7 @@ int cdf_unpack_catalog(const cdf_header_t *h, const cdf_stream_t *sst, cdf_catalog_t **cat) { - size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ? - CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h); + size_t ss = cdf_check_stream(sst, h); const char *b = CAST(const char *, sst->sst_tab); const char *eb = b + ss * sst->sst_len; size_t nr, i, j, k; @@ -1043,6 +1071,8 @@ cdf_unpack_catalog(const cdf_header_t *h, const cdf_stream_t *sst, nr--; *cat = CAST(cdf_catalog_t *, malloc(sizeof(cdf_catalog_t) + nr * sizeof(*ce))); + if (*cat == NULL) + return -1; ce = (*cat)->cat_e; memset(ce, 0, nr * sizeof(*ce)); b = CAST(const char *, sst->sst_tab); @@ -1245,8 +1275,7 @@ cdf_dump(const void *v, size_t len) void cdf_dump_stream(const cdf_header_t *h, const cdf_stream_t *sst) { - size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ? - CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h); + size_t ss = sst->sst_ss; cdf_dump(sst->sst_tab, ss * sst->sst_len); } diff --git a/src/cdf.h b/src/cdf.h index cee8d77..853a719 100644 --- a/src/cdf.h +++ b/src/cdf.h @@ -129,6 +129,7 @@ typedef struct { void *sst_tab; size_t sst_len; size_t sst_dirlen; + size_t sst_ss; } cdf_stream_t; typedef struct { @@ -277,7 +278,7 @@ typedef struct { typedef struct { size_t cat_num; - cdf_catalog_entry_t cat_e[0]; + cdf_catalog_entry_t cat_e[1]; } cdf_catalog_t; struct timespec; diff --git a/src/compress.c b/src/compress.c index f322445..a380899 100644 --- a/src/compress.c +++ b/src/compress.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: compress.c,v 1.92 2016/02/08 01:29:49 christos Exp $") +FILE_RCSID("@(#)$File: compress.c,v 1.95 2016/04/19 23:36:36 christos Exp $") #endif #include "magic.h" @@ -187,7 +187,7 @@ file_zmagic(struct magic_set *ms, int fd, const char *name, size_t i, nsz; char *rbuf; file_pushbuf_t *pb; - int rv = 0; + int urv, prv, rv = 0; int mime = ms->flags & MAGIC_MIME; #ifdef HAVE_SIGNAL_H sig_t osigpipe; @@ -214,22 +214,22 @@ file_zmagic(struct magic_set *ms, int fd, const char *name, if (!zm) continue; nsz = nbytes; - rv = uncompressbuf(fd, ms->bytes_max, i, buf, &newbuf, &nsz); - DPRINTF("uncompressbuf = %d, %s, %zu\n", rv, (char *)newbuf, + urv = uncompressbuf(fd, ms->bytes_max, i, buf, &newbuf, &nsz); + DPRINTF("uncompressbuf = %d, %s, %zu\n", urv, (char *)newbuf, nsz); - switch (rv) { + switch (urv) { case OKDATA: case ERRDATA: ms->flags &= ~MAGIC_COMPRESS; - if (rv == ERRDATA) - rv = file_printf(ms, "%s ERROR: %s", + if (urv == ERRDATA) + prv = file_printf(ms, "%s ERROR: %s", methodname(i), newbuf); else - rv = file_buffer(ms, -1, name, newbuf, nsz); - if (rv == -1) + prv = file_buffer(ms, -1, name, newbuf, nsz); + if (prv == -1) goto error; - DPRINTF("rv = %d\n", rv); + rv = 1; if ((ms->flags & MAGIC_COMPRESS_TRANSP) != 0) goto out; if (mime != MAGIC_MIME && mime != 0) @@ -239,6 +239,10 @@ file_zmagic(struct magic_set *ms, int fd, const char *name, goto error; if ((pb = file_push_buffer(ms)) == NULL) goto error; + /* + * XXX: If file_buffer fails here, we overwrite + * the compressed text. FIXME. + */ if (file_buffer(ms, -1, NULL, buf, nbytes) == -1) goto error; if ((rbuf = file_pop_buffer(ms, pb)) != NULL) { @@ -250,16 +254,20 @@ file_zmagic(struct magic_set *ms, int fd, const char *name, } if (!mime && file_printf(ms, ")") == -1) goto error; - goto out; + /*FALLTHROUGH*/ case NODATA: - goto out; + break; default: abort(); + /*NOTREACHED*/ + error: + rv = -1; + break; } } out: - rv = 1; -error: + DPRINTF("rv = %d\n", rv); + #ifdef HAVE_SIGNAL_H (void)signal(SIGPIPE, osigpipe); #endif diff --git a/src/der.c b/src/der.c index 134712c..ff17c9c 100644 --- a/src/der.c +++ b/src/der.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: der.c,v 1.3 2016/03/21 17:41:14 christos Exp $") +FILE_RCSID("@(#)$File: der.c,v 1.5 2016/04/17 19:44:45 christos Exp $") #endif #endif @@ -44,7 +44,6 @@ FILE_RCSID("@(#)$File: der.c,v 1.3 2016/03/21 17:41:14 christos Exp $") #include #include -#include #include #include #include @@ -53,6 +52,8 @@ FILE_RCSID("@(#)$File: der.c,v 1.3 2016/03/21 17:41:14 christos Exp $") #ifndef TEST_DER #include "magic.h" #include "der.h" +#else +#include #endif #define DER_BAD ((uint32_t)-1) @@ -61,11 +62,15 @@ FILE_RCSID("@(#)$File: der.c,v 1.3 2016/03/21 17:41:14 christos Exp $") #define DER_CLASS_APPLICATION 1 #define DER_CLASS_CONTEXT 2 #define DER_CLASS_PRIVATE 3 +#ifdef DEBUG_DER static const char der_class[] = "UACP"; +#endif #define DER_TYPE_PRIMITIVE 0 #define DER_TYPE_CONSTRUCTED 1 +#ifdef DEBUG_DER static const char der_type[] = "PC"; +#endif #define DER_TAG_EOC 0x00 #define DER_TAG_BOOLEAN 0x01 diff --git a/src/magic.c b/src/magic.c index 46e4678..4474793 100644 --- a/src/magic.c +++ b/src/magic.c @@ -33,7 +33,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: magic.c,v 1.96 2016/02/08 02:20:36 christos Exp $") +FILE_RCSID("@(#)$File: magic.c,v 1.98 2016/04/19 20:51:54 christos Exp $") #endif /* lint */ #include "magic.h" @@ -346,7 +346,7 @@ private void close_and_restore(const struct magic_set *ms, const char *name, int fd, const struct stat *sb) { - if (name == NULL) + if (fd == STDIN_FILENO || name == NULL) return; (void) close(fd); @@ -523,9 +523,11 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) rv = 0; done: free(buf); - if (pos != (off_t)-1) - (void)lseek(fd, pos, SEEK_SET); - close_and_restore(ms, inname, fd, &sb); + if (fd != -1) { + if (pos != (off_t)-1) + (void)lseek(fd, pos, SEEK_SET); + close_and_restore(ms, inname, fd, &sb); + } out: return rv == 0 ? file_getbuffer(ms) : NULL; } diff --git a/src/magic.h.in b/src/magic.h.in index 1e567cd..3d6954a 100644 --- a/src/magic.h.in +++ b/src/magic.h.in @@ -114,6 +114,7 @@ int magic_errno(magic_t); #define MAGIC_PARAM_ELF_SHNUM_MAX 3 #define MAGIC_PARAM_ELF_NOTES_MAX 4 #define MAGIC_PARAM_REGEX_MAX 5 +#define MAGIC_PARAM_BYTES_MAX 6 int magic_setparam(magic_t, int, const void *); int magic_getparam(magic_t, int, void *); diff --git a/src/readcdf.c b/src/readcdf.c index e6e060c..d125da5 100644 --- a/src/readcdf.c +++ b/src/readcdf.c @@ -26,7 +26,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: readcdf.c,v 1.55 2016/02/10 15:57:40 christos Exp $") +FILE_RCSID("@(#)$File: readcdf.c,v 1.56 2016/03/03 22:20:03 christos Exp $") #endif #include @@ -373,7 +373,7 @@ cdf_file_catalog_info(struct magic_set *ms, const cdf_info_t *info, dir, "Catalog", scn)) == -1) return i; #ifdef CDF_DEBUG - cdf_dump_catalog(&h, &scn); + cdf_dump_catalog(&h, scn); #endif if ((i = cdf_file_catalog(ms, h, scn)) == -1) return -1; diff --git a/src/softmagic.c b/src/softmagic.c index 14a8bc5..84e394c 100644 --- a/src/softmagic.c +++ b/src/softmagic.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: softmagic.c,v 1.228 2016/03/21 17:41:14 christos Exp $") +FILE_RCSID("@(#)$File: softmagic.c,v 1.230 2016/04/18 15:10:34 christos Exp $") #endif /* lint */ #include "magic.h" @@ -186,11 +186,11 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, ((text && (m->str_flags & FLT) == STRING_BINTEST) || (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) || (m->flag & mode) != mode) { +flush: /* Skip sub-tests */ - while (magindex + 1 < nmagic && - magic[magindex + 1].cont_level != 0 && - ++magindex) - continue; + while (magindex < nmagic - 1 && + magic[magindex + 1].cont_level != 0) + magindex++; continue; /* Skip to next top-level test*/ } @@ -227,10 +227,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, * main entry didn't match, * flush its continuations */ - while (magindex < nmagic - 1 && - magic[magindex + 1].cont_level != 0) - magindex++; - continue; + goto flush; } if ((e = handle_annotation(ms, m)) != 0) { @@ -255,8 +252,13 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, if (print && mprint(ms, m) == -1) return -1; - if (moffset(ms, m, nbytes, &ms->c.li[cont_level].off) == -1) - return -1; + switch (moffset(ms, m, nbytes, &ms->c.li[cont_level].off)) { + case -1: + case 0: + goto flush; + default: + break; + } /* and any continuations that match */ if (file_check_mem(ms, ++cont_level) == -1) @@ -362,9 +364,15 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, if (print && mprint(ms, m) == -1) return -1; - if (moffset(ms, m, nbytes, - &ms->c.li[cont_level].off) == -1) - return -1; + switch (moffset(ms, m, nbytes, + &ms->c.li[cont_level].off)) { + case -1: + case 0: + flush = 1; + break; + default: + break; + } if (*m->desc) *need_separator = 1; @@ -813,9 +821,13 @@ moffset(struct magic_set *ms, struct magic *m, size_t nbytes, int32_t *op) case FILE_DER: { o = der_offs(ms, m, nbytes); - if (o == -1) { - file_error(ms, 0, "EOF computing DER offset"); - return -1; + if (o == -1 || (size_t)o > nbytes) { + if ((ms->flags & MAGIC_DEBUG) != 0) { + (void)fprintf(stderr, + "Bad DER offset %d nbytes=%zu", + o, nbytes); + } + return 0; } break; } @@ -825,12 +837,15 @@ moffset(struct magic_set *ms, struct magic *m, size_t nbytes, int32_t *op) break; } - if ((size_t)o >= nbytes) { - file_error(ms, 0, "Offset out of range"); + if ((size_t)o > nbytes) { +#if 0 + file_error(ms, 0, "Offset out of range %zu > %zu", + (size_t)o, nbytes); +#endif return -1; } *op = o; - return 0; + return 1; } private uint32_t @@ -2107,8 +2122,13 @@ magiccheck(struct magic_set *ms, struct magic *m) return 1; case FILE_DER: matched = der_cmp(ms, m); - if (matched == -1) - file_error(ms, 0, "EOF comparing DER entries"); + if (matched == -1) { + if ((ms->flags & MAGIC_DEBUG) != 0) { + (void) fprintf(stderr, + "EOF comparing DER entries"); + } + return 0; + } return matched; default: file_magerror(ms, "invalid type %d in magiccheck()", m->type); diff --git a/tests/CVE-2014-1943.result b/tests/CVE-2014-1943.result index 1c589bb..68b5089 100644 --- a/tests/CVE-2014-1943.result +++ b/tests/CVE-2014-1943.result @@ -1 +1 @@ -ERROR: Apple Driver Map Offset out of range +Apple Driver Map, blocksize 0 \ No newline at end of file diff --git a/tests/Makefile.am b/tests/Makefile.am index c2cb5ee..46c02e8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -13,4 +13,4 @@ issue311docx.testfile T = $(top_srcdir)/tests check-local: MAGIC=$(top_builddir)/magic/magic ./test - for i in $T/*.testfile; do echo Running test: $$i; MAGIC=$(top_builddir)/magic/magic ./test $$i $${i%%.testfile}.result; done + set -e; for i in $T/*.testfile; do echo Running test: $$i; TZ=UTC MAGIC=$(top_builddir)/magic/magic ./test $$i $${i%%.testfile}.result; done diff --git a/tests/fit-map-data.result b/tests/fit-map-data.result index 90bf20d..0dbbb1b 100644 --- a/tests/fit-map-data.result +++ b/tests/fit-map-data.result @@ -1 +1 @@ -FIT Map data, unit id 65536, serial 3879446968, Sat May 31 06:00:34 2014, manufacturer 1 (garmin), product 1632, type 4 (Activity) \ No newline at end of file +FIT Map data, unit id 65536, serial 3879446968, Sat May 31 10:00:34 2014, manufacturer 1 (garmin), product 1632, type 4 (Activity) \ No newline at end of file -- 2.7.4