fix(tf): validate flattened multi-device op widths - #5827
Conversation
Reject partial per-atom rows and descriptor/neighbor stride mismatches before TensorFlow force and virial kernels allocate outputs or access raw pointers. Coding-Agent: Codex Codex-Version: codex-cli 0.144.4 Model: gpt-5.6-sol Reasoning-Effort: xhigh
|
Warning Review limit reached
Next review available in: 32 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds shared flattened-width validation for TensorFlow multi-device custom ops, applies descriptor and neighbor consistency checks to force and virial kernels, and adds regression tests for malformed dimensions. ChangesMulti-device shape validation
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant TensorFlowCustomOp
participant GetPerAtomWidth
participant RawKernel
TensorFlowCustomOp->>GetPerAtomWidth: validate flattened width and nloc
GetPerAtomWidth-->>TensorFlowCustomOp: return width or InvalidArgument
TensorFlowCustomOp->>TensorFlowCustomOp: validate descriptor/neighbor relationship
TensorFlowCustomOp->>RawKernel: dispatch validated tensors
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #5827 +/- ##
==========================================
- Coverage 79.64% 79.38% -0.26%
==========================================
Files 1085 1085
Lines 126583 126611 +28
Branches 4593 4598 +5
==========================================
- Hits 100813 100509 -304
- Misses 24117 24451 +334
+ Partials 1653 1651 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Possible reviewers based on changed lines, exact file history, and exact-file review history:
No review request was made automatically. Coding agent: Codex |
wanghan-iapcm
left a comment
There was a problem hiding this comment.
Nicely done — returning a Status via OP_REQUIRES_OK (rather than throwing) means the error surfaces as a clean InvalidArgumentError and avoids the safe_compute→errors::Internal downgrade. Two notes; the test-coverage one is inline below.
Incomplete fix — the forward virial op is left with the same latent OOB. ProdVirialSeAOp / ProdVirialSeROp in prod_virial_multi_device.cc still use the unchecked truncating dim_size(1) / nloc with no GetPerAtomWidth / nnei*4 == ndescrpt guard:
deepmd-kit/source/op/tf/prod_virial_multi_device.cc
Lines 75 to 79 in 4cf48fd
prod_virial_a_cpu recomputes ndescrpt = 4 * nnei internally and indexes with that, so the op's existing nloc*ndescrpt*3 == in_deriv_width / nloc*nnei*3 == rij_width checks (which only tie the buffers to the truncated widths, never ndescrpt against nnei) don't prevent a malformed net_deriv width from driving an out-of-bounds read. It runs on every inference/training step. Issue #5623 enumerated only the three ops you fixed, but the forward virial shares the identical pattern — worth applying the same helper + stride guard here (and a matching test).
Coding-Agent: Codex Codex-Version: codex-cli 0.144.6 Model: gpt-5.6-sol Reasoning-Effort: xhigh
wanghan-iapcm
left a comment
There was a problem hiding this comment.
All four gaps are closed, and I was able to verify it by running rather than reading, which is worth spelling out because it makes the result unambiguous.
The TensorFlow custom ops installed in my environment predate this change -- neither libdeepmd_op.so nor libop_grads.so contains the "should be divisible by nloc" string -- so running the new suite against them is a genuine pre-fix run. Eight of the twelve collected cases fail there, including every one of the four I asked for:
| gap I raised | new test | unpatched |
|---|---|---|
GetPerAtomWidth nloc < 0 |
test_negative_nloc_is_rejected |
fails |
nloc == 0 |
test_zero_nloc_rejects_nonempty_flattened_width |
fails |
prod_force_se_r_grad untested |
test_prod_force_r_grad_rejects_partial_nlist_atom |
fails |
prod_virial_se_r_grad untested |
test_prod_virial_r_grad_rejects_partial_net_deriv_atom |
fails |
Including test_zero_nloc_accepts_empty_flattened_widths was a good call -- the zero-nloc guard has a legitimate accepting case, and without it a future change could satisfy every rejection test by simply refusing all zero-nloc input.
Two of the remaining cases, test_prod_force_rejects_in_deriv_width_mismatch and test_prod_virial_grad_rejects_rij_width_mismatch, already pass on the unpatched ops, because an existing check rejects those inputs. That is not a problem and I am not asking for anything -- they are regression guards for behaviour that already worked rather than demonstrations of the bug -- but it is worth knowing which of these tests would actually catch a revert of this PR and which would not.
Agreed on leaving the width > INT_MAX branch alone; it is not practically constructible through the op API and a test for it would cost more than it protects.
Approving.
njzjz-bot
left a comment
There was a problem hiding this comment.
Reviewed draft head e736a90b9064223261bc1cce014a8c568375e608 with three independent full subagent reviews. Three issues remain inline: two P1 native-buffer safety gaps (nall < nloc in force output sizing and the still-unvalidated forward virial operators), plus one P2 CPU/GPU behavior mismatch for accepted zero-work shapes. The current PR is unstable and its failing/pending checks should be rerun after these cases are addressed. Because this PR was opened by the active njzjz-bot account, this is a comment-only review rather than a self-request-changes event.
The quota is about to reset, so I am concentrating the remaining token budget on these reviews.
Coding agent: Codex
Codex version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning effort: xhigh
Validate forward force and virial atom/descriptor dimensions, and make GPU force and virial kernels return safely after zeroing outputs when no work is present. Coding-Agent: Codex Codex-Version: codex-cli 0.144.6 Model: gpt-5.6-sol Reasoning-Effort: xhigh
Coding-Agent: Codex Codex-Version: codex-cli 0.144.6 Model: gpt-5.6-sol Reasoning-Effort: xhigh
Fixes #5623
Summary
se_afour-value descriptor stride and these_rone-value stride before output allocationnet_deriv,in_deriv,nlist,rij, and descriptor/neighbor stride mismatchesWhy existing tests missed this
The existing tests use placeholders whose second dimensions are fixed to the correct
nloc * ndescrpt,nloc * ndescrpt * 3, andnloc * nneiwidths. Feeding a differently sized array is therefore rejected by TensorFlow before the custom op executes. The tests also cover only valid descriptor layouts, so the release-build paths whereassertis compiled out were never exercised.The new tests construct malformed tensors directly at the op boundary. They verify
InvalidArgumentis returned by the custom op before output allocation or raw CPU/GPU pointer dispatch.Validation
cmake --build source/build --target deepmd_oplibdeepmd_opandlibop_gradspytest source/tests/tf/test_multi_device_shape_validation.py -v(6 validation cases plus TensorFlowtest_session, all passed)TestProdForce::test_prod_force,TestProdForceGrad::test_prod_force_grad, andTestProdVirialGrad::test_prod_virial_grad(3 passed)ruff format .ruff check .Coding agent: Codex
Codex version: codex-cli 0.144.4
Model: gpt-5.6-sol
Reasoning effort: xhigh
Summary by CodeRabbit
Bug Fixes
Tests