From 426a7f82f6ce4d75ec8bfd30d1fa198c49efaa97 Mon Sep 17 00:00:00 2001 From: Mark Kittisopikul Date: Sun, 16 Jul 2023 00:31:57 -0400 Subject: [PATCH] Avoid truncating at null byte when copying to std::string (#3083) --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- c++/src/H5DataSet.cpp | 2 +- c++/test/dsets.cpp | 78 ++++++++++++++++++++++++++++++++++++++++ release_docs/RELEASE.txt | 7 ++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/c++/src/H5DataSet.cpp b/c++/src/H5DataSet.cpp index 7d19a6df9c3..40b40f2f21e 100644 --- a/c++/src/H5DataSet.cpp +++ b/c++/src/H5DataSet.cpp @@ -729,7 +729,7 @@ DataSet::p_read_fixed_len(const hid_t mem_type_id, const hid_t mem_space_id, con } // Get string from the C char* and release resource allocated locally - strg = strg_C; + strg = H5std_string(strg_C, data_size); delete[] strg_C; } } diff --git a/c++/test/dsets.cpp b/c++/test/dsets.cpp index e1cee972eaa..9de6db1319f 100644 --- a/c++/test/dsets.cpp +++ b/c++/test/dsets.cpp @@ -1363,6 +1363,83 @@ test_operator(H5File &file) } } // test_operator +/*------------------------------------------------------------------------- + * Function: test_read_string + * + * Purpose Tests DataSet::read(H5std_string ...) + * + * Return Success: 0 + * + * Failure: -1 + *------------------------------------------------------------------------- + */ +static herr_t +test_read_string(H5File &file) +{ + SUBTEST("DataSet::read(H5std_string)"); + try { + const H5std_string DATASET_NAME("test_read_string"); + const unsigned long NX = 8; + const char DATA[NX] = {'a', 0, 0, 0, 0, 0, 0, 'Z'}; + const H5std_string EXPECTED_STR = H5std_string(DATA, NX); + H5std_string str; + + /* + * Write characters with internal null bytes + */ + + PredType datatype(PredType::NATIVE_INT8); + hsize_t dimsf[RANK1] = {NX}; + DataSpace dataspace(RANK1, dimsf); + DataSet dataset = file.createDataSet(DATASET_NAME, datatype, dataspace); + dataset.write(DATA, datatype); + dataset.close(); + + /* + * Read characters with internal null bytes as a string. + * The read std::string should NOT be truncated at the first null byte. + */ + + dataset = file.openDataSet(DATASET_NAME); + dataset.read(str, datatype); + dataset.close(); + verify_val(str.length(), NX, "test_read_string", __LINE__, __FILE__); + verify_val(str, EXPECTED_STR, "test_read_string", __LINE__, __FILE__); + + /* + * Write the H5std_string back to the dataset. + */ + dataset = file.openDataSet(DATASET_NAME); + dataset.write(str, datatype); + dataset.close(); + + /* + * Read characters with internal null bytes as a string, after rewrite. + * The read std::string should NOT be truncated at the first null byte. + */ + + dataset = file.openDataSet(DATASET_NAME); + dataset.read(str, datatype); + dataset.close(); + verify_val(str.length(), NX, "test_read_string", __LINE__, __FILE__); + verify_val(str, EXPECTED_STR, "test_read_string", __LINE__, __FILE__); + + /* + * Success + */ + PASSED(); + return 0; + } + catch (Exception &E) { + // H5_FAILED should probably be invoked before verify_val + H5_FAILED(); + issue_fail_msg("test_read_string", __LINE__, __FILE__); + + // clean up and return with failure + return -1; + } +} // test_read_string + /*------------------------------------------------------------------------- * Function: test_dset * @@ -1403,6 +1480,7 @@ test_dset() nerrors += test_virtual() < 0 ? 1 : 0; nerrors += test_operator(file) < 0 ? 1 : 0; nerrors += test_chunk_cache(fapl) < 0 ? 1 : 0; + nerrors += test_read_string(file) < 0 ? 1 : 0; // Close group "emit diagnostics". grp.close(); diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 1c12071aaab..bdd9a1e2044 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -477,6 +477,13 @@ Bug Fixes since HDF5-1.14.0 release Fixes GitHub issue #2432 + - Reading a H5std_string (std::string) via a C++ DataSet previously + truncated the string at the first null byte as if reading a C string. + Fixed length datasets are now read into H5std_string as a fixed length + string of the appropriate size. Variable length datasets will still be + truncated at the first null byte. + + Fixes Github issue #3034 Java Library ------------