Skip to content

Fix buffer overflow in nbit and scaleoffset filters when not first in the pipeline - #6771

Open
ojessop01 wants to merge 3 commits into
HDFGroup:developfrom
ojessop01:fix/nbit-scaleoffset-input-size
Open

ojessop01 wants to merge 3 commits into
HDFGroup:developfrom
ojessop01:fix/nbit-scaleoffset-input-size

Conversation

@ojessop01

@ojessop01 ojessop01 commented Oct 22, 2026 •

Copy link
Copy Markdown

Describe your changes

The nbit and scaleoffset filters assume their input is exactly one full chunk (nelmts * datatype size bytes). That only holds when they are the first filter in the pipeline. The only check was an assert(), which release builds remove.

When it triggers: a chunked dataset where another filter runs before nbit/scaleoffset and makes the chunk smaller, for example H5Pset_deflate() followed by H5Pset_nbit(). nbit then sizes its output buffer from the smaller input but packs all nelmts elements, so it writes past the end of the buffer (ASan: heap-buffer-overflow in H5Z__nbit_compress_one_byte; without ASan, free(): invalid next size). scaleoffset after deflate shows a heap over-read under ASan.

Fix: return an error instead of asserting. Both filters are optional, so the pipeline skips them for that chunk and the data is stored and read back correctly.

Test: test_filter_after_deflate in test/dsets.c writes and reads back a deflate+nbit and a deflate+scaleoffset dataset. It checks that deflate really ran and the second filter was skipped, and that the data round trips. Without the fix it aborts under ASan; with it it passes. (It is skipped when deflate is unavailable; test_missing_filter() unregisters deflate for the rest of the process, so it runs once per dsets run.)

Issue ticket number (GitHub or JIRA)

None.

Checklist before requesting a review

  • My code conforms to the guidelines in CONTRIBUTING.md
  • I made an entry in release_docs/CHANGELOG.md (bug fixes, new features)
  • I added a test (bug fixes, new features)

H5Z__filter_nbit and H5Z__filter_scaleoffset assume their input is
exactly nelmts * datatype-size bytes, which is only true when they are
the first filter in the pipeline. They only checked this with an
assert(), which release builds remove. With e.g. deflate before nbit,
the smaller buffer was over-read/over-written when writing a chunk.

Return an error instead, so the pipeline skips these optional filters.
Add a regression test and a changelog entry.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing. Review the Copilot code review billing settings.

@github-actions

Copy link
Copy Markdown
Contributor

Review Checklist

This PR touches the following areas. Each needs a sign-off
from its listed owners before merging.

ojessop01 and others added 2 commits October 22, 2026 17:53
Assert that deflate was applied and the second filter was skipped, so
the test cannot pass without exercising the bug. Skip it when deflate
is unregistered, which test_missing_filter() does for the rest of the run.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: To be triaged

Development

Successfully merging this pull request may close these issues.

4 participants