From 084866be6884a0cab243fd10da079bc555045f4a Mon Sep 17 00:00:00 2001 From: Jordan Henderson Date: Wed, 2 Oct 2024 18:09:46 -0500 Subject: [PATCH] Disable H5Tset_size for array, vlen and complex number datatypes --- src/H5T.c | 28 +++------ src/H5Tpublic.h | 18 +----- test/dtypes.c | 162 ++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 139 insertions(+), 69 deletions(-) diff --git a/src/H5T.c b/src/H5T.c index c3e373e0e7c..f1b783f7673 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -2918,7 +2918,10 @@ H5Tset_size(hid_t type_id, size_t size) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "only strings may be variable length"); if (H5T_ENUM == dt->shared->type && dt->shared->u.enumer.nmembs > 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); - if (H5T_REFERENCE == dt->shared->type) + if (H5T_ARRAY == dt->shared->type || H5T_REFERENCE == dt->shared->type + || H5T_COMPLEX == dt->shared->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for this datatype"); + if (H5T_VLEN == dt->shared->type && H5T_VLEN_STRING != dt->shared->u.vlen.type) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for this datatype"); /* Modify the datatype */ @@ -4725,30 +4728,15 @@ H5T__set_size(H5T_t *dt, size_t size) assert(dt); assert(dt->shared); assert(size != 0); + assert(H5T_ARRAY != dt->shared->type); assert(H5T_REFERENCE != dt->shared->type); + assert(H5T_COMPLEX != dt->shared->type); + assert(H5T_VLEN != dt->shared->type || H5T_VLEN_STRING == dt->shared->u.vlen.type); assert(!(H5T_ENUM == dt->shared->type && 0 == dt->shared->u.enumer.nmembs)); if (dt->shared->parent) { - size_t new_size = size; - - if (dt->shared->type == H5T_COMPLEX) { - if ((new_size % 2) != 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, - "new datatype size is not evenly divisible by 2"); - - new_size /= 2; - } - - if (H5T__set_size(dt->shared->parent, new_size) < 0) + if (H5T__set_size(dt->shared->parent, size) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for parent data type"); - - /* Adjust size of datatype appropriately */ - if (dt->shared->type == H5T_ARRAY) - dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem; - else if (dt->shared->type == H5T_COMPLEX) - dt->shared->size = 2 * dt->shared->parent->shared->size; - else if (dt->shared->type != H5T_VLEN) - dt->shared->size = dt->shared->parent->shared->size; } else { if (H5T_IS_ATOMIC(dt->shared)) { diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h index 7ee092fe2c4..efb68de42e0 100644 --- a/src/H5Tpublic.h +++ b/src/H5Tpublic.h @@ -2508,22 +2508,10 @@ H5_DLL hid_t H5Tget_native_type(hid_t type_id, H5T_direction_t direction); * decrease the size of a compound datatype, but the function will * fail if the new size is too small to accommodate all member fields. * - * \li Variable-length datatypes: This function sets the size of - * the base datatype for the variable-length datatype. - * - * \li Array datatypes: This function sets the size of the base - * datatype for the array datatype. The array datatype's size is - * then adjusted to be the size of the base datatype multiplied - * by the number of elements in the array datatype's dimensions. - * - * \li Complex number datatypes: The size set for a complex number - * datatype is the size for the entire datatype, which is shared - * evenly among the datatype's real and imaginary parts. Thus, - * the specified size must be a multiple of 2. - * * \li Ineligible datatypes: This function cannot be used with - * enumerated datatypes (#H5T_ENUM) or reference datatypes - * (#H5T_REFERENCE). + * enumerated datatypes (#H5T_ENUM), array datatypes (#H5T_ARRAY), + * variable-length array datatypes (#H5T_VLEN), reference datatypes + * (#H5T_REFERENCE), or complex number datatypes (#H5T_COMPLEX). * * \see H5Tget_size() * diff --git a/test/dtypes.c b/test/dtypes.c index 7c9452fe983..b86c32c9117 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -6770,7 +6770,6 @@ test_complex_type(void) const char *driver_name; char filename[256]; hsize_t dims[1]; - herr_t status; hid_t fid = H5I_INVALID_HID; hid_t space_id = H5I_INVALID_HID; hid_t dset_id = H5I_INVALID_HID; @@ -6996,60 +6995,29 @@ test_complex_type(void) } /* - * Check that H5Tset_size and H5Tset_offset work correctly on a complex - * number type (H5Tset_size sets the size for the whole datatype with - * each of the two parts of the type sharing half the size, while - * H5Tset_offset sets the offset for the base datatype) + * Check that H5Tset_offset works correctly on a complex number type + * (H5Tset_offset sets the offset for the base datatype) */ if ((complex_type = H5Tcopy(H5T_NATIVE_FLOAT_COMPLEX)) < 0) { H5_FAILED(); printf("Can't copy H5T_NATIVE_FLOAT_COMPLEX datatype\n"); goto error; } - - H5E_BEGIN_TRY - { - /* Size must be a multiple of 2 since the real and - * imaginary parts will each share half the datatype size - */ - status = H5Tset_size(complex_type, 13); - } - H5E_END_TRY - if (status >= 0) { - H5_FAILED(); - printf("Changed the size of complex number type to a size that isn't a multiple of 2\n"); - goto error; - } - if (H5Tset_offset(complex_type, 3) < 0) { H5_FAILED(); printf("Can't set offset for complex number type's base datatype\n"); goto error; } - if (H5Tset_size(complex_type, 128) < 0) { - H5_FAILED(); - printf("Can't change size of complex number type\n"); - goto error; - } - if ((base_type = H5Tget_super(complex_type)) < 0) { H5_FAILED(); printf("Can't get base datatype of complex number datatype\n"); goto error; } - - type_size = H5Tget_size(base_type); - if (0 == type_size || 64 != type_size) { - H5_FAILED(); - printf("Invalid size for complex number type's base datatype\n"); - goto error; - } if (3 != H5Tget_offset(base_type)) { H5_FAILED(); printf("Invalid offset value for complex number type's base datatype\n"); goto error; } - if (H5Tclose(base_type) < 0) { H5_FAILED(); printf("Can't close datatype\n"); @@ -8821,6 +8789,131 @@ test_array_cmpd_vl(void) return 1; } /* end test_array_cmpd_vl() */ +/*------------------------------------------------------------------------- + * Function: test_set_size_invalid + * + * Purpose: Tests that H5Tset_size fails when called on an array, + * variable-length, reference or complex number datatype. + * + * Return: Success: 0 + * Failure: number of errors + * + *------------------------------------------------------------------------- + */ +static int +test_set_size_invalid(void) +{ + hsize_t array_dims[] = { 10 }; + hid_t array_tid = H5I_INVALID_HID; + hid_t vlen_tid = H5I_INVALID_HID; + hid_t ref_tid = H5I_INVALID_HID; + hid_t complex_tid = H5I_INVALID_HID; + hid_t string_tid = H5I_INVALID_HID; + herr_t status; + + TESTING("H5Tset_size on ineligible datatypes"); + + if ((array_tid = H5Tarray_create2(H5T_NATIVE_INT, 1, array_dims)) < 0) + TEST_ERROR; + if ((vlen_tid = H5Tvlen_create(array_tid)) < 0) + TEST_ERROR; + if ((ref_tid = H5Tcopy(H5T_STD_REF)) < 0) + TEST_ERROR; + if ((complex_tid = H5Tcomplex_create(H5T_NATIVE_FLOAT)) < 0) + TEST_ERROR; + if ((string_tid = H5Tcopy(H5T_C_S1)) < 0) + TEST_ERROR; + + H5E_BEGIN_TRY + { + status = H5Tset_size(array_tid, 100); + } + H5E_END_TRY; + if (status >= 0) { + H5_FAILED(); + AT(); + printf("Set size on array datatype\n"); + goto error; + } + + H5E_BEGIN_TRY + { + status = H5Tset_size(vlen_tid, 100); + } + H5E_END_TRY; + if (status >= 0) { + H5_FAILED(); + AT(); + printf("Set size on variable-length datatype\n"); + goto error; + } + + H5E_BEGIN_TRY + { + status = H5Tset_size(ref_tid, 100); + } + H5E_END_TRY; + if (status >= 0) { + H5_FAILED(); + AT(); + printf("Set size on reference datatype\n"); + goto error; + } + + H5E_BEGIN_TRY + { + status = H5Tset_size(complex_tid, 100); + } + H5E_END_TRY; + if (status >= 0) { + H5_FAILED(); + AT(); + printf("Set size on complex number datatype\n"); + goto error; + } + + /* Should still be able to convert a variable-length string datatype + * back into a fixed-length string datatype even though variable-length + * string datatypes are tested as H5T_VLEN + */ + if (H5Tset_size(string_tid, H5T_VARIABLE) < 0) + TEST_ERROR; + if (H5Tset_size(string_tid, 100) < 0) { + H5_FAILED(); + AT(); + printf("Unable to set size on variable-length string datatype\n"); + goto error; + } + + if (H5Tclose(array_tid) < 0) + TEST_ERROR; + if (H5Tclose(vlen_tid) < 0) + TEST_ERROR; + if (H5Tclose(ref_tid) < 0) + TEST_ERROR; + if (H5Tclose(complex_tid) < 0) + TEST_ERROR; + if (H5Tclose(string_tid) < 0) + TEST_ERROR; + + PASSED(); + + return 0; + +error: + H5E_BEGIN_TRY + { + H5Tclose(array_tid); + H5Tclose(vlen_tid); + H5Tclose(ref_tid); + H5Tclose(complex_tid); + H5Tclose(string_tid); + } + H5E_END_TRY + + return 1; +} /* end test_set_size_invalid() */ + /*------------------------------------------------------------------------- * Function: test_encode * @@ -12785,6 +12878,7 @@ main(void) nerrors += test_opaque(); nerrors += test_set_order(); nerrors += test_array_cmpd_vl(); + nerrors += test_set_size_invalid(); nerrors += test__Float16(); nerrors += test_complex_type();