From 7ce34755ef286a0661bec8b598190f1e4605cbf7 Mon Sep 17 00:00:00 2001
From: Lucas Givord <lucas.givord@kitware.com>
Date: Mon, 28 Oct 2024 11:32:51 +0100
Subject: [PATCH] vtkHDF: fix overflow issue

Reader regarding overlappingAMR can have an overflow issue due to his
offset. Few places in the writer should rely on vtkIdType instead of int
too.

(cherry picked from commit fd2e7a9aa0b5069bdacfd6280da9865656622bee)
---
 IO/HDF/vtkHDFReaderImplementation.cxx | 17 ++++++++---------
 IO/HDF/vtkHDFReaderImplementation.h   | 10 +++++-----
 IO/HDF/vtkHDFUtilities.h              | 10 ++++++++++
 IO/HDF/vtkHDFWriter.cxx               | 14 +++++++-------
 4 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/IO/HDF/vtkHDFReaderImplementation.cxx b/IO/HDF/vtkHDFReaderImplementation.cxx
index d77ec3d320a..a3e1c098836 100644
--- a/IO/HDF/vtkHDFReaderImplementation.cxx
+++ b/IO/HDF/vtkHDFReaderImplementation.cxx
@@ -1312,7 +1312,7 @@ bool vtkHDFReader::Implementation::ComputeAMROffsetsPerLevels(
     std::vector<int> numberOfBox;
     numberOfBox.resize(numberOfSteps);
 
-    std::vector<int> boxOffsets;
+    std::vector<vtkIdType> boxOffsets;
     boxOffsets.resize(numberOfSteps);
 
     // Due to an error in the VTKHDF File Format 2.2, few array names miss an 's' at
@@ -1369,7 +1369,7 @@ bool vtkHDFReader::Implementation::ComputeAMROffsetsPerLevels(
       return false;
     }
 
-    if (H5Dread(boxOffsetID, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, boxOffsets.data()) < 0)
+    if (H5Dread(boxOffsetID, VTK_ID_H5T, H5S_ALL, H5S_ALL, H5P_DEFAULT, boxOffsets.data()) < 0)
     {
       vtkErrorWithObjectMacro(this->Reader, << "Error reading hyperslab from ");
       return false;
@@ -1419,10 +1419,9 @@ bool vtkHDFReader::Implementation::ComputeAMROffsetsPerLevels(
           return false;
         }
 
-        std::vector<int> cellOffsets;
+        std::vector<vtkIdType> cellOffsets;
         cellOffsets.resize(numberOfSteps);
-        if (H5Dread(constantID, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, cellOffsets.data()) <
-          0)
+        if (H5Dread(constantID, VTK_ID_H5T, H5S_ALL, H5S_ALL, H5P_DEFAULT, cellOffsets.data()) < 0)
         {
           vtkErrorWithObjectMacro(this->Reader, << "Error reading hyperslab from ");
           return false;
@@ -1440,7 +1439,7 @@ bool vtkHDFReader::Implementation::ComputeAMROffsetsPerLevels(
             this->AMRInformation.FieldOffsetsPerLevel[name].push_back(cellOffsets[step]);
             if (step + 1 < static_cast<int>(cellOffsets.size()))
             {
-              int fieldSize = cellOffsets[step + 1] - cellOffsets[step];
+              vtkIdType fieldSize = cellOffsets[step + 1] - cellOffsets[step];
               this->AMRInformation.FieldSizesPerLevel[name].push_back(fieldSize);
             }
             else
@@ -1494,8 +1493,8 @@ bool vtkHDFReader::Implementation::ReadLevelTopology(unsigned int level,
     return false;
   }
 
-  unsigned int numberOfDatasets = static_cast<unsigned int>(amrBoxRawData.size() / 6);
-  for (unsigned int dataSetIndex = 0; dataSetIndex < numberOfDatasets; ++dataSetIndex)
+  vtkIdType numberOfDatasets = static_cast<vtkIdType>(amrBoxRawData.size() / 6);
+  for (vtkIdType dataSetIndex = 0; dataSetIndex < numberOfDatasets; ++dataSetIndex)
   {
     int* currentAMRBoxRawData = amrBoxRawData.data() + (6 * dataSetIndex);
     vtkAMRBox amrBox(currentAMRBoxRawData);
@@ -1617,7 +1616,7 @@ bool vtkHDFReader::Implementation::ReadLevelData(unsigned int level,
               {
                 cellOffset =
                   this->AMRInformation.FieldOffsetsPerLevel[name][level] / numberOfDatasets;
-                int fieldSize = this->AMRInformation.FieldSizesPerLevel[name][level];
+                vtkIdType fieldSize = this->AMRInformation.FieldSizesPerLevel[name][level];
                 if (fieldSize == -1)
                 {
                   dataSize = (dataSize - cellOffset);
diff --git a/IO/HDF/vtkHDFReaderImplementation.h b/IO/HDF/vtkHDFReaderImplementation.h
index caffcdc3e9d..e27da9df01f 100644
--- a/IO/HDF/vtkHDFReaderImplementation.h
+++ b/IO/HDF/vtkHDFReaderImplementation.h
@@ -289,11 +289,11 @@ private:
   struct AMRBlocksInformation
   {
     std::vector<int> BlocksPerLevel;
-    std::vector<int> BlockOffsetsPerLevel;
-    std::map<std::string, std::vector<int>> CellOffsetsPerLevel;
-    std::map<std::string, std::vector<int>> PointOffsetsPerLevel;
-    std::map<std::string, std::vector<int>> FieldOffsetsPerLevel;
-    std::map<std::string, std::vector<int>> FieldSizesPerLevel;
+    std::vector<vtkIdType> BlockOffsetsPerLevel;
+    std::map<std::string, std::vector<vtkIdType>> CellOffsetsPerLevel;
+    std::map<std::string, std::vector<vtkIdType>> PointOffsetsPerLevel;
+    std::map<std::string, std::vector<vtkIdType>> FieldOffsetsPerLevel;
+    std::map<std::string, std::vector<vtkIdType>> FieldSizesPerLevel;
 
     void Clear()
     {
diff --git a/IO/HDF/vtkHDFUtilities.h b/IO/HDF/vtkHDFUtilities.h
index 6cbbac1ec4f..ec7609ef2ff 100644
--- a/IO/HDF/vtkHDFUtilities.h
+++ b/IO/HDF/vtkHDFUtilities.h
@@ -17,6 +17,16 @@
 
 VTK_ABI_NAMESPACE_BEGIN
 
+#if VTK_ID_TYPE_IMPL == VTK_LONG_LONG
+#define VTK_ID_H5T H5T_NATIVE_LLONG
+#elif VTK_ID_TYPE_IMPL == VTK_LONG
+#define VTK_ID_H5T H5T_NATIVE_LONG
+#elif VTK_ID_TYPE_IMPL == VTK_INT
+#define VTK_ID_H5T H5T_NATIVE_INT
+#else
+#error "No HDF5 type available for vtkIdType"
+#endif
+
 namespace vtkHDFUtilities
 {
 const std::string VTKHDF_ROOT_PATH = "/VTKHDF";
diff --git a/IO/HDF/vtkHDFWriter.cxx b/IO/HDF/vtkHDFWriter.cxx
index 481e6ef6d96..9b5930af07c 100644
--- a/IO/HDF/vtkHDFWriter.cxx
+++ b/IO/HDF/vtkHDFWriter.cxx
@@ -467,13 +467,13 @@ bool vtkHDFWriter::UpdateStepsGroup(vtkPolyData* input)
     H5Dopen(stepsGroup, "ConnectivityIdOffsets", H5P_DEFAULT);
 
   // Get the connectivity offsets for the previous timestep
-  std::vector<int> allValues;
+  std::vector<vtkIdType> allValues;
   allValues.resize(NUM_POLY_DATA_TOPOS * (this->CurrentTimeIndex + 1));
-  H5Dread(connectivityOffsetsHandle, H5T_NATIVE_INT, H5Dget_space(connectivityOffsetsHandle),
-    H5S_ALL, H5P_DEFAULT, allValues.data());
+  H5Dread(connectivityOffsetsHandle, VTK_ID_H5T, H5Dget_space(connectivityOffsetsHandle), H5S_ALL,
+    H5P_DEFAULT, allValues.data());
 
   // Offset the offset by the previous timestep's offset
-  std::vector<int> connectivityOffsetArray{ 0, 0, 0, 0 };
+  std::vector<vtkIdType> connectivityOffsetArray{ 0, 0, 0, 0 };
   auto cellArrayTopos = this->Impl->GetCellArraysForTopos(input);
 
   bool geometryUpdated = this->HasGeometryChangedFromPreviousStep(input);
@@ -486,7 +486,7 @@ bool vtkHDFWriter::UpdateStepsGroup(vtkPolyData* input)
       connectivityOffsetArray[i] += cellArrayTopos[i].cellArray->GetNumberOfConnectivityIds();
     }
   }
-  vtkNew<vtkIntArray> connectivityOffsetvtkArray;
+  vtkNew<vtkIdTypeArray> connectivityOffsetvtkArray;
   connectivityOffsetvtkArray->SetNumberOfComponents(NUM_POLY_DATA_TOPOS);
   connectivityOffsetvtkArray->SetArray(connectivityOffsetArray.data(), NUM_POLY_DATA_TOPOS, 1);
 
@@ -494,8 +494,8 @@ bool vtkHDFWriter::UpdateStepsGroup(vtkPolyData* input)
   if (geometryUpdated)
   {
     // Need to deep copy the data since the pointer will be taken
-    vtkNew<vtkIntArray> connectivityOffsetvtkArrayCopy;
-    std::vector<int> connectivityOffsetArrayCopy = connectivityOffsetArray;
+    vtkNew<vtkIdTypeArray> connectivityOffsetvtkArrayCopy;
+    std::vector<vtkIdType> connectivityOffsetArrayCopy = connectivityOffsetArray;
     connectivityOffsetvtkArrayCopy->SetNumberOfComponents(NUM_POLY_DATA_TOPOS);
     connectivityOffsetvtkArrayCopy->SetArray(
       connectivityOffsetArrayCopy.data(), NUM_POLY_DATA_TOPOS, 1);
-- 
GitLab