diff options
author | Christos Zoulas <christos@zoulas.com> | 2021-09-16 23:59:42 +0000 |
---|---|---|
committer | Christos Zoulas <christos@zoulas.com> | 2021-09-16 23:59:42 +0000 |
commit | a9c8d2a9493c4e0cd201db57801f3502e65c686c (patch) | |
tree | 10c3ae3307970a2ecc310b4308f50cca6b058ee1 | |
parent | 1ee3a7f9860517e28f4dba303d9a65ea983cdf9d (diff) | |
download | file-git-a9c8d2a9493c4e0cd201db57801f3502e65c686c.tar.gz |
Unfortunately gcc pointer overflow -> undefined behavior got rid of our
checks, so be explicit when adding offsets (found by clusterfuzz)
-rw-r--r-- | src/cdf.c | 21 |
1 files changed, 11 insertions, 10 deletions
@@ -35,10 +35,11 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: cdf.c,v 1.116 2019/08/26 14:31:39 christos Exp $") +FILE_RCSID("@(#)$File: cdf.c,v 1.117 2021/09/16 23:59:42 christos Exp $") #endif #include <assert.h> +#define CDF_DEBUG #ifdef CDF_DEBUG #include <err.h> #endif @@ -888,29 +889,29 @@ cdf_get_property_info_pos(const cdf_stream_t *sst, const cdf_header_t *h, { size_t tail = (i << 1) + 1; size_t ofs; - const uint8_t *q; if (p >= e) { DPRINTF(("Past end %p < %p\n", e, p)); return NULL; } + if (cdf_check_stream_offset(sst, h, p, (tail + 1) * 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)); + ofs = CDF_GETUINT32(p, tail); + if (ofs < 2 * sizeof(uint32_t)) { + DPRINTF(("Offset too small %zu\n", ofs)); return NULL; } - if (q >= e) { - DPRINTF(("Ran off the end %p >= %p\n", q, e)); + ofs -= 2 * sizeof(uint32_t); + if (ofs > CAST(size_t, e - p)) { + DPRINTF(("Offset too big %zu %td\n", ofs, e - p)); return NULL; } - return q; + + return CAST(const uint8_t *, cdf_offset(CAST(const void *, p), ofs)); } static cdf_property_info_t * |