summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristos Zoulas <christos@zoulas.com>2021-09-16 23:59:42 +0000
committerChristos Zoulas <christos@zoulas.com>2021-09-16 23:59:42 +0000
commita9c8d2a9493c4e0cd201db57801f3502e65c686c (patch)
tree10c3ae3307970a2ecc310b4308f50cca6b058ee1
parent1ee3a7f9860517e28f4dba303d9a65ea983cdf9d (diff)
downloadfile-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.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/src/cdf.c b/src/cdf.c
index bb81d637..114f8fa3 100644
--- a/src/cdf.c
+++ b/src/cdf.c
@@ -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 *