[PATCH] D138275: [clang][Interp] Avoid leaking init maps of local primitive arrays
Timm Bäder via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 18 02:39:49 PST 2022
tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
This shows up when the interpretation is interrupted, in this case because we're reading an uninitialized value, and so we don't get to the `destroy` instruction for the scope.
This adds a `destroyAll()` that calls deallocates all the local variables of all the scopes in the function. This works, but I was wondering if it should instead be a `cleanupLeftovers()` that's only used by the caller _if_ the interpretation wasn't successful.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D138275
Files:
clang/lib/AST/Interp/InterpFrame.cpp
clang/lib/AST/Interp/InterpFrame.h
clang/test/AST/Interp/cxx20.cpp
Index: clang/test/AST/Interp/cxx20.cpp
===================================================================
--- clang/test/AST/Interp/cxx20.cpp
+++ clang/test/AST/Interp/cxx20.cpp
@@ -304,3 +304,15 @@
}
static_assert(testInc2() == 1, "");
};
+
+constexpr int NoLeakHere() {
+ int abc[2];
+
+ abc[0] = 1;
+ return abc[1]; // expected-note {{read of object outside its lifetime}} \
+ // ref-note {{read of uninitialized object}}
+}
+static_assert(NoLeakHere() == 3); // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to}} \
+ // ref-error {{not an integral constant expression}} \
+ // ref-note {{in call to}}
Index: clang/lib/AST/Interp/InterpFrame.h
===================================================================
--- clang/lib/AST/Interp/InterpFrame.h
+++ clang/lib/AST/Interp/InterpFrame.h
@@ -47,6 +47,11 @@
/// Invokes the destructors for a scope.
void destroy(unsigned Idx);
+ /// Invokes the destructors for all scopes. This is used in the
+ /// InterpFrame destructor to avoid memory leaks in case the
+ /// interpretation was not successful.
+ void destroyAll();
+
/// Pops the arguments off the stack.
void popArgs();
Index: clang/lib/AST/Interp/InterpFrame.cpp
===================================================================
--- clang/lib/AST/Interp/InterpFrame.cpp
+++ clang/lib/AST/Interp/InterpFrame.cpp
@@ -64,6 +64,7 @@
}
InterpFrame::~InterpFrame() {
+ destroyAll();
for (auto &Param : Params)
S.deallocate(reinterpret_cast<Block *>(Param.second.get()));
}
@@ -74,6 +75,16 @@
}
}
+void InterpFrame::destroyAll() {
+ if (!Func)
+ return;
+ for (const Scope &Sc : Func->scopes()) {
+ for (auto &Local : Sc.locals()) {
+ S.deallocate(reinterpret_cast<Block *>(localBlock(Local.Offset)));
+ }
+ }
+}
+
void InterpFrame::popArgs() {
for (PrimType Ty : Func->args_reverse())
TYPE_SWITCH(Ty, S.Stk.discard<T>());
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D138275.476395.patch
Type: text/x-patch
Size: 2059 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20221118/c15f3c57/attachment.bin>
More information about the cfe-commits
mailing list