summaryrefslogtreecommitdiffstats
path: root/src/H5Spoint.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Spoint.c')
-rw-r--r--src/H5Spoint.c55
1 files changed, 40 insertions, 15 deletions
diff --git a/src/H5Spoint.c b/src/H5Spoint.c
index 94a2aa1..1483269 100644
--- a/src/H5Spoint.c
+++ b/src/H5Spoint.c
@@ -59,7 +59,7 @@ static herr_t H5S__point_release(H5S_t *space);
static htri_t H5S__point_is_valid(const H5S_t *space);
static hssize_t H5S__point_serial_size(H5S_t *space);
static herr_t H5S__point_serialize(H5S_t *space, uint8_t **p);
-static herr_t H5S__point_deserialize(H5S_t **space, const uint8_t **p);
+static herr_t H5S__point_deserialize(H5S_t **space, const uint8_t **p, const size_t p_size, hbool_t skip);
static herr_t H5S__point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
static herr_t H5S__point_offset(const H5S_t *space, hsize_t *off);
static int H5S__point_unlim_dim(const H5S_t *space);
@@ -1235,19 +1235,20 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S__point_deserialize(H5S_t **space, const uint8_t **p)
+H5S__point_deserialize(H5S_t **space, const uint8_t **p, const size_t p_size, hbool_t skip)
{
- H5S_t *tmp_space = NULL; /* Pointer to actual dataspace to use,
- either *space or a newly allocated one */
- hsize_t dims[H5S_MAX_RANK]; /* Dimension sizes */
- uint32_t version; /* Version number */
- hsize_t *coord = NULL, *tcoord; /* Pointer to array of elements */
- const uint8_t *pp; /* Local pointer for decoding */
- uint64_t num_elem = 0; /* Number of elements in selection */
- unsigned rank; /* Rank of points */
- unsigned i, j; /* local counting variables */
- herr_t ret_value = SUCCEED; /* Return value */
-
+ H5S_t *tmp_space = NULL; /* Pointer to actual dataspace to use,
+ either *space or a newly allocated one */
+ hsize_t dims[H5S_MAX_RANK]; /* Dimension sizes */
+ uint32_t version; /* Version number */
+ uint8_t enc_size = 0; /* Encoded size of selection info */
+ hsize_t *coord = NULL, *tcoord; /* Pointer to array of elements */
+ const uint8_t *pp; /* Local pointer for decoding */
+ uint64_t num_elem = 0; /* Number of elements in selection */
+ unsigned rank; /* Rank of points */
+ unsigned i, j; /* local counting variables */
+ herr_t ret_value = SUCCEED; /* Return value */
+ const uint8_t *p_end = *p + p_size - 1; /* Pointer to last valid byte in buffer */
FUNC_ENTER_STATIC
/* Check args */
@@ -1268,15 +1269,26 @@ H5S__point_deserialize(H5S_t **space, const uint8_t **p)
tmp_space = *space;
/* Decode version */
+ if (H5_IS_KNOWN_BUFFER_OVERFLOW(skip, pp, sizeof(uint32_t), p_end))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_OVERFLOW, FAIL, "buffer overflow while decoding selection version")
UINT32DECODE(pp, version);
if (version < H5S_POINT_VERSION_1 || version > H5S_POINT_VERSION_LATEST)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "bad version number for point selection")
/* Skip over the remainder of the header */
+ if (H5_IS_KNOWN_BUFFER_OVERFLOW(skip, pp, 8, p_end))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_OVERFLOW, FAIL, "buffer overflow while decoding selection headers")
pp += 8;
+ enc_size = H5S_SELECT_INFO_ENC_SIZE_4;
+
+ /* Check encoded size */
+ if (enc_size & ~H5S_SELECT_INFO_ENC_SIZE_BITS)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown size of point/offset info for selection")
/* Decode the rank of the point selection */
+ if (H5_IS_KNOWN_BUFFER_OVERFLOW(skip, pp, sizeof(uint32_t), p_end))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_OVERFLOW, FAIL, "buffer overflow while decoding selection rank")
UINT32DECODE(pp, rank);
if (!*space) {
@@ -1291,13 +1303,26 @@ H5S__point_deserialize(H5S_t **space, const uint8_t **p)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL,
"rank of serialized selection does not match dataspace")
- /* Deserialize points to select */
- UINT32DECODE(pp, num_elem); /* decode the number of points */
+ /* decode the number of points */
+ if (enc_size != H5S_SELECT_INFO_ENC_SIZE_4)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size")
+
+ if (H5_IS_KNOWN_BUFFER_OVERFLOW(skip, pp, sizeof(uint32_t), p_end))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_OVERFLOW, FAIL, "buffer overflow while decoding number of points")
+
+ UINT32DECODE(pp, num_elem);
/* Allocate space for the coordinates */
if (NULL == (coord = (hsize_t *)H5MM_malloc(num_elem * rank * sizeof(hsize_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate coordinate information")
+ /* Determine necessary size of buffer for coordinates */
+ size_t enc_type_size = sizeof(uint32_t);
+ size_t coordinate_buffer_requirement = num_elem * rank * enc_type_size;
+
+ if (H5_IS_KNOWN_BUFFER_OVERFLOW(skip, pp, coordinate_buffer_requirement, p_end))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_OVERFLOW, FAIL, "buffer overflow while decoding selection coordinates")
+
/* Retrieve the coordinates from the buffer */
for (tcoord = coord, i = 0; i < num_elem; i++)
for (j = 0; j < (unsigned)rank; j++, tcoord++)