Browse Source

Import upstream version 5.03

Christos Zoulas 15 years ago
parent
commit
a0ff519f1d
6 changed files with 84 additions and 50 deletions
  1. 6 0
      ChangeLog
  2. 10 10
      configure
  3. 1 1
      configure.ac
  4. 58 26
      src/cdf.c
  5. 5 2
      src/patchlevel.h
  6. 4 11
      src/readcdf.c

+ 6 - 0
ChangeLog

@@ -1,3 +1,9 @@
+2009-05-06  10:25  Christos Zoulas <christos@zoulas.com>
+
+	* Avoid null dereference in cdf code (Drew Yao)
+
+	* More cdf bounds checks and overflow checks
+
 2009-05-01  18:37  Christos Zoulas <christos@zoulas.com>
 2009-05-01  18:37  Christos Zoulas <christos@zoulas.com>
 
 
 	* Buffer overflow fixes from Drew Yao
 	* Buffer overflow fixes from Drew Yao

+ 10 - 10
configure

@@ -1,6 +1,6 @@
 #! /bin/sh
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for file 5.02.
+# Generated by GNU Autoconf 2.61 for file 5.03.
 #
 #
 # Report bugs to <christos@astron.com>.
 # Report bugs to <christos@astron.com>.
 #
 #
@@ -728,8 +728,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 # Identity of this package.
 PACKAGE_NAME='file'
 PACKAGE_NAME='file'
 PACKAGE_TARNAME='file'
 PACKAGE_TARNAME='file'
-PACKAGE_VERSION='5.02'
-PACKAGE_STRING='file 5.02'
+PACKAGE_VERSION='5.03'
+PACKAGE_STRING='file 5.03'
 PACKAGE_BUGREPORT='christos@astron.com'
 PACKAGE_BUGREPORT='christos@astron.com'
 
 
 # Factoring default headers for most tests.
 # Factoring default headers for most tests.
@@ -1399,7 +1399,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
   cat <<_ACEOF
