fix(dpp): harden nested document-property position parsing#3857
Conversation
The recursive nested-property parser (`insert_values_nested`) sorted sub-properties by a `position` it read with `.expect()`. That sorted result was never used — nested properties are emitted in source-map order by the loop just below — but the read itself could fail on adversarial schema input and bring down the parse during block execution. Remove the dead sort. Accepted contracts parse identically (ordering is unchanged); a previously-failing edge case now parses cleanly. Adds regression tests for malformed nested positions on both the full-validation and check-tx parse paths, plus a valid-position case to confirm behavior is unchanged. Reported-by: Daniel Derefaka <https://github.com/DanielDerefaka> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
✅ Review complete (commit efa1d73) |
|
Warning Review limit reached
More reviews will be available in 13 minutes and 2 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughRemoved dead nested-property position-sorting (and its panicking ChangesSchema Parsing Robustness
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Targeted hardening PR that removes a dead sort_by in insert_values_nested whose .expect("expected a position") could panic on adversarial nested-schema input. The sorted vector was never consumed (the loop iterates properties.iter() directly), so accepted-contract ordering is unchanged. Tests cover both validation paths plus a positive baseline. Two minor test-strengthening suggestions; no blocking issues.
🟡 1 suggestion(s) | 💬 1 nitpick(s)
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs`:
- [SUGGESTION] packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs:834-841: Malformed-position regression tests only assert non-panic, not the parse outcome
`malformed_nested_positions_do_not_panic_check_tx` and `nested_float_position_does_not_panic_full_validation` discard results with `let _ = parse(...)`, so they only lock in the no-panic invariant. The current behavior on these inputs is `Err` (propagated from `get_integer::<u64>()?` or the meta-schema), but a future refactor that silently accepts `Value::Float(0.0)`, `Value::I64(-1)`, or `Value::U128(u64::MAX as u128 + 1)` — or returns a misleading error variant — would still pass. Mirror the style of `valid_nested_positions_still_parse` and assert `Err(_)` (ideally the specific `ProtocolError` / `DataContractError` variant) on each malformed case so the post-fix contract is pinned.
Codecov Report✅ All modified and coverable lines are covered by tests.
Additional details and impacted files@@ Coverage Diff @@
## v3.1-dev #3857 +/- ##
=============================================
- Coverage 87.15% 70.73% -16.43%
=============================================
Files 2641 20 -2621
Lines 327793 2788 -325005
=============================================
- Hits 285701 1972 -283729
+ Misses 42092 816 -41276
🚀 New features to boost your workflow:
|
|
✅ DashSDKFFI.xcframework built for this PR.
SwiftPM (host the zip at a stable URL, then use): .binaryTarget(
name: "DashSDKFFI",
url: "https://your.cdn.example/DashSDKFFI.xcframework.zip",
checksum: "402aa45da1e981df92e7b1f074d74dd3242ae721234e3f5b56af8cdff906fbce"
)Xcode manual integration:
|
…t ordering invariant Addresses review feedback on the nested-property position hardening: - The malformed-position tests now assert the actual parse outcome instead of only non-panic (verified empirically): a zero-fraction float (a valid integer per the meta-schema) parses in both modes; negative / >u64::MAX positions are admitted on the check_tx path (meta-schema skipped) but rejected with a clean ConsensusError under full validation. - The comment on the removed sort now states that nested-property IndexMap insertion order is consensus-observable (historical contracts were committed in source-map order), so reintroducing even a correct position sort would soft-fork existing contracts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Incremental review of b953432 over 43d6c01. Both prior findings are FIXED on the current head: the malformed-position regression tests now pin Ok/Err parse outcomes via assert_matches! (v1/mod.rs:826-886), and the comment at mod.rs:207-216 now documents the consensus-observable source-map IndexMap insertion-order invariant and explicitly warns against any nested-property sort. The genuinely new diff (test outcome assertions + invariant comment) directly resolves both carried-forward findings; no new in-scope issues identified.
Drives a DataContractCreate whose document schema has a nested object property with a zero-fraction float `position` through `process_raw_state_transitions` — the exact path a validator runs during block execution. Before the fix this panicked in `insert_values_nested` (node shutdown / chain halt); it now completes deterministically (SuccessfulExecution). Complements the dpp parse-layer tests with coverage of the real consensus execution path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
All six agents (Claude + Codex across general/security/rust-quality) converged on a clean review: the PR removes a dead position-based sort in insert_values_nested whose .expect() could panic deterministically on adversarial nested-property positions (floats, negatives, or values exceeding u64), eliminating a chain-halt vector while preserving source-map ordering already provided by properties.iter(). Test coverage is layered (DPP unit tests across both validation modes plus a drive-abci end-to-end regression through process_raw_state_transitions). Prior-finding revalidation list is empty as expected (the b953432 review was clean), so there are no carried-forward findings, and no new in-scope issues were identified in the latest delta.
Issue being fixed or feature implemented
Hardens parsing of
positionon nested document-schema properties. The recursive nested-property parser performed aposition-based sort whose result was never used, and that sort could fail on certain malformed schema inputs reached during contract processing. This removes the dead sort so nested properties parse robustly.Reported by @DanielDerefaka — thanks for the careful report.
What was done?
positionsort intry_from_schema/insert_values_nested. Its result was never consumed — nested properties are emitted in source-map order by the existingproperties.iter()loop just below it — so removing it changes no accepted-contract behavior while eliminating the failure path. Added a code comment so it isn't reintroduced.How Has This Been Tested?
cargo test -p dpp --features validation --lib try_from_schema— all 49 tests pass, including the 3 new regression tests and the existing nested-property tests (behavior unchanged).cargo clippy -p dpp --features validationandcargo fmt --all— clean.Breaking Changes
None. The removed sort had no effect (its output was discarded), so accepted contracts parse identically; only a previously-failing edge case now parses cleanly.
Checklist:
For repository code-owners and collaborators only
🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests