Skip to content

Add depth guard for schema type parsing#2402

Open
john-h-kastner-aws wants to merge 2 commits into
mainfrom
schema-depth-guard
Open

Add depth guard for schema type parsing#2402
john-h-kastner-aws wants to merge 2 commits into
mainfrom
schema-depth-guard

Conversation

@john-h-kastner-aws

@john-h-kastner-aws john-h-kastner-aws commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

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):

  • A breaking change requiring a major version bump to cedar-policy (e.g., changes to the signature of an existing API).
  • A backwards-compatible change requiring a minor version bump to cedar-policy (e.g., addition of a new API).
  • A bug fix or other functionality change requiring a patch to cedar-policy.
  • A change "invisible" to users (e.g., documentation, changes to "internal" crates like cedar-policy-core, cedar-validator, etc.)
  • A change (breaking or otherwise) that only impacts unreleased or experimental code.

I confirm that this PR (choose one, and delete the other options):

  • Updates the "Unreleased" section of the CHANGELOG with a description of my change (required for major/minor version bumps).
  • Does not update the CHANGELOG because my change does not significantly impact released code.

I confirm that cedar-spec (choose one, and delete the other options):

  • Does not require updates because my change does not impact the Cedar formal model or DRT infrastructure.
  • Requires updates, and I have made / will make these updates myself. (Please include in your description a timeline or link to the relevant PR in cedar-spec, and how you have tested that your updates are correct.)
  • Requires updates, but I do not plan to make them in the near future. (Make sure that your changes are hidden behind a feature flag to mark them as experimental.)
  • I'm not sure how my change impacts 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):

  • Does not require updates because my change does not impact the Cedar language specification.
  • Requires updates, and I have made / will make these updates myself. (Please include in your description a timeline or link to the relevant PR in cedar-docs. PRs should be targeted at a staging-X.Y branch, not main.)
  • I'm not sure how my change impacts the documentation. (Post your PR anyways, and we'll discuss in the comments.)

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>
@github-actions

Copy link
Copy Markdown

Coverage Report

Head Commit: 300f721f55386c485fbb9c832a23a79986221bdf

Base Commit: 7754f634b9ed3bbf45f44e1551aed9a4bcf3770e

Download the full coverage report.

Coverage of Added or Modified Lines of Rust Code

Required coverage: 80.00%

Actual coverage: 91.62%

Status: PASSED ✅

Details
File Status Covered Coverage Missed Lines
cedar-policy-core/src/validator/cedar_schema/ast.rs 🟢 20/20 100.00%
cedar-policy-core/src/validator/cedar_schema/depth.rs 🟢 74/75 98.67% 73
cedar-policy-core/src/validator/cedar_schema/parser.rs 🟢 31/33 93.94% 167-168
cedar-policy-core/src/validator/cedar_schema/to_json_schema.rs 🟢 14/14 100.00%
cedar-policy-core/src/validator/json_schema.rs 🟢 30/36 83.33% 184-188, 215
cedar-policy-core/src/validator/schema.rs 🟡 27/36 75.00% 544-551, 553
cedar-policy-core/src/validator/schema_type_depth.rs 🟢 90/93 96.77% 67, 151-152
cedar-policy-core/src/validator/topo_sort.rs 🟢 42/43 97.67% 76
cedar-policy/src/api.rs 🔴 22/32 68.75% 2010-2013, 2015-2019, 2021

Coverage of All Lines of Rust Code

Required coverage: 80.00%

Actual coverage: 87.89%

Status: PASSED ✅

Details
Package Status Covered Coverage Base Coverage
cedar-language-server 🟢 4722/5102 92.55% --
cedar-policy 🟡 4498/5632 79.87% --
cedar-policy-cli 🟡 1251/1643 76.14% --
cedar-policy-core 🟢 24858/28178 88.22% --
cedar-policy-formatter 🟢 914/1088 84.01% --
cedar-policy-symcc 🟢 6777/7274 93.17% --
cedar-wasm 🔴 0/28 0.00% --

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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_limit APIs (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.

Comment thread cedar-policy-core/src/validator/schema_type_depth.rs
Comment thread cedar-policy-core/src/validator/schema_type_depth.rs Outdated
Comment thread cedar-policy-core/src/validator/cedar_schema/to_json_schema.rs Outdated
Comment thread cedar-policy-core/src/validator/cedar_schema.rs Outdated
Comment thread cedar-policy-core/src/validator/cedar_schema/parser.rs
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 15 changed files in this pull request and generated 3 comments.

Comment on lines +202 to +206
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 {
Comment on lines +127 to +140
/// 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) => {
Comment on lines +12434 to +12439
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",
);
@github-actions

Copy link
Copy Markdown

Coverage Report

Head Commit: e6d2fac05bd1b52c3fdef8b35a69cc9b8686d3ca

Base Commit: 7754f634b9ed3bbf45f44e1551aed9a4bcf3770e

Download the full coverage report.

Coverage of Added or Modified Lines of Rust Code

Required coverage: 80.00%

Actual coverage: 91.62%

Status: PASSED ✅

Details
File Status Covered Coverage Missed Lines
cedar-policy-core/src/validator/cedar_schema/ast.rs 🟢 20/20 100.00%
cedar-policy-core/src/validator/cedar_schema/depth.rs 🟢 74/75 98.67% 73
cedar-policy-core/src/validator/cedar_schema/parser.rs 🟢 31/33 93.94% 167-168
cedar-policy-core/src/validator/cedar_schema/to_json_schema.rs 🟢 14/14 100.00%
cedar-policy-core/src/validator/json_schema.rs 🟢 30/36 83.33% 184-188, 215
cedar-policy-core/src/validator/schema.rs 🟡 27/36 75.00% 544-551, 553
cedar-policy-core/src/validator/schema_type_depth.rs 🟢 90/93 96.77% 67, 151-152
cedar-policy-core/src/validator/topo_sort.rs 🟢 42/43 97.67% 76
cedar-policy/src/api.rs 🔴 22/32 68.75% 2010-2013, 2015-2019, 2021

Coverage of All Lines of Rust Code

Required coverage: 80.00%

Actual coverage: 87.89%

Status: PASSED ✅

Details
Package Status Covered Coverage Base Coverage
cedar-language-server 🟢 4722/5102 92.55% 92.55%
cedar-policy 🟡 4498/5632 79.87% 79.93%
cedar-policy-cli 🟡 1251/1643 76.14% 76.14%
cedar-policy-core 🟢 24858/28178 88.22% 88.14%
cedar-policy-formatter 🟢 914/1088 84.01% 84.01%
cedar-policy-symcc 🟢 6777/7274 93.17% 93.17%
cedar-wasm 🔴 0/28 0.00% 0.00%

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