[cfe-commits] r116503 - in /cfe/trunk: include/clang/Driver/CC1Options.td include/clang/Frontend/PreprocessorOptions.h lib/Frontend/CompilerInvocation.cpp lib/Frontend/FrontendAction.cpp
Argyrios Kyrtzidis
akyrtzi at gmail.com
Wed May 7 18:34:47 PDT 2014
On May 7, 2014, at 11:56 AM, Nico Weber <thakis at chromium.org> wrote:
> Here's a patch that fixes the leak. The approach is to give ASTReader
> a DeleteListener bool, since different codepaths need different
> ownership semantics. (I explored two other options that didn't work
> out, see comments on PR19560.)
Did you consider using a ref-counted pointer ?
>
> Can people live with this patch?
>
> On Sat, May 3, 2014 at 10:01 AM, Argyrios Kyrtzidis <akyrtzi at gmail.com> wrote:
>> On May 3, 2014, at 3:55 AM, Chandler Carruth <chandlerc at gmail.com> wrote:
>>
>> On Sat, May 3, 2014 at 3:20 AM, Chandler Carruth <chandlerc at gmail.com>
>> wrote:
>>>
>>> First off, sorry for the commit necromancy, but I tried to fix a memory
>>> leak here and discovered completely broken ownership semantics that really
>>> need to be fixed, and need to be fixed by the person who really understands
>>> the intended design here.
>>>
>>> On Thu, Oct 14, 2010 at 1:14 PM, Argyrios Kyrtzidis <akyrtzi at gmail.com>
>>> wrote:
>>>>
>>>> Author: akirtzidis
>>>> Date: Thu Oct 14 15:14:18 2010
>>>> New Revision: 116503
>>>>
>>>> URL: http://llvm.org/viewvc/llvm-project?rev=116503&view=rev
>>>> Log:
>>>> Introduce command line option -dump-deserialized-decls which is used to
>>>> print the PCH decls that got deserialized, for testing purposes.
>>>
>>>
>>> <snip>
>>>
>>>>
>>>> Modified: cfe/trunk/lib/Frontend/FrontendAction.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendAction.cpp?rev=116503&r1=116502&r2=116503&view=diff
>>>>
>>>> ==============================================================================
>>>> --- cfe/trunk/lib/Frontend/FrontendAction.cpp (original)
>>>> +++ cfe/trunk/lib/Frontend/FrontendAction.cpp Thu Oct 14 15:14:18 2010
>>>> @@ -16,12 +16,43 @@
>>>> #include "clang/Frontend/CompilerInstance.h"
>>>> #include "clang/Frontend/FrontendDiagnostic.h"
>>>> #include "clang/Parse/ParseAST.h"
>>>> +#include "clang/Serialization/ASTDeserializationListener.h"
>>>> #include "llvm/Support/MemoryBuffer.h"
>>>> #include "llvm/Support/Timer.h"
>>>> #include "llvm/Support/ErrorHandling.h"
>>>> #include "llvm/Support/raw_ostream.h"
>>>> using namespace clang;
>>>>
>>>> +namespace {
>>>> +
>>>> +/// \brief Dumps deserialized declarations.
>>>> +class DeserializedDeclsDumper : public ASTDeserializationListener {
>>>> + ASTDeserializationListener *Previous;
>>>> +
>>>> +public:
>>>> + DeserializedDeclsDumper(ASTDeserializationListener *Previous)
>>>> + : Previous(Previous) { }
>>>> +
>>>> + virtual void DeclRead(serialization::DeclID ID, const Decl *D) {
>>>> + llvm::outs() << "PCH DECL: " << D->getDeclKindName();
>>>> + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
>>>> + llvm::outs() << " - " << ND->getNameAsString();
>>>> + llvm::outs() << "\n";
>>>> +
>>>> + if (Previous)
>>>> + Previous->DeclRead(ID, D);
>>>> + }
>>>> +
>>>> + virtual void SetReader(ASTReader *Reader) {}
>>>> + virtual void IdentifierRead(serialization::IdentID ID, IdentifierInfo
>>>> *II) {}
>>>> + virtual void TypeRead(serialization::TypeIdx Idx, QualType T) {}
>>>> + virtual void SelectorRead(serialization::SelectorID iD, Selector Sel)
>>>> {}
>>>> + virtual void MacroDefinitionRead(serialization::MacroID,
>>>> + MacroDefinition *MD) {}
>>>> +};
>>>> +
>>>> +} // end anonymous namespace
>>>> +
>>>> FrontendAction::FrontendAction() : Instance(0) {}
>>>>
>>>> FrontendAction::~FrontendAction() {}
>>>> @@ -118,11 +149,15 @@
>>>> /// Use PCH?
>>>> if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
>>>> assert(hasPCHSupport() && "This action does not have PCH
>>>> support!");
>>>> + ASTDeserializationListener *DeserialListener
>>>> + = CI.getInvocation().getFrontendOpts().ChainedPCH ?
>>>> + Consumer->GetASTDeserializationListener() : 0;
>>>> + if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls)
>>>> + DeserialListener = new
>>>> DeserializedDeclsDumper(DeserialListener);
>>>
>>>
>>> This listener leaks. So does the DeserializedDeclsChecker that follows the
>>> same pattern. LSan catches this.
>>>
>>> I went to plug the leak by storing the listeners in the FrontendAction if
>>> they end up being used, and deallocating them when the action is destroyed.
>>> To my great surprise, this caused use-after-free bugs as these listeners are
>>> somehow reached *after* the action is destroyed!
>>>
>>> Could you look into this? It should be pretty easy to reproduce. Forward
>>> declare the classes (or make them private classes nested within
>>> FrontendAction, or use a raw pointer and manually cast back to the derived
>>> type prior to deleting) and add unique_ptrs to the action, reseting them
>>> with the new listeners, and just wiring up DeserialListener to the raw
>>> pointer side. If you're having trouble reproducing, let me know, and I can
>>> send you a nascent patch.
>>>
>>> -Chandler
>>
>>
>> Just FYI, this is also filed as PR19560.
>>
>>
>> Thanks for bringing this to my attention! Please attach your patch to the
>> PR.
>> Unfortunately I'm not going to look into this soon, so I suggest disabling
>> the test, that uses the flag, for LSan.
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>
> <clang-deserialisten.patch>
More information about the cfe-commits
mailing list