From: Egbert Eich Date: Sat Feb 11 13:54:17 2023 +0100 Subject: Check for overflow when calculating on-disk attribute data size (#2459) Patch-mainline: Not yet Git-repo: https://github.com/HDFGroup/hdf5 Git-commit: 0d026daa13a81be72495872f651c036fdc84ae5e References: A bogus hdf5 file may contain dataspace messages with sizes which lead to the on-disk data sizes to exceed what is addressable. When calculating the size, make sure, the multiplication does not overflow. The test case was crafted in a way that the overflow caused the size to be 0. This fixes CVE-2021-37501 / Bug #2458. Signed-off-by: Egbert Eich Signed-off-by: Egbert Eich --- src/H5Oattr.c | 3 +++ src/H5private.h | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/H5Oattr.c b/src/H5Oattr.c index 4dee7aa187..3ef0b99aa4 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -235,6 +235,9 @@ H5O_attr_decode(H5F_t *f, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, un /* Compute the size of the data */ H5_CHECKED_ASSIGN(attr->shared->data_size, size_t, ds_size * (hsize_t)dt_size, hsize_t); + H5_CHECK_MUL_OVERFLOW(attr->shared->data_size, ds_size, dt_size, + HGOTO_ERROR(H5E_RESOURCE, H5E_OVERFLOW, NULL, + "data size exceeds addressable range")) /* Go get the data */ if (attr->shared->data_size) { diff --git a/src/H5private.h b/src/H5private.h index 931d7b9046..a115aee1a4 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -1605,6 +1605,24 @@ H5_DLL int HDvasprintf(char **bufp, const char *fmt, va_list _ap); #define H5_CHECK_OVERFLOW(var, vartype, casttype) #endif /* NDEBUG */ +/* + * A macro for checking whether a multiplication has overflown + * r is assumed to be the result of a prior multiplication of a and b + */ +#define H5_CHECK_MUL_OVERFLOW(r, a, b, err) \ + { \ + bool mul_overflow = false; \ + if (r != 0) { \ + if (r / a != b) \ + mul_overflow = true; \ + } else { \ + if (a != 0 && b != 0) \ + mul_overflow = true; \ + } \ + if (mul_overflow) \ + err \ + } + /* * A macro for detecting over/under-flow when assigning between types */