diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2015-12-17 17:19:11 +1100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-07-19 07:01:08 +0200 |
commit | 87acb61eeab78ff031b0ffc0c12cdfaba04fc869 (patch) | |
tree | ea1c07989e6bea27cd6b3efb6a729b2ab2e3c1b9 /cpukit/dtc/libfdt/fdt.c | |
parent | libfdt: check for potential overrun in _fdt_splice() (diff) | |
download | rtems-87acb61eeab78ff031b0ffc0c12cdfaba04fc869.tar.bz2 |
libfdt: Fix undefined behaviour in fdt_offset_ptr()
Using pointer arithmetic to generate a pointer outside a known object is,
technically, undefined behaviour in C. Unfortunately, we were using that
in fdt_offset_ptr() to detect overflows.
To fix this we need to do our bounds / overflow checking on the offsets
before constructing pointers from them.
Reported-by: David Binderman <dcb314@hotmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'cpukit/dtc/libfdt/fdt.c')
-rw-r--r-- | cpukit/dtc/libfdt/fdt.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/cpukit/dtc/libfdt/fdt.c b/cpukit/dtc/libfdt/fdt.c index 2ce6a44179..22286a1aae 100644 --- a/cpukit/dtc/libfdt/fdt.c +++ b/cpukit/dtc/libfdt/fdt.c @@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt) const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { - const char *p; + unsigned absoffset = offset + fdt_off_dt_struct(fdt); + + if ((absoffset < offset) + || ((absoffset + len) < absoffset) + || (absoffset + len) > fdt_totalsize(fdt)) + return NULL; if (fdt_version(fdt) >= 0x11) if (((offset + len) < offset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; - p = _fdt_offset_ptr(fdt, offset); - - if (p + len < p) - return NULL; - return p; + return _fdt_offset_ptr(fdt, offset); } uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) |