From 9f0d281d87c0544be5b54e881482c7f18c33725d Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Tue, 20 Jun 2017 02:05:35 +0000 Subject: [PATCH] [Coverage] PR33517: Check for failure to load func records With PR33517, it became apparent that symbol table creation can fail when presented with malformed inputs. This patch makes that sort of error detectable, so llvm-cov etc. can fail more gracefully. Specifically, we now check that function records loaded from corrupted coverage mapping data are rejected, e.g when the recorded function name is garbage. Testing: check-{llvm,clang,profile}, some unit test updates. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305767 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/ProfileData/Coverage/CoverageMapping.cpp | 3 + unittests/ProfileData/CoverageMappingTest.cpp | 55 +++++++++++++------ 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/lib/ProfileData/Coverage/CoverageMapping.cpp b/lib/ProfileData/Coverage/CoverageMapping.cpp index 015b3c6c202..953972968d6 100644 --- a/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -200,6 +200,9 @@ Error CoverageMapping::loadFunctionRecord( const CoverageMappingRecord &Record, IndexedInstrProfReader &ProfileReader) { StringRef OrigFuncName = Record.FunctionName; + if (OrigFuncName.empty()) + return make_error(coveragemap_error::malformed); + if (Record.Filenames.empty()) OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName); else diff --git a/unittests/ProfileData/CoverageMappingTest.cpp b/unittests/ProfileData/CoverageMappingTest.cpp index 0e6e993cf3d..ea51f717a1d 100644 --- a/unittests/ProfileData/CoverageMappingTest.cpp +++ b/unittests/ProfileData/CoverageMappingTest.cpp @@ -28,6 +28,19 @@ static ::testing::AssertionResult NoError(Error E) { << "\n"; } +static ::testing::AssertionResult ErrorEquals(coveragemap_error Expected, + Error E) { + coveragemap_error Found; + std::string FoundMsg; + handleAllErrors(std::move(E), [&](const CoverageMapError &CME) { + Found = CME.get(); + FoundMsg = CME.message(); + }); + if (Expected == Found) + return ::testing::AssertionSuccess(); + return ::testing::AssertionFailure() << "error: " << FoundMsg << "\n"; +} + namespace llvm { namespace coverage { void PrintTo(const Counter &C, ::std::ostream *os) { @@ -232,12 +245,14 @@ struct CoverageMappingTest : ::testing::TestWithParam> { return CoverageMapping::load(CoverageReaders, *ProfileReader); } - void loadCoverageMapping(bool EmitFilenames = true) { + Error loadCoverageMapping(bool EmitFilenames = true) { readProfCounts(); writeAndReadCoverageRegions(EmitFilenames); auto CoverageOrErr = readOutputFunctions(); - ASSERT_TRUE(NoError(CoverageOrErr.takeError())); + if (!CoverageOrErr) + return CoverageOrErr.takeError(); LoadedCoverage = std::move(CoverageOrErr.get()); + return Error::success(); } }; @@ -304,7 +319,7 @@ TEST_P(CoverageMappingTest, load_coverage_for_more_than_two_files) { // in order to preserve that information during possible sorting of CMRs. addCMR(Counter::getCounter(0), FileNames[I], I, 1, I, 1); - loadCoverageMapping(); + NoError(loadCoverageMapping()); for (unsigned I = 0; I < N; ++I) { CoverageData Data = LoadedCoverage->getCoverageForFile(FileNames[I]); @@ -313,6 +328,14 @@ TEST_P(CoverageMappingTest, load_coverage_for_more_than_two_files) { } } +TEST_P(CoverageMappingTest, load_coverage_with_bogus_function_name) { + InstrProfRecord RecordFunc1("", 0x1234, {10}); + NoError(ProfileWriter.addRecord(std::move(RecordFunc1))); + startFunction("", 0x1234); + addCMR(Counter::getCounter(0), "foo", 1, 1, 5, 5); + ErrorEquals(coveragemap_error::malformed, loadCoverageMapping()); +} + TEST_P(CoverageMappingTest, load_coverage_for_several_functions) { InstrProfRecord RecordFunc1("func1", 0x1234, {10}); NoError(ProfileWriter.addRecord(std::move(RecordFunc1))); @@ -325,7 +348,7 @@ TEST_P(CoverageMappingTest, load_coverage_for_several_functions) { startFunction("func2", 0x2345); addCMR(Counter::getCounter(0), "bar", 2, 2, 6, 6); - loadCoverageMapping(); + NoError(loadCoverageMapping()); const auto FunctionRecords = LoadedCoverage->getCoveredFunctions(); EXPECT_EQ(2, std::distance(FunctionRecords.begin(), FunctionRecords.end())); @@ -369,7 +392,7 @@ TEST_P(CoverageMappingTest, basic_coverage_iteration) { addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7); addCMR(Counter::getCounter(2), "file1", 5, 8, 9, 1); addCMR(Counter::getCounter(3), "file1", 10, 10, 11, 11); - loadCoverageMapping(); + NoError(loadCoverageMapping()); CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); std::vector Segments(Data.begin(), Data.end()); @@ -386,7 +409,7 @@ TEST_P(CoverageMappingTest, basic_coverage_iteration) { TEST_P(CoverageMappingTest, uncovered_function) { startFunction("func", 0x1234); addCMR(Counter::getZero(), "file1", 1, 2, 3, 4); - loadCoverageMapping(); + NoError(loadCoverageMapping()); CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); std::vector Segments(Data.begin(), Data.end()); @@ -399,7 +422,7 @@ TEST_P(CoverageMappingTest, uncovered_function_with_mapping) { startFunction("func", 0x1234); addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7); - loadCoverageMapping(); + NoError(loadCoverageMapping()); CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); std::vector Segments(Data.begin(), Data.end()); @@ -417,7 +440,7 @@ TEST_P(CoverageMappingTest, combine_regions) { addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4); addCMR(Counter::getCounter(2), "file1", 3, 3, 4, 4); - loadCoverageMapping(); + NoError(loadCoverageMapping()); CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); std::vector Segments(Data.begin(), Data.end()); @@ -436,7 +459,7 @@ TEST_P(CoverageMappingTest, restore_combined_counter_after_nested_region) { addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); addCMR(Counter::getCounter(1), "file1", 1, 1, 9, 9); addCMR(Counter::getCounter(2), "file1", 3, 3, 5, 5); - loadCoverageMapping(); + NoError(loadCoverageMapping()); CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); std::vector Segments(Data.begin(), Data.end()); @@ -460,7 +483,7 @@ TEST_P(CoverageMappingTest, dont_combine_expansions) { addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4); addCMR(Counter::getCounter(1), "include1", 6, 6, 7, 7); addExpansionCMR("file1", "include1", 3, 3, 4, 4); - loadCoverageMapping(); + NoError(loadCoverageMapping()); CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); std::vector Segments(Data.begin(), Data.end()); @@ -483,7 +506,7 @@ TEST_P(CoverageMappingTest, combine_expansions) { addExpansionCMR("file", "include1", 3, 1, 3, 5); addExpansionCMR("file", "include2", 3, 1, 3, 5); - loadCoverageMapping(); + NoError(loadCoverageMapping()); CoverageData Data = LoadedCoverage->getCoverageForFile("file"); std::vector Segments(Data.begin(), Data.end()); @@ -500,7 +523,7 @@ TEST_P(CoverageMappingTest, strip_filename_prefix) { startFunction("file1:func", 0x1234); addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); - loadCoverageMapping(); + NoError(loadCoverageMapping()); std::vector Names; for (const auto &Func : LoadedCoverage->getCoveredFunctions()) @@ -515,7 +538,7 @@ TEST_P(CoverageMappingTest, strip_unknown_filename_prefix) { startFunction(":func", 0x1234); addCMR(Counter::getCounter(0), "", 1, 1, 9, 9); - loadCoverageMapping(/*EmitFilenames=*/false); + NoError(loadCoverageMapping(/*EmitFilenames=*/false)); std::vector Names; for (const auto &Func : LoadedCoverage->getCoveredFunctions()) @@ -538,7 +561,7 @@ TEST_P(CoverageMappingTest, dont_detect_false_instantiations) { addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10); addExpansionCMR("main", "expanded", 9, 1, 9, 5); - loadCoverageMapping(); + NoError(loadCoverageMapping()); std::vector Instantiations = LoadedCoverage->getInstantiations("expanded"); @@ -553,7 +576,7 @@ TEST_P(CoverageMappingTest, load_coverage_for_expanded_file) { addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10); addExpansionCMR("main", "expanded", 4, 1, 4, 5); - loadCoverageMapping(); + NoError(loadCoverageMapping()); CoverageData Data = LoadedCoverage->getCoverageForFile("expanded"); std::vector Segments(Data.begin(), Data.end()); @@ -572,7 +595,7 @@ TEST_P(CoverageMappingTest, skip_duplicate_function_record) { startFunction("func", 0x1234); addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); - loadCoverageMapping(); + NoError(loadCoverageMapping()); auto Funcs = LoadedCoverage->getCoveredFunctions(); unsigned NumFuncs = std::distance(Funcs.begin(), Funcs.end()); -- 2.40.0