-
Notifications
You must be signed in to change notification settings - Fork 12.4k
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
[Bug][Clang][ARM] Wrong assembly code generation, "LR" corrupted. #80287
Comments
Smells like shrink-wrapping. |
@llvm/issue-subscribers-backend-arm Author: Victor Signaevskyi (P1119r1m)
The Clang compiler generates code for a function that overwrites the `lr` register without saving its data on stack beforehand.
This bug was detected on a large software component and the problem was minimized to a PoC (see `example.c`).
Clang versions info:
Host OS: Ubuntu 20.04.3 LTS In disassembler the bug looks like this (generated
Steps to reproduce.
|
I suspect this was fixed by swiftlang@b1a5ee1 Could you check with a build from current |
I still see the same in https://godbolt.org/z/7PKxqj7vx I'm afraid. It looks like what @jroelofs says - shrink wrapping leads to frame lowering in one of the two branches, followed by a bit of tail folding ends up with the load/store optimizing using lr that it thinks is available. |
BTW, there is no bug if to build it for |
Dear contributors/collaborators, are there any chance to fix this compiler bug? There is a feeling that this bug can manifest itself in many other places in the code. Also, I think this bug could be used in some hacker attacks. |
@jroelofs @davemgreen @fhahn |
If you feel like this is a security issue please report using the process in https://llvm.org/docs/Security.html . My instinct is that this would not be a worthy of a CVE. CVEs are used to report security vulnerabilities in programs, this looks like a code-generation bug that if it affects your program it is likely to crash. It doesn't look like something that would be systemicly reproduced across many programs. |
@smithp35 Thanks for the link. |
Feel free to report it to the LLVM security group if you disagree with me. |
@smithp35 Thank you. Reported locally to LLVM security group as: |
workaround: |
This test shows the bug where LR is used as a general-purpose register on a code path where it is not spilled to the stack.
PR llvm#75527 fixed ARMFrameLowering to set the IsRestored flag for LR based on all of the return instructions in the function, not just one. However, there is also code in ARMLoadStoreOptimizer which changes return instructions, but it set IsRestored based on the one instruction it changed, not the whole function. The fix is to factor out the code added in llvm#75527, and also call it from ARMLoadStoreOptimizer if it made a change to return instructions. Fixes llvm#80287.
This test shows the bug where LR is used as a general-purpose register on a code path where it is not spilled to the stack.
PR llvm#75527 fixed ARMFrameLowering to set the IsRestored flag for LR based on all of the return instructions in the function, not just one. However, there is also code in ARMLoadStoreOptimizer which changes return instructions, but it set IsRestored based on the one instruction it changed, not the whole function. The fix is to factor out the code added in llvm#75527, and also call it from ARMLoadStoreOptimizer if it made a change to return instructions. Fixes llvm#80287.
PR #75527 fixed ARMFrameLowering to set the IsRestored flag for LR based on all of the return instructions in the function, not just one. However, there is also code in ARMLoadStoreOptimizer which changes return instructions, but it set IsRestored based on the one instruction it changed, not the whole function. The fix is to factor out the code added in #75527, and also call it from ARMLoadStoreOptimizer if it made a change to return instructions. Fixes #80287.
This test shows the bug where LR is used as a general-purpose register on a code path where it is not spilled to the stack. (cherry picked from commit 8779cf6)
PR llvm#75527 fixed ARMFrameLowering to set the IsRestored flag for LR based on all of the return instructions in the function, not just one. However, there is also code in ARMLoadStoreOptimizer which changes return instructions, but it set IsRestored based on the one instruction it changed, not the whole function. The fix is to factor out the code added in llvm#75527, and also call it from ARMLoadStoreOptimizer if it made a change to return instructions. Fixes llvm#80287. (cherry picked from commit 749384c)
/pull-request #83129 |
This test shows the bug where LR is used as a general-purpose register on a code path where it is not spilled to the stack. (cherry picked from commit 8779cf6)
PR llvm#75527 fixed ARMFrameLowering to set the IsRestored flag for LR based on all of the return instructions in the function, not just one. However, there is also code in ARMLoadStoreOptimizer which changes return instructions, but it set IsRestored based on the one instruction it changed, not the whole function. The fix is to factor out the code added in llvm#75527, and also call it from ARMLoadStoreOptimizer if it made a change to return instructions. Fixes llvm#80287. (cherry picked from commit 749384c)
Do we have a conclusion about which versions of LLVM and which targets this affects? Does it affect 64-bit ARM? |
The fix is only for 32-bit ARM, so I'm assuming it doesn't affect 64-bit ARM. |
The Clang compiler generates code for a function that overwrites the
lr
register without saving its data on stack beforehand.This bug was detected on a large software component and the problem was minimized to a PoC (see example.c).
Clang versions info:
Host OS: Ubuntu 20.04.3 LTS
In disassembler the bug looks like this (generated
example.c.o.objdump
):Steps to reproduce.
The text was updated successfully, but these errors were encountered: