Skip to content

Commit

Permalink
fix: Panic when schema registry base URI contains an unencoded fragment
Browse files Browse the repository at this point in the history
Signed-off-by: Dmitry Dygalo <[email protected]>
  • Loading branch information
Stranger6667 committed Jan 24, 2025
1 parent fe6e0b7 commit ecc60d4
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 5 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

## [Unreleased]

### Fixed

- Panic when schema registry base URI contains an unencoded fragment.

### Performance

- Fewer JSON pointer lookups.

## [0.28.2] - 2025-01-22

### Fixed
Expand Down
8 changes: 8 additions & 0 deletions crates/jsonschema-py/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

## [Unreleased]

### Fixed

- Panic when schema registry base URI contains an unencoded fragment.

### Performance

- Fewer JSON pointer lookups.

## [0.28.2] - 2025-01-22

### Fixed
Expand Down
33 changes: 29 additions & 4 deletions crates/jsonschema-referencing/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ fn process_resources(
let mut queue = VecDeque::with_capacity(32);
let mut seen = AHashSet::new();
let mut external = AHashSet::new();
let mut scratch = String::new();

// Populate the resources & queue from the input
for (uri, resource) in pairs {
Expand Down Expand Up @@ -377,7 +378,13 @@ fn process_resources(
}

// Collect references to external resources in this resource
collect_external_resources(&base, resource.contents(), &mut external, &mut seen)?;
collect_external_resources(
&base,
resource.contents(),
&mut external,
&mut seen,
&mut scratch,
)?;

// Process subresources
for subresource in resource.subresources() {
Expand All @@ -390,13 +397,15 @@ fn process_resources(
subresource.contents(),
&mut external,
&mut seen,
&mut scratch,
)?;
} else {
collect_external_resources(
&base,
subresource.contents(),
&mut external,
&mut seen,
&mut scratch,
)?;
};
queue.push_back((base.clone(), subresource));
Expand Down Expand Up @@ -445,6 +454,7 @@ fn collect_external_resources(
contents: &Value,
collected: &mut AHashSet<Uri<String>>,
seen: &mut AHashSet<u64>,
scratch: &mut String,
) -> Result<(), Error> {
// URN schemes are not supported for external resolution
if base.scheme().as_str() == "urn" {
Expand Down Expand Up @@ -477,7 +487,7 @@ fn collect_external_resources(
// Handle local references separately as they may have nested references to external resources
if reference.starts_with('#') {
if let Some(referenced) = pointer(contents, reference.trim_start_matches('#')) {
collect_external_resources(base, referenced, collected, seen)?;
collect_external_resources(base, referenced, collected, seen, scratch)?;
}
continue;
}
Expand All @@ -494,8 +504,16 @@ fn collect_external_resources(
let mut resolved = uri::resolve_against(&base_without_fragment.borrow(), path)?;
// Add the fragment back if present
if let Some(fragment) = fragment {
resolved =
resolved.with_fragment(Some(uri::EncodedString::new_or_panic(fragment)));
// It is cheaper to check if it is properly encoded than allocate given that
// the majority of inputs do not need to be additionally encoded
if let Some(encoded) = uri::EncodedString::new(fragment) {
resolved = resolved.with_fragment(Some(encoded));
} else {
uri::encode_to(fragment, scratch);
resolved =
resolved.with_fragment(Some(uri::EncodedString::new_or_panic(scratch)));
scratch.clear();
}
}
resolved
} else {
Expand Down Expand Up @@ -954,4 +972,11 @@ mod tests {
.expect("Lookup failed");
assert_eq!(resolved.contents(), &json!({"type": "object"}));
}

#[test]
fn test_invalid_reference() {
// Found via fuzzing
let resource = Draft::Draft202012.create_resource(json!({"$schema": "$##"}));
let _ = Registry::try_new("http://#/", resource);
}
}
2 changes: 1 addition & 1 deletion crates/jsonschema-referencing/tests/suite

0 comments on commit ecc60d4

Please sign in to comment.