From: Christos Zoulas Date: Thu, 10 Feb 2011 21:35:05 +0000 (+0000) Subject: fix cdf bounds checks X-Git-Tag: FILE5_07~44 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dfe012e4dbdbf8bb98e340f6577972e7225a525a;p=file fix cdf bounds checks --- diff --git a/ChangeLog b/ChangeLog index fb17e0f5..71ae0841 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-02-10 16:36 Christos Zoulas + + * fix CDF bounds checking (Guy Helmer) + 2011-02-10 12:03 Christos Zoulas * add cdf_ctime() that prints a meaningful error when time cannot diff --git a/src/cdf.c b/src/cdf.c index 57e2ff55..fbba9521 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.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 @@ -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; } diff --git a/src/cdf.h b/src/cdf.h index f31d9aa3..7f3126b8 100644 --- 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); diff --git a/src/readcdf.c b/src/readcdf.c index 95d5298d..1c7e909b 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.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 @@ -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: