diff options
author | Dan Liew <daniel.liew@imperial.ac.uk> | 2015-12-16 18:13:11 +0000 |
---|---|---|
committer | Dan Liew <daniel.liew@imperial.ac.uk> | 2015-12-18 11:22:50 +0000 |
commit | 53ff7a002a8213a5d5e778bef2a895998d9890e1 (patch) | |
tree | 026a4f1b16c1996755954f7824e0d10f8ed0ef8e /lib/Expr/Parser.cpp | |
parent | 7e75fa79b2e76251c2cd417a7eae8a7620b014ae (diff) | |
download | klee-53ff7a002a8213a5d5e778bef2a895998d9890e1.tar.gz |
Fix memory leaks of ``Array`` objects detected by ASan.
Some of these leaks were introduced by the factory constructor for Array objects (f049ff3bc04daead8c3bb9f06e89e71e2054c82a) but a few others have been around for far longer. This leak was fixed by introducing a ``ArrayCache`` object which has two purposes * Retains ownership of all created ``Array`` objects and destroys them when the ``ArrayCache`` destructor is called. * Mimic the caching behaviour for symbolic arrays that was introduced by f049ff3bc04daead8c3bb9f06e89e71e2054c82a where arrays with the same name and size get "uniqued". The Executor now maintains a ``arrayCache`` member that it uses and passes by pointer to objects that need to construct ``Array`` objects (i.e. ``ObjectState``). This way when the Executor is destroyed all the ``Array`` objects get freed which seems like the right time to do this. For Kleaver the ``ParserImpl`` has a ``TheArrayCache`` member that is used for building ``Array`` objects. This means that the Parser must live as long as the built expressions will be used otherwise we will have a use after free. I'm not sure this is the right design choice. It might be better to transfer ownership of the ``Array`` objects to the root ``Decl`` returned by the parser.
Diffstat (limited to 'lib/Expr/Parser.cpp')
-rw-r--r-- | lib/Expr/Parser.cpp | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/lib/Expr/Parser.cpp b/lib/Expr/Parser.cpp index 23a292fa..854f6d52 100644 --- a/lib/Expr/Parser.cpp +++ b/lib/Expr/Parser.cpp @@ -16,6 +16,7 @@ #include "klee/ExprBuilder.h" #include "klee/Solver.h" #include "klee/util/ExprPPrinter.h" +#include "klee/util/ArrayCache.h" #include "llvm/ADT/APInt.h" #include "llvm/Support/MemoryBuffer.h" @@ -109,6 +110,7 @@ namespace { const std::string Filename; const MemoryBuffer *TheMemoryBuffer; ExprBuilder *Builder; + ArrayCache TheArrayCache; Lexer TheLexer; unsigned MaxErrors; @@ -521,10 +523,10 @@ DeclResult ParserImpl::ParseArrayDecl() { const Identifier *Label = GetOrCreateIdentifier(Name); const Array *Root; if (!Values.empty()) - Root = Array::CreateArray(Label->Name, Size.get(), - &Values[0], &Values[0] + Values.size()); + Root = TheArrayCache.CreateArray(Label->Name, Size.get(), &Values[0], + &Values[0] + Values.size()); else - Root = Array::CreateArray(Label->Name, Size.get()); + Root = TheArrayCache.CreateArray(Label->Name, Size.get()); ArrayDecl *AD = new ArrayDecl(Label, Size.get(), DomainType.get(), RangeType.get(), Root); @@ -1306,7 +1308,9 @@ VersionResult ParserImpl::ParseVersionSpecifier() { VersionResult Res = ParseVersion(); // Define update list to avoid use-of-undef errors. if (!Res.isValid()) { - Res = VersionResult(true, UpdateList(Array::CreateArray("", 0), NULL)); + // FIXME: I'm not sure if this is right. Do we need a unique array here? + Res = + VersionResult(true, UpdateList(TheArrayCache.CreateArray("", 0), NULL)); } if (Label) |