Add depth guard for schema type parsing#2402
Conversation
limits depths of types in schemas prevent stack overflows, including types constructed with chains of common type references. Signed-off-by: John Kastner <jkastner@amazon.com>
b36be30 to
300f721
Compare
Coverage ReportHead Commit: Base Commit: Download the full coverage report. Coverage of Added or Modified Lines of Rust CodeRequired coverage: 80.00% Actual coverage: 91.62% Status: PASSED ✅ Details
Coverage of All Lines of Rust CodeRequired coverage: 80.00% Actual coverage: 87.89% Status: PASSED ✅ Details
|
There was a problem hiding this comment.
Pull request overview
This PR introduces optional schema type-depth limits for both Cedar-schema and JSON-schema parsing, preventing stack overflows from deeply nested types and long chains of common-type (typedef) references. It adds internal utilities to compute “syntactic” and “effective” type depth (including common-type inlining effects), surfaces a dedicated error when the limit is exceeded, and extends the public cedar-policy API with depth-limited schema parsing entry points.
Changes:
- Add new
Schema::{from_json_*, from_cedarschema_*}_with_depth_limitAPIs (and corresponding core validator entry points) to reject schemas whose type depth exceeds a caller-provided limit. - Implement iterative depth computation for Cedar schema AST, plus effective-depth computation over JSON schema fragments (resolving common-type reference chains).
- Add tests covering limit enforcement and “no stack overflow” behavior for very deep constructed schemas/common-type chains.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| cedar-policy/src/test/test.rs | Adds unit tests exercising depth limits and deep-schema non-overflow scenarios. |
| cedar-policy/src/api.rs | Exposes new public depth-limited schema parsing constructors. |
| cedar-policy-core/src/validator/topo_sort.rs | Introduces a shared generic topological sort utility (used for common-type dependency ordering). |
| cedar-policy-core/src/validator/schema/err.rs | Adds TypeTooDeep error variant and exported TypeTooDeepError. |
| cedar-policy-core/src/validator/schema.rs | Switches common-type resolver ordering to use the shared topo sort implementation. |
| cedar-policy-core/src/validator/schema_type_depth.rs | New effective-depth computation across schema fragments, accounting for common-type chains. |
| cedar-policy-core/src/validator/json_schema.rs | Adds depth-limit parsing helpers and enforces effective depth limits for JSON schema inputs. |
| cedar-policy-core/src/validator/cedar_schema/to_json_schema.rs | Adjusts Cedar→JSON type conversion to accommodate Type: Drop (stack-safe dropping). |
| cedar-policy-core/src/validator/cedar_schema/parser.rs | Adds depth-limited Cedar schema parsing path (syntactic + effective depth checks). |
| cedar-policy-core/src/validator/cedar_schema/depth.rs | New iterative syntactic depth computation for Cedar schema AST types. |
| cedar-policy-core/src/validator/cedar_schema/ast.rs | Adds an iterative Drop for Type to avoid recursive drop overflows on deep types. |
| cedar-policy-core/src/validator/cedar_schema.rs | Wires in the new depth module. |
| cedar-policy-core/src/validator.rs | Registers new internal modules (schema_type_depth, topo_sort). |
| cedar-policy-core/Cargo.toml | Adds rstest dev-dependency for new core tests. |
| Cargo.lock | Updates lockfile for new dev-dependency. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
| fn check_depth_limit(&self, depth_limit: usize) -> Result<()> { | ||
| use crate::validator::schema_type_depth::fragment_effective_depth; | ||
| let resolved = self.to_internal_name_fragment_with_resolved_types()?; | ||
| if let Some(depth) = fragment_effective_depth(&resolved) { | ||
| if depth > depth_limit { |
| /// Compute the structural depth of a type, substituting resolved depths for | ||
| /// common type references. We can directly recurse on `ty` because we assume we | ||
| /// have already checked its direct depth and we do not follow common type | ||
| /// references, instead looking them up in `common_type_defs`. | ||
| fn type_depth(ty: &Type<InternalName>, common_type_defs: &HashMap<InternalName, usize>) -> usize { | ||
| match ty { | ||
| Type::Type { ty: variant, .. } => match variant { | ||
| TypeVariant::String | ||
| | TypeVariant::Long | ||
| | TypeVariant::Boolean | ||
| | TypeVariant::Entity { .. } | ||
| | TypeVariant::Extension { .. } => 0, | ||
| TypeVariant::Set { element } => 1 + type_depth(element, common_type_defs), | ||
| TypeVariant::Record(record) => { |
| let result = Schema::from_json_str(&json); | ||
| assert!(result.is_err(), "serde should reject deeply nested JSON"); | ||
| assert!( | ||
| result.unwrap_err().to_string().contains("recursion limit"), | ||
| "expected serde recursion limit error", | ||
| ); |
Coverage ReportHead Commit: Base Commit: Download the full coverage report. Coverage of Added or Modified Lines of Rust CodeRequired coverage: 80.00% Actual coverage: 91.62% Status: PASSED ✅ Details
Coverage of All Lines of Rust CodeRequired coverage: 80.00% Actual coverage: 87.89% Status: PASSED ✅ Details
|
Limits depths of types in schemas prevent stack overflows, including types constructed with chains of common type references.
See also #2383. They're solving the same problem with very similar designs, so at a high level they're best reviewed together. But, their implementation is entirely separate, so we handle low level code review separately.
Description of changes
Issue #, if available
Checklist for requesting a review
The change in this PR is (choose one, and delete the other options):
cedar-policy(e.g., changes to the signature of an existing API).cedar-policy(e.g., addition of a new API).cedar-policy.cedar-policy-core,cedar-validator, etc.)I confirm that this PR (choose one, and delete the other options):
I confirm that
cedar-spec(choose one, and delete the other options):cedar-spec, and how you have tested that your updates are correct.)cedar-spec. (Post your PR anyways, and we'll discuss in the comments.)I confirm that
docs.cedarpolicy.com(choose one, and delete the other options):cedar-docs. PRs should be targeted at astaging-X.Ybranch, notmain.)