summaryrefslogtreecommitdiffstats
path: root/src/H5Odtype.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Odtype.c')
-rw-r--r--src/H5Odtype.c95
1 files changed, 77 insertions, 18 deletions
diff --git a/src/H5Odtype.c b/src/H5Odtype.c
index ba343bc..9c669e0 100644
--- a/src/H5Odtype.c
+++ b/src/H5Odtype.c
@@ -29,7 +29,8 @@
/* PRIVATE PROTOTYPES */
static herr_t H5O_dtype_encode(H5F_t *f, uint8_t *p, const void *mesg);
-static void *H5O_dtype_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_dtype_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static void *H5O_dtype_copy(const void *_mesg, void *_dest);
static size_t H5O_dtype_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_dtype_reset(void *_mesg);
@@ -65,6 +66,25 @@ static herr_t H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
#define H5O_SHARED_DEBUG_REAL H5O_dtype_debug
#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
+/* Macros to check for the proper version of a datatype */
+#ifdef H5_STRICT_FORMAT_CHECKS
+/* If the version is too low, give an error. No error if nochange is set
+ * because in that case we are either debugging or deleting the object header */
+#define H5O_DTYPE_CHECK_VERSION(DT, VERS, MIN_VERS, IOF, CLASS, ERR) \
+ if(((VERS) < (MIN_VERS)) && !(*(IOF) & H5O_DECODEIO_NOCHANGE)) \
+ HGOTO_ERROR(H5E_DATATYPE, H5E_VERSION, ERR, "incorrect " CLASS " datatype version")
+#else /* H5_STRICT_FORMAT_CHECKS */
+/* If the version is too low and we are allowed to change the message, upgrade
+ * it and mark the object header as dirty */
+#define H5O_DTYPE_CHECK_VERSION(DT, VERS, MIN_VERS, IOF, CLASS, ERR) \
+ if(((VERS) < (MIN_VERS)) && !(*(IOF) & H5O_DECODEIO_NOCHANGE)) { \
+ (VERS) = (MIN_VERS); \
+ if(H5T_upgrade_version((DT), (VERS)) < 0) \
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't upgrade " CLASS " encoding version") \
+ *(IOF) |= H5O_DECODEIO_DIRTY; \
+ } /* end if */
+#endif /* H5_STRICT_FORMAT_CHECKS */
+
/* This message derives from H5O message class */
const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{
H5O_DTYPE_ID, /* message id number */
@@ -103,7 +123,7 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
+H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **pp, H5T_t *dt)
{
unsigned flags, version;
unsigned i;
@@ -233,6 +253,7 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
{
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 */
unsigned j;
/* Compute the # of bytes required to store a member offset */
@@ -297,13 +318,17 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Decode the field's datatype information */
- if(H5O_dtype_decode_helper(f, pp, temp_type) < 0) {
+ if(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;
+
/* Go create the array datatype now, for older versions of the datatype message */
if(version == H5O_DTYPE_VERSION_1) {
/* Check if this member is an array field */
@@ -372,6 +397,9 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
dt->shared->u.compnd.packed = FALSE;
} /* end if */
} /* end for */
+ /* 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)
}
break;
@@ -402,8 +430,14 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
dt->shared->u.enumer.nmembs = dt->shared->u.enumer.nalloc = flags & 0xffff;
if(NULL == (dt->shared->parent = H5T_alloc()))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- if(H5O_dtype_decode_helper(f, pp, dt->shared->parent) < 0)
+ if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode parent datatype")
+
+ /* Check if the parent of this enum has a version greater than the
+ * enum itself. */
+ H5O_DTYPE_CHECK_VERSION(dt, version, dt->shared->parent->shared->version,
+ ioflags, "enum", FAIL)
+
if(NULL == (dt->shared->u.enumer.name = (char **)H5MM_calloc(dt->shared->u.enumer.nalloc * sizeof(char*))) ||
NULL == (dt->shared->u.enumer.value = (uint8_t *)H5MM_calloc(dt->shared->u.enumer.nalloc * dt->shared->parent->shared->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
@@ -438,9 +472,14 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
/* Decode base type of VL information */
if(NULL == (dt->shared->parent = H5T_alloc()))
HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "memory allocation failed")
- if(H5O_dtype_decode_helper(f, pp, dt->shared->parent) < 0)
+ if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode VL parent type")
+ /* Check if the parent of this vlen has a version greater than the
+ * vlen itself. */
+ H5O_DTYPE_CHECK_VERSION(dt, version, dt->shared->parent->shared->version,
+ ioflags, "vlen", FAIL)
+
dt->shared->force_conv=TRUE;
/* Mark this type as on disk */
if(H5T_set_loc(dt, f, H5T_LOC_DISK) < 0)
@@ -471,8 +510,17 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
/* Decode base type of array */
if(NULL == (dt->shared->parent = H5T_alloc()))
HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "memory allocation failed")
- if(H5O_dtype_decode_helper(f, pp, dt->shared->parent) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode VL parent type")
+ if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode array parent type")
+
+ /* Check if the parent of this array has a version greater than the
+ * array itself. */
+ H5O_DTYPE_CHECK_VERSION(dt, version, dt->shared->parent->shared->version,
+ ioflags, "array", FAIL)
+
+ /* There should be no array datatypes with version < 2. */
+ H5O_DTYPE_CHECK_VERSION(dt, version, H5O_DTYPE_VERSION_2, ioflags,
+ "array", FAIL)
/*
* Set the "force conversion" flag if a VL base datatype is used or
@@ -757,6 +805,9 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
/* Sanity check */
/* (compound datatypes w/array members must be encoded w/version >= 2) */
HDassert(dt->shared->u.compnd.memb[i].type->shared->type != H5T_ARRAY || dt->shared->version >= H5O_DTYPE_VERSION_2);
+
+ /* Check that the version is at least as great as the member */
+ HDassert(dt->shared->version >= dt->shared->u.compnd.memb[i].type->shared->version);
/* Name */
HDstrcpy((char*)(*pp), dt->shared->u.compnd.memb[i].name);
@@ -817,6 +868,9 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
break;
case H5T_ENUM:
+ /* Check that the version is at least as great as the parent */
+ HDassert(dt->shared->version >= dt->shared->parent->shared->version);
+
/*
* Enumeration datatypes...
*/
@@ -849,6 +903,9 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
break;
case H5T_VLEN: /* Variable length datatypes... */
+ /* Check that the version is at least as great as the parent */
+ HDassert(dt->shared->version >= dt->shared->parent->shared->version);
+
flags |= (dt->shared->u.vlen.type & 0x0f);
if(dt->shared->u.vlen.type == H5T_VLEN_STRING) {
flags |= (dt->shared->u.vlen.pad & 0x0f) << 4;
@@ -864,6 +921,12 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
/* Double-check the number of dimensions */
HDassert(dt->shared->u.array.ndims <= H5S_MAX_RANK);
+ /* Check that the version is valid */
+ HDassert(dt->shared->version >= H5O_DTYPE_VERSION_2);
+
+ /* Check that the version is at least as great as the parent */
+ HDassert(dt->shared->version >= dt->shared->parent->shared->version);
+
/* Encode the number of dimensions */
*(*pp)++ = dt->shared->u.array.ndims;
@@ -927,7 +990,8 @@ done:
function using malloc() and is returned to the caller.
--------------------------------------------------------------------------*/
static void *
-H5O_dtype_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags, const uint8_t *p)
+H5O_dtype_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
+ unsigned *ioflags/*in,out*/, const uint8_t *p)
{
H5T_t *dt = NULL;
void *ret_value; /* Return value */
@@ -942,21 +1006,13 @@ H5O_dtype_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags, con
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Perform actual decode of message */
- if(H5O_dtype_decode_helper(f, &p, dt) < 0)
+ if(H5O_dtype_decode_helper(f, ioflags, &p, dt) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode type")
/* Set return value */
ret_value = dt;
done:
- if(ret_value == NULL) {
- if(dt != NULL) {
- if(dt->shared != NULL)
- H5FL_FREE(H5T_shared_t, dt->shared);
- H5FL_FREE(H5T_t, dt);
- } /* end if */
- } /* end if */
-
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_dtype_decode() */
@@ -1522,6 +1578,9 @@ H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream,
fprintf(stream, "%*s%-*s %lu byte%s\n", indent, "", fwidth,
"Size:",
(unsigned long)(dt->shared->size), 1 == dt->shared->size ? "" : "s");
+
+ fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Version:", dt->shared->version);
if (H5T_COMPOUND == dt->shared->type) {
fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth,
@@ -1815,7 +1874,7 @@ H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream,
"Sign scheme:", s);
}
}
-
+
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_dtype_debug() */