From f909cb6c9b0f3eb0ddc77377065a9bc58ea6265c Mon Sep 17 00:00:00 2001 From: Dana Robinson <43805+derobins@users.noreply.github.com> Date: Tue, 25 Apr 2023 10:03:12 -0700 Subject: H5Odtype.c decode cleanup (#2797) * Adds bounds checking to H5Odtype.c * Minor tidy of dtypes test --- src/H5Odtype.c | 319 ++++++++++++++++++++++++++++++++++++++++++--------------- test/dtypes.c | 171 ++++++++++++++++--------------- 2 files changed, 321 insertions(+), 169 deletions(-) diff --git a/src/H5Odtype.c b/src/H5Odtype.c index e5e8996..b6e1b90 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -24,6 +24,15 @@ #include "H5Tpkg.h" /* Datatypes */ #include "H5VMprivate.h" /* Vectors and arrays */ +/* Variant boundary-checking macro, used here since H5Tdecode() doesn't take a + * size parameter so we need to ignore the bounds checks. + * + * This is a separate macro since we don't want to inflict that behavior on + * the rest of the library. + */ +#define H5_DTYPE_IS_BUFFER_OVERFLOW(skip, ptr, size, buffer_end) \ + (skip ? FALSE : ((ptr) + (size)-1) > (buffer_end)) + /* 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, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags, @@ -108,35 +117,46 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{ }}; /*------------------------------------------------------------------------- - * Function: H5O__dtype_decode_helper + * Function: H5O__dtype_decode_helper * - * Purpose: Decodes a datatype + * Purpose: Decodes a datatype * - * Return: TRUE if we can upgrade the parent type's version even + * 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 - * + * NEGATIVE on failure *------------------------------------------------------------------------- */ static htri_t -H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t *dt) +H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t *dt, hbool_t skip, + const uint8_t *p_end) { - unsigned flags, version; - unsigned i; - size_t z; - htri_t ret_value = FALSE; /* Return value */ + unsigned flags; + unsigned version; + htri_t ret_value = FALSE; FUNC_ENTER_PACKAGE - /* check args */ HDassert(pp && *pp); HDassert(dt && dt->shared); + /* XXX NOTE! + * + * H5Tencode() does not take a buffer size, so normal bounds checking in + * that case is impossible. + * + * Instead of using our normal H5_IS_BUFFER_OVERFLOW macro, use + * H5_DTYPE_IS_BUFFER_OVERFLOW, which will skip the check when the + * we're decoding a buffer from H5Tconvert(). + * + * Even if this is fixed at some point in the future, as long as we + * support the old, size-less API call, we will need to use the modified + * macros. + */ + /* Version, class & flags */ + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 4, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT32DECODE(*pp, flags); version = (flags >> 4) & 0x0f; if (version < H5O_DTYPE_VERSION_1 || version > H5O_DTYPE_VERSION_LATEST) @@ -146,6 +166,8 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t flags >>= 8; /* Size */ + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 4, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT32DECODE(*pp, dt->shared->size); /* Check for invalid datatype size */ @@ -161,6 +183,8 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t dt->shared->u.atomic.lsb_pad = (flags & 0x2) ? H5T_PAD_ONE : H5T_PAD_ZERO; dt->shared->u.atomic.msb_pad = (flags & 0x4) ? H5T_PAD_ONE : H5T_PAD_ZERO; dt->shared->u.atomic.u.i.sign = (flags & 0x8) ? H5T_SGN_2 : H5T_SGN_NONE; + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 2 + 2, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT16DECODE(*pp, dt->shared->u.atomic.offset); UINT16DECODE(*pp, dt->shared->u.atomic.prec); break; @@ -178,7 +202,7 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t /* VAX order if both 1st and 6th bits are turned on*/ if (flags & 0x40) dt->shared->u.atomic.order = H5T_ORDER_VAX; - } /* end if */ + } dt->shared->u.atomic.lsb_pad = (flags & 0x2) ? H5T_PAD_ONE : H5T_PAD_ZERO; dt->shared->u.atomic.msb_pad = (flags & 0x4) ? H5T_PAD_ONE : H5T_PAD_ZERO; dt->shared->u.atomic.u.f.pad = (flags & 0x8) ? H5T_PAD_ONE : H5T_PAD_ZERO; @@ -197,21 +221,40 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown floating-point normalization") - } /* end switch */ + } dt->shared->u.atomic.u.f.sign = (flags >> 8) & 0xff; + + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 2 + 2, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT16DECODE(*pp, dt->shared->u.atomic.offset); UINT16DECODE(*pp, dt->shared->u.atomic.prec); + + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 1 + 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); dt->shared->u.atomic.u.f.epos = *(*pp)++; dt->shared->u.atomic.u.f.esize = *(*pp)++; - HDassert(dt->shared->u.atomic.u.f.esize > 0); + if (dt->shared->u.atomic.u.f.esize == 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "exponent size can't be zero") + + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 1 + 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); dt->shared->u.atomic.u.f.mpos = *(*pp)++; dt->shared->u.atomic.u.f.msize = *(*pp)++; - HDassert(dt->shared->u.atomic.u.f.msize > 0); + if (dt->shared->u.atomic.u.f.msize == 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "mantissa size can't be zero") + + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 4, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT32DECODE(*pp, dt->shared->u.atomic.u.f.ebias); break; - case H5T_TIME: /* Time datatypes */ + case H5T_TIME: + /* + * Time datatypes... + */ dt->shared->u.atomic.order = (flags & 0x1) ? H5T_ORDER_BE : H5T_ORDER_LE; + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 2, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT16DECODE(*pp, dt->shared->u.atomic.prec); break; @@ -236,22 +279,35 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t dt->shared->u.atomic.order = (flags & 0x1) ? H5T_ORDER_BE : H5T_ORDER_LE; dt->shared->u.atomic.lsb_pad = (flags & 0x2) ? H5T_PAD_ONE : H5T_PAD_ZERO; dt->shared->u.atomic.msb_pad = (flags & 0x4) ? H5T_PAD_ONE : H5T_PAD_ZERO; + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 2 + 2, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); UINT16DECODE(*pp, dt->shared->u.atomic.offset); UINT16DECODE(*pp, dt->shared->u.atomic.prec); break; - case H5T_OPAQUE: + case H5T_OPAQUE: { + size_t z; + /* * Opaque types... */ + + /* The opaque tag flag field must be aligned */ z = flags & (H5T_OPAQUE_TAG_MAX - 1); - HDassert(0 == (z & 0x7)); /*must be aligned*/ + if (0 != (z & 0x7)) + HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "opaque flag field must be aligned") + if (NULL == (dt->shared->u.opaque.tag = (char *)H5MM_malloc(z + 1))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, z, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); H5MM_memcpy(dt->shared->u.opaque.tag, *pp, z); dt->shared->u.opaque.tag[z] = '\0'; + *pp += z; break; + } case H5T_COMPOUND: { unsigned nmembs; /* Number of compound members */ @@ -274,15 +330,26 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed") dt->shared->u.compnd.nalloc = nmembs; - HDassert(dt->shared->u.compnd.memb_size == 0); + if (dt->shared->u.compnd.memb_size != 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "member size not initialized to zero") for (dt->shared->u.compnd.nmembs = 0; dt->shared->u.compnd.nmembs < nmembs; dt->shared->u.compnd.nmembs++) { - 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 */ + + size_t actual_name_length; /* Actual length of name */ + size_t max = (size_t)(p_end - *pp + 1); /* Max possible name length */ + 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 */ + + /* Get the length of the field name */ + actual_name_length = HDstrnlen((const char *)*pp, max); + if (actual_name_length == max) + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "field name not null terminated") + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, actual_name_length, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); /* Decode the field name */ if (NULL == (dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].name = @@ -291,26 +358,45 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t "can't duplicate compound member name string") /* Version 3 of the datatype message eliminated the padding to multiple of 8 bytes */ - if (version >= H5O_DTYPE_VERSION_3) + if (version >= H5O_DTYPE_VERSION_3) { /* Advance past name, including null terminator */ - *pp += HDstrlen((const char *)*pp) + 1; - else + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, actual_name_length + 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, + "ran off end of input buffer while decoding"); + *pp += actual_name_length + 1; + } + else { /* Advance multiple of 8 w/ null terminator */ - *pp += ((HDstrlen((const char *)*pp) + 8) / 8) * 8; + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, ((actual_name_length + 8) / 8) * 8, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, + "ran off end of input buffer while decoding"); + *pp += ((actual_name_length + 8) / 8) * 8; + } /* Decode the field offset */ /* (starting with version 3 of the datatype message, use the minimum # of bytes required) */ - if (version >= H5O_DTYPE_VERSION_3) + if (version >= H5O_DTYPE_VERSION_3) { + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, offset_nbytes, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, + "ran off end of input buffer while decoding"); UINT32DECODE_VAR(*pp, dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].offset, offset_nbytes) - else + } + else { + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 4, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, + "ran off end of input buffer while decoding"); UINT32DECODE(*pp, dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].offset) + } /* Older versions of the library allowed a field to have * intrinsic 'arrayness'. Newer versions of the library * use the separate array datatypes. */ if (version == H5O_DTYPE_VERSION_1) { /* Decode the number of dimensions */ + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, + "ran off end of input buffer while decoding"); ndims = *(*pp)++; /* Check that ndims is valid */ @@ -320,18 +406,31 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "invalid number of dimensions for array") } - *pp += 3; /*reserved bytes */ + /* Skip reserved bytes */ + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 3, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, + "ran off end of input buffer while decoding"); + *pp += 3; /* Skip dimension permutation */ + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 4, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, + "ran off end of input buffer while decoding"); *pp += 4; /* Skip reserved bytes */ + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 4, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, + "ran off end of input buffer while decoding"); *pp += 4; /* Decode array dimension sizes */ - for (i = 0; i < 4; i++) + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, (4 * 4), p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, + "ran off end of input buffer while decoding"); + for (int i = 0; i < 4; i++) UINT32DECODE(*pp, dim[i]); - } /* end if */ + } /* Allocate space for the field's datatype */ if (NULL == (temp_type = H5T__alloc())) { @@ -341,14 +440,15 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t } /* Decode the field's datatype information */ - if ((can_upgrade = H5O__dtype_decode_helper(ioflags, pp, temp_type)) < 0) { + if ((can_upgrade = H5O__dtype_decode_helper(ioflags, pp, temp_type, skip, p_end)) < 0) { dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].name = H5MM_xfree(dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].name); if (H5T_close_real(temp_type) < 0) HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't release datatype info") HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode member type") - } /* end if */ - HDassert(temp_type->shared->size > 0); + } + if (temp_type->shared->size == 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "type size can't be zero") /* Upgrade the version if we can and it is necessary */ if (can_upgrade && temp_type->shared->version > version) { @@ -356,7 +456,7 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t /* 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) { @@ -371,7 +471,7 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t "can't release datatype info") HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to create array datatype") - } /* end if */ + } /* Close the base type for the array */ if (H5T_close_real(temp_type) < 0) { @@ -394,16 +494,15 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t /* 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 + /* Set the "force conversion" flag if VL datatype fields exist in this * type or any component types */ if (temp_type->shared->force_conv == TRUE) @@ -416,29 +515,30 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t /* Set the field datatype (finally :-) */ dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].type = temp_type; - /* Check if this field overlaps with a prior field */ - /* (probably indicates that the file is corrupt) */ + /* Check if this field overlaps with a prior field + * (probably indicates that the file is corrupt) + */ if (dt->shared->u.compnd.nmembs > 0 && dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].offset < max_memb_pos) { - for (i = 0; i < dt->shared->u.compnd.nmembs; i++) + for (unsigned u = 0; u < dt->shared->u.compnd.nmembs; u++) if ((dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].offset >= - dt->shared->u.compnd.memb[i].offset && + dt->shared->u.compnd.memb[u].offset && dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].offset < - (dt->shared->u.compnd.memb[i].offset + dt->shared->u.compnd.memb[i].size)) || + (dt->shared->u.compnd.memb[u].offset + dt->shared->u.compnd.memb[u].size)) || (dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].offset < - dt->shared->u.compnd.memb[i].offset && + dt->shared->u.compnd.memb[u].offset && (dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].offset + dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].size) > - dt->shared->u.compnd.memb[i].offset)) + dt->shared->u.compnd.memb[u].offset)) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "member overlaps with previous member") - } /* end if */ + } /* Update the maximum member position covered */ max_memb_pos = MAX(max_memb_pos, (dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].offset + dt->shared->u.compnd.memb[dt->shared->u.compnd.nmembs].size)); - } /* end for */ + } /* Check if the compound type is packed */ H5T__update_packed(dt); @@ -451,14 +551,17 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t /* 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) } break; - case H5T_REFERENCE: /* Reference datatypes... */ + case H5T_REFERENCE: + /* + * Reference datatypes... + */ dt->shared->u.atomic.order = H5T_ORDER_NONE; dt->shared->u.atomic.prec = 8 * dt->shared->size; dt->shared->u.atomic.offset = 0; @@ -501,7 +604,7 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t nmembs = flags & 0xffff; if (NULL == (dt->shared->parent = H5T__alloc())) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate parent datatype") - if (H5O__dtype_decode_helper(ioflags, pp, dt->shared->parent) < 0) + if (H5O__dtype_decode_helper(ioflags, pp, dt->shared->parent, skip, p_end) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode parent datatype") if (dt->shared->parent->shared->size != dt->shared->size) HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "ENUM datatype size does not match parent") @@ -520,37 +623,61 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t /* Names */ for (dt->shared->u.enumer.nmembs = 0; dt->shared->u.enumer.nmembs < nmembs; dt->shared->u.enumer.nmembs++) { + + size_t actual_name_length; /* Actual length of name */ + size_t max = (size_t)(p_end - *pp + 1); /* Max possible name length */ + + actual_name_length = HDstrnlen((const char *)*pp, max); + if (actual_name_length == max) + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "enum name not null terminated") + + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, actual_name_length, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); if (NULL == (dt->shared->u.enumer.name[dt->shared->u.enumer.nmembs] = H5MM_xstrdup((const char *)*pp))) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "can't duplicate enum name string") /* Version 3 of the datatype message eliminated the padding to multiple of 8 bytes */ - if (version >= H5O_DTYPE_VERSION_3) + if (version >= H5O_DTYPE_VERSION_3) { /* Advance past name, including null terminator */ - *pp += HDstrlen((const char *)*pp) + 1; - else + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, actual_name_length + 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, + "ran off end of input buffer while decoding"); + *pp += actual_name_length + 1; + } + else { /* Advance multiple of 8 w/ null terminator */ - *pp += ((HDstrlen((const char *)*pp) + 8) / 8) * 8; - } /* end for */ - HDassert(dt->shared->u.enumer.nmembs == nmembs); + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, ((actual_name_length + 8) / 8) * 8, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, + "ran off end of input buffer while decoding"); + *pp += ((actual_name_length + 8) / 8) * 8; + } + } + if (dt->shared->u.enumer.nmembs != nmembs) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "incorrect number of enum members decoded"); /* Values */ + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, nmembs * dt->shared->parent->shared->size, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); H5MM_memcpy(dt->shared->u.enumer.value, *pp, nmembs * dt->shared->parent->shared->size); *pp += nmembs * dt->shared->parent->shared->size; } break; - case H5T_VLEN: /* Variable length datatypes... */ + case H5T_VLEN: + /* + * Variable length datatypes... + */ /* Set the type of VL information, either sequence or string */ dt->shared->u.vlen.type = (H5T_vlen_type_t)(flags & 0x0f); if (dt->shared->u.vlen.type == H5T_VLEN_STRING) { dt->shared->u.vlen.pad = (H5T_str_t)((flags >> 4) & 0x0f); dt->shared->u.vlen.cset = (H5T_cset_t)((flags >> 8) & 0x0f); - } /* end if */ + } /* 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(ioflags, pp, dt->shared->parent) < 0) + if (H5O__dtype_decode_helper(ioflags, pp, dt->shared->parent, skip, p_end) < 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 @@ -565,8 +692,13 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location") break; - case H5T_ARRAY: /* Array datatypes */ + case H5T_ARRAY: + /* + * Array datatypes... + */ /* Decode the number of dimensions */ + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 1, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); dt->shared->u.array.ndims = *(*pp)++; /* Double-check the number of dimensions */ @@ -574,23 +706,32 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t HGOTO_ERROR(H5E_DATATYPE, H5E_CANTLOAD, FAIL, "too many dimensions for array datatype") /* Skip reserved bytes, if version has them */ - if (version < H5O_DTYPE_VERSION_3) + if (version < H5O_DTYPE_VERSION_3) { + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, 3, p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); *pp += 3; + } /* Decode array dimension sizes & compute number of elements */ - for (i = 0, dt->shared->u.array.nelem = 1; i < (unsigned)dt->shared->u.array.ndims; i++) { - UINT32DECODE(*pp, dt->shared->u.array.dim[i]); - dt->shared->u.array.nelem *= dt->shared->u.array.dim[i]; - } /* end for */ + dt->shared->u.array.nelem = 1; + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, (dt->shared->u.array.ndims * 4), p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); + for (unsigned u = 0; u < dt->shared->u.array.ndims; u++) { + UINT32DECODE(*pp, dt->shared->u.array.dim[u]); + dt->shared->u.array.nelem *= dt->shared->u.array.dim[u]; + } /* Skip array dimension permutations, if version has them */ - if (version < H5O_DTYPE_VERSION_3) + if (version < H5O_DTYPE_VERSION_3) { + if (H5_DTYPE_IS_BUFFER_OVERFLOW(skip, *pp, (dt->shared->u.array.ndims * 4), p_end)) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, FAIL, "ran off end of input buffer while decoding"); *pp += dt->shared->u.array.ndims * 4; + } /* 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(ioflags, pp, dt->shared->parent) < 0) + if (H5O__dtype_decode_helper(ioflags, pp, dt->shared->parent, skip, p_end) < 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 @@ -600,8 +741,7 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t /* 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 + /* Set the "force conversion" flag if a VL base datatype is used or * or if any components of the base datatype are VL types. */ if (dt->shared->parent->shared->force_conv == TRUE) @@ -612,7 +752,7 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t case H5T_NCLASSES: default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown datatype class found") - } /* end switch */ + } done: /* Cleanup on error */ @@ -1150,27 +1290,36 @@ done: Pointer to the new message in native order on success, NULL on failure DESCRIPTION This function decodes the "raw" disk form of a simple datatype message - into a struct in memory native format. The struct is allocated within this - function using malloc() and is returned to the caller. + into a struct in memory native format. The struct is allocated within this + function using malloc() and is returned to the caller. --------------------------------------------------------------------------*/ static void * H5O__dtype_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, - unsigned *ioflags /*in,out*/, size_t H5_ATTR_UNUSED p_size, const uint8_t *p) + unsigned *ioflags /*in,out*/, size_t p_size, const uint8_t *p) { - H5T_t *dt = NULL; - void *ret_value = NULL; /* Return value */ + hbool_t skip; + H5T_t *dt = NULL; + const uint8_t *p_end = p + p_size - 1; + void *ret_value = NULL; FUNC_ENTER_PACKAGE - /* check args */ + HDassert(f); HDassert(p); /* Allocate datatype message */ if (NULL == (dt = H5T__alloc())) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + /* If we are decoding a buffer from H5Tdecode(), we won't have the size + * of the buffer and bounds checking will be impossible. In this case, + * the library will have set p_size to SIZE_MAX and we can use that + * as a signal to skip bounds checking. + */ + skip = (p_size == SIZE_MAX ? TRUE : FALSE); + /* Perform actual decode of message */ - if (H5O__dtype_decode_helper(ioflags, &p, dt) < 0) + if (H5O__dtype_decode_helper(ioflags, &p, dt, skip, p_end) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode type") /* Set return value */ diff --git a/test/dtypes.c b/test/dtypes.c index 37fc8c7..bd55491 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -5965,34 +5965,37 @@ error: * * Purpose: Tests functions of encoding and decoding datatype. * - * Return: Success: 0 - * - * Failure: number of errors - * - * Programmer: Raymond Lu - * July 14, 2004 - * + * Return: Success: 0 + * Failure: number of errors *------------------------------------------------------------------------- */ static int test_encode(void) { - struct s1 { + struct cmpd { int a; float b; long c; double d; }; - hid_t file = -1, tid1 = -1, tid2 = -1, tid3 = -1; - hid_t decoded_tid1 = -1, decoded_tid2 = -1, decoded_tid3 = -1; + hid_t file = H5I_INVALID_HID; + hid_t tid1 = H5I_INVALID_HID; + hid_t tid2 = H5I_INVALID_HID; + hid_t tid3 = H5I_INVALID_HID; + hid_t decoded_tid1 = H5I_INVALID_HID; + hid_t decoded_tid2 = H5I_INVALID_HID; + hid_t decoded_tid3 = H5I_INVALID_HID; char filename[1024]; - char compnd_type[] = "Compound_type", enum_type[] = "Enum_type"; - char vlstr_type[] = "VLstring_type"; + char compnd_type[] = "Compound_type"; + char enum_type[] = "Enum_type"; + char vlstr_type[] = "VLstring_type"; short enum_val; size_t cmpd_buf_size = 0; size_t enum_buf_size = 0; size_t vlstr_buf_size = 0; - unsigned char *cmpd_buf = NULL, *enum_buf = NULL, *vlstr_buf = NULL; + unsigned char *cmpd_buf = NULL; + unsigned char *enum_buf = NULL; + unsigned char *vlstr_buf = NULL; hid_t ret_id; herr_t ret; @@ -6008,75 +6011,75 @@ test_encode(void) *----------------------------------------------------------------------- */ /* Create a compound datatype */ - if ((tid1 = H5Tcreate(H5T_COMPOUND, sizeof(struct s1))) < 0) { + if ((tid1 = H5Tcreate(H5T_COMPOUND, sizeof(struct cmpd))) < 0) { H5_FAILED(); HDprintf("Can't create datatype!\n"); goto error; - } /* end if */ - if (H5Tinsert(tid1, "a", HOFFSET(struct s1, a), H5T_NATIVE_INT) < 0) { + } + if (H5Tinsert(tid1, "a", HOFFSET(struct cmpd, a), H5T_NATIVE_INT) < 0) { H5_FAILED(); HDprintf("Can't insert field 'a'\n"); goto error; - } /* end if */ - if (H5Tinsert(tid1, "b", HOFFSET(struct s1, b), H5T_NATIVE_FLOAT) < 0) { + } + if (H5Tinsert(tid1, "b", HOFFSET(struct cmpd, b), H5T_NATIVE_FLOAT) < 0) { H5_FAILED(); HDprintf("Can't insert field 'b'\n"); goto error; - } /* end if */ - if (H5Tinsert(tid1, "c", HOFFSET(struct s1, c), H5T_NATIVE_LONG) < 0) { + } + if (H5Tinsert(tid1, "c", HOFFSET(struct cmpd, c), H5T_NATIVE_LONG) < 0) { H5_FAILED(); HDprintf("Can't insert field 'c'\n"); goto error; - } /* end if */ - if (H5Tinsert(tid1, "d", HOFFSET(struct s1, d), H5T_NATIVE_DOUBLE) < 0) { + } + if (H5Tinsert(tid1, "d", HOFFSET(struct cmpd, d), H5T_NATIVE_DOUBLE) < 0) { H5_FAILED(); HDprintf("Can't insert field 'd'\n"); goto error; - } /* end if */ + } /* Create a enumerate datatype */ if ((tid2 = H5Tcreate(H5T_ENUM, sizeof(short))) < 0) { H5_FAILED(); HDprintf("Can't create enumerate type\n"); goto error; - } /* end if */ + } if (H5Tenum_insert(tid2, "RED", (enum_val = 0, &enum_val)) < 0) { H5_FAILED(); HDprintf("Can't insert field into enumeration type\n"); goto error; - } /* end if */ + } if (H5Tenum_insert(tid2, "GREEN", (enum_val = 1, &enum_val)) < 0) { H5_FAILED(); HDprintf("Can't insert field into enumeration type\n"); goto error; - } /* end if */ + } if (H5Tenum_insert(tid2, "BLUE", (enum_val = 2, &enum_val)) < 0) { H5_FAILED(); HDprintf("Can't insert field into enumeration type\n"); goto error; - } /* end if */ + } if (H5Tenum_insert(tid2, "ORANGE", (enum_val = 3, &enum_val)) < 0) { H5_FAILED(); HDprintf("Can't insert field into enumeration type\n"); goto error; - } /* end if */ + } if (H5Tenum_insert(tid2, "YELLOW", (enum_val = 4, &enum_val)) < 0) { H5_FAILED(); HDprintf("Can't insert field into enumeration type\n"); goto error; - } /* end if */ + } /* Create a variable-length string type */ if ((tid3 = H5Tcopy(H5T_C_S1)) < 0) { H5_FAILED(); HDprintf("Can't copy a string type\n"); goto error; - } /* end if */ + } if (H5Tset_size(tid3, H5T_VARIABLE) < 0) { H5_FAILED(); HDprintf("Can't the string type to be variable-length\n"); goto error; - } /* end if */ + } /*----------------------------------------------------------------------- * Test encoding and decoding compound, enumerate, and VL string datatypes @@ -6087,12 +6090,12 @@ test_encode(void) H5_FAILED(); HDprintf("Can't encode compound type\n"); goto error; - } /* end if */ + } if (cmpd_buf_size > 0) cmpd_buf = (unsigned char *)HDcalloc((size_t)1, cmpd_buf_size); - /* Try decoding bogus buffer */ + /* Try decoding an incorrect (empty) buffer (should fail) */ H5E_BEGIN_TRY { ret_id = H5Tdecode(cmpd_buf); @@ -6100,7 +6103,7 @@ test_encode(void) H5E_END_TRY; if (ret_id != FAIL) { H5_FAILED(); - HDprintf("Decoded bogus buffer!\n"); + HDprintf("Decoded an empty buffer!\n"); goto error; } @@ -6108,7 +6111,7 @@ test_encode(void) H5_FAILED(); HDprintf("Can't encode compound type\n"); goto error; - } /* end if */ + } /* Decode from the compound buffer and return an object handle */ if ((decoded_tid1 = H5Tdecode(cmpd_buf)) < 0) @@ -6119,26 +6122,26 @@ test_encode(void) H5_FAILED(); HDprintf("Datatype wasn't encoded & decoded identically\n"); goto error; - } /* end if */ + } /* Query member number and member index by name, for compound type. */ if (H5Tget_nmembers(decoded_tid1) != 4) { H5_FAILED(); HDprintf("Can't get member number\n"); goto error; - } /* end if */ + } if (H5Tget_member_index(decoded_tid1, "c") != 2) { H5_FAILED(); HDprintf("Can't get correct index number\n"); goto error; - } /* end if */ + } /* Encode enumerate type in a buffer */ if (H5Tencode(tid2, NULL, &enum_buf_size) < 0) { H5_FAILED(); HDprintf("Can't encode enumerate type\n"); goto error; - } /* end if */ + } if (enum_buf_size > 0) enum_buf = (unsigned char *)HDcalloc((size_t)1, enum_buf_size); @@ -6147,40 +6150,40 @@ test_encode(void) H5_FAILED(); HDprintf("Can't encode enumerate type\n"); goto error; - } /* end if */ + } /* Decode from the enumerate buffer and return an object handle */ if ((decoded_tid2 = H5Tdecode(enum_buf)) < 0) { H5_FAILED(); HDprintf("Can't decode enumerate type\n"); goto error; - } /* end if */ + } /* Verify that the datatype was copied exactly */ if (H5Tequal(decoded_tid2, tid2) <= 0) { H5_FAILED(); HDprintf("Datatype wasn't encoded & decoded identically\n"); goto error; - } /* end if */ + } /* Query member number and member index by name, for enumeration type. */ if (H5Tget_nmembers(decoded_tid2) != 5) { H5_FAILED(); HDprintf("Can't get member number\n"); goto error; - } /* end if */ + } if (H5Tget_member_index(decoded_tid2, "ORANGE") != 3) { H5_FAILED(); HDprintf("Can't get correct index number\n"); goto error; - } /* end if */ + } /* Encode VL string type in a buffer */ if (H5Tencode(tid3, NULL, &vlstr_buf_size) < 0) { H5_FAILED(); HDprintf("Can't encode VL string type\n"); goto error; - } /* end if */ + } if (vlstr_buf_size > 0) vlstr_buf = (unsigned char *)HDcalloc((size_t)1, vlstr_buf_size); @@ -6189,26 +6192,26 @@ test_encode(void) H5_FAILED(); HDprintf("Can't encode VL string type\n"); goto error; - } /* end if */ + } /* Decode from the VL string buffer and return an object handle */ if ((decoded_tid3 = H5Tdecode(vlstr_buf)) < 0) { H5_FAILED(); HDprintf("Can't decode VL string type\n"); goto error; - } /* end if */ + } /* Verify that the datatype was copied exactly */ if (H5Tequal(decoded_tid3, tid3) <= 0) { H5_FAILED(); HDprintf("Datatype wasn't encoded & decoded identically\n"); goto error; - } /* end if */ + } if (!H5Tis_variable_str(decoded_tid3)) { H5_FAILED(); HDprintf("Datatype wasn't encoded & decoded identically\n"); goto error; - } /* end if */ + } /*----------------------------------------------------------------------- * Commit and reopen the compound, enumerate, VL string datatypes @@ -6219,17 +6222,17 @@ test_encode(void) H5_FAILED(); HDprintf("Can't commit compound datatype\n"); goto error; - } /* end if */ + } if (H5Tclose(tid1) < 0) { H5_FAILED(); HDprintf("Can't close datatype\n"); goto error; - } /* end if */ + } if (H5Tclose(decoded_tid1) < 0) { H5_FAILED(); HDprintf("Can't close datatype\n"); goto error; - } /* end if */ + } HDfree(cmpd_buf); cmpd_buf_size = 0; @@ -6238,17 +6241,17 @@ test_encode(void) H5_FAILED(); HDprintf("Can't commit compound datatype\n"); goto error; - } /* end if */ + } if (H5Tclose(tid2) < 0) { H5_FAILED(); HDprintf("Can't close datatype\n"); goto error; - } /* end if */ + } if (H5Tclose(decoded_tid2) < 0) { H5_FAILED(); HDprintf("Can't close datatype\n"); goto error; - } /* end if */ + } HDfree(enum_buf); enum_buf_size = 0; @@ -6257,17 +6260,17 @@ test_encode(void) H5_FAILED(); HDprintf("Can't commit vl string datatype\n"); goto error; - } /* end if */ + } if (H5Tclose(tid3) < 0) { H5_FAILED(); HDprintf("Can't close datatype\n"); goto error; - } /* end if */ + } if (H5Tclose(decoded_tid3) < 0) { H5_FAILED(); HDprintf("Can't close datatype\n"); goto error; - } /* end if */ + } HDfree(vlstr_buf); vlstr_buf_size = 0; @@ -6288,7 +6291,7 @@ test_encode(void) H5_FAILED(); HDprintf("Can't encode compound type\n"); goto error; - } /* end if */ + } if (cmpd_buf_size > 0) cmpd_buf = (unsigned char *)HDcalloc((size_t)1, cmpd_buf_size); @@ -6297,7 +6300,7 @@ test_encode(void) H5_FAILED(); HDprintf("Can't encode compound type\n"); goto error; - } /* end if */ + } /* Decode from the compound buffer and return an object handle */ if ((decoded_tid1 = H5Tdecode(cmpd_buf)) < 0) @@ -6308,26 +6311,26 @@ test_encode(void) H5_FAILED(); HDprintf("Datatype wasn't encoded & decoded identically\n"); goto error; - } /* end if */ + } /* Query member number and member index by name, for compound type. */ if (H5Tget_nmembers(decoded_tid1) != 4) { H5_FAILED(); HDprintf("Can't get member number\n"); goto error; - } /* end if */ + } if (H5Tget_member_index(decoded_tid1, "c") != 2) { H5_FAILED(); HDprintf("Can't get correct index number\n"); goto error; - } /* end if */ + } /* Encode enumerate type in a buffer */ if (H5Tencode(tid2, NULL, &enum_buf_size) < 0) { H5_FAILED(); HDprintf("Can't encode enumerate type\n"); goto error; - } /* end if */ + } if (enum_buf_size > 0) enum_buf = (unsigned char *)HDcalloc((size_t)1, enum_buf_size); @@ -6336,40 +6339,40 @@ test_encode(void) H5_FAILED(); HDprintf("Can't encode enumerate type\n"); goto error; - } /* end if */ + } /* Decode from the enumerate buffer and return an object handle */ if ((decoded_tid2 = H5Tdecode(enum_buf)) < 0) { H5_FAILED(); HDprintf("Can't decode enumerate type\n"); goto error; - } /* end if */ + } /* Verify that the datatype was copied exactly */ if (H5Tequal(decoded_tid2, tid2) <= 0) { H5_FAILED(); HDprintf("Datatype wasn't encoded & decoded identically\n"); goto error; - } /* end if */ + } /* Query member number and member index by name, for enumeration type. */ if (H5Tget_nmembers(decoded_tid2) != 5) { H5_FAILED(); HDprintf("Can't get member number\n"); goto error; - } /* end if */ + } if (H5Tget_member_index(decoded_tid2, "ORANGE") != 3) { H5_FAILED(); HDprintf("Can't get correct index number\n"); goto error; - } /* end if */ + } /* Encode VL string type in a buffer */ if (H5Tencode(tid3, NULL, &vlstr_buf_size) < 0) { H5_FAILED(); HDprintf("Can't encode VL string type\n"); goto error; - } /* end if */ + } if (vlstr_buf_size > 0) vlstr_buf = (unsigned char *)HDcalloc((size_t)1, vlstr_buf_size); @@ -6378,14 +6381,14 @@ test_encode(void) H5_FAILED(); HDprintf("Can't encode VL string type\n"); goto error; - } /* end if */ + } /* Decode from the VL string buffer and return an object handle */ if ((decoded_tid3 = H5Tdecode(vlstr_buf)) < 0) { H5_FAILED(); HDprintf("Can't decode VL string type\n"); goto error; - } /* end if */ + } HDfree(vlstr_buf); /* Verify that the datatype was copied exactly */ @@ -6393,12 +6396,12 @@ test_encode(void) H5_FAILED(); HDprintf("Datatype wasn't encoded & decoded identically\n"); goto error; - } /* end if */ + } if (!H5Tis_variable_str(decoded_tid3)) { H5_FAILED(); HDprintf("Datatype wasn't encoded & decoded identically\n"); goto error; - } /* end if */ + } /*----------------------------------------------------------------------- * Test the reference count of the decoded datatypes @@ -6410,19 +6413,19 @@ test_encode(void) H5_FAILED(); HDprintf("Decoded datatype has incorrect reference count\n"); goto error; - } /* end if */ + } if (H5Iget_ref(decoded_tid2) != 1) { H5_FAILED(); HDprintf("Decoded datatype has incorrect reference count\n"); goto error; - } /* end if */ + } if (H5Iget_ref(decoded_tid3) != 1) { H5_FAILED(); HDprintf("Decoded datatype has incorrect reference count\n"); goto error; - } /* end if */ + } /* Make sure the reference counts for the decoded datatypes can be * decremented and the datatypes are closed. */ @@ -6430,19 +6433,19 @@ test_encode(void) H5_FAILED(); HDprintf("Decoded datatype can't close\n"); goto error; - } /* end if */ + } if (H5Idec_ref(decoded_tid2) != 0) { H5_FAILED(); HDprintf("Decoded datatype can't close\n"); goto error; - } /* end if */ + } if (H5Idec_ref(decoded_tid3) != 0) { H5_FAILED(); HDprintf("Decoded datatype can't close\n"); goto error; - } /* end if */ + } /* Make sure the decoded datatypes are already closed. */ H5E_BEGIN_TRY @@ -6487,23 +6490,23 @@ test_encode(void) H5_FAILED(); HDprintf("Can't close datatype\n"); goto error; - } /* end if */ + } if (H5Tclose(tid2) < 0) { H5_FAILED(); HDprintf("Can't close datatype\n"); goto error; - } /* end if */ + } if (H5Tclose(tid3) < 0) { H5_FAILED(); HDprintf("Can't close datatype\n"); goto error; - } /* end if */ + } if (H5Fclose(file) < 0) { H5_FAILED(); HDprintf("Can't close file\n"); goto error; - } /* end if */ + } HDfree(cmpd_buf); HDfree(enum_buf); -- cgit v0.12