diff options
author | Kobrin Eli <kobrineli@ispras.ru> | 2023-04-13 21:37:10 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-13 21:37:10 (GMT) |
commit | 10d4a6d0941240702b5e8d77d57184a88bb69e6c (patch) | |
tree | a166f5fa73f5d993b4a87c492f745774f912de34 /src/H5Fsuper_cache.c | |
parent | 65eff22348634144cd5a6e77159c27eb895d54b4 (diff) | |
download | hdf5-10d4a6d0941240702b5e8d77d57184a88bb69e6c.zip hdf5-10d4a6d0941240702b5e8d77d57184a88bb69e6c.tar.gz hdf5-10d4a6d0941240702b5e8d77d57184a88bb69e6c.tar.bz2 |
Fix out of bounds in `hdf5/src/H5Fint.c:2859` (#2691)
Diffstat (limited to 'src/H5Fsuper_cache.c')
-rw-r--r-- | src/H5Fsuper_cache.c | 58 |
1 files changed, 54 insertions, 4 deletions
diff --git a/src/H5Fsuper_cache.c b/src/H5Fsuper_cache.c index 5d9b628..467e287 100644 --- a/src/H5Fsuper_cache.c +++ b/src/H5Fsuper_cache.c @@ -433,6 +433,8 @@ H5F__cache_superblock_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUS if (H5F__superblock_prefix_decode(sblock, &image, udata, FALSE) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "can't decode file superblock prefix") + const uint8_t *image_end = image + len - 1; + /* Check for older version of superblock format */ if (sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) { uint32_t status_flags; /* File status flags */ @@ -440,10 +442,18 @@ H5F__cache_superblock_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUS unsigned snode_btree_k; /* B-tree symbol table internal node 'K' value */ unsigned chunk_btree_k; /* B-tree chunk internal node 'K' value */ + /* Check whether the image pointer is out of bounds */ + if (H5_IS_BUFFER_OVERFLOW(image, 1, image_end)) + HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds") + /* Freespace version (hard-wired) */ if (HDF5_FREESPACE_VERSION != *image++) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad free space version number") + /* Check whether the image pointer is out of bounds */ + if (H5_IS_BUFFER_OVERFLOW(image, 1, image_end)) + HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds") + /* Root group version number (hard-wired) */ if (HDF5_OBJECTDIR_VERSION != *image++) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad object directory version number") @@ -451,6 +461,10 @@ H5F__cache_superblock_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUS /* Skip over reserved byte */ image++; + /* Check whether the image pointer is out of bounds */ + if (H5_IS_BUFFER_OVERFLOW(image, 1, image_end)) + HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds") + /* Shared header version number (hard-wired) */ if (HDF5_SHAREDHEADER_VERSION != *image++) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad shared-header format version number") @@ -466,12 +480,20 @@ H5F__cache_superblock_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUS /* Skip over reserved byte */ image++; + /* Check whether the image pointer is out of bounds */ + if (H5_IS_BUFFER_OVERFLOW(image, sizeof(uint16_t), image_end)) + HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds") + /* Various B-tree sizes */ UINT16DECODE(image, sym_leaf_k); if (sym_leaf_k == 0) HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, NULL, "bad symbol table leaf node 1/2 rank") udata->sym_leaf_k = sym_leaf_k; /* Keep a local copy also */ + /* Check whether the image pointer is out of bounds */ + if (H5_IS_BUFFER_OVERFLOW(image, sizeof(uint16_t), image_end)) + HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds") + /* Need 'get' call to set other array values */ UINT16DECODE(image, snode_btree_k); if (snode_btree_k == 0) @@ -483,6 +505,10 @@ H5F__cache_superblock_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUS * for the indexed storage B-tree internal 'K' value later. */ + /* Check whether the image pointer is out of bounds */ + if (H5_IS_BUFFER_OVERFLOW(image, sizeof(uint32_t), image_end)) + HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds") + /* File status flags (not really used yet) */ UINT32DECODE(image, status_flags); HDassert(status_flags <= 255); @@ -495,16 +521,29 @@ H5F__cache_superblock_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUS * storage B-tree internal 'K' value */ if (sblock->super_vers > HDF5_SUPERBLOCK_VERSION_DEF) { + /* Check whether the image pointer is out of bounds */ + if (H5_IS_BUFFER_OVERFLOW(image, sizeof(uint16_t), image_end)) + HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds") + UINT16DECODE(image, chunk_btree_k); /* Reserved bytes are present only in version 1 */ - if (sblock->super_vers == HDF5_SUPERBLOCK_VERSION_1) + if (sblock->super_vers == HDF5_SUPERBLOCK_VERSION_1) { image += 2; /* reserved */ - } /* end if */ + + /* Check whether the image pointer is out of bounds */ + if (H5_IS_BUFFER_OVERFLOW(image, 1, image_end)) + HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds") + } + } /* end if */ else chunk_btree_k = HDF5_BTREE_CHUNK_IK_DEF; udata->btree_k[H5B_CHUNK_ID] = chunk_btree_k; + /* Check whether the image pointer will be out of bounds */ + if (H5_IS_BUFFER_OVERFLOW(image, H5F_SIZEOF_ADDR(udata->f) * 4, image_end)) + HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds") + /* Remainder of "variable-sized" portion of superblock */ H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->base_addr /*out*/); H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->ext_addr /*out*/); @@ -518,7 +557,7 @@ H5F__cache_superblock_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUS "can't allocate space for root group symbol table entry") /* decode the root group symbol table entry */ - if (H5G_ent_decode(udata->f, (const uint8_t **)&image, sblock->root_ent) < 0) + if (H5G_ent_decode(udata->f, (const uint8_t **)&image, sblock->root_ent, image_end) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, NULL, "can't decode root group symbol table entry") /* Set the root group address to the correct value */ @@ -544,16 +583,23 @@ H5F__cache_superblock_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUS /* Skip over size of file addresses (already decoded) */ image++; udata->f->shared->sizeof_addr = sblock->sizeof_addr; /* Keep a local copy also */ - /* Skip over size of file sizes (already decoded) */ image++; udata->f->shared->sizeof_size = sblock->sizeof_size; /* Keep a local copy also */ + /* Check whether the image pointer is out of bounds */ + if (H5_IS_BUFFER_OVERFLOW(image, 1, image_end)) + HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds") + /* File status flags (not really used yet) */ sblock->status_flags = *image++; if (sblock->status_flags & ~H5F_SUPER_ALL_FLAGS) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad flag value for superblock") + /* Check whether the image pointer will be out of bounds */ + if (H5_IS_BUFFER_OVERFLOW(image, H5F_SIZEOF_ADDR(udata->f) * 4, image_end)) + HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds") + /* Base, superblock extension, end of file & root group object header addresses */ H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->base_addr /*out*/); H5F_addr_decode(udata->f, (const uint8_t **)&image, &sblock->ext_addr /*out*/); @@ -562,6 +608,10 @@ H5F__cache_superblock_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUS /* checksum verification already done in verify_chksum cb */ + /* Check whether the image pointer will be out of bounds */ + if (H5_IS_BUFFER_OVERFLOW(image, sizeof(uint32_t), image_end)) + HGOTO_ERROR(H5E_FILE, H5E_OVERFLOW, NULL, "image pointer is out of bounds") + /* Decode checksum */ UINT32DECODE(image, read_chksum); |