]> granicus.if.org Git - file/commitdiff
fix cdf bounds checks
authorChristos Zoulas <christos@zoulas.com>
Thu, 10 Feb 2011 21:35:05 +0000 (21:35 +0000)
committerChristos Zoulas <christos@zoulas.com>
Thu, 10 Feb 2011 21:35:05 +0000 (21:35 +0000)
ChangeLog
src/cdf.c
src/cdf.h
src/readcdf.c

index fb17e0f537b256453c363a97ae479522dbfc2e68..71ae0841ef1f8bc7a47974f685d8c9cb2db170a4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2011-02-10  16:36  Christos Zoulas <christos@zoulas.com>
+
+       * fix CDF bounds checking (Guy Helmer)
+
 2011-02-10  12:03  Christos Zoulas <christos@zoulas.com>
 
        * add cdf_ctime() that prints a meaningful error when time cannot
index 57e2ff55737c71083d18620d88fe1fb37567a6fd..fbba9521a1a7a478b292e5153ac79f05f968b5d8 100644 (file)
--- a/src/cdf.c
+++ b/src/cdf.c
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: cdf.c,v 1.40 2011/02/03 01:43:07 christos Exp $")
+FILE_RCSID("@(#)$File: cdf.c,v 1.41 2011/02/10 17:03:16 christos Exp $")
 #endif
 
 #include <assert.h>
@@ -247,18 +247,18 @@ cdf_unpack_dir(cdf_directory_t *d, char *buf)
 }
 
 static int
-cdf_check_stream_offset(const cdf_stream_t *sst, const void *p, size_t tail,
-    int line)
+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;
        (void)&line;
-       if (e >= b && (size_t)(e - b) < sst->sst_dirlen * sst->sst_len)
+       if (e >= b && (size_t)(e - b) < CDF_SEC_SIZE(h) * sst->sst_len)
                return 0;
        DPRINTF(("%d: offset begin %p end %p %" SIZE_T_FORMAT "u"
            " >= %" SIZE_T_FORMAT "u [%" SIZE_T_FORMAT "u %"
            SIZE_T_FORMAT "u]\n", line, b, e, (size_t)(e - b),
-           sst->sst_dirlen * sst->sst_len, sst->sst_dirlen, sst->sst_len));
+           CDF_SEC_SIZE(h) * sst->sst_len, CDF_SEC_SIZE(h), sst->sst_len));
        errno = EFTYPE;
        return -1;
 }
@@ -712,8 +712,8 @@ cdf_read_summary_info(const cdf_info_t *info, const cdf_header_t *h,
 }
 
 int
