Fix panic on malformed queries with recursive fragments.
This is a potential denial-of-service attack vector. Thanks to [@quapka](https://github.com/quapka) for the detailed vulnerability report and reproduction steps.
This commit is contained in:
parent
88b10fe009
commit
c28c77e458
2 changed files with 39 additions and 1 deletions
|
@ -1,6 +1,6 @@
|
|||
# master
|
||||
|
||||
- No changes yet
|
||||
- Fix panic on malformed queries with recursive fragments. *This is a potential denial-of-service attack vector.* Thanks to [@quapka](https://github.com/quapka) for the detailed vulnerability report and reproduction steps.
|
||||
|
||||
# [[0.15.7] 2021-07-08](https://github.com/graphql-rust/juniper/releases/tag/juniper-v0.15.7)
|
||||
|
||||
|
|
|
@ -172,6 +172,13 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> {
|
|||
);
|
||||
|
||||
for frag_name2 in &fragment_names[i + 1..] {
|
||||
// Prevent infinite fragment recursion. This case is
|
||||
// caught by fragment validators, but because the validation is
|
||||
// done in parallel we can't rely on fragments being
|
||||
// non-recursive here.
|
||||
if frag_name1 == frag_name2 {
|
||||
continue;
|
||||
}
|
||||
self.collect_conflicts_between_fragments(
|
||||
&mut conflicts,
|
||||
frag_name1,
|
||||
|
@ -195,6 +202,10 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> {
|
|||
) where
|
||||
S: ScalarValue,
|
||||
{
|
||||
// Prevent infinite fragment recursion. This case is
|
||||
// caught by fragment validators, but because the validation is
|
||||
// done in parallel we can't rely on fragments being
|
||||
// non-recursive here.
|
||||
if fragment_name1 == fragment_name2 {
|
||||
return;
|
||||
}
|
||||
|
@ -282,6 +293,13 @@ impl<'a, S: Debug> OverlappingFieldsCanBeMerged<'a, S> {
|
|||
self.collect_conflicts_between(conflicts, mutually_exclusive, field_map, &field_map2, ctx);
|
||||
|
||||
for fragment_name2 in fragment_names2 {
|
||||
// Prevent infinite fragment recursion. This case is
|
||||
// caught by fragment validators, but because the validation is
|
||||
// done in parallel we can't rely on fragments being
|
||||
// non-recursive here.
|
||||
if fragment_name == fragment_name2 {
|
||||
return;
|
||||
}
|
||||
self.collect_conflicts_between_fields_and_fragment(
|
||||
conflicts,
|
||||
field_map,
|
||||
|
@ -2261,6 +2279,26 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handles_recursive_fragments() {
|
||||
expect_passes_rule_with_schema::<
|
||||
_,
|
||||
EmptyMutation<()>,
|
||||
EmptySubscription<()>,
|
||||
_,
|
||||
_,
|
||||
DefaultScalarValue,
|
||||
>(
|
||||
QueryRoot,
|
||||
EmptyMutation::new(),
|
||||
EmptySubscription::new(),
|
||||
factory,
|
||||
r#"
|
||||
fragment f on Query { ...f }
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_message_contains_hint_for_alias_conflict() {
|
||||
assert_eq!(
|
||||
|
|
Loading…
Reference in a new issue