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

Remove recursion from AMode lowering rules #6968

Merged
merged 2 commits into from
Sep 11, 2023

Conversation

alexcrichton
Copy link
Member

This commit removes recursion from AMode lowering rules for both the x64 and aarch64 backends. On the x64 backend this can lead to stack overflow on the host given wasm inputs during compilation due to the fact that i32.add goes through this path of lowering (e.g. trying to use the lea instruction). The recursion in these rules are rewritten to hunt for constants differently in a non-recursive fashion which relies on egraph optimizations to place constants in the right place to get good code output.

This PR additionally updates the AArch64 backend to remove the recursion there as well. While not reachable from wasm this is still reachable from Cranelift and is a good bug to fix regardless.

Note that the stack overflow during compilation requires optimizations to be disabled, as otherwise egraphs will already fold constants together which means that recursion won't happen deeply.

Thanks to DFINITY for notifying the security@bytecodealliance.org mailing list for this issue! We concluded this in the end wasn't a CVE-worthy issue because it requires non-default settings to trigger (e.g. disabling optimizations). This is something I'll backport to the 13 release branch, however.

This commit removes the recursion present in the x64 backend's
`to_amode` and `to_amode_add` helpers. The recursion is currently
unbounded and controlled by user input meaning it's not too hard to
craft user input which triggers stack overflow in the host. By removing
recursion there's no need to worry about this since the stack depth will
never be hit.

The main concern with removing recursion is that code quality may not be
quite as good any more. The purpose of the recursion here is to "hunt
for constants" and update the immediate `Offset32`, and now without
recursion only at most one constant is found and folded instead of an
arbitrary number of constants as before. This should continue to produce
the same code as before so long as optimizations are enabled, but
without optimizations this will produce worse code than before.

Note with a hypothetical mid-end optimization that does this constant
folding for us the rules here could be further simplified to purely
consider the shape of the input `Value` to amode computation without
considering constants at all.
Same as the prior commit for x64, but for aarch64 instead. Unlikely to
be reachable from wasm due to this only being a part of addressing modes
which are more strictly controlled in wasm (e.g. wasm addresses are
always a zero-extended value added to a base, so it's not possible to
have a long chain of constants at the top level in clif)
@alexcrichton alexcrichton requested review from a team as code owners September 6, 2023 15:08
@alexcrichton alexcrichton requested review from fitzgen and removed request for a team September 6, 2023 15:08
@github-actions github-actions bot added cranelift Issues related to the Cranelift code generator cranelift:area:aarch64 Issues related to AArch64 backend. cranelift:area:x64 Issues related to x64 codegen labels Sep 6, 2023
@alexcrichton
Copy link
Member Author

Given our pending patch releases I'll go ahead and backport this to all the branches once this is approved.

Copy link
Member

@cfallin cfallin left a comment

Choose a reason for hiding this comment

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

Carrying over LGTM from private branch -- thanks!

@alexcrichton alexcrichton added this pull request to the merge queue Sep 11, 2023
Merged via the queue into bytecodealliance:main with commit 86a6f5c Sep 11, 2023
20 checks passed
@alexcrichton alexcrichton deleted the fix-stack-overflow branch September 11, 2023 16:40
alexcrichton added a commit that referenced this pull request Sep 12, 2023
* x64: Remove recursion in `to_amode` helper

This commit removes the recursion present in the x64 backend's
`to_amode` and `to_amode_add` helpers. The recursion is currently
unbounded and controlled by user input meaning it's not too hard to
craft user input which triggers stack overflow in the host. By removing
recursion there's no need to worry about this since the stack depth will
never be hit.

The main concern with removing recursion is that code quality may not be
quite as good any more. The purpose of the recursion here is to "hunt
for constants" and update the immediate `Offset32`, and now without
recursion only at most one constant is found and folded instead of an
arbitrary number of constants as before. This should continue to produce
the same code as before so long as optimizations are enabled, but
without optimizations this will produce worse code than before.

Note with a hypothetical mid-end optimization that does this constant
folding for us the rules here could be further simplified to purely
consider the shape of the input `Value` to amode computation without
considering constants at all.

* aarch64: Remove recursion from amode lowering rules

Same as the prior commit for x64, but for aarch64 instead. Unlikely to
be reachable from wasm due to this only being a part of addressing modes
which are more strictly controlled in wasm (e.g. wasm addresses are
always a zero-extended value added to a base, so it's not possible to
have a long chain of constants at the top level in clif)
eduardomourar pushed a commit to eduardomourar/wasmtime that referenced this pull request Sep 13, 2023
* x64: Remove recursion in `to_amode` helper

This commit removes the recursion present in the x64 backend's
`to_amode` and `to_amode_add` helpers. The recursion is currently
unbounded and controlled by user input meaning it's not too hard to
craft user input which triggers stack overflow in the host. By removing
recursion there's no need to worry about this since the stack depth will
never be hit.

The main concern with removing recursion is that code quality may not be
quite as good any more. The purpose of the recursion here is to "hunt
for constants" and update the immediate `Offset32`, and now without
recursion only at most one constant is found and folded instead of an
arbitrary number of constants as before. This should continue to produce
the same code as before so long as optimizations are enabled, but
without optimizations this will produce worse code than before.

Note with a hypothetical mid-end optimization that does this constant
folding for us the rules here could be further simplified to purely
consider the shape of the input `Value` to amode computation without
considering constants at all.

* aarch64: Remove recursion from amode lowering rules

Same as the prior commit for x64, but for aarch64 instead. Unlikely to
be reachable from wasm due to this only being a part of addressing modes
which are more strictly controlled in wasm (e.g. wasm addresses are
always a zero-extended value added to a base, so it's not possible to
have a long chain of constants at the top level in clif)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cranelift:area:aarch64 Issues related to AArch64 backend. cranelift:area:x64 Issues related to x64 codegen cranelift Issues related to the Cranelift code generator
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants