123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- Subject: Try to clean this up; the vector code is still fishy
- Origin: FILE5_30-28-g393555f2
- Upstream-Author: Christos Zoulas <christos@zoulas.com>
- Date: Mon Mar 27 20:58:11 2017 +0000
- [ Also contains the spello fix FILE5_30-10-ga25f230f -CB ]
- --- a/src/cdf.c
- +++ b/src/cdf.c
- @@ -818,6 +818,66 @@
- return 0;
- }
-
- +#define CDF_SHLEN_LIMIT (UINT32_MAX / 8)
- +#define CDF_PROP_LIMIT (UINT32_MAX / (4 * sizeof(cdf_property_info_t)))
- +
- +static const void *
- +cdf_offset(const void *p, size_t l)
- +{
- + return CAST(const void *, CAST(const uint8_t *, p) + l);
- +}
- +
- +static const uint8_t *
- +cdf_get_property_info_pos(const cdf_stream_t *sst, const cdf_header_t *h,
- + const uint8_t *p, const uint8_t *e, size_t i)
- +{
- + size_t tail = (i << 1) + 1;
- + size_t ofs;
- + const uint8_t *q;
- +
- + if (cdf_check_stream_offset(sst, h, p, tail * sizeof(uint32_t),
- + __LINE__) == -1)
- + return NULL;
- + ofs = CDF_GETUINT32(p, tail);
- + q = CAST(const uint8_t *, cdf_offset(CAST(const void *, p),
- + ofs - 2 * sizeof(uint32_t)));
- +
- + if (q < p) {
- + DPRINTF(("Wrapped around %p < %p\n", q, p));
- + return NULL;
- + }
- +
- + if (q >= e) {
- + DPRINTF(("Ran off the end %p >= %p\n", q, e));
- + return NULL;
- + }
- + return q;
- +}
- +
- +static cdf_property_info_t *
- +cdf_grow_info(cdf_property_info_t **info, size_t *maxcount, size_t incr)
- +{
- + cdf_property_info_t *inp;
- + size_t newcount = *maxcount + incr;
- +
- + if (newcount > CDF_PROP_LIMIT)
- + goto out;
- +
- + inp = CAST(cdf_property_info_t *,
- + realloc(*info, newcount * sizeof(*inp)));
- + if (inp == NULL)
- + goto out;
- +
- + *info = inp;
- + *maxcount = newcount;
- + return inp;
- +out:
- + free(*info);
- + *maxcount = 0;
- + *info = NULL;
- + return NULL;
- +}
- +
- int
- 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)
- @@ -831,70 +891,40 @@
- int64_t s64;
- uint64_t u64;
- cdf_timestamp_t tp;
- - size_t i, o, o4, nelements, j;
- + size_t i, o4, nelements, j, slen;
- cdf_property_info_t *inp;
-
- if (offs > UINT32_MAX / 4) {
- errno = EFTYPE;
- goto out;
- }
- - shp = CAST(const cdf_section_header_t *, (const void *)
- - ((const char *)sst->sst_tab + offs));
- + shp = CAST(const cdf_section_header_t *,
- + cdf_offset(sst->sst_tab, offs));
- 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)
- if (sh.sh_len > CDF_SHLEN_LIMIT) {
- errno = EFTYPE;
- goto out;
- }
- sh.sh_properties = CDF_TOLE4(shp->sh_properties);
- -#define CDF_PROP_LIMIT (UINT32_MAX / (4 * sizeof(*inp)))
- if (sh.sh_properties > CDF_PROP_LIMIT)
- goto out;
- DPRINTF(("section len: %u properties %u\n", sh.sh_len,
- sh.sh_properties));
- - if (*maxcount) {
- - if (*maxcount > CDF_PROP_LIMIT)
- - goto out;
- - *maxcount += sh.sh_properties;
- - inp = CAST(cdf_property_info_t *,
- - realloc(*info, *maxcount * sizeof(*inp)));
- - } else {
- - *maxcount = sh.sh_properties;
- - inp = CAST(cdf_property_info_t *,
- - malloc(*maxcount * sizeof(*inp)));
- - }
- + inp = cdf_grow_info(info, maxcount, sh.sh_properties);
- if (inp == NULL)
- - goto out1;
- - *info = inp;
- + goto out;
- inp += *count;
- *count += sh.sh_properties;
- - p = CAST(const uint8_t *, (const void *)
- - ((const char *)(const void *)sst->sst_tab +
- - offs + sizeof(sh)));
- - e = CAST(const uint8_t *, (const void *)
- - (((const char *)(const void *)shp) + sh.sh_len));
- + p = CAST(const uint8_t *, cdf_offset(sst->sst_tab, offs + sizeof(sh)));
- + e = CAST(const uint8_t *, cdf_offset(shp, sh.sh_len));
- if (cdf_check_stream_offset(sst, h, e, 0, __LINE__) == -1)
- goto out;
- +
- for (i = 0; i < sh.sh_properties; i++) {
- - size_t tail = (i << 1) + 1;
- - size_t ofs;
- - if (cdf_check_stream_offset(sst, h, p, tail * sizeof(uint32_t),
- - __LINE__) == -1)
- - goto out;
- - ofs = CDF_GETUINT32(p, tail);
- - q = (const uint8_t *)(const void *)
- - ((const char *)(const void *)p + ofs
- - - 2 * sizeof(uint32_t));
- - if (q < p) {
- - DPRINTF(("Wrapped around %p < %p\n", q, p));
- - goto out;
- - }
- - if (q >= e) {
- - DPRINTF(("Ran of the end %p >= %p\n", q, e));
- + if ((q = cdf_get_property_info_pos(sst, h, p, e, i)) == NULL)
- goto out;
- - }
- inp[i].pi_id = CDF_GETUINT32(p, i << 1);
- inp[i].pi_type = CDF_GETUINT32(q, 0);
- DPRINTF(("%" SIZE_T_FORMAT "u) id=%x type=%x offs=0x%tx,0x%x\n",
- @@ -905,12 +935,12 @@
- DPRINTF(("CDF_VECTOR with nelements == 0\n"));
- goto out;
- }
- - o = 2;
- + slen = 2;
- } else {
- nelements = 1;
- - o = 1;
- + slen = 1;
- }
- - o4 = o * sizeof(uint32_t);
- + o4 = slen * sizeof(uint32_t);
- if (inp[i].pi_type & (CDF_ARRAY|CDF_BYREF|CDF_RESERVED))
- goto unknown;
- switch (inp[i].pi_type & CDF_TYPEMASK) {
- @@ -966,16 +996,10 @@
- case CDF_LENGTH32_WSTRING:
- if (nelements > 1) {
- size_t nelem = inp - *info;
- - if (*maxcount > CDF_PROP_LIMIT
- - || nelements > CDF_PROP_LIMIT)
- - goto out;
- - *maxcount += nelements;
- - inp = CAST(cdf_property_info_t *,
- - realloc(*info, *maxcount * sizeof(*inp)));
- + inp = cdf_grow_info(info, maxcount, nelements);
- if (inp == NULL)
- - goto out1;
- - *info = inp;
- - inp = *info + nelem;
- + goto out;
- + inp += nelem;
- }
- DPRINTF(("nelements = %" SIZE_T_FORMAT "u\n",
- nelements));
- @@ -984,28 +1008,28 @@
- {
- uint32_t l;
-
- - if (q + o + sizeof(uint32_t) >= e)
- + if (q + slen + sizeof(uint32_t) >= e)
- goto out;
-
- - l = CDF_GETUINT32(q, o);
- + l = CDF_GETUINT32(q, slen);
- o4 += sizeof(uint32_t);
- - if (q + o4 + l >= e)
- + if (o4 + l > CAST(size_t, e - q))
- goto out;
-
- inp[i].pi_str.s_len = l;
- inp[i].pi_str.s_buf = CAST(const char *,
- CAST(const void *, &q[o4]));
-
- - DPRINTF(("l = %d, r = %" SIZE_T_FORMAT
- - "u, s = %s\n", l,
- - CDF_ROUND(l, sizeof(l)),
- + DPRINTF(("o=%zu l=%d(%" SIZE_T_FORMAT
- + "u), t=%td s=%s\n", o4, l,
- + CDF_ROUND(l, sizeof(l)), e - q,
- inp[i].pi_str.s_buf));
-
- if (l & 1)
- l++;
-
- - o += l >> 1;
- - o4 = o * sizeof(uint32_t);
- + slen += l >> 1;
- + o4 = slen * sizeof(uint32_t);
- }
- i--;
- break;
- @@ -1029,8 +1053,6 @@
- return 0;
- out:
- errno = EFTYPE;
- -out1:
- - free(*info);
- return -1;
- }
-
|