summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVailin Choi <vchoi@jam.ad.hdfgroup.org>2017-07-10 08:22:48 (GMT)
committerVailin Choi <vchoi@jam.ad.hdfgroup.org>2017-07-10 08:22:48 (GMT)
commit8935c921f7e50607cd91c86b2237ac39a9b600af (patch)
treeda0b7139c2145c0167d42338f5481e94a1fac458
parent46450bd9d02d87469d0c74df17cc76616822b8d4 (diff)
downloadhdf5-8935c921f7e50607cd91c86b2237ac39a9b600af.zip
hdf5-8935c921f7e50607cd91c86b2237ac39a9b600af.tar.gz
hdf5-8935c921f7e50607cd91c86b2237ac39a9b600af.tar.bz2
Fix for HDFFV-10217 infinite loop in H5VM_power2up().
The function H5VM_power2up() returns the next power of 2 for n. When n exceeds 2^63, it overflows and becomes 0 causing the infinite looping. The fix ensures that the function checks for n >= 2^63 and returns 0.
-rw-r--r--src/H5Dchunk.c7
-rw-r--r--src/H5Ddeprec.c5
-rw-r--r--src/H5Dint.c14
-rw-r--r--src/H5VMprivate.h6
-rw-r--r--test/dsets.c97
5 files changed, 121 insertions, 8 deletions
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index d693466..b7b8b03 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -1019,11 +1019,16 @@ H5D__chunk_init(H5F_t *f, hid_t dxpl_id, const H5D_t *dset, hid_t dapl_id)
unsigned u; /* Local index value */
for(u = 0; u < dset->shared->ndims; u++) {
+ hsize_t scaled_power2up; /* Scaled value, rounded to next power of 2 */
+
/* Initial scaled dimension sizes */
rdcc->scaled_dims[u] = dset->shared->curr_dims[u] / dset->shared->layout.u.chunk.dim[u];
+ if( !(scaled_power2up = H5VM_power2up(rdcc->scaled_dims[u])) )
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get the next power of 2")
+
/* Inital 'power2up' values for scaled dimensions */
- rdcc->scaled_power2up[u] = H5VM_power2up(rdcc->scaled_dims[u]);
+ rdcc->scaled_power2up[u] = scaled_power2up;
/* Number of bits required to encode scaled dimension size */
rdcc->scaled_encode_bits[u] = H5VM_log2_gen(rdcc->scaled_power2up[u]);
diff --git a/src/H5Ddeprec.c b/src/H5Ddeprec.c
index 8d9461c..0807048 100644
--- a/src/H5Ddeprec.c
+++ b/src/H5Ddeprec.c
@@ -329,8 +329,11 @@ H5D__extend(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id)
dataset->shared->cache.chunk.scaled_dims[u] > dataset->shared->cache.chunk.nslots))
update_chunks = TRUE;
+ if( !(scaled_power2up = H5VM_power2up(scaled)) )
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get the next power of 2")
+
/* Check if the number of bits required to encode the scaled size value changed */
- if(dataset->shared->cache.chunk.scaled_power2up[u] != (scaled_power2up = H5VM_power2up(scaled))) {
+ if(dataset->shared->cache.chunk.scaled_power2up[u] != scaled_power2up) {
/* Update the 'power2up' & 'encode_bits' values for the current dimension */
dataset->shared->cache.chunk.scaled_power2up[u] = scaled_power2up;
dataset->shared->cache.chunk.scaled_encode_bits[u] = H5VM_log2_gen(scaled_power2up);
diff --git a/src/H5Dint.c b/src/H5Dint.c
index 08b3eb8..3b938e2 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -745,8 +745,13 @@ H5D__cache_dataspace_info(const H5D_t *dset)
dset->shared->ndims = (unsigned)sndims;
/* Compute the inital 'power2up' values */
- for(u = 0; u < dset->shared->ndims; u++)
- dset->shared->curr_power2up[u] = H5VM_power2up(dset->shared->curr_dims[u]);
+ for(u = 0; u < dset->shared->ndims; u++) {
+ hsize_t scaled_power2up; /* Scaled value, rounded to next power of 2 */
+
+ if( !(scaled_power2up = H5VM_power2up(dset->shared->curr_dims[u])) )
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get the next power of 2")
+ dset->shared->curr_power2up[u] = scaled_power2up;
+ }
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2809,8 +2814,11 @@ H5D__set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id)
dset->shared->cache.chunk.scaled_dims[u] > dset->shared->cache.chunk.nslots))
update_chunks = TRUE;
+ if( !(scaled_power2up = H5VM_power2up(scaled)) )
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get the next power of 2")
+
/* Check if the number of bits required to encode the scaled size value changed */
- if(dset->shared->cache.chunk.scaled_power2up[u] != (scaled_power2up = H5VM_power2up(scaled))) {
+ if(dset->shared->cache.chunk.scaled_power2up[u] != scaled_power2up) {
/* Update the 'power2up' & 'encode_bits' values for the current dimension */
dset->shared->cache.chunk.scaled_power2up[u] = scaled_power2up;
dset->shared->cache.chunk.scaled_encode_bits[u] = H5VM_log2_gen(scaled_power2up);
diff --git a/src/H5VMprivate.h b/src/H5VMprivate.h
index 4d71b29..decac7e 100644
--- a/src/H5VMprivate.h
+++ b/src/H5VMprivate.h
@@ -460,7 +460,11 @@ H5VM_power2up(hsize_t n)
{
hsize_t ret_value = 1; /* Return value */
- while(ret_value < n)
+ /* Returns 0 when n exceeds 2^63 */
+ if(n >= (hsize_t)1 << ((sizeof(hsize_t) * CHAR_BIT) - 1))
+ ret_value = 0;
+
+ while(ret_value && ret_value < n)
ret_value <<= 1;
return(ret_value);
diff --git a/test/dsets.c b/test/dsets.c
index c29d18e..0ca08e4 100644
--- a/test/dsets.c
+++ b/test/dsets.c
@@ -51,14 +51,15 @@ const char *FILENAME[] = {
"copy_dcpl_newfile",/* 13 */
"partial_chunks", /* 14 */
"layout_extend", /* 15 */
- "zero_chunk", /* 16 */
+ "zero_chunk", /* 16 */
"chunk_single", /* 17 */
"swmr_non_latest", /* 18 */
"earray_hdr_fd", /* 19 */
"farray_hdr_fd", /* 20 */
"bt2_hdr_fd", /* 21 */
- "storage_size", /* 22 */
+ "storage_size", /* 22 */
"dls_01_strings", /* 23 */
+ "power2up", /* 24 */
NULL
};
#define FILENAME_BUF_SIZE 1024
@@ -11345,6 +11346,97 @@ error:
/*-------------------------------------------------------------------------
+ * Function: test_power2up
+ *
+ * Purpose: Tests that the H5VM_power2up(n) function does not result in an
+ * infinite loop when input n exceeds 2^63. (HDFFV-10217)
+ * H5VM_power2up() is used to calculate the next power of 2 for
+ * a dataset's scaled dimension sizes.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi; June 2017
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+test_power2up(hid_t fapl)
+{
+ char filename[FILENAME_BUF_SIZE];
+ hid_t fid = -1; /* File ID */
+ hid_t dcpl = -1; /* Dataset creation property list */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t did = -1; /* Dataset ID */
+ hsize_t dims[2]; /* Dataset dimension sizes */
+ hsize_t max_dims[2]; /* Maximum dimension sizes */
+ hsize_t chunk_dims[2]; /* Chunk dimensions */
+ hsize_t ext_dims[2]; /* Extended dimension sizes */
+ herr_t status; /* Error status */
+
+ TESTING("the next power of 2");
+
+ h5_fixname(FILENAME[24], fapl, filename, sizeof filename);
+
+ /* Create file */
+ if((fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) FAIL_STACK_ERROR
+
+ /* Set dims[1] to ((2^63) -1) */
+ dims[0] = 0;
+ dims[1] = ((hsize_t)1 << ((sizeof(hsize_t) * CHAR_BIT) -1)) - 1;
+ max_dims[0] = max_dims[1] = H5S_UNLIMITED;
+ sid = H5Screate_simple(2, dims, max_dims);
+
+ /* Create dataset creation property list */
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ TEST_ERROR
+
+ /* Set chunk size */
+ chunk_dims[0] = chunk_dims[1] = 1;
+ if(H5Pset_chunk(dcpl, 2, chunk_dims) < 0)
+ TEST_ERROR
+
+ /* Create chunked dataset */
+ if((did = H5Dcreate2(fid, "dset", H5T_NATIVE_INT64, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ TEST_ERROR
+
+ ext_dims[0] = 1;
+ ext_dims[1] = dims[1] + 5;
+
+ /* Extend to (2^63)+ */
+ H5E_BEGIN_TRY {
+ status = H5Dset_extent(did, ext_dims);
+ } H5E_END_TRY;
+ if(status >= 0)
+ TEST_ERROR
+
+ /* Closing */
+ if(H5Dclose(did) < 0)
+ TEST_ERROR
+ if(H5Sclose(sid) < 0)
+ TEST_ERROR
+ if(H5Pclose(dcpl) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid) < 0)
+ TEST_ERROR
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Pclose(dcpl);
+ H5Dclose(did);
+ H5Sclose(sid);
+ H5Pclose(dcpl);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+ return -1;
+} /* end test_power2up() */
+
+
+/*-------------------------------------------------------------------------
* Function: test_scatter
*
* Purpose: Tests H5Dscatter with a variety of different selections
@@ -12928,6 +13020,7 @@ main(void)
nerrors += (test_large_chunk_shrink(my_fapl) < 0 ? 1 : 0);
nerrors += (test_zero_dim_dset(my_fapl) < 0 ? 1 : 0);
nerrors += (test_storage_size(my_fapl) < 0 ? 1 : 0);
+ nerrors += (test_power2up(my_fapl) < 0 ? 1 : 0);
nerrors += (test_swmr_non_latest(envval, my_fapl) < 0 ? 1 : 0);
nerrors += (test_earray_hdr_fd(envval, my_fapl) < 0 ? 1 : 0);