From c760a821c1c0ef03ab41edfa3ddfedc44a25c99d Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Tue, 17 May 2016 02:15:12 +0000 Subject: [PATCH] Modules: set SystemHeader to true if we are building a system module. If we are processing a #include from a module build, we should treat it as a system header if we're building a system module. Passing an optional flag to HeaderSearch::LookupFile. Before this, the testing case will crash when accessing a freed FileEntry. rdar://26214027 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@269730 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/HeaderSearch.h | 2 +- lib/Lex/HeaderSearch.cpp | 7 +++--- lib/Lex/PPDirectives.cpp | 9 ++++--- .../Inputs/UseAfterFree/UseAfterFreePrivate.h | 1 + .../Inputs/UseAfterFree/UseAfterFreePublic.h | 2 ++ test/Modules/Inputs/UseAfterFree/module.map | 3 +++ .../Inputs/UseAfterFree/module_private.map | 3 +++ test/Modules/use-after-free.m | 24 +++++++++++++++++++ 8 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 test/Modules/Inputs/UseAfterFree/UseAfterFreePrivate.h create mode 100644 test/Modules/Inputs/UseAfterFree/UseAfterFreePublic.h create mode 100644 test/Modules/Inputs/UseAfterFree/module.map create mode 100644 test/Modules/Inputs/UseAfterFree/module_private.map create mode 100644 test/Modules/use-after-free.m diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 6d7817f862..152258af16 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -381,7 +381,7 @@ public: ArrayRef> Includers, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, - bool SkipCache = false); + bool SkipCache = false, bool BuildSystemModule = false); /// \brief Look up a subframework for the specified \#include file. /// diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 3bb7f8e042..e627c78640 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -565,7 +565,7 @@ const FileEntry *HeaderSearch::LookupFile( ArrayRef> Includers, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, - bool SkipCache) { + bool SkipCache, bool BuildSystemModule) { if (SuggestedModule) *SuggestedModule = ModuleMap::KnownHeader(); @@ -613,11 +613,12 @@ const FileEntry *HeaderSearch::LookupFile( // getFileAndSuggestModule, because it's a reference to an element of // a container that could be reallocated across this call. // - // FIXME: If we have no includer, that means we're processing a #include + // If we have no includer, that means we're processing a #include // from a module build. We should treat this as a system header if we're // building a [system] module. bool IncluderIsSystemHeader = - Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User; + (Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User) || + (!Includer && BuildSystemModule); if (const FileEntry *FE = getFileAndSuggestModule( TmpDir, IncluderAndDir.second, IncluderIsSystemHeader, RequestingModule, SuggestedModule)) { diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index c33f9aba26..34adf7fac2 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -671,6 +671,7 @@ const FileEntry *Preprocessor::LookupFile( // stack, record the parent #includes. SmallVector, 16> Includers; + bool BuildSystemModule = false; if (!FromDir && !FromFile) { FileID FID = getCurrentFileLexer()->getFileID(); const FileEntry *FileEnt = SourceMgr.getFileEntryForID(FID); @@ -688,9 +689,10 @@ const FileEntry *Preprocessor::LookupFile( // come from header declarations in the module map) relative to the module // map file. if (!FileEnt) { - if (FID == SourceMgr.getMainFileID() && MainFileDir) + if (FID == SourceMgr.getMainFileID() && MainFileDir) { Includers.push_back(std::make_pair(nullptr, MainFileDir)); - else if ((FileEnt = + BuildSystemModule = getCurrentModule()->IsSystem; + } else if ((FileEnt = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()))) Includers.push_back(std::make_pair(FileEnt, FileMgr.getDirectory("."))); } else { @@ -736,7 +738,8 @@ const FileEntry *Preprocessor::LookupFile( // Do a standard file entry lookup. const FileEntry *FE = HeaderInfo.LookupFile( Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath, - RelativePath, RequestingModule, SuggestedModule, SkipCache); + RelativePath, RequestingModule, SuggestedModule, SkipCache, + BuildSystemModule); if (FE) { if (SuggestedModule && !LangOpts.AsmPreprocessor) HeaderInfo.getModuleMap().diagnoseHeaderInclusion( diff --git a/test/Modules/Inputs/UseAfterFree/UseAfterFreePrivate.h b/test/Modules/Inputs/UseAfterFree/UseAfterFreePrivate.h new file mode 100644 index 0000000000..e8ed9fda58 --- /dev/null +++ b/test/Modules/Inputs/UseAfterFree/UseAfterFreePrivate.h @@ -0,0 +1 @@ +@import UseAfterFreePublic; diff --git a/test/Modules/Inputs/UseAfterFree/UseAfterFreePublic.h b/test/Modules/Inputs/UseAfterFree/UseAfterFreePublic.h new file mode 100644 index 0000000000..d017b0f310 --- /dev/null +++ b/test/Modules/Inputs/UseAfterFree/UseAfterFreePublic.h @@ -0,0 +1,2 @@ +@interface S1 +@end diff --git a/test/Modules/Inputs/UseAfterFree/module.map b/test/Modules/Inputs/UseAfterFree/module.map new file mode 100644 index 0000000000..35c0b3d230 --- /dev/null +++ b/test/Modules/Inputs/UseAfterFree/module.map @@ -0,0 +1,3 @@ +module UseAfterFreePublic { + header "UseAfterFreePublic.h" +} diff --git a/test/Modules/Inputs/UseAfterFree/module_private.map b/test/Modules/Inputs/UseAfterFree/module_private.map new file mode 100644 index 0000000000..75eec4162c --- /dev/null +++ b/test/Modules/Inputs/UseAfterFree/module_private.map @@ -0,0 +1,3 @@ +module UseAfterFreePrivate { + header "UseAfterFreePrivate.h" +} diff --git a/test/Modules/use-after-free.m b/test/Modules/use-after-free.m new file mode 100644 index 0000000000..fa7200933a --- /dev/null +++ b/test/Modules/use-after-free.m @@ -0,0 +1,24 @@ +// RUN: rm -rf %t + +// Here, we build the module without "non-modular-include-in-framework-module". +// RUN: echo '@import UseAfterFreePublic;' | \ +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps \ +// RUN: -fmodules-cache-path=%t -isystem %S/Inputs/UseAfterFree/ -fsyntax-only \ +// RUN: -x objective-c - + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps \ +// RUN: -fmodules-cache-path=%t -isystem %S/Inputs/UseAfterFree/ -fsyntax-only \ +// RUN: -Wnon-modular-include-in-framework-module -Werror=non-modular-include-in-framework-module \ +// RUN: -x objective-c %s -verify +// expected-no-diagnostics + +// Here, we load the module UseAfterFreePublic, it is treated as a system module, +// we ignore the inconsistency for "non-modular-include-in-framework-module". +@import UseAfterFreePublic; + +// We start a thread to build the module for UseAfterFreePrivate.h. In the thread, +// we load UseAfterFreePublic and should treat it as a system module as well. +// If not, we will invalidate UseAfterFreePublic because of the inconsistency +// for "non-modular-include-in-framework-module", and have a use-after-free error +// of the FileEntry. +#import -- 2.40.0