Author: Jan Svoboda Date: 2026-09-25T08:57:45-07:00 New Revision: 73fc71b19905b15e6ff14ae3149c6fabce961c1b
URL: https://github.com/llvm/llvm-project/commit/73fc71b19905b15e6ff14ae3149c6fabce961c1b DIFF: https://github.com/llvm/llvm-project/commit/73fc71b19905b15e6ff14ae3149c6fabce961c1b.diff LOG: [clang][test] Fix lifetimes of HS/PP options (#225885) PR #133467 changed how lifetimes work for `PreprocessorOptions`. In LexerTest.cpp, the lifetimes were set up incorrectly, leading to potential use-after-free crashes. This PR fixes that by expanding the lifetime of both `PreprocessorOptions` and `HeaderSearchOptions`. Added: Modified: clang/unittests/Lex/LexerTest.cpp Removed: ################################################################################ diff --git a/clang/unittests/Lex/LexerTest.cpp b/clang/unittests/Lex/LexerTest.cpp index eaac861fa5e2c..8f632ccc5b931 100644 --- a/clang/unittests/Lex/LexerTest.cpp +++ b/clang/unittests/Lex/LexerTest.cpp @@ -43,34 +43,29 @@ class LexerTest : public ::testing::Test { LexerTest() : FileMgr(FileMgrOpts), Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()), - SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) { - TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; - Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts); - } - - std::unique_ptr<Preprocessor> CreatePP(StringRef Source, - TrivialModuleLoader &ModLoader) { + SourceMgr(Diags, FileMgr), TargetOpts([] { + TargetOptions TargetOpts; + TargetOpts.Triple = "x86_64-apple-darwin11.1.0"; + return TargetOpts; + }()), + Target(TargetInfo::CreateTargetInfo(Diags, TargetOpts)), + HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get()), + PP(std::make_unique<Preprocessor>(PPOpts, Diags, LangOpts, SourceMgr, + HeaderInfo, ModLoader)) {} + + void InitializePP(StringRef Source) { std::unique_ptr<llvm::MemoryBuffer> Buf = llvm::MemoryBuffer::getMemBuffer(Source); SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf))); - HeaderSearchOptions HSOpts; - HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get()); - PreprocessorOptions PPOpts; - std::unique_ptr<Preprocessor> PP = std::make_unique<Preprocessor>( - PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader, - /*IILookup =*/nullptr, - /*OwnsHeaderSearch =*/false); if (!PreDefines.empty()) PP->setPredefines(PreDefines); PP->Initialize(*Target); PP->EnterMainSourceFile(); - return PP; } std::vector<Token> Lex(StringRef Source) { - TrivialModuleLoader ModLoader; - PP = CreatePP(Source, ModLoader); + InitializePP(Source); std::vector<Token> toks; PP->LexTokensUntilEOF(&toks); @@ -130,8 +125,12 @@ class LexerTest : public ::testing::Test { DiagnosticsEngine Diags; SourceManager SourceMgr; LangOptions LangOpts; - std::shared_ptr<TargetOptions> TargetOpts; + TargetOptions TargetOpts; IntrusiveRefCntPtr<TargetInfo> Target; + HeaderSearchOptions HSOpts; + HeaderSearch HeaderInfo; + TrivialModuleLoader ModLoader; + PreprocessorOptions PPOpts; std::unique_ptr<Preprocessor> PP; std::string PreDefines; }; @@ -471,8 +470,7 @@ TEST_F(LexerTest, DontMergeMacroArgsFromDifferentMacroFiles) { } TEST_F(LexerTest, DontOverallocateStringifyArgs) { - TrivialModuleLoader ModLoader; - auto PP = CreatePP("\"StrArg\", 5, 'C'", ModLoader); + InitializePP("\"StrArg\", 5, 'C'"); llvm::BumpPtrAllocator Allocator; std::array<IdentifierInfo *, 3> ParamList; @@ -498,7 +496,7 @@ TEST_F(LexerTest, DontOverallocateStringifyArgs) { ArgTokens.push_back(tok); } - auto MacroArgsDeleter = [&PP](MacroArgs *M) { M->destroy(*PP); }; + auto MacroArgsDeleter = [this](MacroArgs *M) { M->destroy(*PP); }; std::unique_ptr<MacroArgs, decltype(MacroArgsDeleter)> MA( MacroArgs::create(MI, ArgTokens, false, *PP), MacroArgsDeleter); auto StringifyArg = [&](int ArgNo) { @@ -571,9 +569,15 @@ TEST_F(LexerTest, GetBeginningOfTokenWithEscapedNewLine) { } } -TEST_F(LexerTest, AvoidPastEndOfStringDereference) { +TEST_F(LexerTest, AvoidPastEndOfStringDereference01) { EXPECT_TRUE(Lex(" // \\\n").empty()); +} + +TEST_F(LexerTest, AvoidPastEndOfStringDereference02) { EXPECT_TRUE(Lex("#include <\\\\").empty()); +} + +TEST_F(LexerTest, AvoidPastEndOfStringDereference03) { EXPECT_TRUE(Lex("#include <\\\\\n").empty()); } @@ -709,8 +713,7 @@ TEST_F(LexerTest, FindPreviousTokenIncludingComments) { } TEST_F(LexerTest, CreatedFIDCountForPredefinedBuffer) { - TrivialModuleLoader ModLoader; - auto PP = CreatePP("", ModLoader); + InitializePP(""); PP->LexTokensUntilEOF(); EXPECT_EQ(SourceMgr.getNumCreatedFIDsForFileID(PP->getPredefinesFileID()), 1U); @@ -804,51 +807,46 @@ TEST(LexerPreambleTest, PreambleBounds) { } } -TEST_F(LexerTest, CheckFirstPPToken) { +TEST_F(LexerTest, CheckFirstPPToken01) { LangOpts.CPlusPlusModules = true; - { - TrivialModuleLoader ModLoader; - auto PP = CreatePP("// This is a comment\n" - "int a;", - ModLoader); - Token Tok; - PP->Lex(Tok); - EXPECT_TRUE(Tok.is(tok::kw_int)); - EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc().isValid()); - EXPECT_EQ(PP->getMainFileFirstPPTokenLoc(), Tok.getLocation()); - } - { - TrivialModuleLoader ModLoader; - auto PP = CreatePP("// This is a comment\n" - "#define FOO int\n" - "FOO a;", - ModLoader); - Token Tok; - PP->Lex(Tok); - EXPECT_TRUE(Tok.is(tok::kw_int)); - EXPECT_FALSE(Lexer::getRawToken(PP->getMainFileFirstPPTokenLoc(), Tok, - PP->getSourceManager(), PP->getLangOpts(), - /*IgnoreWhiteSpace=*/false)); - EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc() == Tok.getLocation()); - EXPECT_TRUE(Tok.is(tok::hash)); - } + InitializePP("// This is a comment\n" + "int a;"); + Token Tok; + PP->Lex(Tok); + EXPECT_TRUE(Tok.is(tok::kw_int)); + EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc().isValid()); + EXPECT_EQ(PP->getMainFileFirstPPTokenLoc(), Tok.getLocation()); +} - { - PreDefines = "#define FOO int\n"; - TrivialModuleLoader ModLoader; - auto PP = CreatePP("// This is a comment\n" - "FOO a;", - ModLoader); - Token Tok; - PP->Lex(Tok); - EXPECT_TRUE(Tok.is(tok::kw_int)); - EXPECT_FALSE(Lexer::getRawToken(PP->getMainFileFirstPPTokenLoc(), Tok, - PP->getSourceManager(), PP->getLangOpts(), - /*IgnoreWhiteSpace=*/false)); - EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc() == Tok.getLocation()); - EXPECT_TRUE(Tok.is(tok::raw_identifier)); - EXPECT_TRUE(Tok.getRawIdentifier() == "FOO"); - } +TEST_F(LexerTest, CheckFirstPPToken02) { + LangOpts.CPlusPlusModules = true; + InitializePP("// This is a comment\n" + "#define FOO int\n" + "FOO a;"); + Token Tok; + PP->Lex(Tok); + EXPECT_TRUE(Tok.is(tok::kw_int)); + EXPECT_FALSE(Lexer::getRawToken(PP->getMainFileFirstPPTokenLoc(), Tok, + PP->getSourceManager(), PP->getLangOpts(), + /*IgnoreWhiteSpace=*/false)); + EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc() == Tok.getLocation()); + EXPECT_TRUE(Tok.is(tok::hash)); +} + +TEST_F(LexerTest, CheckFirstPPToken03) { + LangOpts.CPlusPlusModules = true; + PreDefines = "#define FOO int\n"; + InitializePP("// This is a comment\n" + "FOO a;"); + Token Tok; + PP->Lex(Tok); + EXPECT_TRUE(Tok.is(tok::kw_int)); + EXPECT_FALSE(Lexer::getRawToken(PP->getMainFileFirstPPTokenLoc(), Tok, + PP->getSourceManager(), PP->getLangOpts(), + /*IgnoreWhiteSpace=*/false)); + EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc() == Tok.getLocation()); + EXPECT_TRUE(Tok.is(tok::raw_identifier)); + EXPECT_TRUE(Tok.getRawIdentifier() == "FOO"); } TEST_F(LexerTest, FindEndOfIdentifierContinuation) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
