Skip to content

Fix three related input-validation bugs in Mixture.calc_property - #163

Open
djkees wants to merge 4 commits into
nasa:mainfrom
djkees:up/calc-property-input-validation
Open

djkees wants to merge 4 commits into
nasa:mainfrom
djkees:up/calc-property-input-validation

Conversation

@djkees

@djkees djkees commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Three small, related fixes to Mixture.calc_property's input dispatch, all in the same ~20-line region of source/bind/python/CEA.pyx. Combined into one PR since they touch the same code and would otherwise conflict with each other if merged out of order as separate PRs. Supersedes #161 and #162, which covered the first two of these individually.

Changes

  • Invalid prop_type inconsistency: prop_type was typed as the Cython enum cea_property_type, so a negative out-of-range value raised a Cython-internal OverflowError instead of the method's own ValueError allowlist check. Changed the parameter to plain int, with explicit <cea_property_type> casts added at the four downstream C-call sites.
  • Numpy/int scalar temperature rejected: both scalar-dispatch checks only accepted Python float, so numpy floating scalars (e.g. np.float32, which doesn't subclass float) and plain int were incorrectly rejected. Widened to isinstance(temperature, (float, int, np.floating)). Numpy integer scalars remain deliberately rejected.
  • Multi-temperature length not validated: the array/list dispatch branches read temperature[i] for i in range(nspecies) without checking len(temperature) == nspecies, so a too-short array crashed with a raw IndexError and a too-long array silently truncated with no error. Both dispatch blocks now check the length up front and raise a clear ValueError naming the actual and expected counts.

source/bind/python/tests/test_mixture.py gained the corresponding regression tests for all three (parametrized over the invalid prop_type sign, numpy/int scalar types, and length-mismatch direction × container type).

Testing

  • make py-rebuild
  • pytest source/bind/python/tests — 128 passed
  • Manually reproduced all three original failure modes before writing each fix, and confirmed each now behaves as described above

Compatibility / Numerical behavior

  • No expected changes to numerical results

Only changes exception-raising/dispatch-acceptance behavior for already-invalid or already-broken inputs; no change to any previously-correct call path.


Drafted with Claude's assistance

  • Each fix was verified empirically against a locally built cea module before being written, reproducing the original bug first
  • Ran the full Python test suite after rebuilding the extension against this branch's upstream/main base, confirming all 128 tests pass including the new regression tests for all three fixes

🤖 Generated with Claude Code

djkees and others added 3 commits September 17, 2026 13:47
…290)

prop_type was typed as the Cython enum cea_property_type, so negative
values raised OverflowError at the function boundary before the
method's own ValueError allowlist check could run. Typed as plain int
instead, with explicit casts at the four downstream C-call sites.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Widens the temperature-type dispatch to accept np.floating scalars
and plain Python int, not just Python float, so values like arr[0]
from a float32/float64 array no longer raise a spurious ValueError.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Raises a clear ValueError on a temperature array/list length mismatch instead of a raw IndexError (too few) or silent truncation (too many).

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>

@sylvesterkaczmarek sylvesterkaczmarek left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The new invalid-prop_type path leaks reac_weights. It is allocated before the property/pressure validation, while the try/finally that frees it starts only after the second allocation. Unsupported properties and missing-pressure errors therefore exit before cleanup. Could those checks move before allocation, or could cleanup start immediately after the first malloc?

Move the prop_type and pressure checks before the malloc so
neither early-exit path can leak the buffer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@djkees

djkees commented Sep 18, 2026

Copy link
Copy Markdown
Contributor Author

@sylvesterkaczmarek Good catch — confirmed. reac_weights is allocated at the top of calc_property, but the prop_type allowlist check and the missing-pressure check both raise before the try/finally (which only starts after the second buffer, reac_temps, is allocated) — so both of those exits leaked reac_weights.

Fixed by moving both validation checks ahead of the reac_weights allocation, so the buffer is only ever created after both checks have passed — those two early-exit paths can no longer leak it. Pushed to this branch (078e3ba).

Verified:

  • Rebuilt the extension and ran the full suite: 131/131 passed, no behavior change
  • Reverted the fix, rebuilt, and stress-tested the two error paths (200k calls each): ~12 MB RSS growth on the pre-fix code vs. ~0.05 MB (noise) on the fixed code, confirming the leak and the fix empirically
  • Filed [feature] Add ASan-based leak detection to CI for the Python binding layer #164 to add ASan-based leak detection to CI for this binding layer, since nothing in the existing test suite (or Python's own leak tooling) can see a leaked raw malloc — this one was only caught by review

Drafted with Claude's assistance

  • Fix verified by rebuilding the Cython extension and running the full Python binding test suite (131/131 passed)
  • Leak itself verified empirically: stress-tested both error paths at 200k iterations each against the pre-fix and post-fix code, confirming ~12 MB growth vs. ~0.05 MB (noise)

@sylvesterkaczmarek sylvesterkaczmarek left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Rechecked 078e3ba. Both early validation paths now run before reac_weights is allocated, so unsupported property types and missing-pressure errors cannot leak the buffer. The full current build/test matrix is green, and the stress result confirms the leak is gone. My concern is resolved.

nicholascanovas pushed a commit that referenced this pull request Sep 25, 2026
…#165) (#134)

* Reconcile CONTRIBUTING.md and developer_guide.rst on GFE/pFUnit setup (#53)

Both docs described a different, non-working procedure for getting pFUnit available; standardize on the extern/gfe (lowercase) path that actually matches .gitignore and scripts/develop.sh, add the missing build+install+CMAKE_PREFIX_PATH steps, and cross-link the two docs instead of duplicating divergent instructions. Also notes the current Windows pFUnit build limitation (#163).

* Drop stale Windows-fails caveat now that #163 has a fix in progress

See djkees#163 (fix landing in a separate PR).

(cherry picked from commit 1f7ea1f)

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

None yet

Development

Successfully merging this pull request may close these issues.

2 participants