summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/h5_elink_unix2win.c2
-rw-r--r--src/H5L.c19
-rw-r--r--src/H5Lexternal.c31
-rw-r--r--src/H5Lpublic.h4
-rw-r--r--test/links.c17
-rw-r--r--tools/h5dump/h5dump.c4
-rw-r--r--tools/h5ls/h5ls.c2
-rw-r--r--tools/lib/h5trav.c2
8 files changed, 56 insertions, 25 deletions
diff --git a/examples/h5_elink_unix2win.c b/examples/h5_elink_unix2win.c
index b354661..7266347 100644
--- a/examples/h5_elink_unix2win.c
+++ b/examples/h5_elink_unix2win.c
@@ -54,7 +54,7 @@ static hid_t elink_unix2win_trav(const char *link_name, hid_t cur_group, void *
printf("Converting Unix path to Windows path.\n");
- if(H5Lunpack_elink_val(udata, &file_name, &obj_name) < 0)
+ if(H5Lunpack_elink_val(udata, udata_size, &file_name, &obj_name) < 0)
goto error;
fname_len = strlen(file_name);
diff --git a/src/H5L.c b/src/H5L.c
index 3cc46c7..24d5211 100644
--- a/src/H5L.c
+++ b/src/H5L.c
@@ -62,7 +62,7 @@ typedef struct {
/* User data for path traversal routine for getting soft link value */
typedef struct {
size_t size; /* Size of user buffer */
- char *buf; /* User buffer */
+ void *buf; /* User buffer */
} H5L_trav_ud5_t;
/* User data for path traversal routine for removing link (i.e. unlink) */
@@ -103,7 +103,7 @@ static herr_t H5L_linkval_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
H5G_own_loc_t *own_loc/*out*/);
static herr_t H5L_linkval(H5G_loc_t *loc, const char *name, size_t size,
- char *buf/*out*/, hid_t lapl_id, hid_t dxpl_id);
+ void *buf/*out*/, hid_t lapl_id, hid_t dxpl_id);
static herr_t H5L_unlink_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
H5G_own_loc_t *own_loc/*out*/);
@@ -780,7 +780,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5Lget_linkval(hid_t loc_id, const char *name, size_t size, char *buf/*out*/,
+H5Lget_linkval(hid_t loc_id, const char *name, size_t size, void *buf/*out*/,
hid_t lapl_id)
{
H5G_loc_t loc;
@@ -1496,13 +1496,15 @@ H5L_linkval_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H
if(udata->size > 0 && udata->buf) {
HDstrncpy(udata->buf, lnk->u.soft.name, udata->size);
if(HDstrlen(lnk->u.soft.name) >= udata->size)
- udata->buf[udata->size - 1] = '\0';
+ ((char *) udata->buf)[udata->size - 1] = '\0';
} /* end if */
}
else if(lnk->type >= H5L_TYPE_UD_MIN)
{
- /* Get the link class for this type of link. It's okay if the class isn't registered, though--we
- * just can't give any more information about it */
+ /* Get the link class for this type of link. It's okay if the class
+ * isn't registered, though--we just can't give any more information
+ * about it
+ */
link_class = H5L_find_class(lnk->type);
if(link_class != NULL && link_class->query_func != NULL) {
@@ -1510,7 +1512,7 @@ H5L_linkval_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H
HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, "query callback returned failure")
}
else if(udata->buf && udata->size > 0)
- udata->buf[0] = '\0';
+ ((char *)udata->buf)[0] = '\0';
}
else
HGOTO_ERROR(H5E_LINK, H5E_BADTYPE, FAIL, "object is not a symbolic or user-defined link")
@@ -1544,7 +1546,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5L_linkval(H5G_loc_t *loc, const char *name, size_t size, char *buf/*out*/, hid_t lapl_id, hid_t dxpl_id)
+H5L_linkval(H5G_loc_t *loc, const char *name, size_t size, void *buf/*out*/, hid_t lapl_id, hid_t dxpl_id)
{
H5L_trav_ud5_t udata; /* User data for callback */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1919,7 +1921,6 @@ done:
udata_out.lnk->u.soft.name = H5MM_xfree(udata_out.lnk->u.soft.name);
else if(udata_out.lnk->type >= H5L_TYPE_UD_MIN && udata_out.lnk->u.ud.size > 0)
udata_out.lnk->u.ud.udata = H5MM_xfree(udata_out.lnk->u.ud.udata);
- /* JAMES: the dest_cb already frees the link name. Hmm. */
H5MM_xfree(udata_out.lnk);
}
diff --git a/src/H5Lexternal.c b/src/H5Lexternal.c
index 4ca5c83..ab2d7e6 100644
--- a/src/H5Lexternal.c
+++ b/src/H5Lexternal.c
@@ -292,7 +292,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Lunpack_elink_path
+ * Function: H5Lunpack_elink_val
*
* Purpose: Given a buffer holding the "link value" from an external link,
* gets pointers to the filename and object path within the
@@ -315,7 +315,8 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5Lunpack_elink_val(char *ext_linkval, char **filename, char **obj_path)
+H5Lunpack_elink_val(char *ext_linkval, size_t link_size, char **filename,
+ char **obj_path)
{
size_t len; /* Length of the filename in the linkval*/
herr_t ret_value=SUCCEED; /* Return value */
@@ -325,15 +326,35 @@ H5Lunpack_elink_val(char *ext_linkval, char **filename, char **obj_path)
if(ext_linkval == NULL )
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an external link linkval buffer")
+ if(link_size <= 1)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid external link buffer")
+ /* Try to do some error checking. If the last character in the linkval
+ * (the last character of obj_path) isn't NULL, then something's wrong.
+ */
+ if(ext_linkval[link_size-1] != '\0')
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "linkval buffer is not NULL-terminated")
+
+ /* We're now guaranteed that HDstrlen won't segfault, since the buffer has
+ * at least one NULL in it.
+ */
+ len = HDstrlen(ext_linkval);
+
+ /* If the first NULL we found was at the very end of the buffer, then
+ * this external link value has no object name and is invalid.
+ */
+ if(len + 1>= link_size)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "linkval buffer doesn't contain an object path")
+
+ /* If we got here then the buffer contains (at least) two strings packed
+ * in the correct way. Assume it's correct and return pointers to the
+ * filename and object path.
+ */
if(filename != NULL)
*filename = ext_linkval;
if(obj_path != NULL)
- {
- len = HDstrlen(ext_linkval);
*obj_path = ext_linkval + len + 1; /* Add one for NULL terminator */
- }
done:
FUNC_LEAVE_API(ret_value)
diff --git a/src/H5Lpublic.h b/src/H5Lpublic.h
index a351ab6..6462170 100644
--- a/src/H5Lpublic.h
+++ b/src/H5Lpublic.h
@@ -127,7 +127,7 @@ H5_DLL herr_t H5Lcreate_soft(const char *target_path, hid_t cur_loc,
const char *cur_name, hid_t lcpl_id, hid_t lapl_id);
H5_DLL herr_t H5Lunlink(hid_t loc_id, const char *name, hid_t lapl_id);
H5_DLL herr_t H5Lget_linkval(hid_t loc_id, const char *name, size_t size,
- char *buf/*out*/, hid_t lapl_id);
+ void *buf/*out*/, hid_t lapl_id);
H5_DLL herr_t H5Lget_linkinfo(hid_t loc_id, const char *name,
H5L_linkinfo_t *linkbuf /*out*/, hid_t lapl_id);
@@ -140,7 +140,7 @@ H5_DLL herr_t H5Lunregister(H5L_type_t id);
H5_DLL htri_t H5Lis_registered(H5L_type_t id);
/* External link functions */
-H5_DLL herr_t H5Lunpack_elink_val(char * ext_linkval/*in*/,
+H5_DLL herr_t H5Lunpack_elink_val(char * ext_linkval/*in*/, size_t link_size,
char ** filename/*out*/, char** obj_path /*out*/);
H5_DLL herr_t H5Lcreate_external(const char *file_name, const char *obj_name,
hid_t link_loc_id, const char *link_name, hid_t lcpl_id, hid_t lapl_id);
diff --git a/test/links.c b/test/links.c
index 4c22b6e..e8b2e36 100644
--- a/test/links.c
+++ b/test/links.c
@@ -1602,7 +1602,7 @@ external_link_root(hid_t fapl, hbool_t new_format)
goto error;
}
if(H5Lget_linkval(fid, "ext_link", sizeof(objname), objname, H5P_DEFAULT) < 0) TEST_ERROR
- if(H5Lunpack_elink_val(objname, &file, &path) < 0) TEST_ERROR
+ if(H5Lunpack_elink_val(objname, sb.linklen, &file, &path) < 0) TEST_ERROR
if(HDstrcmp(file, filename1))
{
H5_FAILED();
@@ -2628,7 +2628,7 @@ external_link_query(hid_t fapl, hbool_t new_format)
if(H5Lget_linkval(fid, "src", (size_t)NAME_BUF_SIZE, query_buf, H5P_DEFAULT) < 0) TEST_ERROR
/* Extract the file and object names from the buffer */
- if(H5Lunpack_elink_val(query_buf, &file_name, &object_name) < 0) TEST_ERROR
+ if(H5Lunpack_elink_val(query_buf, li.u.link_size, &file_name, &object_name) < 0) TEST_ERROR
/* Compare the file and object names */
if(strcmp(file_name, filename2)) TEST_ERROR
@@ -2646,11 +2646,20 @@ external_link_query(hid_t fapl, hbool_t new_format)
if(H5Fclose(fid) < 0) TEST_ERROR
/* Make sure that passing in NULLs to H5Lunpack_elink_val works */
- if(H5Lunpack_elink_val(query_buf, NULL, NULL) < 0) TEST_ERROR
+ if(H5Lunpack_elink_val(query_buf, li.u.link_size, NULL, NULL) < 0) TEST_ERROR
/* Make sure that bogus cases trigger errors in H5Lunpack_elink_val */
H5E_BEGIN_TRY {
- if(H5Lunpack_elink_val(NULL, NULL, NULL) >= 0) TEST_ERROR
+ if(H5Lunpack_elink_val(query_buf, li.u.link_size - 1, NULL, NULL) >= 0) TEST_ERROR
+ } H5E_END_TRY
+ H5E_BEGIN_TRY {
+ if(H5Lunpack_elink_val(query_buf, 0, NULL, NULL) >= 0) TEST_ERROR
+ } H5E_END_TRY
+ H5E_BEGIN_TRY {
+ if(H5Lunpack_elink_val(NULL, 0, NULL, NULL) >= 0) TEST_ERROR
+ } H5E_END_TRY
+ H5E_BEGIN_TRY {
+ if(H5Lunpack_elink_val(NULL, 1000, NULL, NULL) >= 0) TEST_ERROR
} H5E_END_TRY
PASSED();
diff --git a/tools/h5dump/h5dump.c b/tools/h5dump/h5dump.c
index 3f51f81..384b765 100644
--- a/tools/h5dump/h5dump.c
+++ b/tools/h5dump/h5dump.c
@@ -1560,7 +1560,7 @@ dump_all(hid_t group, const char *name, void * op_data)
d_status = EXIT_FAILURE;
ret = FAIL;
} else {
- if(H5Lunpack_elink_val(targbuf, &filename, &targname) < 0) {
+ if(H5Lunpack_elink_val(targbuf, statbuf.linklen, &filename, &targname) < 0) {
error_msg(progname, "unable to unpack external link value\n");
d_status = EXIT_FAILURE;
ret = FAIL;
@@ -3248,7 +3248,7 @@ handle_links(hid_t fid, char *links, void UNUSED * data)
begin_obj(dump_header_format->extlinkbegin, links,
dump_header_format->extlinkblockbegin);
if (H5Lget_linkval(fid, links, statbuf.linklen, buf, H5P_DEFAULT) >= 0) {
- if(H5Lunpack_elink_val(buf, &elink_file, &elink_path)>=0) {
+ if(H5Lunpack_elink_val(buf, statbuf.linklen, &elink_file, &elink_path)>=0) {
indentation(COL);
printf("LINKCLASS %d\n", linfo.type);
indentation(COL);
diff --git a/tools/h5ls/h5ls.c b/tools/h5ls/h5ls.c
index 04a9371..d34cae0 100644
--- a/tools/h5ls/h5ls.c
+++ b/tools/h5ls/h5ls.c
@@ -1764,7 +1764,7 @@ udlink_open(hid_t location, const char *name)
if ((buf = HDmalloc(linfo.u.link_size))==NULL) goto error;
if (H5Lget_linkval (location, name, sizeof(buf), buf, H5P_DEFAULT)<0) goto error;
- if(H5Lunpack_elink_val(buf, &filename, &path) < 0) goto error;
+ if(H5Lunpack_elink_val(buf, linfo.u.link_size, &filename, &path) < 0) goto error;
fputs("file: ", stdout);
fputs(filename, stdout);
fputs(" path: ", stdout);
diff --git a/tools/lib/h5trav.c b/tools/lib/h5trav.c
index 8a6173c..8480f57 100644
--- a/tools/lib/h5trav.c
+++ b/tools/lib/h5trav.c
@@ -521,7 +521,7 @@ static int traverse( hid_t loc_id,
targbuf = HDmalloc(statbuf.linklen);
assert(targbuf);
H5Gget_linkval(loc_id,path,statbuf.linklen,targbuf);
- H5Lunpack_elink_val(targbuf, NULL, &objname);
+ H5Lunpack_elink_val(targbuf, statbuf.linklen, NULL, &objname);
if (print)
printf(" %-10s %s -> %s %s\n", "ext link", path, targbuf, objname);
free(targbuf);