summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Fortner <nfortne2@hdfgroup.org>2008-10-07 03:47:09 (GMT)
committerNeil Fortner <nfortne2@hdfgroup.org>2008-10-07 03:47:09 (GMT)
commit7d95527f306abb71d54e19d1deb435c5038b98b4 (patch)
tree035899c1b4641a7b818ce1a86a8d498d781b3746
parent2e9986a01ec179e4254622ab2b581631374b30ad (diff)
downloadhdf5-7d95527f306abb71d54e19d1deb435c5038b98b4.zip
hdf5-7d95527f306abb71d54e19d1deb435c5038b98b4.tar.gz
hdf5-7d95527f306abb71d54e19d1deb435c5038b98b4.tar.bz2
[svn-r15796] Purpose: Close bug #1322
Description: Fixes a possible datatype id leak that could occur during compound datatype conversion, or more precisely, when unregistering those conversions. Datatype ids normally registered by the library are no longer visible to the application via H5Fget_obj_ids and H5Fget_obj_count. Tested: kagiso, linew, smirom (h5committest)
-rw-r--r--release_docs/RELEASE.txt7
-rw-r--r--src/H5Dint.c2
-rw-r--r--src/H5E.c2
-rw-r--r--src/H5F.c30
-rw-r--r--src/H5Fprivate.h4
-rw-r--r--src/H5Gname.c6
-rw-r--r--src/H5I.c11
-rw-r--r--src/H5Iprivate.h2
-rw-r--r--src/H5Oattribute.c4
-rw-r--r--src/H5Pint.c4
-rw-r--r--src/H5T.c2
-rw-r--r--src/H5Tconv.c68
-rw-r--r--test/dtypes.c180
13 files changed, 246 insertions, 76 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 473df55..c0cc931 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -93,6 +93,9 @@ New Features
the same. (PVN - 2008/08/26)
- h5ls: added capability to traverse through external links when the -r
(recursive) flag is given. (NAF - 2008/09/16)
+ - h5ls: added -E option to enable traversal of external links. h5ls will
+ not traverse external links without this flag being set.
+ (NAF - 2008/10/06)
@@ -111,6 +114,10 @@ Bug Fixes since HDF5-1.8.0 release
Library
-------
+ - Changed H5Fget_obj_count and H5Fget_obj_ids to ignore objects registered
+ by the library for internal library use. (NAF - 2008/10/06)
+ - Fixed potential memory leak during compound conversion.
+ (NAF - 2008/10/06)
- Changed the return value of H5Fget_obj_count from INT to SSIZE_T. Also
changed the return value of H5Fget_obj_ids from HERR_T to SSIZE_T and
the type of the parameter MAX_OBJS from INT to SIZE_T. (SLU - 2008/09/26)
diff --git a/src/H5Dint.c b/src/H5Dint.c
index 7a2dcc9..bab3038 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -2570,7 +2570,7 @@ H5D_flush(const H5F_t *f, hid_t dxpl_id, unsigned flags)
udata.flags = flags;
/* Iterate over all the open datasets */
- H5I_search(H5I_DATASET, H5D_flush_cb, &udata);
+ H5I_search(H5I_DATASET, H5D_flush_cb, &udata, FALSE);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5E.c b/src/H5E.c
index 2aaa342..6eb7768 100644
--- a/src/H5E.c
+++ b/src/H5E.c
@@ -501,7 +501,7 @@ H5E_unregister_class(H5E_cls_t *cls)
/* Iterate over all the messages and delete those in this error class */
/* (Ignore return value, since callback isn't designed to return a particular object) */
- (void)H5I_search(H5I_ERROR_MSG, H5E_close_msg_cb, cls);
+ (void)H5I_search(H5I_ERROR_MSG, H5E_close_msg_cb, cls, FALSE);
/* Free error class structure */
if(cls->cls_name)
diff --git a/src/H5F.c b/src/H5F.c
index 083adcc..02687eb 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -64,7 +64,7 @@ typedef struct H5F_olist_t {
} H5F_olist_t;
/* PRIVATE PROTOTYPES */
-static size_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list);
+static size_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref);
static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key);
static herr_t H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void** file_handle);
static H5F_t *H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id,
@@ -393,7 +393,7 @@ H5Fget_obj_count(hid_t file_id, unsigned types)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type")
/* H5F_get_obj_count doesn't fail */
- ret_value = H5F_get_obj_count(f, types);
+ ret_value = H5F_get_obj_count(f, types, TRUE);
done:
FUNC_LEAVE_API(ret_value)
@@ -420,14 +420,14 @@ done:
*-------------------------------------------------------------------------
*/
size_t
-H5F_get_obj_count(const H5F_t *f, unsigned types)
+H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref)
{
size_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_obj_count)
/* H5F_get_objects doesn't fail */
- ret_value=H5F_get_objects(f, types, 0, NULL);
+ ret_value=H5F_get_objects(f, types, 0, NULL, app_ref);
FUNC_LEAVE_NOAPI(ret_value)
}
@@ -467,7 +467,7 @@ H5Fget_obj_ids(hid_t file_id, unsigned types, size_t max_objs, hid_t *oid_list)
HDassert(oid_list);
/* H5F_get_objects doesn't fail */
- ret_value = H5F_get_obj_ids(f, types, max_objs, oid_list);
+ ret_value = H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE);
done:
FUNC_LEAVE_API(ret_value)
@@ -493,14 +493,14 @@ done:
*-------------------------------------------------------------------------
*/
size_t
-H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list)
+H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref)
{
size_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_obj_ids)
/* H5F_get_objects doesn't fail */
- ret_value = H5F_get_objects(f, types, max_objs, oid_list);
+ ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref);
FUNC_LEAVE_NOAPI(ret_value)
}
@@ -522,7 +522,7 @@ H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list
*---------------------------------------------------------------------------
*/
static size_t
-H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list)
+H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref)
{
size_t obj_id_count=0; /* Number of open IDs */
H5F_olist_t olist; /* Structure to hold search results */
@@ -551,35 +551,35 @@ H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_
* is found, so don't return failure in this function. */
if(types & H5F_OBJ_FILE) {
olist.obj_type = H5I_FILE;
- (void)H5I_search(H5I_FILE, H5F_get_objects_cb, &olist);
+ (void)H5I_search(H5I_FILE, H5F_get_objects_cb, &olist, app_ref);
} /* end if */
/* Search through dataset IDs to count number of datasets, and put their
* IDs on the object list */
if(types & H5F_OBJ_DATASET) {
olist.obj_type = H5I_DATASET;
- (void)H5I_search(H5I_DATASET, H5F_get_objects_cb, &olist);
+ (void)H5I_search(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref);
}
/* Search through group IDs to count number of groups, and put their
* IDs on the object list */
if(types & H5F_OBJ_GROUP) {
olist.obj_type = H5I_GROUP;
- (void)H5I_search(H5I_GROUP, H5F_get_objects_cb, &olist);
+ (void)H5I_search(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref);
}
/* Search through datatype IDs to count number of named datatypes, and put their
* IDs on the object list */
if(types & H5F_OBJ_DATATYPE) {
olist.obj_type = H5I_DATATYPE;
- (void)H5I_search(H5I_DATATYPE, H5F_get_objects_cb, &olist);
+ (void)H5I_search(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref);
}
/* Search through attribute IDs to count number of attributes, and put their
* IDs on the object list */
if(types & H5F_OBJ_ATTR) {
olist.obj_type = H5I_ATTR;
- (void)H5I_search(H5I_ATTR, H5F_get_objects_cb, &olist);
+ (void)H5I_search(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref);
}
/* Set the number of objects currently open */
@@ -1964,7 +1964,7 @@ H5F_try_close(H5F_t *f)
unsigned u; /* Local index variable */
/* Get the list of IDs of open dataset, group, & attribute objects */
- while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_ATTR, (int)(sizeof(objs)/sizeof(objs[0])), objs)) != 0) {
+ while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_ATTR, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) {
/* Try to close all the open objects in this file */
for(u = 0; u < obj_count; u++)
if(H5I_dec_ref(objs[u], FALSE) < 0)
@@ -1976,7 +1976,7 @@ H5F_try_close(H5F_t *f)
* they could be using one of the named datatypes and then the
* open named datatype ID will get closed twice)
*/
- while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATATYPE, (int)(sizeof(objs)/sizeof(objs[0])), objs)) != 0) {
+ while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATATYPE, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) {
/* Try to close all the open objects in this file */
for(u = 0; u < obj_count; u++)
if(H5I_dec_ref(objs[u], FALSE) < 0)
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index cb716fc..d975167 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -471,8 +471,8 @@ H5_DLL unsigned H5F_get_intent(const H5F_t *f);
H5_DLL char *H5F_get_extpath(const H5F_t *f);
H5_DLL herr_t H5F_get_fileno(const H5F_t *f, unsigned long *filenum);
H5_DLL hid_t H5F_get_id(H5F_t *file, hbool_t app_ref);
-H5_DLL size_t H5F_get_obj_count(const H5F_t *f, unsigned types);
-H5_DLL size_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list);
+H5_DLL size_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref);
+H5_DLL size_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref);
H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f);
H5_DLL haddr_t H5F_get_eoa(const H5F_t *f);
#ifdef H5_HAVE_PARALLEL
diff --git a/src/H5Gname.c b/src/H5Gname.c
index d745b87..0634aef 100644
--- a/src/H5Gname.c
+++ b/src/H5Gname.c
@@ -1009,15 +1009,15 @@ H5G_name_replace(const H5O_link_t *lnk, H5G_names_op_t op, H5F_t *src_file,
/* Search through group IDs */
if(search_group)
- H5I_search(H5I_GROUP, H5G_name_replace_cb, &names);
+ H5I_search(H5I_GROUP, H5G_name_replace_cb, &names, FALSE);
/* Search through dataset IDs */
if(search_dataset)
- H5I_search(H5I_DATASET, H5G_name_replace_cb, &names);
+ H5I_search(H5I_DATASET, H5G_name_replace_cb, &names, FALSE);
/* Search through datatype IDs */
if(search_datatype)
- H5I_search(H5I_DATATYPE, H5G_name_replace_cb, &names);
+ H5I_search(H5I_DATATYPE, H5G_name_replace_cb, &names, FALSE);
} /* end if */
} /* end if */
diff --git a/src/H5I.c b/src/H5I.c
index 8cc2910..40fec88 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -1877,7 +1877,7 @@ H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key)
if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
- ret_value = H5I_search(type, func, key);
+ ret_value = H5I_search(type, func, key, TRUE);
done:
FUNC_LEAVE_API(ret_value)
@@ -1905,12 +1905,15 @@ done:
* Programmer: Robb Matzke
* Friday, February 19, 1999
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * Wednesday, October 1, 2008
+ * Added app_ref parameter. When set to TRUE, the function will only
+ * operate on ids that have a nonzero application reference count.
*
*-------------------------------------------------------------------------
*/
void *
-H5I_search(H5I_type_t type, H5I_search_func_t func, void *key)
+H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref)
{
H5I_id_type_t *type_ptr; /*ptr to the type */
void *ret_value = NULL; /*return value */
@@ -1935,7 +1938,7 @@ H5I_search(H5I_type_t type, H5I_search_func_t func, void *key)
id_ptr = type_ptr->id_list[i];
while(id_ptr) {
next_id = id_ptr->next; /* Protect against ID being deleted in callback */
- if((*func)(id_ptr->obj_ptr, id_ptr->id, key))
+ if((!app_ref || id_ptr->app_count) && (*func)(id_ptr->obj_ptr, id_ptr->id, key))
HGOTO_DONE(id_ptr->obj_ptr); /*found the item*/
id_ptr = next_id;
} /* end while */
diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h
index f06bf79..0923af7 100644
--- a/src/H5Iprivate.h
+++ b/src/H5Iprivate.h
@@ -61,7 +61,7 @@ H5_DLL H5I_type_t H5I_get_type(hid_t id);
H5_DLL hid_t H5I_get_file_id(hid_t obj_id, hbool_t app_ref);
H5_DLL void *H5I_remove(hid_t id);
H5_DLL void *H5I_remove_verify(hid_t id, H5I_type_t id_type);
-H5_DLL void *H5I_search(H5I_type_t type, H5I_search_func_t func, void *key);
+H5_DLL void *H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref);
H5_DLL int H5I_get_ref(hid_t id, hbool_t app_ref);
H5_DLL int H5I_inc_ref(hid_t id, hbool_t app_ref);
H5_DLL int H5I_dec_ref(hid_t id, hbool_t app_ref);
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index 71c59f3..846d2ec 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -684,7 +684,7 @@ htri_t H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr, const char*
HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "can't get file serial number")
/* Count all opened attributes */
- if((num_open_attr = H5F_get_obj_count(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL)) < 0)
+ if((num_open_attr = H5F_get_obj_count(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, FALSE)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "can't get number of opened attributes")
/* Find out whether the attribute has been opened */
@@ -692,7 +692,7 @@ htri_t H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr, const char*
attr_id_list = (hid_t*)H5MM_malloc(num_open_attr*sizeof(hid_t));
/* Retrieve the IDs of all opened attributes */
- if(H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, num_open_attr, attr_id_list) < 0)
+ if(H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, num_open_attr, attr_id_list, FALSE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't IDs of opened attributes")
for(i=0; i<num_open_attr; i++) {
diff --git a/src/H5Pint.c b/src/H5Pint.c
index a7bad06..e522010 100644
--- a/src/H5Pint.c
+++ b/src/H5Pint.c
@@ -4348,7 +4348,7 @@ H5P_open_class_path(const char *path)
check_info.name=curr_name;
/* Find the class with this name & parent by iterating over the open classes */
- if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info)))
+ if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info, FALSE)))
HGOTO_ERROR (H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class");
/* Advance the pointer in the path to the start of the next component */
@@ -4362,7 +4362,7 @@ H5P_open_class_path(const char *path)
check_info.name = curr_name;
/* Find the class with this name & parent by iterating over the open classes */
- if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info)))
+ if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info, FALSE)))
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class")
/* Copy it */
diff --git a/src/H5T.c b/src/H5T.c
index 293a5c5..ee02016 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -1449,7 +1449,7 @@ H5T_term_interface(void)
H5T_g.nsoft = H5T_g.asoft = 0;
/* Unlock all datatypes, then free them */
- H5I_search (H5I_DATATYPE, H5T_unlock_cb, NULL);
+ H5I_search (H5I_DATATYPE, H5T_unlock_cb, NULL, FALSE);
H5I_dec_type_ref(H5I_DATATYPE);
/* Reset all the datatype IDs */
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index b02e72a..05277a8 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -884,6 +884,7 @@ typedef struct H5T_conv_struct_t {
hid_t *dst_memb_id; /*destination member type ID's */
H5T_path_t **memb_path; /*conversion path for each member */
H5T_subset_info_t subset_info; /*info related to compound subsets */
+ unsigned src_nmembs; /*needed by free function */
} H5T_conv_struct_t;
/* Conversion data for H5T_conv_enum() */
@@ -1751,6 +1752,48 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5T_conv_struct_free
+ *
+ * Purpose: Free the private data structure used by the compound
+ * conversion functions.
+ *
+ * Return: The result of H5MM_xfree(priv) (NULL)
+ *
+ * Programmer: Neil Fortner
+ * Wednesday, October 1, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5T_conv_struct_t *
+H5T_conv_struct_free(H5T_conv_struct_t *priv)
+{
+ int *src2dst = priv->src2dst;
+ hid_t *src_memb_id = priv->src_memb_id,
+ *dst_memb_id = priv->dst_memb_id;
+ unsigned i;
+ int status;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_conv_struct_free)
+
+ for (i=0; i<priv->src_nmembs; i++)
+ if (src2dst[i] >= 0) {
+ status = H5I_dec_ref(src_memb_id[i], FALSE);
+ HDassert(status >= 0);
+ status = H5I_dec_ref(dst_memb_id[src2dst[i]], FALSE);
+ HDassert(status >= 0);
+ }
+
+ H5MM_xfree(src2dst);
+ H5MM_xfree(src_memb_id);
+ H5MM_xfree(dst_memb_id);
+ H5MM_xfree(priv->memb_path);
+ FUNC_LEAVE_NOAPI(H5MM_xfree(priv));
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5T_conv_struct_init
*
* Purpose: Initialize the `priv' field of `cdata' with conversion
@@ -1824,6 +1867,7 @@ H5T_conv_struct_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id)
NULL == (priv->dst_memb_id = H5MM_malloc(dst_nmembs * sizeof(hid_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
src2dst = priv->src2dst;
+ priv->src_nmembs = src_nmembs;
/* The flag of special optimization to indicate if source members and destination
* members are a subset of each other. Initialize it to FALSE */
@@ -1885,11 +1929,7 @@ H5T_conv_struct_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id)
H5T_path_t *tpath = H5T_path_find(src->shared->u.compnd.memb[i].type, dst->shared->u.compnd.memb[src2dst[i]].type, NULL, NULL, dxpl_id, FALSE);
if(NULL == (priv->memb_path[i] = tpath)) {
- H5MM_xfree(priv->src2dst);
- H5MM_xfree(priv->src_memb_id);
- H5MM_xfree(priv->dst_memb_id);
- H5MM_xfree(priv->memb_path);
- cdata->priv = priv = H5MM_xfree (priv);
+ cdata->priv = priv = H5T_conv_struct_free(priv);
HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unable to convert member datatype")
} /* end if */
} /* end if */
@@ -2073,11 +2113,7 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
/*
* Free the private conversion data.
*/
- H5MM_xfree(priv->src2dst);
- H5MM_xfree(priv->src_memb_id);
- H5MM_xfree(priv->dst_memb_id);
- H5MM_xfree(priv->memb_path);
- cdata->priv = priv = H5MM_xfree (priv);
+ cdata->priv = priv = H5T_conv_struct_free(priv);
break;
case H5T_CONV_CONV:
@@ -2346,11 +2382,7 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
if (dst_memb->size > src_memb->size) {
offset -= src_memb->size;
if (dst_memb->size > src->shared->size-offset) {
- H5MM_xfree(priv->src2dst);
- H5MM_xfree(priv->src_memb_id);
- H5MM_xfree(priv->dst_memb_id);
- H5MM_xfree(priv->memb_path);
- cdata->priv = priv = H5MM_xfree (priv);
+ cdata->priv = priv = H5T_conv_struct_free(priv);
HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "convertion is unsupported by this function");
}
}
@@ -2363,11 +2395,7 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
* Free the private conversion data.
*/
priv = (H5T_conv_struct_t *)(cdata->priv);
- H5MM_xfree(priv->src2dst);
- H5MM_xfree(priv->src_memb_id);
- H5MM_xfree(priv->dst_memb_id);
- H5MM_xfree(priv->memb_path);
- cdata->priv = priv = H5MM_xfree (priv);
+ cdata->priv = priv = H5T_conv_struct_free(priv);
break;
case H5T_CONV_CONV:
diff --git a/test/dtypes.c b/test/dtypes.c
index 674c42f..f58dc90 100644
--- a/test/dtypes.c
+++ b/test/dtypes.c
@@ -23,6 +23,7 @@
#include <math.h>
#include <time.h>
#include "h5test.h"
+#include "H5Iprivate.h" /* For checking that datatype id's don't leak */
/* Number of times to run each test */
#define NTESTS 1
@@ -57,6 +58,27 @@
#define SET_ALIGNMENT(TYPE,VAL) \
H5T_NATIVE_##TYPE##_ALIGN_g=MAX(H5T_NATIVE_##TYPE##_ALIGN_g, VAL)
+/*
+ * Macro for checking that the correct number of datatype ids are present. Be
+ * careful as the call to H5Tunregister removes *ALL* compound conversions from
+ * the soft conversion list. One must call reset_hdf5() after this.
+ */
+#define CHECK_NMEMBS(NMEMBS,SRC_ID,DST_ID) \
+ if (H5Tunregister(H5T_PERS_SOFT, NULL, SRC_ID, DST_ID, NULL) < 0) { \
+ FAIL_STACK_ERROR \
+ goto error; \
+ } \
+ if (H5Tclose(SRC_ID) < 0 || ((SRC_ID) != (DST_ID) && H5Tclose(DST_ID) < 0)) { \
+ FAIL_STACK_ERROR \
+ goto error; \
+ } \
+ if ((NMEMBS) != H5I_nmembers(H5I_DATATYPE)) { \
+ H5_FAILED(); \
+ printf(" #dtype ids expected: %d; found: %d\n", NMEMBS, \
+ H5I_nmembers(H5I_DATATYPE)); \
+ goto error; \
+ }
+
const char *FILENAME[] = {
"dtypes1",
"dtypes2",
@@ -628,6 +650,7 @@ test_compound_1(void)
} /* end if */
if (H5Tclose (complex_id) < 0) goto error;
+
PASSED();
return 0;
@@ -669,10 +692,13 @@ test_compound_2(void)
unsigned char *buf=NULL, *orig=NULL, *bkg=NULL;
hid_t st=-1, dt=-1;
hid_t array_dt;
- int i;
+ int i, nmembs;
TESTING("compound element reordering");
+ if ((nmembs = H5I_nmembers(H5I_DATATYPE)) < 0)
+ FAIL_STACK_ERROR
+
/* Sizes should be the same, but be careful just in case */
buf = (unsigned char*)malloc(nelmts * MAX(sizeof(struct st), sizeof(struct dt)));
bkg = (unsigned char*)malloc(nelmts * sizeof(struct dt));
@@ -742,13 +768,14 @@ test_compound_2(void)
free(buf);
free(bkg);
free(orig);
- if (H5Tclose(st) < 0 || H5Tclose(dt) < 0) goto error;
+ CHECK_NMEMBS(nmembs , st, dt)
PASSED();
reset_hdf5();
return 0;
error:
+ reset_hdf5();
return 1;
}
@@ -786,10 +813,13 @@ test_compound_3(void)
unsigned char *buf=NULL, *orig=NULL, *bkg=NULL;
hid_t st=-1, dt=-1;
hid_t array_dt;
- int i;
+ int i, nmembs;
TESTING("compound subset conversions");
+ if ((nmembs = H5I_nmembers(H5I_DATATYPE)) < 0)
+ FAIL_STACK_ERROR
+
/* Initialize */
buf = (unsigned char*)malloc(nelmts * MAX(sizeof(struct st), sizeof(struct dt)));
bkg = (unsigned char*)malloc(nelmts * sizeof(struct dt));
@@ -856,13 +886,14 @@ test_compound_3(void)
free(buf);
free(bkg);
free(orig);
- if (H5Tclose(st) < 0 || H5Tclose(dt) < 0) goto error;
+ CHECK_NMEMBS(nmembs, st, dt)
PASSED();
reset_hdf5();
return 0;
error:
+ reset_hdf5();
return 1;
}
@@ -904,10 +935,13 @@ test_compound_4(void)
unsigned char *buf=NULL, *orig=NULL, *bkg=NULL;
hid_t st=-1, dt=-1;
hid_t array_dt;
- int i;
+ int i, nmembs;
TESTING("compound element shrinking & reordering");
+ if ((nmembs = H5I_nmembers(H5I_DATATYPE)) < 0)
+ FAIL_STACK_ERROR
+
/* Sizes should be the same, but be careful just in case */
buf = (unsigned char*)malloc(nelmts * MAX(sizeof(struct st), sizeof(struct dt)));
bkg = (unsigned char*)malloc(nelmts * sizeof(struct dt));
@@ -978,13 +1012,14 @@ test_compound_4(void)
free(buf);
free(bkg);
free(orig);
- if (H5Tclose(st) < 0 || H5Tclose(dt) < 0) goto error;
+ CHECK_NMEMBS(nmembs, st, dt)
PASSED();
reset_hdf5();
return 0;
error:
+ reset_hdf5();
return 1;
}
@@ -1133,10 +1168,13 @@ test_compound_6(void)
const size_t nelmts = NTESTELEM;
unsigned char *buf=NULL, *orig=NULL, *bkg=NULL;
hid_t st=-1, dt=-1;
- int i;
+ int i, nmembs;
TESTING("compound element growing");
+ if ((nmembs = H5I_nmembers(H5I_DATATYPE)) < 0)
+ FAIL_STACK_ERROR
+
/* Sizes should be the same, but be careful just in case */
buf = (unsigned char*)malloc(nelmts * MAX(sizeof(struct st), sizeof(struct dt)));
bkg = (unsigned char*)malloc(nelmts * sizeof(struct dt));
@@ -1189,16 +1227,14 @@ test_compound_6(void)
free(buf);
free(bkg);
free(orig);
- if (H5Tclose(st) < 0 || H5Tclose(dt) < 0) {
- H5_FAILED();
- goto error;
- }
+ CHECK_NMEMBS(nmembs, st, dt)
PASSED();
reset_hdf5();
return 0;
error:
+ reset_hdf5();
return 1;
}
@@ -1337,6 +1373,7 @@ test_compound_7(void)
return 0;
error:
+ reset_hdf5();
return 1;
}
@@ -1955,10 +1992,10 @@ test_compound_10(void)
if(H5Dclose(dset_id) < 0)
goto error;
- if(H5Tclose(cmpd_tid) < 0)
- goto error;
if(H5Tclose(arr_tid) < 0)
goto error;
+ if(H5Tclose(cmpd_tid) < 0)
+ goto error;
if(H5Tclose(cstr_id) < 0)
goto error;
if(H5Tclose(vlstr_id) < 0)
@@ -2400,19 +2437,19 @@ static int
test_compound_14(void)
{
typedef struct cmpd_struct_1 {
- char c1;
- char c2;
- char* str;
+ char c1;
+ char c2;
+ char* str;
} cmpd_struct_1;
typedef struct cmpd_struct_2 {
- char c1;
- char c2;
- char* str;
- long l1;
- long l2;
- long l3;
- long l4;
+ char c1;
+ char c2;
+ char* str;
+ long l1;
+ long l2;
+ long l3;
+ long l4;
} cmpd_struct_2;
cmpd_struct_1 wdata1 = {'A', 'B', "variable-length string"};
@@ -2891,7 +2928,101 @@ test_compound_15(void)
error:
return 1;
-} /* end test_compound_14() */
+} /* end test_compound_15() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_compound_16
+ *
+ * Purpose: Tests that committed types that can be registered during
+ * compound conversion are not visible to the application
+ * with H5Fget_obj_count or H5Fget_obj_ids.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Neil Fortner
+ * Friday, October 3, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_compound_16(void)
+{
+ typedef struct cmpd_struct {
+ int i1;
+ int i2;
+ } cmpd_struct;
+
+ cmpd_struct wdata1 = {1254, 5471};
+ cmpd_struct rdata;
+ int wdata2[2] = {1, 2};
+ int obj_count;
+ hid_t file;
+ hid_t cmpd_m_tid, cmpd_f_tid, int_id;
+ hid_t space_id;
+ hid_t dset_id;
+ hid_t open_dtypes[2] = {0, 0};
+ hsize_t dim1[1] = {1};
+ char filename[1024];
+
+ TESTING("visibility of internally registered type ids");
+
+ /* Create File */
+ h5_fixname(FILENAME[3], H5P_DEFAULT, filename, sizeof filename);
+ if((file=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* Copy and commit integer datatype */
+ if((int_id = H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR
+ if(H5Tcommit (file, "int", int_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR
+
+ /* Create file compound datatype */
+ if((cmpd_f_tid = H5Tcreate(H5T_COMPOUND, 2 * sizeof(int) + 2)) < 0) TEST_ERROR
+ if(H5Tinsert(cmpd_f_tid, "i1", 0, int_id) < 0) TEST_ERROR
+ if(H5Tinsert(cmpd_f_tid, "i2", sizeof(int) + 1, int_id) < 0) TEST_ERROR
+
+ /* Create memory compound datatype */
+ if((cmpd_m_tid = H5Tcreate(H5T_COMPOUND, sizeof(struct cmpd_struct))) < 0) TEST_ERROR
+ if(H5Tinsert(cmpd_m_tid, "i1", HOFFSET(struct cmpd_struct, i1), int_id) < 0) TEST_ERROR
+ if(H5Tinsert(cmpd_m_tid, "i2", HOFFSET(struct cmpd_struct, i2), int_id) < 0) TEST_ERROR
+
+ /* Create space, dataset, write wdata1 */
+ if((space_id = H5Screate_simple(1, dim1, NULL)) < 0) TEST_ERROR
+ if((dset_id = H5Dcreate2(file, "Dataset", cmpd_f_tid, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR
+ if(H5Dwrite(dset_id, cmpd_m_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, &wdata1) < 0) TEST_ERROR
+
+ /* Check behavior of H5Fget_obj_count */
+ if((obj_count = H5Fget_obj_count(file, H5F_OBJ_DATATYPE)) != 1) {
+ H5_FAILED(); AT();
+ printf(" H5Fget_obj_count returned: %d; expected: 1\n", obj_count);
+ goto error;
+ }
+
+ /* Check behavior of H5Fget_obj_ids */
+ if(H5Fget_obj_ids(file, H5F_OBJ_DATATYPE, 2, open_dtypes) < 0) TEST_ERROR
+ if(open_dtypes[1]) {
+ H5_FAILED(); AT();
+ printf(" H5Fget_obj_ids returned as second id: %d; expected: 0\n", open_dtypes[1]);
+ goto error;
+ }
+
+ /* Close */
+ if(H5Dclose(dset_id) < 0) TEST_ERROR
+ if(H5Sclose(space_id) < 0) TEST_ERROR
+ if(H5Tclose(cmpd_f_tid) < 0) TEST_ERROR
+ if(H5Tclose(cmpd_m_tid) < 0) TEST_ERROR
+ if(H5Tclose(int_id) < 0) TEST_ERROR
+ if(H5Fclose(file) < 0) TEST_ERROR
+
+ PASSED();
+ return 0;
+
+error:
+ return 1;
+} /* end test_compound_16() */
/*-------------------------------------------------------------------------
@@ -5587,6 +5718,7 @@ main(void)
nerrors += test_compound_13();
nerrors += test_compound_14();
nerrors += test_compound_15();
+ nerrors += test_compound_16();
nerrors += test_conv_enum_1();
nerrors += test_conv_enum_2();
nerrors += test_conv_bitfield();