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.
This commit is contained in:
Vailin Choi 2017-07-10 03:22:48 -05:00
parent 45724d8082
commit fc76c77852
5 changed files with 121 additions and 8 deletions

View File

@ -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]);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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
@ -11343,6 +11344,97 @@ error:
return -1;
} /* end test_storage_size() */
/*-------------------------------------------------------------------------
* 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
@ -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);