-
Notifications
You must be signed in to change notification settings - Fork 46
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
Conversation
assert_eq!(ast.document().definitions().into_iter().count(), 2); | ||
assert_eq!(ast.document().definitions().into_iter().count(), 1); |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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 🤔
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unexpected behaviour*** 🤦♂️
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
#519 is the actual fix |
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.
An operation like this should have a recursion high of 3.