diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a3a017f..a289728e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -356,6 +356,32 @@ if (nexus) message(FATAL_ERROR "HDF4 library not found. Please install libhdf4-dev or hdf-devel") endif() + # HDF4 4.4.0 changed the Vgetname() prototype from + # int32 Vgetname(int32 vkey, char *vgname) + # to + # int32 Vgetname(int32 vkey, char *vgname, size_t *buf_size) + # (a fix for a buffer-overflow issue). Detect which one is present so + # PNeXus.cpp can call the right form for both old and new HDF4 releases. + include(CheckCXXSourceCompiles) + set(CMAKE_REQUIRED_INCLUDES ${HDF4_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_LIBRARIES ${HDF4_LIBRARIES}) + check_cxx_source_compiles(" + #include + int main() { + int32 vkey = 0; + char name[64]; + size_t buf_size = sizeof(name); + Vgetname(vkey, name, &buf_size); + return 0; + } + " HDF4_VGETNAME_HAS_BUFSIZE) + unset(CMAKE_REQUIRED_INCLUDES) + unset(CMAKE_REQUIRED_LIBRARIES) + + if (HDF4_VGETNAME_HAS_BUFSIZE) + add_compile_definitions(HDF4_VGETNAME_HAS_BUFSIZE) + endif (HDF4_VGETNAME_HAS_BUFSIZE) + add_compile_definitions(HAVE_HDF4) endif (HAVE_HDF4) add_compile_definitions(PNEXUS_ENABLED) diff --git a/src/external/nexus/PNeXus.cpp b/src/external/nexus/PNeXus.cpp index 77b31981..a0b7dd74 100644 --- a/src/external/nexus/PNeXus.cpp +++ b/src/external/nexus/PNeXus.cpp @@ -157,6 +157,28 @@ std::string nxs::getIso8601TimestampLocal() { } #ifdef HAVE_HDF4 +namespace { +/** + * @brief Portable wrapper around HDF4's Vgetname(). + * + * HDF4 4.4.0 changed the Vgetname() prototype from + * `int32 Vgetname(int32 vkey, char *vgname)` to + * `int32 Vgetname(int32 vkey, char *vgname, size_t *buf_size)` (a fix for a + * buffer-overflow issue). HDF4_VGETNAME_HAS_BUFSIZE is set by CMake based on + * a compile-time check of the header actually in use, so this call works + * against both old (< 4.4.0) and new (>= 4.4.0) HDF4 releases. + */ +int32 Vgetname_portable(int32 vkey, char *vgname, size_t bufSize) +{ +#ifdef HDF4_VGETNAME_HAS_BUFSIZE + return Vgetname(vkey, vgname, &bufSize); +#else + (void)bufSize; + return Vgetname(vkey, vgname); +#endif +} +} // namespace + //============================================================================= // nxH4::PNeXusDeadTime Constructor //============================================================================= @@ -2633,7 +2655,7 @@ int32 nxH4::PNeXus::FindDatasetRefByPath(const std::string& path) int32 vg_id = Vattach(fFileId, vgroup_refs[i], "r"); if (vg_id != FAIL) { char vg_name[VGNAMELENMAX]; - if (Vgetname(vg_id, vg_name) != FAIL) { + if (Vgetname_portable(vg_id, vg_name, sizeof(vg_name)) != FAIL) { if (CaseInsensitiveEquals(vg_name, components[0])) { current_vg_ref = vgroup_refs[i]; Vdetach(vg_id); @@ -2667,7 +2689,7 @@ int32 nxH4::PNeXus::FindDatasetRefByPath(const std::string& path) int32 child_vg_id = Vattach(fFileId, ref, "r"); if (child_vg_id != FAIL) { char child_name[VGNAMELENMAX]; - if (Vgetname(child_vg_id, child_name) != FAIL) { + if (Vgetname_portable(child_vg_id, child_name, sizeof(child_name)) != FAIL) { if (CaseInsensitiveEquals(child_name, components[comp_idx])) { current_vg_ref = ref; found = true;