Fixes buffer underflow (#6143)

Fixes security issue by treating non-NULL buffer with size 0 as length-only query in get_name API functions.

Behavior:
Modify get_name API functions to treat (buffer != NULL, size == 0) as length-only queries, preventing undefined behavior.
Fix applied to H5Aget_name, H5Aget_name_by_idx, H5Fget_name, H5Gget_objname_by_idx, H5Iget_name, H5Lget_name_by_idx, H5Rget_file_name, H5Rget_obj_name, H5Rget_attr_name, and 8 other functions.
Tests:
Update test/links.c, test/tattr.c, test/tfile.c, test/titerate.c, and test/trefer.c to verify new behavior with non-null buffer and size 0.
Documentation:
Update comments in H5A.c, H5F.c, H5Gdeprec.c, H5I.c, H5L.c, H5R.c, and H5Rdeprec.c to reflect new behavior.t]@users.noreply.github.com>
This commit is contained in:
bmribler
2026-01-26 18:07:23 -06:00
committed by GitHub
parent 8ebdb2f6d4
commit 9268b803b7
13 changed files with 271 additions and 49 deletions
+5
View File
@@ -112,6 +112,11 @@ We would like to thank the many HDF5 community members who contributed to this r
## Library
### Fixes potential security issues
The get_name API functions allow passing NULL when querying the object name length. However, passing a non-NULL buffer with size == 0 will result in security vulnerability of invalid write. That was because the library wrote a null terminator to the buffer regardless of what the size of the buffer was as long as the buffer was non-NULL.
These functions are now fixed to treat (buffer != NULL, size == 0) as a length-only query to eliminate Valgrind error of invalid write.
### Fixed a performance issue with chunked dataset I/O
When dataset chunks are unable to be placed in the dataset chunk cache (for example, if a chunk
+10 -1
View File
@@ -1221,7 +1221,8 @@ done:
Up to 'buf_size'-1 characters are stored in 'buf' followed by a '\0' string
terminator. If the name of the attribute is longer than 'buf_size'-1,
the string terminator is stored in the last position of the buffer to
properly terminate the string.
properly terminate the string. If 'buf' is non-NULL but 'buf_size' is 0,
treat the call as length being queried.
--------------------------------------------------------------------------*/
ssize_t
H5Aget_name(hid_t attr_id, size_t buf_size, char *buf /*out*/)
@@ -1233,6 +1234,10 @@ H5Aget_name(hid_t attr_id, size_t buf_size, char *buf /*out*/)
FUNC_ENTER_API((-1))
/* If buffer size is zero, treat as length query and do not write, even a '\0' */
if (buf && buf_size == 0)
buf = NULL;
/* check arguments */
if (NULL == (vol_obj = H5VL_vol_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not an attribute");
@@ -1295,6 +1300,10 @@ H5Aget_name_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type, H5_i
FUNC_ENTER_API(FAIL)
/* If buffer size is zero, treat as length query and do not write, even a '\0' */
if (name && size == 0)
name = NULL;
/* Check args */
if (H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute");
+22 -10
View File
@@ -1972,19 +1972,27 @@ done:
* Function: H5Fget_name
*
* Purpose: Gets the name of the file to which object OBJ_ID belongs.
* If 'name' is non-NULL then write up to 'size' bytes into that
* buffer and always return the length of the entry name.
* Otherwise `size' is ignored and the function does not store
* the name, just returning the number of characters required to
* store the name. If an error occurs then the buffer pointed to
* by 'name' (NULL or non-NULL) is unchanged and the function
* returns a negative value.
*
* Description:
* When 'name' is non-NULL:
* - if 'size' > 0: writes up to 'size' bytes into the buffer
* (including null terminator) and returns the actual length
* of the name (excluding null terminator).
* - if 'size' == 0: treats the call as length query, does not
* write anything to the buffer (not even a null terminator), and
* returns the actual length of the name (excluding null terminator).
*
* When 'name' is NULL: does not write anything regardless of 'size'
* and returns the actual length of the name (excluding null terminator).
*
* On error, the buffer is unchanged and the function returns
* a negative value.
*
* Return: Success: Length of the name (excluding null terminator)
* Failure: Negative
*
* Note: This routine returns the name that was used to open the file,
* not the actual name after resolving symlinks, etc.
*
* Return: Success: The length of the file name
* Failure: -1
*-------------------------------------------------------------------------
*/
ssize_t
@@ -1998,6 +2006,10 @@ H5Fget_name(hid_t obj_id, char *name /*out*/, size_t size)
FUNC_ENTER_API((-1))
/* If name size is zero, treat as length query and do not write, even a '\0' */
if (name && size == 0)
name = NULL;
/* Check the type */
type = H5I_get_type(obj_id);
if (H5I_FILE != type && H5I_GROUP != type && H5I_DATATYPE != type && H5I_DATASET != type &&
+22 -12
View File
@@ -1145,20 +1145,26 @@ done:
* Function: H5Gget_objname_by_idx
*
* Purpose: Returns the name of objects in the group by giving index.
* If `name' is non-NULL then write up to `size' bytes into that
* buffer and always return the length of the entry name.
* Otherwise `size' is ignored and the function does not store the name,
* just returning the number of characters required to store the name.
* If an error occurs then the buffer pointed to by `name' (NULL or non-NULL)
* is unchanged and the function returns a negative value.
* If a zero is returned for the name's length, then there is no name
* associated with the ID.
*
* Description:
* When 'name' is non-NULL:
* - if 'size' > 0: writes up to 'size' bytes into the buffer
* (including null terminator) and returns the actual length
* of the name (excluding null terminator).
* - if 'size' == 0: treats the call as length query, does not
* write anything to the buffer (not even a null terminator), and
* returns the actual length of the name (excluding null terminator).
*
* When 'name' is NULL: does not write anything regardless of 'size'
* and returns the actual length of the name (excluding null terminator).
*
* On error, the buffer is unchanged and the function returns
* a negative value.
*
* Return: Success: Length of the name (excluding null terminator)
* Failure: Negative
*
* Note: Deprecated in favor of H5Lget_name_by_idx
*
* Return: Success: Non-negative
* Failure: Negative
*
*-------------------------------------------------------------------------
*/
ssize_t
@@ -1172,6 +1178,10 @@ H5Gget_objname_by_idx(hid_t loc_id, hsize_t idx, char *name /*out*/, size_t size
FUNC_ENTER_API(-1)
/* If name size is zero, treat as length query and do not write, even a '\0' */
if (name && size == 0)
name = NULL;
/* Set up collective metadata if appropriate */
if (H5CX_set_loc(loc_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTSET, (-1), "can't set collective metadata read info");
+22 -10
View File
@@ -824,19 +824,27 @@ done:
*
* Purpose: Gets a name of an object from its ID.
*
* Return: Success: The length of the name
* Description:
* When 'name' is non-NULL:
* - if 'size' > 0: writes up to 'size' bytes into the buffer
* (including null terminator) and returns the actual length
* of the name (excluding null terminator).
* - if 'size' == 0: treats the call as length query, does not
* write anything to the buffer (not even a null terminator), and
* returns the actual length of the name (excluding null terminator).
*
* Failure: -1
* When 'name' is NULL: does not write anything regardless of 'size'
* and returns the actual length of the name (excluding null terminator).
*
* On error, the buffer is unchanged and the function returns
* a negative value.
*
* Return: Success: The length of the name (excluding null terminator)
* Failure: Negative
*
* Notes:
* If 'name' is non-NULL then write up to 'size' bytes into that
* buffer and always return the length of the entry name.
* Otherwise 'size' is ignored and the function does not store the name,
* just returning the number of characters required to store the name.
* If an error occurs then the buffer pointed to by 'name' (NULL or non-NULL)
* is unchanged and the function returns a negative value.
* If a zero is returned for the name's length, then there is no name
* associated with the ID.
* If a zero is returned for the name's length, then there is no name
* associated with the ID.
*
*-------------------------------------------------------------------------
*/
@@ -851,6 +859,10 @@ H5Iget_name(hid_t id, char *name /*out*/, size_t size)
FUNC_ENTER_API((-1))
/* If name size is zero, treat as length query and do not write, even a '\0' */
if (name && size == 0)
name = NULL;
/* Get the object pointer */
if (NULL == (vol_obj = H5VL_vol_object(id)))
HGOTO_ERROR(H5E_ID, H5E_BADTYPE, (-1), "invalid identifier");
+4
View File
@@ -1478,6 +1478,10 @@ H5Lget_name_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type, H5
FUNC_ENTER_API((-1))
/* If name size is zero, treat as length query and do not write, even a '\0' */
if (name && size == 0)
name = NULL;
/* Check arguments */
if (!group_name || !*group_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "no name specified");
+58 -1
View File
@@ -1013,8 +1013,23 @@ done:
* Purpose: Given a reference to some object, determine a file name of the
* object located into.
*
* Return: Non-negative length of the path on success / -1 on failure
* Description:
* When 'buf' is non-NULL:
* - if 'size' > 0: writes up to 'size' bytes into the buffer
* (including null terminator) and returns the actual length
* of the name (excluding null terminator).
* - if 'size' == 0: treats the call as length query, does not
* write anything to the buffer (not even a null terminator), and
* returns the actual length of the name (excluding null terminator).
*
* When 'buf' is NULL: does not write anything regardless of 'size'
* and returns the actual length of the name (excluding null terminator).
*
* On error, the buffer is unchanged and the function returns
* a negative value.
*
* Return: Success: The length of the name (excluding null terminator)
* Failure: Negative
*-------------------------------------------------------------------------
*/
ssize_t
@@ -1032,6 +1047,10 @@ H5Rget_file_name(const H5R_ref_t *ref_ptr, char *buf /*out*/, size_t size)
H5R__get_type((const H5R_ref_priv_t *)ref_ptr) >= H5R_MAXTYPE)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid reference type");
/* If buffer size is zero, treat as length query and do not write, even a '\0' */
if (buf && size == 0)
buf = NULL;
/* Get name */
if (H5I_INVALID_HID == (loc_id = H5R__get_loc_id((const H5R_ref_priv_t *)ref_ptr))) {
/* Un-opened external references do not have loc_id set but hold a
@@ -1073,6 +1092,21 @@ done:
* Purpose: Given a reference to some object, determine a path to the
* object referenced in the file.
*
* Description:
* When 'buf' is non-NULL:
* - if 'size' > 0: writes up to 'size' bytes into the buffer
* (including null terminator) and returns the actual length
* of the name (excluding null terminator).
* - if 'size' == 0: treats the call as length query, does not
* write anything to the buffer (not even a null terminator), and
* returns the actual length of the name (excluding null terminator).
*
* When 'buf' is NULL: does not write anything regardless of 'size'
* and returns the actual length of the name (excluding null terminator).
*
* On error, the buffer is unchanged and the function returns
* a negative value.
*
* Return: Non-negative length of the path on success / -1 on failure
*
*-------------------------------------------------------------------------
@@ -1099,6 +1133,10 @@ H5Rget_obj_name(H5R_ref_t *ref_ptr, hid_t rapl_id, char *buf /*out*/, size_t siz
if (rapl_id < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a property list");
/* If buffer size is zero, treat as length query and do not write, even a '\0' */
if (buf && size == 0)
buf = NULL;
/* Retrieve loc_id from reference */
if (H5I_INVALID_HID == (loc_id = H5R__get_loc_id((const H5R_ref_priv_t *)ref_ptr)))
/* Attempt to re-open file and pass rapl_id as a fapl_id */
@@ -1140,6 +1178,21 @@ done:
*
* Purpose: Given a reference to some attribute, determine its name.
*
* Description:
* When 'buf' is non-NULL:
* - if 'size' > 0: writes up to 'size' bytes into the buffer
* (including null terminator) and returns the actual length
* of the name (excluding null terminator).
* - if 'size' == 0: treats the call as length query, does not
* write anything to the buffer (not even a null terminator), and
* returns the actual length of the name (excluding null terminator).
*
* When 'buf' is NULL: does not write anything regardless of 'size'
* and returns the actual length of the name (excluding null terminator).
*
* On error, the buffer is unchanged and the function returns
* a negative value.
*
* Return: Non-negative length of the path on success / -1 on failure
*
*-------------------------------------------------------------------------
@@ -1157,6 +1210,10 @@ H5Rget_attr_name(const H5R_ref_t *ref_ptr, char *buf /*out*/, size_t size)
if (H5R__get_type((const H5R_ref_priv_t *)ref_ptr) != H5R_ATTR)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid reference type");
/* If buffer size is zero, treat as length query and do not write, even a '\0' */
if (buf && size == 0)
buf = NULL;
/* Get attribute name */
if ((ret_value = H5R__get_attr_name((const H5R_ref_priv_t *)ref_ptr, buf, size)) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, (-1), "unable to determine attribute name");
+20 -2
View File
@@ -741,9 +741,23 @@ done:
* Purpose: Given a reference to some object, determine a path to the
* object referenced in the file.
*
* Return: Success: Non-negative length of the path
* Failure: -1
* Description:
* When 'name' is non-NULL:
* - if 'size' > 0: writes up to 'size' bytes into the buffer
* (including null terminator) and returns the actual length
* of the name (excluding null terminator).
* - if 'size' == 0: treats the call as length query, does not
* write anything to the buffer (not even a null terminator), and
* returns the actual length of the name (excluding null terminator).
*
* When 'name' is NULL: does not write anything regardless of 'size'
* and returns the actual length of the path (excluding null terminator).
*
* On error, the buffer is unchanged and the function returns
* a negative value.
*
* Return: Success: The length of the path (excluding null terminator)
* Failure: Negative
*-------------------------------------------------------------------------
*/
ssize_t
@@ -766,6 +780,10 @@ H5Rget_name(hid_t id, H5R_type_t ref_type, const void *ref, char *name /*out*/,
if (ref_type != H5R_OBJECT1 && ref_type != H5R_DATASET_REGION1)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "invalid reference type");
/* If buffer size is zero, treat as length query and do not write, even a '\0' */
if (name && size == 0)
name = NULL;
/* Get the VOL object */
if (NULL == (vol_obj = H5VL_vol_object(id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "invalid file identifier");
+19 -2
View File
@@ -154,6 +154,9 @@ static const char *FILENAME[] = {"links0",
#define TIMESTAMP_GROUP_1 "timestamp1"
#define TIMESTAMP_GROUP_2 "timestamp2"
/* Used by test_deprec() */
#define NON_NULL_BUF "NON_NULL_BUF"
/* Link iteration struct */
typedef struct {
H5_iter_order_t order; /* Direction of iteration */
@@ -1990,8 +1993,11 @@ test_deprec(hid_t fapl, bool new_format)
hsize_t num_objs; /* Number of objects in a group */
char filename[1024];
char tmpstr[1024];
int len = 0; /* Length of comment */
herr_t status; /* Generic return value */
int len = 0; /* Length of comment */
char non_null_buf[80]; /* Buffer to test non-null buffer calls */
char *buf_ptr; /* To pass mid-string */
ssize_t name_len; /* Length of name */
herr_t status; /* Generic return value */
if (new_format)
TESTING("backwards compatibility (w/new group format)");
@@ -2052,6 +2058,17 @@ test_deprec(hid_t fapl, bool new_format)
if (len >= 0)
TEST_ERROR;
/* Verify that passing a non-null buffer with size 0 still returns the correct name
size and the buffer is not modified */
strcpy(non_null_buf, NON_NULL_BUF);
buf_ptr = &non_null_buf[4];
if ((name_len = H5Gget_objname_by_idx(group1_id, (hsize_t)0, buf_ptr, 0)) < 0)
FAIL_STACK_ERROR;
if ((size_t)name_len != strlen(tmpstr))
TEST_ERROR;
if ((strcmp(non_null_buf, NON_NULL_BUF) != 0))
TEST_ERROR;
/* Test getting the type for objects */
if ((obj_type = H5Gget_objtype_by_idx(group1_id, (hsize_t)0)) < 0)
FAIL_STACK_ERROR;
+23 -2
View File
@@ -148,6 +148,7 @@ static float attr_data5 = -5.123F; /* Test data for 5th attribute */
/* Used by test_attr_info_null_info_pointer() */
#define GET_INFO_NULL_POINTER_ATTR_NAME "NullInfoPointerAttr"
#define NON_NULL_BUF "NON_NULL_BUF"
/* Used by test_attr_rename_invalid_name() */
#define INVALID_RENAME_TEST_ATTR_NAME "InvalidRenameTestAttr"
@@ -6526,10 +6527,13 @@ test_attr_rename_invalid_name(hid_t fcpl, hid_t fapl)
/***************************************************************
**
** test_attr_get_name_invalid_buf(): A test to ensure that
** passing a NULL buffer to H5Aget_name(_by_idx) when
** test_attr_get_name_invalid_buf(): A test to ensure that:
** - passing a NULL buffer to H5Aget_name(_by_idx) when
** the 'size' parameter is non-zero doesn't cause bad
** behavior.
** - passing a non-NULL buffer to H5Aget_name(_by_idx)
** when the 'size' parameter is zero treats as a length
** query call.
**
****************************************************************/
static void
@@ -6539,6 +6543,9 @@ test_attr_get_name_invalid_buf(hid_t fcpl, hid_t fapl)
hid_t fid;
hid_t attr;
hid_t sid;
char non_null_buf[80]; /* Buffer to test non-null buffer calls */
char *buf_ptr; /* To pass mid-string */
ssize_t namelen; /* Length of attribute name */
/* Create dataspace for attribute */
sid = H5Screate(H5S_SCALAR);
@@ -6569,6 +6576,20 @@ test_attr_get_name_invalid_buf(hid_t fcpl, hid_t fapl)
VERIFY(err_ret, FAIL, "H5Aget_name_by_idx");
/* Verify that passing a non-null buffer with size 0 still returns the correct name
size and the buffer is not modified */
strcpy(non_null_buf, NON_NULL_BUF);
buf_ptr = &non_null_buf[4];
namelen = H5Aget_name(attr, (size_t)0, buf_ptr);
CHECK(namelen, FAIL, "H5Aget_name");
VERIFY(namelen, (ssize_t)strlen(GET_NAME_INVALID_BUF_TEST_ATTR_NAME), "H5Aget_name");
VERIFY(strcmp(non_null_buf, NON_NULL_BUF), 0, "H5Aget_name");
namelen = H5Aget_name_by_idx(fid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, 0, buf_ptr, 0, H5P_DEFAULT);
CHECK(namelen, FAIL, "H5Aget_name_by_idx");
VERIFY(namelen, (ssize_t)strlen(GET_NAME_INVALID_BUF_TEST_ATTR_NAME), "H5Aget_name_by_idx");
VERIFY(strcmp(non_null_buf, NON_NULL_BUF), 0, "H5Aget_name_by_idx");
/* Close dataspace */
err_ret = H5Sclose(sid);
CHECK(err_ret, FAIL, "H5Sclose");
+15 -1
View File
@@ -147,6 +147,9 @@
/* Declaration for test_incr_filesize() */
#define FILE_INCR_FILESIZE "tfile_incr_filesize"
/* Used by test_file_getname() */
#define NON_NULL_BUF "NON_NULL_BUF"
/* Files created under 1.6 branch and 1.8 branch--used in test_filespace_compatible() */
static const char *OLD_FILENAME[] = {
"filespace_1_6.h5", /* 1.6 HDF5 file */
@@ -2411,7 +2414,9 @@ test_file_getname(void)
hsize_t dims[TESTA_RANK] = {TESTA_NX, TESTA_NY};
char name[TESTA_NAME_BUF_SIZE];
ssize_t name_len;
herr_t ret; /* Generic return value */
char non_null_buf[80]; /* Buffer to test non-null buffer calls */
char *buf_ptr; /* To pass mid-string */
herr_t ret; /* Generic return value */
/* Output message about test being performed */
MESSAGE(5, ("Testing H5Fget_name() functionality\n"));
@@ -2426,6 +2431,15 @@ test_file_getname(void)
VERIFY_STR(name, FILE1, "H5Fget_name");
VERIFY(name_len, strlen(FILE1), "H5Fget_name");
/* Verify that passing a non-null buffer with size 0 still returns the correct name
size and the buffer is not modified */
strcpy(non_null_buf, NON_NULL_BUF);
buf_ptr = &non_null_buf[4];
name_len = H5Fget_name(file_id, buf_ptr, 0);
CHECK(name_len, FAIL, "H5Fget_name");
VERIFY(name_len, strlen(FILE1), "H5Fget_name");
VERIFY(strcmp(non_null_buf, NON_NULL_BUF), 0, "H5Fget_name");
/* Create a group in the root group */
group_id = H5Gcreate2(file_id, TESTA_GROUPNAME, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
CHECK(group_id, FAIL, "H5Gcreate2");
+15 -1
View File
@@ -39,6 +39,9 @@
#define SPACE1_RANK 1
#define SPACE1_DIM1 4
/* Used by test_reference_obj() and test_reference_attr() */
#define NON_NULL_BUF "NON_NULL_BUF"
typedef enum { RET_ZERO, RET_TWO, RET_CHANGE, RET_CHANGE2 } iter_enum;
/* Custom group iteration callback data */
@@ -894,7 +897,9 @@ test_grp_memb_funcs(hid_t fapl)
VERIFY(ginfo.nlinks, (NDATASETS + 2), "H5Gget_info");
for (i = 0; i < (int)ginfo.nlinks; i++) {
H5O_info2_t oinfo; /* Object info */
H5O_info2_t oinfo; /* Object info */
char non_null_buf[80]; /* Buffer to test non-null buffer calls */
char *buf_ptr; /* To pass mid-string */
/* Test with NULL for name, to query length */
name_len = H5Lget_name_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, NULL,
@@ -908,6 +913,15 @@ test_grp_memb_funcs(hid_t fapl)
/* Double-check that the length is the same */
VERIFY(ret, name_len, "H5Lget_name_by_idx");
/* Test with non-null buffer for name and 0 for size */
strcpy(non_null_buf, NON_NULL_BUF);
buf_ptr = &non_null_buf[4];
ret = (herr_t)H5Lget_name_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, buf_ptr, 0,
H5P_DEFAULT);
CHECK(ret, FAIL, "H5Lget_name_by_idx");
VERIFY(ret, name_len, "H5Lget_name_by_idx");
VERIFY(strcmp(non_null_buf, NON_NULL_BUF), 0, "H5Lget_name_by_idx");
/* Keep a copy of the dataset names around for later */
obj_names[i] = strdup(dataset_name);
CHECK_PTR(obj_names[i], "strdup");
+36 -7
View File
@@ -88,6 +88,9 @@ typedef struct s2_t {
#define MAX_ITER_WRITE MAX_ITER_CREATE
#define MAX_ITER_READ MAX_ITER_CREATE
/* Used by test_reference_obj() and test_reference_attr() */
#define NON_NULL_BUF "NON_NULL_BUF"
/****************************************************************
**
** test_reference_params(): Test basic H5R (reference) parameters
@@ -458,11 +461,13 @@ test_reference_obj(void)
*rbuf; /* buffer read from disk */
H5R_ref_t *wbuf_cp; /* copy buffer */
unsigned *ibuf, *obuf;
unsigned i, j; /* Counters */
ssize_t namelen; /* String buffer size return value */
char *namebuf; /* Buffer for attribute's or dataset's name */
H5O_type_t obj_type; /* Object type */
herr_t ret; /* Generic return value */
unsigned i, j; /* Counters */
ssize_t namelen; /* String buffer size return value */
char *namebuf; /* Buffer for attribute's or dataset's name */
H5O_type_t obj_type; /* Object type */
char non_null_buf[80]; /* Buffer to test non-null buffer calls */
char *buf_ptr; /* To pass mid-string */
herr_t ret; /* Generic return value */
/* Output message about test being performed */
MESSAGE(5, ("Testing Object Reference Functions\n"));
@@ -626,17 +631,31 @@ test_reference_obj(void)
CHECK(namelen, FAIL, "H5Rget_file_name");
VERIFY(namelen, strlen(FILE_REF_OBJ), "H5Rget_file_name");
/* Test passing in non-null buffer with buffer size is zero */
strcpy(non_null_buf, NON_NULL_BUF);
buf_ptr = &non_null_buf[4];
namelen = H5Rget_file_name(&rbuf[0], buf_ptr, 0);
CHECK(namelen, FAIL, "H5Rget_file_name");
VERIFY(namelen, strlen(FILE_REF_OBJ), "H5Rget_file_name");
VERIFY(strcmp(non_null_buf, NON_NULL_BUF), 0, "H5Rget_file_name");
/* Get the file name for the reference */
namebuf = (char *)malloc((size_t)namelen + 1);
namelen = H5Rget_file_name(&rbuf[0], namebuf, (size_t)namelen + 1);
CHECK(namelen, FAIL, "H5Rget_file_name");
VERIFY(strcmp(namebuf, FILE_REF_OBJ), 0, "namebuf vs FILE_REF_OBJ");
VERIFY(namelen, strlen(FILE_REF_OBJ), "H5Rget_file_name");
free(namebuf);
/* Testing Dataset1 */
/* Test passing in non-null buffer with buffer size is zero */
buf_ptr = &non_null_buf[8];
namelen = H5Rget_obj_name(&rbuf[0], H5P_DEFAULT, buf_ptr, 0);
CHECK(namelen, FAIL, "H5Rget_obj_name");
VERIFY(namelen, strlen(DS1_REF_OBJ), "H5Rget_obj_name");
VERIFY(strcmp(non_null_buf, NON_NULL_BUF), 0, "H5Rget_obj_name");
/* Getting the name of the referenced object and verify it */
namelen = H5Rget_obj_name(&rbuf[0], H5P_DEFAULT, NULL, 0);
CHECK(namelen, FAIL, "H5Rget_obj_name");
@@ -2479,6 +2498,8 @@ test_reference_attr(void)
char *attr_name = NULL; /* name of attribute, from H5A */
ssize_t attr_name_size; /* size of attribute name */
H5O_type_t obj_type; /* Object type */
char non_null_buf[80]; /* Buffer to test non-null buffer calls */
char *buf_ptr; /* To pass mid-string */
herr_t ret; /* Generic return value */
/* Output message about test being performed */
@@ -2649,10 +2670,18 @@ test_reference_attr(void)
/* Testing "Attr1" */
/* Test passing in non-null buffer with buffer size is zero */
strcpy(non_null_buf, NON_NULL_BUF);
buf_ptr = &non_null_buf[4];
namelen = H5Rget_attr_name(&ref_rbuf[0], buf_ptr, 0);
CHECK(namelen, FAIL, "H5Rget_attr_name");
VERIFY(namelen, strlen(ATTR1_REF_OBJ), "H5Rget_attr_name");
VERIFY(strcmp(non_null_buf, NON_NULL_BUF), 0, "H5Rget_attr_name");
/* Getting the name of the referenced attribute and verify it */
namelen = H5Rget_attr_name(&ref_rbuf[0], NULL, 0);
CHECK(namelen, FAIL, "H5Rget_attr_name");
VERIFY(namelen, strlen(ATTR1_REF_OBJ), "H5Rget_obj_name");
VERIFY(namelen, strlen(ATTR1_REF_OBJ), "H5Rget_attr_name");
namebuf = (char *)malloc((size_t)namelen + 1);
namelen = H5Rget_attr_name(&ref_rbuf[0], namebuf, (size_t)namelen + 1);