]> granicus.if.org Git - llvm/commitdiff
[Coverage] PR33517: Check for failure to load func records
authorVedant Kumar <vsk@apple.com>
Tue, 20 Jun 2017 02:05:35 +0000 (02:05 +0000)
committerVedant Kumar <vsk@apple.com>
Tue, 20 Jun 2017 02:05:35 +0000 (02:05 +0000)
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
unittests/ProfileData/CoverageMappingTest.cpp

index 015b3c6c2021d293a7ed8c9ce0c70cc26bd2e2d0..953972968d6cade254f03745cd325de878f1ab0c 100644 (file)
@@ -200,6 +200,9 @@ Error CoverageMapping::loadFunctionRecord(
     const CoverageMappingRecord &Record,
     IndexedInstrProfReader &ProfileReader) {
   StringRef OrigFuncName = Record.FunctionName;
+  if (OrigFuncName.empty())
+    return make_error<CoverageMapError>(coveragemap_error::malformed);
+
   if (Record.Filenames.empty())
     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
   else
index 0e6e993cf3da2104c414a3a700c6401886dffa33..ea51f717a1db89ad69f5ae15514243a233c5cd14 100644 (file)
@@ -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<std::pair<bool, bool>> {
     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<CoverageSegment> 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<CoverageSegment> 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<CoverageSegment> 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<CoverageSegment> 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<CoverageSegment> 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<CoverageSegment> 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<CoverageSegment> 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<std::string> Names;
   for (const auto &Func : LoadedCoverage->getCoveredFunctions())
@@ -515,7 +538,7 @@ TEST_P(CoverageMappingTest, strip_unknown_filename_prefix) {
 
   startFunction("<unknown>:func", 0x1234);
   addCMR(Counter::getCounter(0), "", 1, 1, 9, 9);
-  loadCoverageMapping(/*EmitFilenames=*/false);
+  NoError(loadCoverageMapping(/*EmitFilenames=*/false));
 
   std::vector<std::string> 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<const FunctionRecord *> 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<CoverageSegment> 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());