Skip to content

Pass contiguous buffer to H5Dwrite in 2D/3D append and overwrite - #165

Open
jeanbez wants to merge 2 commits into
developfrom
fix-jagged-2d-3d-writes
Open

jeanbez wants to merge 2 commits into
developfrom
fix-jagged-2d-3d-writes

Conversation

@jeanbez

@jeanbez jeanbez commented Jun 30, 2026

Copy link
Copy Markdown
Member

Summary

`h5bench_overwrite.c` and `h5bench_append.c` allocate the 2D and 3D fill buffers as jagged arrays (`float **` and `float ***`, with each row a separate malloc) and then pass the outer pointer directly to `H5Dwrite`. HDF5 expects one contiguous buffer of `element_size * total_elements` bytes; it reads the first row correctly, then walks straight past the end of that row's allocation into adjacent memory.

The sanitizers workflow (next PR up) caught this as a heap-buffer-overflow on the very first 2D run.

Fix

Keep the `[i][j]` / `[i][j][k]` indexing in the fill loops, but back the row and plane pointers with one contiguous allocation per type and pass that contiguous block to `H5Dwrite`. The free path collapses from a nested per-row loop to a few frees per branch.

  • No change to 1D path.
  • No change to the values written, only their physical layout in memory.

Test plan

  • Build with HDF5 1.14.x.
  • Run an existing 2D sample (`sync-write-2d-contig-contig.json`) and confirm it produces the same output as before.
  • Run a 3D sample (`sync-write-3d-contig-contig.json`) and confirm the same.
  • Sanitizers workflow (separate PR) goes green on the 2D and 3D paths.

jeanbez and others added 2 commits June 30, 2026 11:27
h5bench_overwrite.c and h5bench_append.c allocate the 2D and 3D fill
buffers as jagged arrays (data_2D_FLOAT as float**, each row a separate
malloc; data_3D_FLOAT as float***, each plane a separate row-pointer
array, each row a separate malloc) and then pass the outer pointer
directly to H5Dwrite.

H5Dwrite expects a single contiguous buffer of element-size *
total-element-count bytes. With a jagged array it dereferences the
first row correctly, then walks straight past the end of that row's
allocation into adjacent memory and treats whatever it finds as the
next dim_2 (or dim_3) elements. The sanitizers workflow I am about to
land flagged this as a heap-buffer-overflow on the very first 2D run.

Fix: keep the [i][j] / [i][j][k] indexing for the fill loops (the
surrounding code stays unchanged) but back the row and plane pointers
with one contiguous allocation per type and pass that contiguous block
to H5Dwrite. The free path simplifies to three or four frees per
branch instead of the nested per-row loop.

No behavior change for the 1D path. No behavior change for the
contents of the data written; only the storage layout in memory
changes so the write reads from valid memory throughout.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant