summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST1
-rw-r--r--src/H5B.c44
-rw-r--r--src/H5Bprivate.h4
-rw-r--r--src/H5F.c3
-rw-r--r--src/H5Fdbg.c35
-rw-r--r--src/H5Fpkg.h3
-rw-r--r--src/H5Fsuper.c3
-rw-r--r--src/H5G.c18
-rw-r--r--src/H5Gobj.c40
-rw-r--r--src/H5Gpkg.h8
-rw-r--r--src/H5Gprivate.h3
-rw-r--r--src/H5Gstab.c75
-rw-r--r--src/H5Odtype.c51
-rw-r--r--src/H5Omessage.c2
-rw-r--r--src/H5Oprivate.h1
-rwxr-xr-xtest/corrupt_stab_msg.h5bin0 -> 2928 bytes
-rw-r--r--test/stab.c123
-rw-r--r--test/tarray.c16
-rw-r--r--test/tmisc.c2
19 files changed, 384 insertions, 48 deletions
diff --git a/MANIFEST b/MANIFEST
index e096838..1952f65 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -790,6 +790,7 @@
./test/cache_common.c
./test/cache_common.h
./test/cmpd_dset.c
+./test/corrupt_stab_msg.h5
./test/cross_read.c
./test/dangle.c
./test/deflate.h5
diff --git a/src/H5B.c b/src/H5B.c
index d5ac87a..254183f 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -2057,3 +2057,47 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B_get_info() */
+#ifndef H5_STRICT_FORMAT_CHECKS
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_valid
+ *
+ * Purpose: Attempt to load a b-tree node.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * March 17, 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5B_valid(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr)
+{
+ H5B_t *bt; /* The btree */
+ htri_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5B_valid, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(type);
+
+ if(!H5F_addr_defined(addr))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "address is undefined")
+
+ /* Protect the node */
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, NULL, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree node")
+
+ /* Release the node */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B_valid() */
+#endif /* H5_STRICT_FORMAT_CHECKS */
+
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
index 93c2d80..2ec2c22 100644
--- a/src/H5Bprivate.h
+++ b/src/H5Bprivate.h
@@ -168,5 +168,9 @@ H5_DLL H5B_shared_t *H5B_shared_new(const H5F_t *f, const H5B_class_t *type,
H5_DLL herr_t H5B_shared_free(void *_shared);
H5_DLL herr_t H5B_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream,
int indent, int fwidth, const H5B_class_t *type, void *udata);
+#ifndef H5_STRICT_FORMAT_CHECKS
+H5_DLL htri_t H5B_valid(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type,
+ haddr_t addr);
+#endif /* H5_STRICT_FORMAT_CHECKS */
#endif /* _H5Bprivate_H */
diff --git a/src/H5F.c b/src/H5F.c
index 7b9ce79..e7b4cd3 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -1115,6 +1115,9 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
f->shared->mtab.child = (H5F_mount_t *)H5MM_xfree(f->shared->mtab.child);
f->shared->mtab.nalloc = 0;
+ /* Free root group symbol table entry, if any */
+ f->shared->root_ent = H5MM_xfree(f->shared->root_ent);
+
/* Destroy shared file struct */
f->shared = (H5F_file_t *)H5FL_FREE(H5F_file_t, f->shared);
diff --git a/src/H5Fdbg.c b/src/H5Fdbg.c
index e05c32a..a4577c9 100644
--- a/src/H5Fdbg.c
+++ b/src/H5Fdbg.c
@@ -123,21 +123,26 @@ H5F_debug(H5F_t *f, FILE *stream, int indent, int fwidth)
"Root group symbol table entry:",
f->shared->root_grp ? "" : "(none)");
if(f->shared->root_grp) {
- H5O_loc_t *root_oloc; /* Root object location */
- H5G_entry_t root_ent; /* Constructed root symbol table entry */
-
- /* Reset the root group entry */
- H5G_ent_reset(&root_ent);
-
- /* Build up a simulated root group symbol table entry */
- root_oloc = H5G_oloc(f->shared->root_grp);
- HDassert(root_oloc);
- root_ent.type = H5G_NOTHING_CACHED;
- root_ent.header = root_oloc->addr;
- root_ent.file = f;
-
- /* Display root group symbol table entry info */
- H5G_ent_debug(f, &root_ent, stream, indent + 3, MAX(0, fwidth - 3), NULL);
+ if(f->shared->root_ent) /* Use real root group symbol table entry */
+ H5G_ent_debug(f, f->shared->root_ent, stream, indent + 3,
+ MAX(0, fwidth - 3), NULL);
+ else {
+ H5O_loc_t *root_oloc; /* Root object location */
+ H5G_entry_t root_ent; /* Constructed root symbol table entry */
+
+ /* Reset the root group entry */
+ H5G_ent_reset(&root_ent);
+
+ /* Build up a simulated root group symbol table entry */
+ root_oloc = H5G_oloc(f->shared->root_grp);
+ HDassert(root_oloc);
+ root_ent.type = H5G_NOTHING_CACHED;
+ root_ent.header = root_oloc->addr;
+ root_ent.file = f;
+
+ /* Display root group symbol table entry info */
+ H5G_ent_debug(f, &root_ent, stream, indent + 3, MAX(0, fwidth - 3), NULL);
+ }
} /* end if */
done:
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index cc74a80..4080705 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -158,6 +158,7 @@ typedef struct H5F_file_t {
int ncwfs; /* Num entries on cwfs list */
struct H5HG_heap_t **cwfs; /* Global heap cache */
struct H5G_t *root_grp; /* Open root group */
+ H5G_entry_t *root_ent; /* Root group symbol table entry */
H5FO_t *open_objs; /* Open objects in file */
H5RC_t *grp_btree_shared; /* Ref-counted group B-tree node info */
@@ -193,7 +194,7 @@ struct H5F_t {
H5FO_t *obj_count; /* # of time each object is opened through top file structure */
hid_t file_id; /* ID of this file */
hbool_t closing; /* File is in the process of being closed */
- struct H5F_t *parent; /* Parent file that this file is mounted to */
+ struct H5F_t *parent; /* Parent file that this file is mounted to */
unsigned nmounts; /* Number of children mounted to this file */
};
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index 3c914bd..70e0954 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -383,7 +383,8 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
H5F_addr_decode(f, (const uint8_t **)&p, &shared->extension_addr/*out*/);
H5F_addr_decode(f, (const uint8_t **)&p, &stored_eoa/*out*/);
H5F_addr_decode(f, (const uint8_t **)&p, &shared->driver_addr/*out*/);
- if(H5G_obj_ent_decode(f, (const uint8_t **)&p, root_loc->oloc/*out*/) < 0)
+ if(H5G_obj_ent_decode(f, (const uint8_t **)&p, root_loc->oloc/*out*/,
+ &shared->root_ent/*out*/) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read root symbol entry")
/*
diff --git a/src/H5G.c b/src/H5G.c
index 6a7e505..042ce90 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -896,6 +896,24 @@ H5G_mkroot(H5F_t *f, hid_t dxpl_id, H5G_loc_t *loc)
*/
if(H5O_open(loc->oloc) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open root group")
+
+#ifndef H5_STRICT_FORMAT_CHECKS
+ /* If symbol table information is cached, check if we should replace the
+ * symbol table message with the cached symbol table information */
+ if((H5F_INTENT(f) & H5F_ACC_RDWR) && f->shared->root_ent
+ && (f->shared->root_ent->type == H5G_CACHED_STAB)) {
+ H5O_stab_t cached_stab;
+
+ /* Retrieve the cached symbol table information */
+ cached_stab.btree_addr = f->shared->root_ent->cache.stab.btree_addr;
+ cached_stab.heap_addr = f->shared->root_ent->cache.stab.heap_addr;
+
+ /* Check if the symbol table message is valid, and replace with the
+ * cached symbol table if necessary */
+ if(H5G_stab_valid(loc->oloc, dxpl_id, &cached_stab) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to verify symbol table")
+ } /* end if */
+#endif /* H5_STRICT_FORMAT_CHECKS */
} /* end else */
/* Create the path names for the root group's entry */
diff --git a/src/H5Gobj.c b/src/H5Gobj.c
index 3220b67..2eb1924 100644
--- a/src/H5Gobj.c
+++ b/src/H5Gobj.c
@@ -237,31 +237,49 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp, H5O_loc_t *oloc)
+H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp, H5O_loc_t *oloc, H5G_entry_t **entp)
{
const uint8_t *p_ret = *pp;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOFUNC(H5G_obj_ent_decode)
+ FUNC_ENTER_NOAPI(H5G_obj_ent_decode, FAIL)
/* check arguments */
HDassert(f);
HDassert(pp);
HDassert(oloc);
- /* Set file pointer for root object location */
- oloc->file = f;
+ if(entp) {
+ /* If entp is not NULL we allocate space for the symbol table entry and
+ * decode the entire entry. */
+ if(!(*entp)) /* Only allocate space if *entp is NULL */
+ if(NULL == (*entp = (H5G_entry_t *) H5MM_calloc(sizeof(H5G_entry_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate space for symbol table entry")
+ if(H5G_ent_decode_vec(f, pp, *entp, 1) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode symbol table entry")
+
+ /* Set oloc to the correct values */
+ oloc->file = (*entp)->file;
+ oloc->addr = (*entp)->header;
+ } else {
+ /* Set file pointer for root object location */
+ oloc->file = f;
+
+ /* decode header */
+ *pp += H5F_SIZEOF_SIZE(f); /* Skip over local heap address */
+ H5F_addr_decode(f, pp, &(oloc->addr));
+ *pp += 4; /* Skip over "cache type" */
+ *pp += 4; /* Reserved */
+ }
+
+ /* Common oloc settings */
oloc->holding_file = FALSE;
- /* decode header */
- *pp += H5F_SIZEOF_SIZE(f); /* Skip over local heap address */
- H5F_addr_decode(f, pp, &(oloc->addr));
- *pp += 4; /* Skip over "cache type" */
- *pp += 4; /* Reserved */
-
/* Set decode pointer */
*pp = p_ret + H5G_SIZEOF_ENTRY(f);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_obj_ent_decode() */
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index 31e5713..38c7628 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -100,14 +100,14 @@ typedef union H5G_cache_t {
* also appears in the object header to which this symbol table entry
* points.
*/
-typedef struct H5G_entry_t {
+struct H5G_entry_t {
hbool_t dirty; /*entry out-of-date? */
H5G_cache_type_t type; /*type of information cached */
H5G_cache_t cache; /*cached data from object header */
size_t name_off; /*offset of name within name heap */
haddr_t header; /*file address of object header */
H5F_t *file; /*file to which this obj hdr belongs */
-} H5G_entry_t;
+};
/*
* A symbol table node is a collection of symbol table entries. It can
@@ -402,6 +402,10 @@ H5_DLL herr_t H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name,
H5O_link_t *lnk, hid_t dxpl_id);
H5_DLL herr_t H5G_stab_lookup_by_idx(H5O_loc_t *grp_oloc, H5_iter_order_t order,
hsize_t n, H5O_link_t *lnk, hid_t dxpl_id);
+#ifndef H5_STRICT_FORMAT_CHECKS
+H5_DLL herr_t H5G_stab_valid(H5O_loc_t *grp_oloc, hid_t dxpl_id,
+ H5O_stab_t *alt_stab);
+#endif /* H5_STRICT_FORMAT_CHECKS */
#ifndef H5_NO_DEPRECATED_SYMBOLS
H5_DLL H5G_obj_t H5G_stab_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx,
hid_t dxpl_id);
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index 591be6b..b1db96f 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -145,6 +145,7 @@ typedef struct {
typedef struct H5G_t H5G_t;
typedef struct H5G_shared_t H5G_shared_t;
+typedef struct H5G_entry_t H5G_entry_t;
/*
* Library prototypes... These are the ones that other packages routinely
@@ -181,7 +182,7 @@ H5_DLL herr_t H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream
* These functions operate on group object locations.
*/
H5_DLL herr_t H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp,
- struct H5O_loc_t *oloc);
+ struct H5O_loc_t *oloc, H5G_entry_t **entp);
H5_DLL herr_t H5G_obj_ent_encode(const H5F_t *f, uint8_t **pp,
const struct H5O_loc_t *oloc);
diff --git a/src/H5Gstab.c b/src/H5Gstab.c
index f79d78b..c2df8e7 100644
--- a/src/H5Gstab.c
+++ b/src/H5Gstab.c
@@ -982,6 +982,81 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_stab_lookup_by_idx() */
+#ifndef H5_STRICT_FORMAT_CHECKS
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_stab_valid
+ *
+ * Purpose: Verify that a group's symbol table message is valid. If
+ * provided, the addresses in alt_stab will be tried if the
+ * addresses in the group's stab message are invalid, and
+ * the stab message will be updated if necessary.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * nfortne2@hdfgroup.org
+ * Mar 17, 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_stab_valid(H5O_loc_t *grp_oloc, hid_t dxpl_id, H5O_stab_t *alt_stab)
+{
+ H5O_stab_t stab; /* Current symbol table */
+ H5HL_t *heap = NULL; /* Pointer to local heap */
+ hbool_t changed = FALSE; /* Whether stab has been modified */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_stab_valid, FAIL)
+
+ /* Read the symbol table message */
+ H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id);
+
+ /* Check if the symbol table message's b-tree address is valid */
+ if(H5B_valid(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr) < 0) {
+ /* Address is invalid, try the b-tree address in the alternate symbol
+ * table message */
+ if(!alt_stab || H5B_valid(grp_oloc->file, dxpl_id, H5B_SNODE, alt_stab->btree_addr) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to locate b-tree")
+ else {
+ /* The alternate symbol table's b-tree address is valid. Adjust the
+ * symbol table message in the group. */
+ stab.btree_addr = alt_stab->btree_addr;
+ changed = TRUE;
+ } /* end else */
+ } /* end if */
+
+ /* Check if the symbol table message's heap address is valid */
+ if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC_READ))) {
+ /* Address is invalid, try the heap address in the alternate symbol
+ * table message */
+ if(!alt_stab || NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, alt_stab->heap_addr, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "unable to locate heap")
+ else {
+ /* The alternate symbol table's heap address is valid. Adjust the
+ * symbol table message in the group. */
+ stab.heap_addr = alt_stab->heap_addr;
+ changed = TRUE;
+ } /* end else */
+ } /* end if */
+
+ /* Update the symbol table message and clear errors if necessary */
+ if(changed) {
+ H5E_clear_stack(NULL);
+ if(H5O_msg_write(grp_oloc, H5O_STAB_ID, 0, H5O_UPDATE_TIME | H5O_UPDATE_FORCE, &stab, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to correct symbol table message")
+ } /* end if */
+
+done:
+ /* Release resources */
+ if(heap && H5HL_unprotect(grp_oloc->file, dxpl_id, heap, stab.heap_addr) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_stab_valid */
+#endif /* H5_STRICT_FORMAT_CHECKS */
+
#ifndef H5_NO_DEPRECATED_SYMBOLS
/*-------------------------------------------------------------------------
diff --git a/src/H5Odtype.c b/src/H5Odtype.c
index 60f77d9..fe8c627 100644
--- a/src/H5Odtype.c
+++ b/src/H5Odtype.c
@@ -115,20 +115,23 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{
*
* Purpose: Decodes a datatype
*
- * Return: Non-negative on success/Negative on failure
+ * Return: TRUE if we can upgrade the parent type's version even
+ * with strict format checks
+ * FALSE if we cannot
+ * Negative on failure
*
* Programmer: Robb Matzke
* Monday, December 8, 1997
*
*-------------------------------------------------------------------------
*/
-static herr_t
+static htri_t
H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **pp, H5T_t *dt)
{
unsigned flags, version;
unsigned i;
size_t z;
- herr_t ret_value = SUCCEED; /* Return value */
+ htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_dtype_decode_helper)
@@ -254,6 +257,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
unsigned offset_nbytes; /* Size needed to encode member offsets */
size_t max_memb_pos = 0; /* Maximum member covered, so far */
unsigned max_version = 0; /* Maximum member version */
+ hbool_t upgrade_to = 0; /* Version number we can "soft" upgrade to */
unsigned j;
/* Compute the # of bytes required to store a member offset */
@@ -271,6 +275,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
for(i = 0; i < dt->shared->u.compnd.nmembs; i++) {
unsigned ndims = 0; /* Number of dimensions of the array field */
+ htri_t can_upgrade; /* Whether we can upgrade this type's version */
hsize_t dim[H5O_LAYOUT_NDIMS]; /* Dimensions of the array */
H5T_t *array_dt; /* Temporary pointer to the array datatype */
H5T_t *temp_type; /* Temporary pointer to the field's datatype */
@@ -318,16 +323,20 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Decode the field's datatype information */
- if(H5O_dtype_decode_helper(f, ioflags, pp, temp_type) < 0) {
+ if((can_upgrade = H5O_dtype_decode_helper(f, ioflags, pp, temp_type)) < 0) {
for(j = 0; j <= i; j++)
H5MM_xfree(dt->shared->u.compnd.memb[j].name);
H5MM_xfree(dt->shared->u.compnd.memb);
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode member type")
} /* end if */
- /* Keep track of the maximum member version found */
- if(temp_type->shared->version > max_version)
- max_version = temp_type->shared->version;
+ /* Upgrade the version if we can and it is necessary */
+ if(can_upgrade && temp_type->shared->version > version) {
+ upgrade_to = temp_type->shared->version;
+
+ /* Pass "can_upgrade" flag down to parent type */
+ ret_value = TRUE;
+ } /* end if */
/* Go create the array datatype now, for older versions of the datatype message */
if(version == H5O_DTYPE_VERSION_1) {
@@ -346,9 +355,26 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
/* Make the array type the type that is set for the field */
temp_type = array_dt;
+
+ /* Reset array version if NOCHANGE is specified (i.e. h5debug) */
+ if(*ioflags & H5O_DECODEIO_NOCHANGE)
+ temp_type->shared->version = H5O_DTYPE_VERSION_1;
+ else {
+ /* Otherwise upgrade the compound version */
+ if(upgrade_to < temp_type->shared->version)
+ upgrade_to = temp_type->shared->version;
+
+ /* Set the return value to indicate that we should freely
+ * upgrade parent types */
+ ret_value = TRUE;
+ } /* end else */
} /* end if */
} /* end if */
+ /* Keep track of the maximum member version found */
+ if(temp_type->shared->version > max_version)
+ max_version = temp_type->shared->version;
+
/*
* Set the "force conversion" flag if VL datatype fields exist in this
* type or any component types
@@ -397,6 +423,17 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
dt->shared->u.compnd.packed = FALSE;
} /* end if */
} /* end for */
+
+ /* Upgrade the compound if requested */
+ if(version < upgrade_to) {
+ version = upgrade_to;
+ if(H5T_upgrade_version(dt, upgrade_to) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't upgrade compound encoding version")
+ /* We won't mark the message dirty since there were no
+ * errors in the file, simply type versions that we will no
+ * longer encode. */
+ } /* end if */
+
/* Check that no member of this compound has a version greater
* than the compound itself. */
H5O_DTYPE_CHECK_VERSION(dt, version, max_version, ioflags, "compound", FAIL)
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index 286240c..4a9ecb5 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -393,7 +393,7 @@ H5O_msg_write_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *ty
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message type not found")
/* Check for modifying a constant message */
- if(idx_msg->flags & H5O_MSG_FLAG_CONSTANT)
+ if(!(update_flags & H5O_UPDATE_FORCE) && (idx_msg->flags & H5O_MSG_FLAG_CONSTANT))
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify constant message")
/* This message is shared, but it's being modified. */
else if((idx_msg->flags & H5O_MSG_FLAG_SHARED) || (idx_msg->flags & H5O_MSG_FLAG_SHAREABLE)) {
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 590da0c..d3e3313 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -79,6 +79,7 @@ typedef struct H5O_t H5O_t;
/* Flags for updating messages */
#define H5O_UPDATE_TIME 0x01u
+#define H5O_UPDATE_FORCE 0x02u /* Force updating the message */
/* Hash value constants */
#define H5O_HASH_SIZE 32
diff --git a/test/corrupt_stab_msg.h5 b/test/corrupt_stab_msg.h5
new file mode 100755
index 0000000..4fa287c
--- /dev/null
+++ b/test/corrupt_stab_msg.h5
Binary files differ
diff --git a/test/stab.c b/test/stab.c
index b57b542..319046e 100644
--- a/test/stab.c
+++ b/test/stab.c
@@ -75,6 +75,12 @@ const char *FILENAME[] = {
/* Definitions for 'old_api' test */
#define OLD_API_GROUP "/old_api"
+/* Definitions for 'corrupt_stab_msg' test */
+#define CORRUPT_STAB_FILE "corrupt_stab_msg.h5"
+#define CORRUPT_STAB_TMP_FILE "corrupt_stab_msg_tmp.h5"
+#define CORRUPT_STAB_COPY_BUF_SIZE 4096
+#define CORRUPT_STAB_DSET "DS1"
+
/*-------------------------------------------------------------------------
* Function: test_misc
@@ -1084,6 +1090,121 @@ error:
/*-------------------------------------------------------------------------
+ * Function: corrupt_stab_msg
+ *
+ * Purpose: Test that a corrupt symbol table message can be fixed
+ * using the cached symbol table information.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Neil Fortner
+ * Wednesday, March 18, 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+corrupt_stab_msg(void)
+{
+ char testfile[512]=""; /* Character buffer for corrected test file name */
+ char *srcdir = HDgetenv("srcdir"); /* Pointer to the directory the source code is located within */
+ FILE *tmp_fp, *old_fp; /* Pointers to temp & old files */
+ void *copy_buf; /* Pointer to buffer for copying data */
+ size_t written; /* Amount of data written to new file */
+ size_t read_in; /* Amount of data read in from old file */
+ hid_t fid = (-1); /* File ID */
+ hid_t did = (-1); /* Dataset ID */
+
+ TESTING("corrupt symbol table message");
+
+ /* Generate the correct name for the test file, by prepending the source path */
+ if(srcdir && ((HDstrlen(srcdir) + HDstrlen(CORRUPT_STAB_FILE) + 1) < sizeof(testfile))) {
+ HDstrcpy(testfile, srcdir);
+ HDstrcat(testfile, "/");
+ }
+ HDstrcat(testfile, CORRUPT_STAB_FILE);
+
+ /* Open the temporary file */
+ if(NULL == (tmp_fp = HDfopen(CORRUPT_STAB_TMP_FILE,"wb"))) TEST_ERROR
+
+ /* Open the old file */
+ if(NULL == (old_fp = fopen(testfile,"rb"))) TEST_ERROR
+
+ /* Allocate space for the copy buffer */
+ if(NULL == (copy_buf = HDmalloc((size_t)CORRUPT_STAB_COPY_BUF_SIZE))) TEST_ERROR
+
+ /* Copy data from the old file to the new file */
+ while((read_in = HDfread(copy_buf, (size_t)1, (size_t)CORRUPT_STAB_COPY_BUF_SIZE, old_fp)) > 0)
+ /* Write the data to the new file */
+ if(read_in != (written = HDfwrite(copy_buf, (size_t)1, read_in, tmp_fp))) TEST_ERROR
+
+ /* Close the old file */
+ if(HDfclose(old_fp)) TEST_ERROR
+
+ /* Close the new file */
+ if(HDfclose(tmp_fp)) TEST_ERROR
+
+ /* Free the copy buffer */
+ free(copy_buf);
+
+#ifndef H5_STRICT_FORMAT_CHECKS
+ /* Open temp file through HDF5 library */
+ if((fid = H5Fopen(CORRUPT_STAB_TMP_FILE, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* Open dataset */
+ if((did = H5Dopen2(fid, CORRUPT_STAB_DSET, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* Close dataset and file */
+ if(H5Dclose(did) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+ /* Now reopen with read only access. This verifies that the issue has been
+ * corrected, as the symbol table message is not patched in read only mode.
+ */
+
+ /* Open file */
+ if((fid = H5Fopen(CORRUPT_STAB_TMP_FILE, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* Open dataset */
+ if((did = H5Dopen2(fid, CORRUPT_STAB_DSET, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* Close dataset and file */
+ if(H5Dclose(did) < 0) TEST_ERROR
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+#else /* H5_STRICT_FORMAT_CHECKS */
+ /* Open file */
+ if((fid = H5Fopen(CORRUPT_STAB_TMP_FILE, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) TEST_ERROR
+
+ /* Verify that an error is thrown when we try to access the dataset */
+ H5E_BEGIN_TRY {
+ did = H5Dopen2(fid, CORRUPT_STAB_DSET, H5P_DEFAULT);
+ } H5E_END_TRY
+ if(did >= 0) TEST_ERROR
+
+ /* Close file */
+ if(H5Fclose(fid) < 0) TEST_ERROR
+
+#endif /* H5_STRICT_FORMAT_CHECKS */
+ /* Remove temporary file */
+ if(HDremove(CORRUPT_STAB_TMP_FILE)) TEST_ERROR
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Dclose(did);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+ HDremove(CORRUPT_STAB_TMP_FILE);
+
+ return 1;
+} /* end old_api() */
+
+
+/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Test groups
@@ -1133,6 +1254,7 @@ main(void)
/* Old group API specific tests */
nerrors += old_api(fapl);
+ nerrors += corrupt_stab_msg();
/* Close 2nd FAPL */
H5Pclose(fapl2);
@@ -1152,3 +1274,4 @@ error:
puts("*** TESTS FAILED ***");
return 1;
}
+
diff --git a/test/tarray.c b/test/tarray.c
index 8d739b9..cc0a0ca 100644
--- a/test/tarray.c
+++ b/test/tarray.c
@@ -1952,9 +1952,9 @@ test_compat(void)
/* Check the 1st field's name */
mname=H5Tget_member_name(tid1,0);
CHECK(mname, NULL, "H5Tget_member_name");
- if(HDstrcmp(mname,"i")!=0)
+ if(mname && HDstrcmp(mname,"i")!=0)
TestErrPrintf("Compound field name doesn't match!, mname=%s\n",mname);
- free(mname);
+ if(mname) free(mname);
/* Check the 1st field's offset */
off=H5Tget_member_offset(tid1,0);
@@ -1971,9 +1971,9 @@ test_compat(void)
/* Check the 2nd field's name */
mname=H5Tget_member_name(tid1,1);
CHECK(mname, NULL, "H5Tget_member_name");
- if(HDstrcmp(mname,"f")!=0)
+ if(mname && HDstrcmp(mname,"f")!=0)
TestErrPrintf("Compound field name doesn't match!, mname=%s\n",mname);
- free(mname);
+ if(mname) free(mname);
/* Check the 2nd field's offset */
off=H5Tget_member_offset(tid1,1);
@@ -2016,9 +2016,9 @@ test_compat(void)
/* Check the 3rd field's name */
mname=H5Tget_member_name(tid1,2);
CHECK(mname, NULL, "H5Tget_member_name");
- if(HDstrcmp(mname,"l")!=0)
+ if(mname && HDstrcmp(mname,"l")!=0)
TestErrPrintf("Compound field name doesn't match!, mname=%s\n",mname);
- free(mname);
+ if(mname) free(mname);
/* Check the 3rd field's offset */
off=H5Tget_member_offset(tid1,2);
@@ -2061,9 +2061,9 @@ test_compat(void)
/* Check the 4th field's name */
mname=H5Tget_member_name(tid1,3);
CHECK(mname, NULL, "H5Tget_member_name");
- if(HDstrcmp(mname,"d")!=0)
+ if(mname && HDstrcmp(mname,"d")!=0)
TestErrPrintf("Compound field name doesn't match!, mname=%s\n",mname);
- free(mname);
+ if(mname) free(mname);
/* Check the 4th field's offset */
off=H5Tget_member_offset(tid1,3);
diff --git a/test/tmisc.c b/test/tmisc.c
index 9ac2bc4..4db800c 100644
--- a/test/tmisc.c
+++ b/test/tmisc.c
@@ -2273,7 +2273,7 @@ insert_user_block(const char *old_name, const char *new_name,const char *str,siz
VERIFY(ret, 0, "HDfclose");
/* Close the new file */
- ret=fclose(new_fp);
+ ret=HDfclose(new_fp);
VERIFY(ret, 0, "HDfclose");
/* Free the copy buffer */