-\`configure' configures file 5.02 to adapt to many kinds of systems.
+\`configure' configures file 5.03 to adapt to many kinds of systems.
 
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
 
@@ -1469,7 +1469,7 @@ fi
 
 
 if test -n "$ac_init_help"; then
 if test -n "$ac_init_help"; then
   case $ac_init_help in
   case $ac_init_help in
-     short | recursive ) echo "Configuration of file 5.02:";;
+     short | recursive ) echo "Configuration of file 5.03:";;
    esac
    esac
   cat <<\_ACEOF
   cat <<\_ACEOF
 
 
@@ -1576,7 +1576,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
 if $ac_init_version; then
   cat <<\_ACEOF
   cat <<\_ACEOF
-file configure 5.02
+file configure 5.03
 generated by GNU Autoconf 2.61
 generated by GNU Autoconf 2.61
 
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1590,7 +1590,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 running configure, to aid debugging if configure makes a mistake.
 
 
-It was created by file $as_me 5.02, which was
+It was created by file $as_me 5.03, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
 
   $ $0 $@
   $ $0 $@
@@ -2280,7 +2280,7 @@ fi
 
 
 # Define the identity of the package.
 # Define the identity of the package.
  PACKAGE='file'
  PACKAGE='file'
- VERSION='5.02'
+ VERSION='5.03'
 
 
 
 
 cat >>confdefs.h <<_ACEOF
 cat >>confdefs.h <<_ACEOF
@@ -24303,7 +24303,7 @@ exec 6>&1
 # report actual input values of CONFIG_FILES etc. instead of their
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 # values after options handling.
 ac_log="
 ac_log="
-This file was extended by file $as_me 5.02, which was
+This file was extended by file $as_me 5.03, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_FILES    = $CONFIG_FILES
@@ -24356,7 +24356,7 @@ Report bugs to <bug-autoconf@gnu.org>."
 _ACEOF
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
 ac_cs_version="\\
-file config.status 5.02
+file config.status 5.03
 configured by $0, generated by GNU Autoconf 2.61,
 configured by $0, generated by GNU Autoconf 2.61,
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
 

+ 1 - 1
configure.ac

@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
 dnl Process this file with autoconf to produce a configure script.
-AC_INIT(file, 5.02, christos@astron.com)
+AC_INIT(file, 5.03, christos@astron.com)
 AM_INIT_AUTOMAKE
 AM_INIT_AUTOMAKE
 AM_CONFIG_HEADER(config.h)
 AM_CONFIG_HEADER(config.h)
 #AC_CONFIG_MACRO_DIR([m4])
 #AC_CONFIG_MACRO_DIR([m4])

+ 58 - 26
src/cdf.c

@@ -32,7 +32,7 @@
 #include "file.h"
 #include "file.h"
 
 
 #ifndef lint
 #ifndef lint
-FILE_RCSID("@(#)$File: cdf.c,v 1.26 2009/05/02 20:06:55 christos Exp $")
+FILE_RCSID("@(#)$File: cdf.c,v 1.30 2009/05/06 14:29:47 christos Exp $")
 #endif
 #endif
 
 
 #include <assert.h>
 #include <assert.h>
@@ -227,6 +227,19 @@ cdf_unpack_dir(cdf_directory_t *d, char *buf)
 	CDF_UNPACK(d->d_unused0);
 	CDF_UNPACK(d->d_unused0);
 }
 }
 
 
+static int
+cdf_check_stream_offset(const cdf_stream_t *sst, const void *p, size_t tail)
+{
+	const char *b = (const char *)sst->sst_tab;
+	const char *e = ((const char *)p) + tail;
+	if (e >= b && (size_t)(e - b) < sst->sst_dirlen * sst->sst_len)
+		return 0;
+	DPRINTF((stderr, "offset begin %p end %p %zu >= %zu\n", b, e,
+	    (size_t)(e - b), sst->sst_dirlen * sst->sst_len));
+	errno = EFTYPE;
+	return -1;
+}
+
 static ssize_t
 static ssize_t
 cdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len)
 cdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len)
 {
 {
@@ -321,15 +334,15 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat)
 			break;
 			break;
 
 
 #define CDF_SEC_LIMIT (UINT32_MAX / (4 * ss))
 #define CDF_SEC_LIMIT (UINT32_MAX / (4 * ss))
-	if (h->h_num_sectors_in_master_sat > CDF_SEC_LIMIT ||
-	    i > CDF_SEC_LIMIT / nsatpersec) {
+	if (h->h_num_sectors_in_master_sat > CDF_SEC_LIMIT / nsatpersec ||
+	    i > CDF_SEC_LIMIT) {
 		DPRINTF(("Number of sectors in master SAT too big %u %zu\n",
 		DPRINTF(("Number of sectors in master SAT too big %u %zu\n",
 		    h->h_num_sectors_in_master_sat, i));
 		    h->h_num_sectors_in_master_sat, i));
 		errno = EFTYPE;
 		errno = EFTYPE;
 		return -1;
 		return -1;
 	}
 	}
 
 
-	sat->sat_len = h->h_num_sectors_in_master_sat + i * nsatpersec;
+	sat->sat_len = h->h_num_sectors_in_master_sat * nsatpersec + i;
 	DPRINTF(("sat_len = %zu ss = %zu\n", sat->sat_len, ss));
 	DPRINTF(("sat_len = %zu ss = %zu\n", sat->sat_len, ss));
 	if ((sat->sat_tab = calloc(sat->sat_len, ss)) == NULL)
 	if ((sat->sat_tab = calloc(sat->sat_len, ss)) == NULL)
 		return -1;
 		return -1;
@@ -349,6 +362,8 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat)
 
 
 	mid = h->h_secid_first_sector_in_master_sat;
 	mid = h->h_secid_first_sector_in_master_sat;
 	for (j = 0; j < h->h_num_sectors_in_master_sat; j++) {
 	for (j = 0; j < h->h_num_sectors_in_master_sat; j++) {
+		if (mid < 0)
+			goto out;
 		if (j >= CDF_LOOP_LIMIT) {
 		if (j >= CDF_LOOP_LIMIT) {
 			DPRINTF(("Reading master sector loop limit"));
 			DPRINTF(("Reading master sector loop limit"));
 			errno = EFTYPE;
 			errno = EFTYPE;
@@ -360,10 +375,8 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat)
 		}
 		}
 		for (k = 0; k < nsatpersec; k++, i++) {
 		for (k = 0; k < nsatpersec; k++, i++) {
 			sec = CDF_TOLE4(msa[k]);
 			sec = CDF_TOLE4(msa[k]);
-			if (sec < 0) {
-				sat->sat_len = i;
-				break;
-			}
+			if (sec < 0)
+				goto out;
 			if (i >= sat->sat_len) {
 			if (i >= sat->sat_len) {
 			    DPRINTF(("Out of bounds reading MSA %u >= %u",
 			    DPRINTF(("Out of bounds reading MSA %u >= %u",
 				i, sat->sat_len));
 				i, sat->sat_len));
@@ -379,6 +392,8 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat)
 		}
 		}
 		mid = CDF_TOLE4(msa[nsatpersec]);
 		mid = CDF_TOLE4(msa[nsatpersec]);
 	}
 	}
+out:
+	sat->sat_len = i;
 	free(msa);
 	free(msa);
 	return 0;
 	return 0;
 out2:
 out2:
@@ -467,7 +482,7 @@ cdf_read_short_sector_chain(const cdf_header_t *h,
 	scn->sst_len = cdf_count_chain(ssat, sid, CDF_SEC_SIZE(h));
 	scn->sst_len = cdf_count_chain(ssat, sid, CDF_SEC_SIZE(h));
 	scn->sst_dirlen = len;
 	scn->sst_dirlen = len;
 
 
-	if (scn->sst_len == (size_t)-1)
+	if (sst->sst_tab == NULL || scn->sst_len == (size_t)-1)
 		return -1;
 		return -1;
 
 
 	scn->sst_tab = calloc(scn->sst_len, ss);
 	scn->sst_tab = calloc(scn->sst_len, ss);
@@ -618,22 +633,21 @@ cdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h,
 			break;
 			break;
 
 
 	/* If the it is not there, just fake it; some docs don't have it */
 	/* If the it is not there, just fake it; some docs don't have it */
-	if (i == dir->dir_len) {
-		scn->sst_tab = NULL;
-		scn->sst_len = 0;
-		return 0;
-	}
+	if (i == dir->dir_len)
+		goto out;
 	d = &dir->dir_tab[i];
 	d = &dir->dir_tab[i];
 
 
 	/* If the it is not there, just fake it; some docs don't have it */
 	/* If the it is not there, just fake it; some docs don't have it */
-	if (d->d_stream_first_sector < 0) {
-		scn->sst_tab = NULL;
-		scn->sst_len = 0;
-		return 0;
-	}
+	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);
 	    d->d_stream_first_sector, d->d_size, scn);
+out:
+	scn->sst_tab = NULL;
+	scn->sst_len = 0;
+	scn->sst_dirlen = 0;
+	return 0;
 }
 }
 
 
 static int
 static int
@@ -686,16 +700,27 @@ cdf_read_property_info(const cdf_stream_t *sst, uint32_t offs,
 	size_t i, o, nelements, j;
 	size_t i, o, nelements, j;
 	cdf_property_info_t *inp;
 	cdf_property_info_t *inp;
 
 
+	if (offs > UINT32_MAX / 4) {
+		errno = EFTYPE;
+		goto out;
+	}
 	shp = (const void *)((const char *)sst->sst_tab + offs);
 	shp = (const void *)((const char *)sst->sst_tab + offs);
+	if (cdf_check_stream_offset(sst, shp, sizeof(*shp)) == -1)
+		goto out;
 	sh.sh_len = CDF_TOLE4(shp->sh_len);
 	sh.sh_len = CDF_TOLE4(shp->sh_len);
+#define CDF_SHLEN_LIMIT (UINT32_MAX / 8)
+	if (sh.sh_len > CDF_SHLEN_LIMIT) {
+		errno = EFTYPE;
+		goto out;
+	}
 	sh.sh_properties = CDF_TOLE4(shp->sh_properties);
 	sh.sh_properties = CDF_TOLE4(shp->sh_properties);
-#define CDF_PROP_LIM (UINT32_MAX / (4 * sizeof(*inp)))
-	if (sh.sh_properties > CDF_PROP_LIM)
+#define CDF_PROP_LIMIT (UINT32_MAX / (4 * sizeof(*inp)))
+	if (sh.sh_properties > CDF_PROP_LIMIT)
 		goto out;
 		goto out;
 	DPRINTF(("section len: %u properties %u\n", sh.sh_len,
 	DPRINTF(("section len: %u properties %u\n", sh.sh_len,
 	    sh.sh_properties));
 	    sh.sh_properties));
 	if (*maxcount) {
 	if (*maxcount) {
-		if (*maxcount > CDF_PROP_LIM)
+		if (*maxcount > CDF_PROP_LIMIT)
 			goto out;
 			goto out;
 		*maxcount += sh.sh_properties;
 		*maxcount += sh.sh_properties;
 		inp = realloc(*info, *maxcount * sizeof(*inp));
 		inp = realloc(*info, *maxcount * sizeof(*inp));
@@ -710,6 +735,8 @@ cdf_read_property_info(const cdf_stream_t *sst, uint32_t offs,
 	*count += sh.sh_properties;
 	*count += sh.sh_properties;
 	p = (const void *)((const char *)sst->sst_tab + offs + sizeof(sh));
 	p = (const void *)((const char *)sst->sst_tab + offs + sizeof(sh));
 	e = (const void *)(((const char *)shp) + sh.sh_len);
 	e = (const void *)(((const char *)shp) + sh.sh_len);
+	if (cdf_check_stream_offset(sst, e, 0) == -1)
+		goto out;
 	for (i = 0; i < sh.sh_properties; i++) {
 	for (i = 0; i < sh.sh_properties; i++) {
 		q = (const uint32_t *)((const char *)p +
 		q = (const uint32_t *)((const char *)p +
 		    CDF_TOLE4(p[(i << 1) + 1])) - 2;
 		    CDF_TOLE4(p[(i << 1) + 1])) - 2;
@@ -767,8 +794,8 @@ cdf_read_property_info(const cdf_stream_t *sst, uint32_t offs,
 		case CDF_LENGTH32_STRING:
 		case CDF_LENGTH32_STRING:
 			if (nelements > 1) {
 			if (nelements > 1) {
 				size_t nelem = inp - *info;
 				size_t nelem = inp - *info;
-				if (*maxcount > CDF_PROP_LIM
-				    || nelements > CDF_PROP_LIM)
+				if (*maxcount > CDF_PROP_LIMIT
+				    || nelements > CDF_PROP_LIMIT)
 					goto out;
 					goto out;
 				*maxcount += nelements;
 				*maxcount += nelements;
 				inp = realloc(*info, *maxcount * sizeof(*inp));
 				inp = realloc(*info, *maxcount * sizeof(*inp));
@@ -822,6 +849,9 @@ cdf_unpack_summary_info(const cdf_stream_t *sst, cdf_summary_info_header_t *ssi,
 	const cdf_section_declaration_t *sd = (const void *)
 	const cdf_section_declaration_t *sd = (const void *)
 	    ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET);
 	    ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET);
 
 
+	if (cdf_check_stream_offset(sst, si, sizeof(*si)) == -1 ||
+	    cdf_check_stream_offset(sst, sd, sizeof(*sd)) == -1)
+		return -1;
 	ssi->si_byte_order = CDF_TOLE2(si->si_byte_order);
 	ssi->si_byte_order = CDF_TOLE2(si->si_byte_order);
 	ssi->si_os_version = CDF_TOLE2(si->si_os_version);
 	ssi->si_os_version = CDF_TOLE2(si->si_os_version);
 	ssi->si_os = CDF_TOLE2(si->si_os);
 	ssi->si_os = CDF_TOLE2(si->si_os);
@@ -936,11 +966,13 @@ cdf_dump_header(const cdf_header_t *h)
 	size_t i;
 	size_t i;
 
 
 #define DUMP(a, b) (void)fprintf(stderr, "%40.40s = " a "\n", # b, h->h_ ## b)
 #define DUMP(a, b) (void)fprintf(stderr, "%40.40s = " a "\n", # b, h->h_ ## b)
+#define DUMP2(a, b) (void)fprintf(stderr, "%40.40s = " a " (" a ")\n", # b, \
+    h->h_ ## b, 1 << h->h_ ## b)
 	DUMP("%d", revision);
 	DUMP("%d", revision);
 	DUMP("%d", version);
 	DUMP("%d", version);
 	DUMP("0x%x", byte_order);
 	DUMP("0x%x", byte_order);
-	DUMP("%d", sec_size_p2);
-	DUMP("%d", short_sec_size_p2);
+	DUMP2("%d", sec_size_p2);
+	DUMP2("%d", short_sec_size_p2);
 	DUMP("%d", num_sectors_in_sat);
 	DUMP("%d", num_sectors_in_sat);
 	DUMP("%d", secid_first_directory);
 	DUMP("%d", secid_first_directory);
 	DUMP("%d", min_size_standard_stream);
 	DUMP("%d", min_size_standard_stream);

+ 5 - 2
src/patchlevel.h

@@ -1,11 +1,14 @@
 #define	FILE_VERSION_MAJOR	5
 #define	FILE_VERSION_MAJOR	5
-#define	patchlevel		2
+#define	patchlevel		3
 
 
 /*
 /*
  * Patchlevel file for Ian Darwin's MAGIC command.
  * Patchlevel file for Ian Darwin's MAGIC command.
- * $File: patchlevel.h,v 1.73 2009/05/04 15:15:13 christos Exp $
+ * $File: patchlevel.h,v 1.74 2009/05/06 20:32:48 christos Exp $
  *
  *
  * $Log: patchlevel.h,v $
  * $Log: patchlevel.h,v $
+ * Revision 1.74  2009/05/06 20:32:48  christos
+ * welcome to 5.03
+ *
  * Revision 1.73  2009/05/04 15:15:13  christos
  * Revision 1.73  2009/05/04 15:15:13  christos
  * 5.02...
  * 5.02...
  *
  *

+ 4 - 11
src/readcdf.c

@@ -26,7 +26,7 @@
 #include "file.h"
 #include "file.h"
 
 
 #ifndef lint
 #ifndef lint
-FILE_RCSID("@(#)$File: readcdf.c,v 1.16 2009/05/01 22:36:58 christos Exp $")
+FILE_RCSID("@(#)$File: readcdf.c,v 1.18 2009/05/06 20:48:22 christos Exp $")
 #endif
 #endif
 
 
 #include <stdlib.h>
 #include <stdlib.h>
@@ -147,15 +147,8 @@ cdf_file_summary_info(struct magic_set *ms, const cdf_stream_t *sst)
 	size_t count;
 	size_t count;
 	int m;
 	int m;
 
 
-	if (cdf_unpack_summary_info(sst, &si, &info, &count) == -1) {
-		if (si.si_byte_order != 0xfffe)
-			return 0;
-		else
-			return -1;
-	}
-
-	if (si.si_byte_order != 0xfffe)
-		return 0;
+	if (cdf_unpack_summary_info(sst, &si, &info, &count) == -1)
+		return -1;
 
 
 	if (NOTMIME(ms)) {
 	if (NOTMIME(ms)) {
 		if (file_printf(ms, "CDF V2 Document") == -1)
 		if (file_printf(ms, "CDF V2 Document") == -1)
@@ -246,7 +239,7 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
 
 
 	if ((i = cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir,
 	if ((i = cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir,
 	    &scn)) == -1) {
 	    &scn)) == -1) {
-		expn = "";
+		expn = "Cannot read summary info";
 		goto out4;
 		goto out4;
 	}
 	}
 #ifdef CDF_DEBUG
 #ifdef CDF_DEBUG