-
Notifications
You must be signed in to change notification settings - Fork 12k
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
Inplace new-ing an array overwrites the square of the memory #41441
Comments
Neat! I'll take a look. |
Seems to only happen in the template case, not if you inline it into a non-template situation. Huh. |
Talked to Richard Smith & summarizing that discussion: In general Clang currently strips the first array bound of an array new to handle it differently (because it can be a runtime bound, etc) - but in a non-dependent case then adjusts the type of the new to the nested type (removing that outer bound). But in a dependent case it does not perform that type adjustment - so later on uses both the size of the outer bound that was split off, plus the size of the un-adjusted array, that includes that outer bound. ActOnCXXNew is where all new expressions are handled, and it does the top-bound stripping off for non-dependent types. General thought: Representationally it'd probably be better not to "adjust" the type - extract the top bound for runtime bound/other reasons, but keep the original type (with possible runtime bound). Then when computing the size, always strip off the top bound and multiply it by the extracted bound. |
Updated godbolt link showing this issue is still present on trunk, 2020/12/23: |
Hi, I added a fix for this, but couldn't link it somehow, now sure why. #83124 |
@llvm/issue-subscribers-clang-frontend Author: None (e84ee981-20b7-441e-8de0-adb2190144d6)
| | |
| --- | --- |
| Bugzilla Link | [42096](https://llvm.org/bz42096) |
| Version | 8.0 |
| OS | Linux |
| CC | @dwblaikie,@DougGregor,@jfbastien,@riccibruno,@zygoloid |
Extended DescriptionWhen in-place new-ing a local variable of an array of trivial type, the generated code calls 'memset' with the square of the size of the array, corrupting the stack. Quick example: #include <new> template <typename TYPE>
} int main() Sample code generation can be seen for Clang 7 and 8 via godbolt: |
…ze (#83124) When in-place new-ing a local variable of an array of trivial type, the generated code calls 'memset' with the correct size of the array, earlier it was generating size (squared of the typedef array + size). The cause: `typedef TYPE TArray[8]; TArray x;` The type of declarator is Tarray[8] and in `SemaExprCXX.cpp::BuildCXXNew` we check if it's of typedef and of constant size then we get the original type and it works fine for non-dependent cases. But in case of template we do `TreeTransform.h:TransformCXXNEWExpr` and there we again check the allocated type which is TArray[8] and it stays that way, so ArraySize=(Tarray[8] type, alloc Tarray[8*type]) so the squared size allocation. ArraySize gets calculated earlier in `TreeTransform.h` so that `if(!ArraySize)` condition was failing. fix: I changed that condition to `if(ArraySize)`. Fixes #41441
…ze (llvm#83124) When in-place new-ing a local variable of an array of trivial type, the generated code calls 'memset' with the correct size of the array, earlier it was generating size (squared of the typedef array + size). The cause: `typedef TYPE TArray[8]; TArray x;` The type of declarator is Tarray[8] and in `SemaExprCXX.cpp::BuildCXXNew` we check if it's of typedef and of constant size then we get the original type and it works fine for non-dependent cases. But in case of template we do `TreeTransform.h:TransformCXXNEWExpr` and there we again check the allocated type which is TArray[8] and it stays that way, so ArraySize=(Tarray[8] type, alloc Tarray[8*type]) so the squared size allocation. ArraySize gets calculated earlier in `TreeTransform.h` so that `if(!ArraySize)` condition was failing. fix: I changed that condition to `if(ArraySize)`. Fixes llvm#41441
The "fix" has been reverted, the problem is still with us.
@dwblaikie, I can't find |
Yeah, been a while - but at a cursory glance that correction sounds right. |
(patch was reverted in e1321fa) |
The [last attempt](llvm#89036) to fix llvm#41441 has been reverted immediately. Here I'm trying the simplest idea I've been able to come with: skip handling dependent case in `BuildCXXNew`. The original test (borrowed form llvm#89036) passes. Also I've created and added to the tests a minimal repro of the code llvm#89036 fails on. This (obviously) also passes.
The [last attempt](llvm#89036) to fix llvm#41441 has been reverted immediately. Here I'm trying the simplest idea I've been able to come with: skip handling dependent case in `BuildCXXNew`. The original test (borrowed form llvm#89036) passes. Also I've created and added to the tests a minimal repro of the code llvm#89036 fails on. This (obviously) also passes.
The [last attempt](llvm#89036) to fix llvm#41441 has been reverted immediately. Here I'm trying the simplest idea I've been able to come with: skip handling dependent case in `BuildCXXNew`. The original test (borrowed form llvm#89036) passes. Also I've created and added to the tests a minimal repro of the code llvm#89036 fails on. This (obviously) also passes.
Extended Description
When in-place new-ing a local variable of an array of trivial type, the generated code calls
memset
with the square of the size of the array, corrupting the stack.Quick example:
Sample code generation can be seen for Clang 7 and 8 via godbolt:
https://godbolt.org/z/WjhFrc
The text was updated successfully, but these errors were encountered: