[svn-r5586] Purpose:

Bug Fix

Description:
    H5Dcreate and H5Tcommit allow "empty" compound and enumerated types (i.e.
    ones with no members) to be stored in the file, but this causes an assertion
    failure and is somewhat vapid.

Solution:
    Check the datatype "makes sense" before using it for H5Dcreate and
    H5Tcommit.

Platforms tested:
    FreeBSD 4.5 (sleipnir)
This commit is contained in:
Quincey Koziol 2002-06-11 11:03:04 -05:00
parent e4a300b04e
commit 33a1bc03c4
6 changed files with 188 additions and 12 deletions

View File

@ -35,6 +35,9 @@ Bug Fixes since HDF5-1.4.0
Library
-------
* Fixed bug (#499) which allowed an "empty" compound or enumerated datatype
(one with no members) to be used to create a dataset or committed to a
file. QAK - 2002/06/11
* Fixed bug (#777) which allowed a compound datatype to be inserted into
itself. QAK - 2002/06/10
* Fixed bug (#789) where creating 1-D dataset region reference caused the

View File

@ -1559,6 +1559,18 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type,
if(NULL == (new_dset = H5D_new(dcpl_id)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
/* Check if the datatype is "sensible" for use in a dataset */
if(H5T_is_sensible(type)!=TRUE)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "datatype is not sensible");
/* Copy datatype for dataset */
if((new_dset->type = H5T_copy(type, H5T_COPY_ALL))==NULL)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy datatype");
/* Mark any VL datatypes as being on disk now */
if (H5T_vlen_mark(new_dset->type, f, H5T_VLEN_DISK)<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid VL location");
/* Get new dataset's property list object */
if (NULL == (new_plist = H5I_object(new_dset->dcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get dataset creation property list");
@ -1566,13 +1578,6 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type,
if(H5P_get(new_plist, H5D_CRT_CHUNK_DIM_NAME, &chunk_ndims) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve layout");
/* Copy datatype for dataset */
new_dset->type = H5T_copy(type, H5T_COPY_ALL);
/* Mark any VL datatypes as being on disk now */
if (H5T_vlen_mark(new_dset->type, f, H5T_VLEN_DISK)<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid VL location");
if(H5P_get(new_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve external file list");

View File

@ -5851,14 +5851,15 @@ H5T_commit (H5G_entry_t *loc, const char *name, H5T_t *type)
FUNC_ENTER_NOAPI(H5T_commit, FAIL);
assert (loc);
assert (name && *name);
assert (type);
/*
* Check arguments. We cannot commit an immutable type because H5Tclose()
* normally fails on such types (try H5Tclose(H5T_NATIVE_INT)) but closing
* a named type should always succeed.
*/
assert (loc);
assert (name && *name);
assert (type);
if (H5T_STATE_NAMED==type->state || H5T_STATE_OPEN==type->state) {
HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,
"data type is already committed");
@ -5868,6 +5869,10 @@ H5T_commit (H5G_entry_t *loc, const char *name, H5T_t *type)
"data type is immutable");
}
/* Check for a "sensible" datatype to store on disk */
if(H5T_is_sensible(type)!=TRUE)
HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "datatype is not sensible");
/* Find the insertion file */
if (NULL==(file=H5G_insertion_file(loc, name))) {
HRETURN_ERROR(H5E_SYM, H5E_CANTINIT, FAIL,
@ -8087,6 +8092,59 @@ H5Tget_array_dims(hid_t type_id, hsize_t dims[], int perm[])
FUNC_LEAVE(ret_value);
} /* end H5Tget_array_dims */
/*-------------------------------------------------------------------------
* Function: H5T_is_sensible
*
* Purpose: Determines if a data type is sensible to store on disk
* (i.e. not partially initialized)
*
* Return: Success: TRUE, FALSE
*
* Failure: Negative
*
* Programmer: Quincey Koziol
* Tuesday, June 11, 2002
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
htri_t
H5T_is_sensible(const H5T_t *dt)
{
htri_t ret_value = FAIL;
FUNC_ENTER_NOAPI(H5T_is_sensible, FAIL);
assert(dt);
switch(dt->type) {
case H5T_COMPOUND:
/* Only allow compound datatypes with at least one member to be stored on disk */
if(dt->u.compnd.nmembs > 0)
ret_value=TRUE;
else
ret_value=FALSE;
break;
case H5T_ENUM:
/* Only allow enum datatypes with at least one member to be stored on disk */
if(dt->u.enumer.nmembs > 0)
ret_value=TRUE;
else
ret_value=FALSE;
break;
default:
/* Assume all other datatype are sensible to store on disk */
ret_value=TRUE;
break;
} /* end switch */
FUNC_LEAVE(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5T_print_stats

View File

@ -133,6 +133,7 @@ __DLL__ herr_t H5T_enum_valueof(H5T_t *dt, const char *name,
void *value/*out*/);
__DLL__ herr_t H5T_vlen_reclaim(void *elem, hid_t type_id, hsize_t ndim, hssize_t *point, void *_op_data);
__DLL__ htri_t H5T_vlen_mark(H5T_t *dt, H5F_t *f, H5T_vlen_loc_t loc);
__DLL__ htri_t H5T_is_sensible(const H5T_t *dt);
/* Reference specific functions */
__DLL__ H5R_type_t H5T_get_ref_type(const H5T_t *dt);

View File

@ -48,7 +48,7 @@ MOSTLYCLEAN=cmpd_dset.h5 dataset.h5 extend.h5 istore.h5 tfile1.h5 tfile2.h5 \
mount_[0-9].h5 testmeta.h5 ttime.h5 trefer[12].h5 tvltypes.h5 \
tvlstr.h5 flush.h5 enum1.h5 titerate.h5 ttsafe.h5 tarray1.h5 \
tgenprop.h5 tmisc.h5 tmisc2a.h5 tmisc2b.h5 tmisc3.h5 tmisc4a.h5 \
tmisc4b.h5 tmisc5.h5 tmisc6.h5 set_extent_read.h5 \
tmisc4b.h5 tmisc5.h5 tmisc6.h5 tmisc7.h5 set_extent_read.h5 \
set_extent_create.h5
CLEAN=$(TIMINGS)

View File

@ -112,6 +112,13 @@ typedef struct
#define MISC6_DSETNAME2 "dset2"
#define MISC6_NUMATTR 16
/* Definitions for misc. test #7 */
#define MISC7_FILE "tmisc7.h5"
#define MISC7_DSETNAME1 "Dataset1"
#define MISC7_DSETNAME2 "Dataset2"
#define MISC7_TYPENAME1 "Datatype1"
#define MISC7_TYPENAME2 "Datatype2"
/****************************************************************
**
** test_misc1(): test unlinking a dataset from a group and immediately
@ -903,6 +910,106 @@ test_misc6(void)
} /* end test_misc6() */
/****************************************************************
**
** test_misc7(): Test that datatypes are sensible to store on
** disk. (i.e. not partially initialized)
**
****************************************************************/
static void
test_misc7(void)
{
hid_t fid, did, tid, sid;
int enum_value=1;
herr_t ret;
/* Output message about test being performed */
MESSAGE(5, ("Testing sensible datatype on disk code \n"));
/* Attempt to commit a non-sensible datatype */
/* Create the file */
fid=H5Fcreate(MISC7_FILE,H5F_ACC_TRUNC,H5P_DEFAULT,H5P_DEFAULT);
CHECK(fid,FAIL,"H5Fcreate");
/* Create the dataspace */
sid=H5Screate(H5S_SCALAR);
CHECK(sid,FAIL,"H5Screate");
/* Create the compound datatype to commit*/
tid=H5Tcreate(H5T_COMPOUND,32);
CHECK(tid,FAIL,"H5Tcreate");
/* Attempt to commit an empty compound datatype */
ret=H5Tcommit(fid,MISC7_TYPENAME1,tid);
VERIFY(ret,FAIL,"H5Tcommit");
/* Attempt to use empty compound datatype to create dataset */
did=H5Dcreate(fid,MISC7_DSETNAME1,tid,sid,H5P_DEFAULT);
VERIFY(ret,FAIL,"H5Dcreate");
/* Add a field to the compound datatype */
ret=H5Tinsert(tid,"a",0,H5T_NATIVE_INT);
CHECK(ret,FAIL,"H5Tinsert");
/* Attempt to commit the compound datatype now - should work */
ret=H5Tcommit(fid,MISC7_TYPENAME1,tid);
CHECK(ret,FAIL,"H5Tcommit");
/* Attempt to use compound datatype to create dataset now - should work */
did=H5Dcreate(fid,MISC7_DSETNAME1,tid,sid,H5P_DEFAULT);
CHECK(did,FAIL,"H5Dcreate");
/* Close dataset */
ret=H5Dclose(did);
CHECK(ret, FAIL, "H5Dclose");
/* Close compound datatype */
ret=H5Tclose(tid);
CHECK(ret, FAIL, "H5Tclose");
/* Create the enum datatype to commit*/
tid=H5Tenum_create(H5T_NATIVE_INT);
CHECK(tid,FAIL,"H5Tenum_create");
/* Attempt to commit an empty enum datatype */
ret=H5Tcommit(fid,MISC7_TYPENAME2,tid);
VERIFY(ret,FAIL,"H5Tcommit");
/* Attempt to use empty enum datatype to create dataset */
did=H5Dcreate(fid,MISC7_DSETNAME2,tid,sid,H5P_DEFAULT);
VERIFY(did,FAIL,"H5Dcreate");
/* Add a member to the enum datatype */
ret=H5Tenum_insert(tid,"a",&enum_value);
CHECK(ret,FAIL,"H5Tenum_insert");
/* Attempt to commit the enum datatype now - should work */
ret=H5Tcommit(fid,MISC7_TYPENAME2,tid);
CHECK(ret,FAIL,"H5Tcommit");
/* Attempt to use enum datatype to create dataset now - should work */
did=H5Dcreate(fid,MISC7_DSETNAME2,tid,sid,H5P_DEFAULT);
CHECK(did,FAIL,"H5Dcreate");
/* Close dataset */
ret=H5Dclose(did);
CHECK(ret, FAIL, "H5Dclose");
/* Close enum datatype */
ret=H5Tclose(tid);
CHECK(ret, FAIL, "H5Tclose");
/* Close dataspace */
ret=H5Sclose(sid);
CHECK(ret, FAIL, "H5Sclose");
/* Close file */
ret=H5Fclose(fid);
CHECK(ret, FAIL, "H5Fclose");
} /* end test_misc7() */
/****************************************************************
**
** test_misc(): Main misc. test routine.
@ -920,6 +1027,7 @@ test_misc(void)
test_misc4(); /* Test retrieving the fileno for various objects with H5Gget_objinfo() */
test_misc5(); /* Test several level deep nested compound & VL datatypes */
test_misc6(); /* Test object header continuation code */
test_misc7(); /* Test for sensible datatypes stored on disk */
} /* test_misc() */
@ -949,4 +1057,5 @@ cleanup_misc(void)
remove(MISC4_FILE_2);
remove(MISC5_FILE);
remove(MISC6_FILE);
remove(MISC7_FILE);
}