From 9a500cd913413b39f9c04361ef08abe434f30a13 Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Wed, 5 Oct 2022 07:17:24 +0200 Subject: [PATCH] H5O_fsinfo_decode() Make more resilient to out-of-bounds read Malformed hdf5 files may have trunkated content which does not match the expected size. This function attempts to decode these it will read past the end of the allocated space which may lead to a crash. Make sure each element is within bounds before reading. This fixes CVE-2021-45830 / Bug #2228. Signed-off-by: Egbert Eich Additions --- src/H5Ofsinfo.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/H5Ofsinfo.c b/src/H5Ofsinfo.c index f8455e4b490..4d5934d08da 100644 --- a/src/H5Ofsinfo.c +++ b/src/H5Ofsinfo.c @@ -88,6 +88,7 @@ H5FL_DEFINE_STATIC(H5O_fsinfo_t); * *------------------------------------------------------------------------- */ + static void * H5O__fsinfo_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, size_t p_size, const uint8_t *p) @@ -112,6 +113,8 @@ H5O__fsinfo_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNU fsinfo->fs_addr[ptype - 1] = HADDR_UNDEF; /* Version of message */ + if (p + 1 - 1 > p_end) /* one byte for version */ + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "ran off end of input buffer while decoding") vers = *p++; if (vers == H5O_FSINFO_VERSION_0) { @@ -125,6 +128,8 @@ H5O__fsinfo_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNU fsinfo->pgend_meta_thres = H5F_FILE_SPACE_PGEND_META_THRES; fsinfo->eoa_pre_fsm_fsalloc = HADDR_UNDEF; + if (p + 1 + H5F_SIZEOF_SIZE(f) - 1 > p_end) /* one byte for strategy + sizeof(f) */ + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "ran off end of input buffer while decoding") strategy = (H5F_file_space_type_t)*p++; /* File space strategy */ H5F_DECODE_LENGTH(f, p, threshold); /* Free-space section threshold */ @@ -169,7 +174,10 @@ H5O__fsinfo_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNU else { HDassert(vers >= H5O_FSINFO_VERSION_1); - fsinfo->version = vers; + fsinfo->version = vers; + /* strategy (1) + persist (1) + sizeof(f) + sizeof(f) + pgend_meta_thres (2) + sizeofaddr(f) */ + if (p + 1 + 1 + 2 * H5F_SIZEOF_SIZE(f) + 2 + H5F_SIZEOF_ADDR(f) - 1 > p_end) + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "ran off end of input buffer while decoding") fsinfo->strategy = (H5F_fspace_strategy_t)*p++; /* File space strategy */ fsinfo->persist = *p++; /* Free-space persist or not */ H5F_DECODE_LENGTH(f, p, fsinfo->threshold); /* Free-space section threshold */ @@ -181,9 +189,11 @@ H5O__fsinfo_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNU /* Decode addresses of free space managers, if persisting */ if (fsinfo->persist) - for (ptype = H5F_MEM_PAGE_SUPER; ptype < H5F_MEM_PAGE_NTYPES; ptype++) + for (ptype = H5F_MEM_PAGE_SUPER; ptype < H5F_MEM_PAGE_NTYPES; ptype++) { + if (p + H5F_SIZEOF_SIZE(f) - 1 > p_end) /* one byte for sizeof(f) */ + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "ran off end of input buffer while decoding") H5F_addr_decode(f, &p, &(fsinfo->fs_addr[ptype - 1])); - + } fsinfo->mapped = FALSE; }