diff options
author | mattjala <124107509+mattjala@users.noreply.github.com> | 2023-05-12 20:22:55 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-12 20:22:55 (GMT) |
commit | 364145f144cb68a5635ad9f7dad0e4210e3d513a (patch) | |
tree | 5a5a7b4f2a343c8e96bc486abbbbe4d94fb0b094 /src/H5Sselect.c | |
parent | 0d4a12d7cd0f0c10b385533365fc1f3ebeef8e74 (diff) | |
download | hdf5-364145f144cb68a5635ad9f7dad0e4210e3d513a.zip hdf5-364145f144cb68a5635ad9f7dad0e4210e3d513a.tar.gz hdf5-364145f144cb68a5635ad9f7dad0e4210e3d513a.tar.bz2 |
Prevent buffer overrun in H5S_select_deserialize (#2931)
* Prevent buffer overrun in H5S_select_deserialize
The call to H5S_select_deserialize from H5S_decode doesn't have
the buffer size available to it, so to allow decoding there
I set it to assume a max size buffer for now.
Making the buffer size known in H5S_decode could be done by
modifying the external API's H5Sdecode, or splitting H5Sdecode
into two functions using a macro (similar to H5Sencode), with the
macro taking one argument and assuming a max buffer size.
* Conditional buffer check in H5S_select_deserialize
Moved and renamed a macro for only checking buffer overflow when
buffer size is known from H5Odtype.c to H5private.h,
so it can be used throughout the library.
Also silenced some build warnings about types.
Diffstat (limited to 'src/H5Sselect.c')
-rw-r--r-- | src/H5Sselect.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 02889f7..28c30ea 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -521,11 +521,12 @@ H5S_select_valid(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_deserialize(H5S_t **space, const uint8_t **p) +H5S_select_deserialize(H5S_t **space, const uint8_t **p, const size_t p_size) { - uint32_t sel_type; /* Pointer to the selection type */ - herr_t ret_value = FAIL; /* Return value */ - + uint32_t sel_type; /* Pointer to the selection type */ + herr_t ret_value = FAIL; /* Return value */ + const uint8_t *p_end = *p + p_size - 1; /* Pointer to last valid byte in buffer */ + hbool_t skip = (p_size == SIZE_MAX ? TRUE : FALSE); /* If p_size is unknown, skip buffer checks */ FUNC_ENTER_NOAPI(FAIL) HDassert(space); @@ -533,24 +534,26 @@ H5S_select_deserialize(H5S_t **space, const uint8_t **p) /* Selection-type specific coding is moved to the callbacks. */ /* Decode selection type */ + if (H5_IS_KNOWN_BUFFER_OVERFLOW(skip, *p, sizeof(uint32_t), p_end)) + HGOTO_ERROR(H5E_DATASPACE, H5E_OVERFLOW, FAIL, "buffer overflow while decoding selection type") UINT32DECODE(*p, sel_type); /* Make routine for selection type */ switch (sel_type) { case H5S_SEL_POINTS: /* Sequence of points selected */ - ret_value = (*H5S_sel_point->deserialize)(space, p); + ret_value = (*H5S_sel_point->deserialize)(space, p, p_size - sizeof(uint32_t), skip); break; case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */ - ret_value = (*H5S_sel_hyper->deserialize)(space, p); + ret_value = (*H5S_sel_hyper->deserialize)(space, p, p_size - sizeof(uint32_t), skip); break; case H5S_SEL_ALL: /* Entire extent selected */ - ret_value = (*H5S_sel_all->deserialize)(space, p); + ret_value = (*H5S_sel_all->deserialize)(space, p, p_size - sizeof(uint32_t), skip); break; case H5S_SEL_NONE: /* Nothing selected */ - ret_value = (*H5S_sel_none->deserialize)(space, p); + ret_value = (*H5S_sel_none->deserialize)(space, p, p_size - sizeof(uint32_t), skip); break; default: |