Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Commit 17d8dfd

Browse files
authored
Fix off-by-one in char_buffer_length. (#1060)
1 parent abe8c27 commit 17d8dfd

File tree

2 files changed

+29
-14
lines changed

2 files changed

+29
-14
lines changed

include/highfive/bits/H5Converter_misc.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,14 @@ enum class BufferMode { Read, Write };
103103
///
104104
/// \brief String length in bytes excluding the `\0`.
105105
///
106-
inline size_t char_buffer_size(char const* const str, size_t max_string_length) {
107-
for (size_t i = 0; i <= max_string_length; ++i) {
106+
inline size_t char_buffer_length(char const* const str, size_t max_string_size) {
107+
for (size_t i = 0; i < max_string_size; ++i) {
108108
if (str[i] == '\0') {
109109
return i;
110110
}
111111
}
112112

113-
return max_string_length;
113+
return max_string_size;
114114
}
115115

116116

@@ -229,7 +229,7 @@ struct StringBuffer {
229229
/// `length() + 1` bytes long.
230230
size_t length() const {
231231
if (buffer.isNullTerminated()) {
232-
return char_buffer_size(data(), buffer.string_size);
232+
return char_buffer_length(data(), buffer.string_size);
233233
} else {
234234
return buffer.string_max_length;
235235
}

tests/unit/test_string.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -207,30 +207,45 @@ void check_multiple_string(File file, size_t string_length) {
207207
}
208208

209209
template <class CreateTraits>
210-
void check_supposedly_nullterm(HighFive::File& file) {
210+
void check_supposedly_nullterm(HighFive::File& file, size_t string_length) {
211211
auto dataspace = HighFive::DataSpace::Scalar();
212-
auto datatype = HighFive::FixedLengthStringType(5, HighFive::StringPadding::NullTerminated);
213-
auto obj = CreateTraits::create(file, "not_null_terminated", dataspace, datatype);
214-
215-
// Creates a 5 byte, "null-terminated", fixed-length string. The first five
216-
// bytes are filled with "GROUP". Clearly, this isn't null-terminated. However,
217-
// h5py will read it back as "GROUP", HDF5 allows us to create these; and they're
212+
auto datatype = HighFive::FixedLengthStringType(string_length,
213+
HighFive::StringPadding::NullTerminated);
214+
auto obj = CreateTraits::create(file,
215+
"not_null_terminated_" + std::to_string(string_length),
216+
dataspace,
217+
datatype);
218+
219+
// Creates an `string_length` byte, "null-terminated", fixed-length string. The first
220+
// `string_length` bytes are filled with "a"s. Clearly, this isn't null-terminated. However,
221+
// h5py will read it back, HDF5 allows us to create these; and they're
218222
// found in the wild.
219-
std::string value = "GROUP";
223+
std::string value(string_length, 'a');
220224
obj.write_raw(value.c_str(), datatype);
221225

222226
auto actual = obj.template read<std::string>();
223227
REQUIRE(actual == value);
224228
}
225229

230+
template <class CreateTraits>
231+
void check_supposedly_nullterm_scan(HighFive::File& file) {
232+
for (size_t n = 1; n < 256; ++n) {
233+
check_supposedly_nullterm<CreateTraits>(file, n);
234+
}
235+
236+
check_supposedly_nullterm<CreateTraits>(file, 4091);
237+
check_supposedly_nullterm<CreateTraits>(file, 4092);
238+
check_supposedly_nullterm<CreateTraits>(file, 4093);
239+
}
240+
226241
TEST_CASE("HighFiveSTDString (attribute, nullterm cornercase)") {
227242
auto file = HighFive::File("not_null_terminated_attribute.h5", HighFive::File::Truncate);
228-
check_supposedly_nullterm<testing::AttributeCreateTraits>(file);
243+
check_supposedly_nullterm_scan<testing::AttributeCreateTraits>(file);
229244
}
230245

231246
TEST_CASE("HighFiveSTDString (dataset, nullterm cornercase)") {
232247
auto file = HighFive::File("not_null_terminated_dataset.h5", HighFive::File::Truncate);
233-
check_supposedly_nullterm<testing::DataSetCreateTraits>(file);
248+
check_supposedly_nullterm_scan<testing::DataSetCreateTraits>(file);
234249
}
235250

236251
TEST_CASE("HighFiveSTDString (dataset, single, short)") {

0 commit comments

Comments
 (0)