From a0ffed7df993357fea0a19c7ab24861c760779a3 Mon Sep 17 00:00:00 2001 From: Sean Arms <67096+lesserwhirls@users.noreply.github.com> Date: Fri, 12 Jun 2026 07:55:18 -0600 Subject: [PATCH] Fix hdf5 file position bug when handling indirect blocks Keep track of file position when recursing into readIndirectBlock. Fixes unidata/netcdf-java#1546 --- .../nc2/iosp/hdf5/TestH5IndirectBlocks.java | 68 +++++++++++++++++++ .../java/ucar/nc2/iosp/hdf5/FractalHeap.java | 7 +- 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 cdm-test/src/test/java/ucar/nc2/iosp/hdf5/TestH5IndirectBlocks.java diff --git a/cdm-test/src/test/java/ucar/nc2/iosp/hdf5/TestH5IndirectBlocks.java b/cdm-test/src/test/java/ucar/nc2/iosp/hdf5/TestH5IndirectBlocks.java new file mode 100644 index 0000000000..ebc3929732 --- /dev/null +++ b/cdm-test/src/test/java/ucar/nc2/iosp/hdf5/TestH5IndirectBlocks.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2026 University Corporation for Atmospheric Research/Unidata + * See LICENSE for license information. + */ + +package ucar.nc2.iosp.hdf5; + +import static com.google.common.truth.Truth.assertThat; +import static ucar.unidata.util.test.TestDir.cdmUnitTestDir; + +import java.io.IOException; +import java.util.List; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import ucar.nc2.Group; +import ucar.nc2.NetcdfFile; +import ucar.nc2.NetcdfFiles; +import ucar.nc2.Variable; +import ucar.unidata.util.test.category.NeedsCdmUnitTest; + +@Category(NeedsCdmUnitTest.class) +public class TestH5IndirectBlocks { + + private final String h5FileWithIndirectBlocks = cdmUnitTestDir + "formats/hdf5/bitplane_imaris/indirect_blocks.ims"; + + // demonstrated https://github.com/Unidata/netcdf-java/issues/1546 using old api + @Test + public void testOpenFileWithIndirectBlocksOldApi() throws IOException { + NetcdfFile ncf = NetcdfFile.open(h5FileWithIndirectBlocks); + assertThat(ncf).isNotNull(); + } + + // demonstrated https://github.com/Unidata/netcdf-java/issues/1546 using new api + @Test + public void testOpenFileWithIndirectBlocksNewApi() throws IOException { + NetcdfFile ncf = NetcdfFiles.open(h5FileWithIndirectBlocks); + assertThat(ncf).isNotNull(); + } + + @Test + public void testReadIndirectBlocksOldApi() throws IOException { + NetcdfFile ncf = NetcdfFile.open(h5FileWithIndirectBlocks); + assertThat(ncf).isNotNull(); + readVariableWithIndirectBlocks(ncf); + } + + @Test + public void testReadIndirectBlocksNewApi() throws IOException { + NetcdfFile ncf = NetcdfFiles.open(h5FileWithIndirectBlocks); + assertThat(ncf).isNotNull(); + readVariableWithIndirectBlocks(ncf); + } + + private void readVariableWithIndirectBlocks(NetcdfFile ncf) throws IOException { + Group groupWithIndirectBlocksVariables = ncf.findGroup("/DataSetInfo/ZeissAttrs"); + assertThat(groupWithIndirectBlocksVariables).isNotNull(); + List variablesWithIndirectBlocks = groupWithIndirectBlocksVariables.getVariables(); + assertThat(variablesWithIndirectBlocks).isNotNull(); + assertThat(variablesWithIndirectBlocks.size()).isEqualTo(3); + for (Variable variable : variablesWithIndirectBlocks) { + String data = variable.readScalarString(); + assertThat(data).isNotNull(); + assertThat(data).isNotEmpty(); + assertThat(data).startsWith("= 0) + if (childIndirectAddress >= 0) { + long savePos = raf.getFilePointer(); readIndirectBlock(iblock2, childIndirectAddress, heapAddress, hasFilter); + raf.seek(savePos); + } } }