Since each DumpModuleInfoAction can now contain a pointer to a
raw_ostream, saving there a poiter that owned by a local unique_ptr
may cause use-after-free. Clarify ownership and save a shared_ptr
inside of DumpModuleInfoAction instead.
Found by static analyzer.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Event Timeline
I understand the potential for a use after free, since OutputStream is a raw pointer, but I don't understand the fix.
Okay, probably commit message is a little confusing. The potential for a use after free is that OutputStream is a raw pointer as you already noted, but it is also accessible outside of DumpModuleInfoAction::ExecuteAction. Before the patch there was the case where result of local unique_ptr::get was saved there. When the function is exited, unique_ptr frees the memory it holds, making OutputStream poiniting to freed memory. Since OutputStream can be easily accessed outside of DumpModuleInfoAction::ExecuteAction, hence the potential for use-after-free. I wasn't sure if assigning nullptr to OutputStream at the end of DumpModuleInfoAction::ExecuteAction was a good idea, so I just added code avoiding saving result of unique_ptr::get to OutputStream .
Hmmm, but this looks to be the only place DumpModuleInfoAction will initialize OutputStream to a nonnull value, so that seems to be a pretty significant change in behavior.
Should OutputStream be made into a shared_ptr so we can clarify the memory ownership instead of leaving it as a raw pointer? That should also address the use-after-free.
Should OutputStream be made into a shared_ptr so we can clarify the memory ownership instead of leaving it as a raw pointer? That should also address the use-after-free.
Well, I was thinking about that and wasn't sure about it either. https://reviews.llvm.org/D129456 added initialization of OutputStream from the outside. When last shared_ptr is destroyed, it destroys undelying object as well. In case underlying object came from the outside in a form of raw pointer, we may end up accidentally deleting it when DumpModuleInfoAction is destroyed.
Yeah, exposing that data member was not the cleanest way to implement this functionality. This does fix the issue, but it keeps the unclean design -- I wonder if we could make that member private and use a constructor to specify it, then we can enforce the shared ownership property. (If this suggestion turns out to be a slog, then I'm okay with the current approach as well.)
This looks much better to me, thank you! LGTM with one small nit for safety.
clang/include/clang/Frontend/FrontendActions.h | ||
---|---|---|
191 | A bit of extra safety around implicit conversions. |
lldb/source/Commands/CommandObjectTarget.cpp | ||
---|---|---|
2182–2187 | Use of std::shared_ptr with a deleter that doesn't do anything is unusual; I think this deserves a comment. |
Add comment explaining custom deleter.
lldb/source/Commands/CommandObjectTarget.cpp | ||
---|---|---|
2182–2187 | Sure, done. |
A bit of extra safety around implicit conversions.