summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Fortner <nfortne2@hdfgroup.org>2009-03-23 18:51:29 (GMT)
committerNeil Fortner <nfortne2@hdfgroup.org>2009-03-23 18:51:29 (GMT)
commit849d015bbd0e12c8a920c3367bd67515842790bf (patch)
tree5e041cef4b5b9e932f6ff1101c42efadf88f8b1d
parent6f342514df3dbf035f5401783b9322f6deb0c87a (diff)
downloadhdf5-849d015bbd0e12c8a920c3367bd67515842790bf.zip
hdf5-849d015bbd0e12c8a920c3367bd67515842790bf.tar.gz
hdf5-849d015bbd0e12c8a920c3367bd67515842790bf.tar.bz2
[svn-r16594] Purpose: fix bug 1189
Description: Some files apparently exist in the wild which have corrupt symbol table messages on the root group. These files can be opened by 1.6 (which uses the cached information in the superblock) but not by 1.8. This patch fixes 1.8 and 1.9 so they can now open these files, and will correct them if necessary. Also fix some potential (rare) problems with array datatype versions. Tested: jam (parallel; h5committest not working on linew or smirom)
-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 */