Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(parser): correct recursion counting in selection sets #462

Closed
wants to merge 1 commit into from

Conversation

lrlna
Copy link
Member

@lrlna lrlna commented Feb 21, 2023

We've been not quite double maybe more like 1.5 counting nested selection sets in operations with our recursion limit. This PR should provide a fix.

An operation like this should have a recursion high of 4.

query {
    a {
        a {
            a {
                a
            }
        }
    }
}

An operation like this should have a recursion high of 3.

query {
    a {
        a {
            a
        }
    }
}

@lrlna lrlna requested a review from garypen February 21, 2023 17:50
@lrlna lrlna requested a review from goto-bus-stop as a code owner February 21, 2023 17:50
@lrlna lrlna self-assigned this Feb 21, 2023
assert_eq!(ast.document().definitions().into_iter().count(), 2);
assert_eq!(ast.document().definitions().into_iter().count(), 1);
Copy link
Member Author

Choose a reason for hiding this comment

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

no clue why this supposedly had 2 definitions! clearly there is only one. oh well \o/

@@ -13,7 +13,6 @@ pub(crate) fn field(p: &mut Parser) {
// We need to enforce recursion limits to prevent
// excessive resource consumption or (more seriously)
// stack overflows.
p.recursion_limit.consume();
Copy link
Member Author

Choose a reason for hiding this comment

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

I do not remember why we also added to the recursion limit when parsing a field. Do you remember @garypen? Perhaps there was a significant historical reason I am forgetting 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

@lrlna My (at this point quite vague) recollection is that we had to enforce recursion limits at various points to prevent stack overflow. i.e.: this mechanism isn't about providing an accurate count of GraphQL component processing; it's actually about preventing excessive stack recursion leading to program termination.

Does that help at all? If not, I'll think harder.

Copy link
Member Author

Choose a reason for hiding this comment

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

i think so! it then means incrementing the counter here as well as in the selection set indeed overestimates our recursion counter, which could lead to unexpected stack overflows.

Copy link
Contributor

@garypen garypen Feb 22, 2023

Choose a reason for hiding this comment

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

Wouldn't overestimating lead to fewer stack overflows?

Copy link
Member Author

Choose a reason for hiding this comment

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

unexpected behaviour*** 🤦‍♂️

Copy link
Member Author

Choose a reason for hiding this comment

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

let's say we set a limit of 4_096, and we know that our given operation is exactly 4_096 nested selection sets, we would expect the parser to not abort the operation. but because we are counting in a slightly weird to reason about manner, that operation will abort.

Copy link
Contributor

Choose a reason for hiding this comment

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

I understand, but that's not the same thing as a stack overflow. The reason we count the way we do is because we are (I think) counting exactly recursive invocations of the parser to prevent stack overflow.

@lrlna lrlna marked this pull request as draft February 23, 2023 12:36
@lrlna
Copy link
Member Author

lrlna commented Apr 11, 2023

#519 is the actual fix

@lrlna lrlna closed this Apr 11, 2023
@lrlna lrlna deleted the fix-recursion-limit branch April 21, 2023 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants