Skip to content

Fix out of bounds read in _baseCellToCCWrot60 for face == NUM_ICOSA_FACES (#978) - #1224

Merged
nrabinowitz merged 1 commit into
uber:masterfrom
nileshpatil6:fix/basecell-face-oob-978
Aug 20, 2026
Merged

Fix out of bounds read in _baseCellToCCWrot60 for face == NUM_ICOSA_FACES (#978)#1224
nrabinowitz merged 1 commit into
uber:masterfrom
nileshpatil6:fix/basecell-face-oob-978

Conversation

@nileshpatil6

Copy link
Copy Markdown
Contributor

Fixes #978.

The bug

_baseCellToCCWrot60 guards its face argument with:

if (face < 0 || face > NUM_ICOSA_FACES) return INVALID_ROTATIONS;

The table it then indexes is declared as:

static const BaseCellRotation faceIjkBaseCells[NUM_ICOSA_FACES][3][3][3]

so valid indices are 0 .. NUM_ICOSA_FACES - 1. face == NUM_ICOSA_FACES (20) passes the check and the loop reads one whole [3][3][3] row past the end of the array.

The sibling function _faceIjkToBaseCell and friends use the correct >= form; this one is the odd one out.

Reproduction

Built with the same sanitizer flags the repo CI already uses in .github/workflows/test-linux.yml (-fsanitize=address -fno-sanitize-recover=address), calling _baseCellToCCWrot60(16, NUM_ICOSA_FACES):

==ERROR: AddressSanitizer: global-buffer-overflow on address ...
    #0 ... in _baseCellToCCWrot60 src/h3lib/lib/baseCells.c:882

exit code 1. With the fix applied the same binary passes.

Note for reviewers: in a plain non-sanitizer build the added assertion happens to pass without the fix, because the out of bounds read is undefined behaviour that usually returns garbage that does not equal INVALID_ROTATIONS anyway. It is an effective regression test specifically under the ASAN/MSAN/UBSAN/Valgrind jobs this repo already runs on every PR, which is where the bug is actually detectable.

Change

  • > becomes >= in the bounds check.
  • Regression test in testBaseCellsInternal.c alongside the existing invalid-face assertions.
  • CHANGELOG entry.

This is one of the checks called out in #430: "I did not port two of the checks in baseCells.c since I could not readily test them. They could be added in a future PR."

Testing

Full suite under ASAN: 100% tests passed, 0 tests failed out of 317.

…ACES

The bounds check used > instead of >=, so a face index equal to
NUM_ICOSA_FACES (20) passed validation and indexed one element past the
end of faceIjkBaseCells[NUM_ICOSA_FACES][3][3][3].

Reproduced as an AddressSanitizer global-buffer-overflow at
baseCells.c:882 under the sanitizer flags the repo CI already uses. Adds
a regression test that aborts without the fix.

Fixes uber#978
@CLAassistant

CLAassistant commented Aug 20, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 99.7%. remained the same — nileshpatil6:fix/basecell-face-oob-978 into uber:master

@nileshpatil6

Copy link
Copy Markdown
Contributor Author

Thanks for the review!

Flagging the one red check: LibFuzzer clang failed with SUMMARY: libFuzzer: timeout (exit 70) in fuzzerPolygonToCellsExperimentalNoHoles. I do not think it is related to this change.

  • The only non-test caller of _baseCellToCCWrot60 in the library is cellToVertex in vertex.c. polygonToCells and the experimental variants never reach it, so this fuzzer does not exercise the changed line at all.
  • For every in-range face (0 through NUM_ICOSA_FACES - 1) the old and new conditions are identical; the only input whose behavior changes is face == NUM_ICOSA_FACES, which previously read out of bounds.
  • The same job failed with the same libFuzzer: timeout signature on a plain push to master in run 31322611252 (2026-08-09), with no pull request involved.

Happy to rebase or push an empty commit if you would like the fuzzer job re-run, though that would dismiss the approval, so I would rather leave it to you.

@nrabinowitz
nrabinowitz merged commit 679f6b0 into uber:master Aug 20, 2026
49 of 50 checks passed
@nrabinowitz

Copy link
Copy Markdown
Collaborator

Thanks for the fix! The fuzzer issue does not look related, I think we can ignore for this PR.

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.

int _baseCellToCCWrot60: Possible Buffer Overflow

5 participants