From 5a19f181b35a0928d23c7c12fd7a0698b465855b Mon Sep 17 00:00:00 2001 From: James Laird Date: Tue, 27 Jul 2004 11:55:19 -0500 Subject: [svn-r8953] Purpose: Bug fix Description: When a simple dataspace is created, its extent should be set before using it, or it will silently function as a NULL dataspace. Solution: Added checks on user-supplied dataspaces. Now dataspaces without extents set will throw errors; users must explicitly set a dataspace to be NULL. Platforms tested: sleipnir, windows --- src/H5A.c | 4 +++ src/H5D.c | 6 ++++ src/H5Dio.c | 16 ++++++++++ src/H5S.c | 32 +++++++++++++++++++ src/H5Sprivate.h | 1 + test/th5s.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- test/tvltypes.c | 18 +++++++++++ 7 files changed, 168 insertions(+), 3 deletions(-) diff --git a/src/H5A.c b/src/H5A.c index 21c3390..872d3fe 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -224,6 +224,10 @@ H5A_create(const H5G_entry_t *ent, const char *name, const H5T_t *type, assert(type); assert(space); + /* Check if the dataspace has an extent set (or is NULL) */ + if( !(H5S_has_extent(space)) ) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace extent has not been set") + /* Build the attribute information */ if((attr = H5MM_calloc(sizeof(H5A_t)))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for attribute info") diff --git a/src/H5D.c b/src/H5D.c index cf761c7..177e3e1 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -2135,6 +2135,10 @@ H5D_create(H5G_entry_t *loc, const char *name, hid_t type_id, const H5S_t *space if(H5T_detect_class(type, H5T_VLEN)) has_vl_type=TRUE; + /* Check if the dataspace has an extent set (or is NULL) */ + if( !(H5S_has_extent(space)) ) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "dataspace extent has not been set.") + /* Initialize the dataset object */ if(NULL == (new_dset = H5D_new(dcpl_id,TRUE,has_vl_type))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") @@ -3559,6 +3563,8 @@ H5Diterate(void *buf, hid_t type_id, hid_t space_id, H5D_operator_t op, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid datatype") if (NULL == (space = H5I_object_verify(space_id, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataspace") + if( !(H5S_has_extent(space)) ) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace does not have extent set") ret_value=H5S_select_iterate(buf,type_id,space,op,operator_data); diff --git a/src/H5Dio.c b/src/H5Dio.c index a480209..9fb860e 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -224,6 +224,10 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t assert(buf_type); assert(space); + /* Make sure the dataspace has an extent set (or is NULL) */ + if( !(H5S_has_extent(space)) ) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace extent has not been set") + /* Get the memory and file datatype sizes */ src_type_size = H5T_get_size(fill_type); dst_type_size = H5T_get_size(buf_type); @@ -683,6 +687,12 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, if (nelmts!=(hsize_t)H5S_GET_SELECT_NPOINTS(file_space)) HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes") + /* Make sure that both selections have their extents set */ + if( !(H5S_has_extent(file_space)) ) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file dataspace does not have extent set") + if( !(H5S_has_extent(mem_space)) ) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set") + /* Retrieve dataset properties */ /* */ @@ -933,6 +943,12 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, if (nelmts!=(hsize_t)H5S_GET_SELECT_NPOINTS(file_space)) HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes") + /* Make sure that both selections have their extents set */ + if( !(H5S_has_extent(file_space)) ) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file dataspace does not have extent set") + if( !(H5S_has_extent(mem_space)) ) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set") + /* Retrieve dataset properties */ /* */ diff --git a/src/H5S.c b/src/H5S.c index 86ac23a..1993966 100644 --- a/src/H5S.c +++ b/src/H5S.c @@ -2167,6 +2167,38 @@ done: FUNC_LEAVE_NOAPI(ret_value); } +/*------------------------------------------------------------------------- + * Function: H5S_has_extent + * + * Purpose: Determines if a simple dataspace's extent has been set (e.g., + * by H5Sset_extent_simple() ). Helps avoid write errors. + * + * Return: TRUE if dataspace has extent set + * FALSE if dataspace's extent is uninitialized + * + * Programmer: James Laird + * + * Date: July 23, 2004 + * + *------------------------------------------------------------------------- + */ +hbool_t +H5S_has_extent(const H5S_t *ds) +{ + htri_t ret_value; + FUNC_ENTER_NOAPI(H5S_has_extent, FAIL) + + assert(ds); + + if(ds->extent.rank==0 && ds->extent.nelem == 0 && ds->extent.type != H5S_NULL) + ret_value = FALSE; + else + ret_value = TRUE; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} + /*------------------------------------------------------------------------- * Function: H5S_set_extent_real diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 195a172..be8108e 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -216,6 +216,7 @@ H5_DLL hsize_t H5S_get_npoints_max(const H5S_t *ds); H5_DLL int H5S_get_simple_extent_ndims(const H5S_t *ds); H5_DLL int H5S_get_simple_extent_dims(const H5S_t *ds, hsize_t dims[]/*out*/, hsize_t max_dims[]/*out*/); +H5_DLL hbool_t H5S_has_extent(const H5S_t *ds); H5_DLL herr_t H5S_modify(struct H5G_entry_t *ent, const H5S_t *space, hbool_t update_time, hid_t dxpl_id); H5_DLL herr_t H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, const H5S_t *ds); diff --git a/test/th5s.c b/test/th5s.c index 1029bc0..c3724e2 100644 --- a/test/th5s.c +++ b/test/th5s.c @@ -30,6 +30,10 @@ #define TESTFILE "th5s.h5" #define DATAFILE "th5s1.h5" #define NULLFILE "th5s2.h5" +#define BASICFILE "th5s3.h5" +#define BASICDATASET "basic_dataset" +#define BASICDATASET2 "basic_dataset2" +#define BASICATTR "basic_attribute" #define NULLDATASET "null_dataset" #define NULLATTR "null_attribute" @@ -86,6 +90,7 @@ test_h5s_basic(void) hid_t fid1; /* HDF5 File IDs */ hid_t sid1, sid2; /* Dataspace ID */ hid_t dset1; /* Dataset ID */ + hid_t aid1; /* Attribute ID */ int rank; /* Logical rank of dataspace */ hsize_t dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3}; hsize_t dims2[] = {SPACE2_DIM1, SPACE2_DIM2, SPACE2_DIM3, @@ -205,6 +210,90 @@ test_h5s_basic(void) ret = H5Sclose(sid1); CHECK_I(ret, "H5Sclose"); + + /* + * Try writing simple dataspaces without setting their extents + */ + /* Create the file */ + fid1 = H5Fcreate(BASICFILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + CHECK(fid1, FAIL, "H5Fcreate"); + + dims1[0]=SPACE1_DIM1; + + sid1 = H5Screate(H5S_SIMPLE); + CHECK(sid1, FAIL, "H5Screate"); + sid2 = H5Screate_simple(1, dims1, dims1); + CHECK(sid2, FAIL, "H5Screate"); + + /* This dataset's space has no extent; it should not be created */ + H5E_BEGIN_TRY { + dset1 = H5Dcreate(fid1, BASICDATASET, H5T_NATIVE_INT, sid1, H5P_DEFAULT); + } H5E_END_TRY + VERIFY(dset1, FAIL, "H5Dcreate"); + + dset1 = H5Dcreate(fid1, BASICDATASET2, H5T_NATIVE_INT, sid2, H5P_DEFAULT); + CHECK(dset1, FAIL, "H5Dcreate"); + + /* Try some writes with the bad dataspace (sid1) */ + H5E_BEGIN_TRY { + ret = H5Dwrite(dset1, H5T_NATIVE_INT, sid1, H5S_ALL, H5P_DEFAULT, &n); + } H5E_END_TRY + VERIFY(ret, FAIL, "H5Dwrite"); + + H5E_BEGIN_TRY { + ret = H5Dwrite(dset1, H5T_NATIVE_INT, H5S_ALL, sid1, H5P_DEFAULT, &n); + } H5E_END_TRY + VERIFY(ret, FAIL, "H5Dwrite"); + + H5E_BEGIN_TRY { + ret = H5Dwrite(dset1, H5T_NATIVE_INT, sid1, sid1, H5P_DEFAULT, &n); + } H5E_END_TRY + VERIFY(ret, FAIL, "H5Dwrite"); + + /* Try to iterate using the bad dataspace */ + H5E_BEGIN_TRY { + ret = H5Diterate(&n, H5T_NATIVE_INT, sid1, NULL, NULL); + } H5E_END_TRY + VERIFY(ret, FAIL, "H5Diterate"); + + /* Try to fill using the bad dataspace */ + H5E_BEGIN_TRY { + ret = H5Dfill(NULL, H5T_NATIVE_INT, &n, H5T_NATIVE_INT, sid1); + } H5E_END_TRY + VERIFY(ret, FAIL, "H5Dfill"); + + /* Now use the bad dataspace as the space for an attribute */ + H5E_BEGIN_TRY { + aid1 = H5Acreate(dset1, BASICATTR, + H5T_NATIVE_INT, sid1, H5P_DEFAULT); + } H5E_END_TRY + VERIFY(aid1, FAIL, "H5Acreate"); + + /* Make sure that dataspace reads using the bad dataspace fail */ + H5E_BEGIN_TRY { + ret = H5Dread(dset1, H5T_NATIVE_INT, sid1, H5S_ALL, H5P_DEFAULT, &n); + } H5E_END_TRY + VERIFY(ret, FAIL, "H5Dread"); + + H5E_BEGIN_TRY { + ret = H5Dread(dset1, H5T_NATIVE_INT, H5S_ALL, sid1, H5P_DEFAULT, &n); + } H5E_END_TRY + VERIFY(ret, FAIL, "H5Dread"); + + H5E_BEGIN_TRY { + ret = H5Dread(dset1, H5T_NATIVE_INT, sid1, sid1, H5P_DEFAULT, &n); + } H5E_END_TRY + VERIFY(ret, FAIL, "H5Dread"); + + /* Clean up */ + ret = H5Dclose(dset1); + CHECK(ret, FAIL, "H5Dclose"); + ret = H5Sclose(sid1); + CHECK(ret, FAIL, "H5Sclose"); + ret = H5Sclose(sid2); + CHECK(ret, FAIL, "H5Sclose"); + ret = H5Fclose(fid1); + CHECK(ret, FAIL, "H5Fclose"); } /* test_h5s_basic() */ /**************************************************************** @@ -345,7 +434,7 @@ test_h5s_null(void) /* Close the dataspace */ ret = H5Sclose(sid); CHECK(ret, FAIL, "H5Sclose"); - + /* Close the file */ ret = H5Fclose(fid); CHECK(ret, FAIL, "H5Fclose"); @@ -435,7 +524,6 @@ test_h5s_null(void) static void test_h5s_encode(void) { - hid_t fid1; /* HDF5 File IDs */ hid_t sid1, sid2, sid3; /* Dataspace ID */ hid_t decoded_sid1, decoded_sid2, decoded_sid3; int rank; /* Logical rank of dataspace */ @@ -443,7 +531,6 @@ test_h5s_encode(void) size_t sbuf_size=0, null_size=0, scalar_size=0; unsigned char *sbuf=NULL, *null_sbuf=NULL, *scalar_buf=NULL; hsize_t tdims[4]; /* Dimension array to test with */ - hsize_t tmax[4]; hssize_t n; /* Number of dataspace elements */ hssize_t start[] = {0, 0, 0}; hsize_t stride[] = {2, 5, 3}; @@ -993,4 +1080,5 @@ void cleanup_h5s(void) { remove(DATAFILE); + remove(BASICFILE); } diff --git a/test/tvltypes.c b/test/tvltypes.c index bf22e24..af56eef 100644 --- a/test/tvltypes.c +++ b/test/tvltypes.c @@ -178,6 +178,7 @@ test_vltypes_vlen_atomic(void) hid_t fid1; /* HDF5 File IDs */ hid_t dataset; /* Dataset ID */ hid_t sid1; /* Dataspace ID */ + hid_t sid2; /* ID of bad dataspace (no extent set) */ hid_t tid1; /* Datatype ID */ hid_t dcpl_pid; /* Dataset creation property list ID */ hid_t xfer_pid; /* Dataset transfer property list ID */ @@ -395,6 +396,10 @@ test_vltypes_vlen_atomic(void) tid1 = H5Dget_type(dataset); CHECK(tid1, FAIL, "H5Dget_type"); + /* Create a "bad" dataspace with no extent set */ + sid2 = H5Screate(H5S_SIMPLE); + CHECK(sid2, FAIL, "H5Screate"); + /* Change to the custom memory allocation routines for reading VL data */ xfer_pid=H5Pcreate(H5P_DATASET_XFER); CHECK(xfer_pid, FAIL, "H5Pcreate"); @@ -406,6 +411,12 @@ test_vltypes_vlen_atomic(void) ret=H5Dvlen_get_buf_size(dataset,tid1,sid1,&size); CHECK(ret, FAIL, "H5Dvlen_get_buf_size"); + /* Try to call H5Dvlen_get_buf with bad dataspace */ + H5E_BEGIN_TRY { + ret=H5Dvlen_get_buf_size(dataset,tid1,sid2,&size); + } H5E_END_TRY + VERIFY(ret, FAIL, "H5Dvlen_get_buf_size"); + /* 10 elements allocated = 1 + 2 + 3 + 4 elements for each array position */ VERIFY(size,((SPACE1_DIM1*(SPACE1_DIM1+1))/2)*sizeof(unsigned int),"H5Dvlen_get_buf_size"); @@ -431,6 +442,13 @@ test_vltypes_vlen_atomic(void) } /* end for */ } /* end for */ + /* Try to reclaim read data using "bad" dataspace with no extent + * Should fail */ + H5E_BEGIN_TRY { + ret=H5Dvlen_reclaim(tid1,sid2,xfer_pid,rdata); + } H5E_END_TRY + VERIFY(ret, FAIL, "H5Dvlen_reclaim"); + /* Reclaim the read VL data */ ret=H5Dvlen_reclaim(tid1,sid1,xfer_pid,rdata); CHECK(ret, FAIL, "H5Dvlen_reclaim"); -- cgit v0.12