-cdf_read_property_info(const cdf_stream_t *sst, uint32_t offs,
-    cdf_property_info_t **info, size_t *count, size_t *maxcount)
+cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h,
+    uint32_t offs, cdf_property_info_t **info, size_t *count, size_t *maxcount)
 {
        const cdf_section_header_t *shp;
        cdf_section_header_t sh;
@@ -733,7 +733,7 @@ cdf_read_property_info(const cdf_stream_t *sst, uint32_t offs,
        }
        shp = CAST(const cdf_section_header_t *, (const void *)
            ((const char *)sst->sst_tab + offs));
-       if (cdf_check_stream_offset(sst, shp, sizeof(*shp), __LINE__) == -1)
+       if (cdf_check_stream_offset(sst, h, shp, sizeof(*shp), __LINE__) == -1)
                goto out;
        sh.sh_len = CDF_TOLE4(shp->sh_len);
 #define CDF_SHLEN_LIMIT (UINT32_MAX / 8)
@@ -747,8 +747,6 @@ cdf_read_property_info(const cdf_stream_t *sst, uint32_t offs,
                goto out;
        DPRINTF(("section len: %u properties %u\n", sh.sh_len,
            sh.sh_properties));
-       if (sh.sh_len == 0 || sh.sh_properties == 0)
-           return 0;
        if (*maxcount) {
                if (*maxcount > CDF_PROP_LIMIT)
                        goto out;
@@ -770,7 +768,7 @@ cdf_read_property_info(const cdf_stream_t *sst, uint32_t offs,
            offs + sizeof(sh)));
        e = CAST(const uint8_t *, (const void *)
            (((const char *)(const void *)shp) + sh.sh_len));
-       if (cdf_check_stream_offset(sst, e, 0, __LINE__) == -1)
+       if (cdf_check_stream_offset(sst, h, e, 0, __LINE__) == -1)
                goto out;
        for (i = 0; i < sh.sh_properties; i++) {
                q = (const uint8_t *)(const void *)
@@ -883,8 +881,8 @@ out:
 }
 
 int
-cdf_unpack_summary_info(const cdf_stream_t *sst, cdf_summary_info_header_t *ssi,
-    cdf_property_info_t **info, size_t *count)
+cdf_unpack_summary_info(const cdf_stream_t *sst, const cdf_header_t *h,
+    cdf_summary_info_header_t *ssi, cdf_property_info_t **info, size_t *count)
 {
        size_t i, maxcount;
        const cdf_summary_info_header_t *si =
@@ -893,8 +891,8 @@ cdf_unpack_summary_info(const cdf_stream_t *sst, cdf_summary_info_header_t *ssi,
            CAST(const cdf_section_declaration_t *, (const void *)
            ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET));
 
-       if (cdf_check_stream_offset(sst, si, sizeof(*si), __LINE__) == -1 ||
-           cdf_check_stream_offset(sst, sd, sizeof(*sd), __LINE__) == -1)
+       if (cdf_check_stream_offset(sst, h, si, sizeof(*si), __LINE__) == -1 ||
+           cdf_check_stream_offset(sst, h, sd, sizeof(*sd), __LINE__) == -1)
                return -1;
        ssi->si_byte_order = CDF_TOLE2(si->si_byte_order);
        ssi->si_os_version = CDF_TOLE2(si->si_os_version);
@@ -911,7 +909,7 @@ cdf_unpack_summary_info(const cdf_stream_t *sst, cdf_summary_info_header_t *ssi,
                        errno = EFTYPE;
                        return -1;
                }
-               if (cdf_read_property_info(sst, CDF_TOLE4(sd->sd_offset),
+               if (cdf_read_property_info(sst, h, CDF_TOLE4(sd->sd_offset),
                    info, count, &maxcount) == -1)
                        return -1;
        }
index f31d9aa385630a072239728f1d1dc9d461d4bd5b..7f3126b83d4216fb2594dd9266de0a618c8a6643 100644 (file)
--- a/src/cdf.h
+++ b/src/cdf.h
@@ -291,13 +291,13 @@ int cdf_read_ssat(const cdf_info_t *, const cdf_header_t *, const cdf_sat_t *,
     cdf_sat_t *);
 int cdf_read_short_stream(const cdf_info_t *, const cdf_header_t *,
     const cdf_sat_t *, const cdf_dir_t *, cdf_stream_t *);
-int cdf_read_property_info(const cdf_stream_t *, uint32_t,
+int cdf_read_property_info(const cdf_stream_t *, const cdf_header_t *, uint32_t,
     cdf_property_info_t **, size_t *, size_t *);
 int cdf_read_summary_info(const cdf_info_t *, const cdf_header_t *,
     const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *,
     const cdf_dir_t *, cdf_stream_t *);
-int cdf_unpack_summary_info(const cdf_stream_t *, cdf_summary_info_header_t *,
-    cdf_property_info_t **, size_t *);
+int cdf_unpack_summary_info(const cdf_stream_t *, const cdf_header_t *,
+    cdf_summary_info_header_t *, cdf_property_info_t **, size_t *);
 int cdf_print_classid(char *, size_t, const cdf_classid_t *);
 int cdf_print_property_name(char *, size_t, uint32_t);
 int cdf_print_elapsed_time(char *, size_t, cdf_timestamp_t);
index 95d5298d69339acc8343ef58fdf06694e159da68..1c7e909b38c2d9affe25b18cfeff79db3bcd9675 100644 (file)
@@ -26,7 +26,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: readcdf.c,v 1.23 2010/02/20 15:19:53 rrt Exp $")
+FILE_RCSID("@(#)$File: readcdf.c,v 1.24 2011/02/10 17:03:16 christos Exp $")
 #endif
 
 #include <stdlib.h>
@@ -149,14 +149,15 @@ cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info,
 }
 
 private int
-cdf_file_summary_info(struct magic_set *ms, const cdf_stream_t *sst)
+cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h,
+    const cdf_stream_t *sst)
 {
         cdf_summary_info_header_t si;
         cdf_property_info_t *info;
         size_t count;
         int m;
 
-        if (cdf_unpack_summary_info(sst, &si, &info, &count) == -1)
+        if (cdf_unpack_summary_info(sst, h, &si, &info, &count) == -1)
                 return -1;
 
         if (NOTMIME(ms)) {
@@ -260,7 +261,7 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
 #ifdef CDF_DEBUG
         cdf_dump_summary_info(&h, &scn);
 #endif
-        if ((i = cdf_file_summary_info(ms, &scn)) == -1)
+        if ((i = cdf_file_summary_info(ms, &h, &scn)) == -1)
                 expn = "Can't expand summary_info";
         free(scn.sst_tab);
 out4: