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

[naga wgsl-in] Return error if wgsl parser recurses too deeply. #6885

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from

Conversation

jamienicol
Copy link
Contributor

Connections
Fixes #5757

Description
It's currently trivial to write a shader that causes the wgsl parser to recurse too deeply and overflow the stack. This patch makes the parser return an error when recursing too deeply, before the stack overflows.

It makes use of a new function Parser::track_recursion(). This increments a counter returning an error if the value is too high, before calling the user-provided function and returning its return value after decrementing the counter again.

Any recursively-called functions can simply be modified to call track_recursion(), providing their previous contents in a closure as the argument. All instances of recursion during parsing call through either Parser::statement(), Parser::unary_expression(), or Parser::type_decl(), so only these functions have been updated as described in order to keep the patch as unobtrusive as possible.

A value of 256 has been chosen as the recursion limit, but can be later tweaked if required. This avoids the stack overflow in the testcase attached to issue #5757.

Testing
Ran test suite

Checklist

  • Run cargo fmt.
  • Run taplo format.
  • Run cargo clippy. If applicable, add:
    • --target wasm32-unknown-unknown
    • --target wasm32-unknown-emscripten
  • Run cargo xtask test to run tests.
  • Add change to CHANGELOG.md. See simple instructions inside file.

@jamienicol jamienicol requested a review from a team as a code owner January 9, 2025 13:17
@ErichDonGubler ErichDonGubler self-assigned this Jan 14, 2025
Comment on lines +308 to +309
self.recursion_depth += 1;
if self.recursion_depth >= 256 {
Copy link
Member

Choose a reason for hiding this comment

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

thought: We already have some recursion tracking for curly braces. I wonder how they might be reconciled.

Copy link
Member

Choose a reason for hiding this comment

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

That is definitely something to consider, but I would like to treat it as a follow-up. We have particular reasons that #5757 is urgent to close despite being not very important to users, so we want to put this behind us quickly.

Copy link
Member

Choose a reason for hiding this comment

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

I agree; generally, thoughts I offer are not blocking, so 👍🏻 if it's a problem, weeee'll figure it out!

Copy link
Member

Choose a reason for hiding this comment

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

Okay, right - I should have checked. Thanks for the clarification.

Copy link
Member

@ErichDonGubler ErichDonGubler left a comment

Choose a reason for hiding this comment

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

I'm concerned about disallowing code that should compile under the spec., but I suppose we need to achieve that from a safe place, which we're definitely not, ATM. :shipit:

@jimblandy
Copy link
Member

I'm concerned about disallowing code that should compile under the spec., but I suppose we need to achieve that from a safe place, which we're definitely not, ATM. :shipit:

WGSL explicitly allows us to impose ad-hoc limits like this:

An uncategorized error may occur even when all WGSL and WebGPU requirements have been satisfied. Possible causes include:

  • The shaders are too complex, exceeding the capabilities of the implementation, but in a way not easily captured by prescribed limits. Simplifying the shaders may work around the issue.

  • A defect in the WebGPU implementation.

@jamienicol
Copy link
Contributor Author

And for reference Tint also imposes a similar limit (though tracking recursion at different places and a different value for the limit)

Copy link
Member

@jimblandy jimblandy left a comment

Choose a reason for hiding this comment

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

This looks great. I'm glad to see you took care of the recursion in type parsing, as well.

I filed #6970 to unify this with the statement nesting depth limits.

Comment on lines +308 to +309
self.recursion_depth += 1;
if self.recursion_depth >= 256 {
Copy link
Member

Choose a reason for hiding this comment

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

Okay, right - I should have checked. Thanks for the clarification.

It's currently trivial to write a shader that causes the wgsl parser
to recurse too deeply and overflow the stack. This patch makes the
parser return an error when recursing too deeply, before the stack
overflows.

It makes use of a new function Parser::track_recursion(). This
increments a counter returning an error if the value is too high,
before calling the user-provided function and returning its return
value after decrementing the counter again.

Any recursively-called functions can simply be modified to call
track_recursion(), providing their previous contents in a closure as
the argument. All instances of recursion during parsing call through
either Parser::statement(), Parser::unary_expression(), or
Parser::type_decl(), so only these functions have been updated as
described in order to keep the patch as unobtrusive as possible.

A value of 256 has been chosen as the recursion limit, but can be
later tweaked if required. This avoids the stack overflow in the
testcase attached to issue gfx-rs#5757.
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.

Stack Exhaustion in WGSL Frontend
3 participants