[llvm] r194635 - llvm-cov: Replaced asserts with proper error handling.

Yuchen Wu yuchenericwu at hotmail.com
Wed Nov 13 16:07:15 PST 2013


Author: ywu
Date: Wed Nov 13 18:07:15 2013
New Revision: 194635

URL: http://llvm.org/viewvc/llvm-project?rev=194635&view=rev
Log:
llvm-cov: Replaced asserts with proper error handling.

Unified the interface for read functions. They all return a boolean
indicating if the read from file succeeded. Functions that previously
returned the read value now store it into a variable that is passed in
by reference instead. Callers will need to check the return value to
detect if an error occurred.

Also added a new test which ensures that no assertions occur when file
contains invalid data. llvm-cov should return with error code 1 upon
failure.

Modified:
    llvm/trunk/include/llvm/Support/GCOV.h
    llvm/trunk/lib/IR/GCOV.cpp
    llvm/trunk/test/tools/llvm-cov/llvm-cov.test

Modified: llvm/trunk/include/llvm/Support/GCOV.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/GCOV.h?rev=194635&r1=194634&r2=194635&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/GCOV.h (original)
+++ llvm/trunk/include/llvm/Support/GCOV.h Wed Nov 13 18:07:15 2013
@@ -152,27 +152,35 @@ public:
     return true;
   }
 
-  uint32_t readInt() {
-    uint32_t Result;
+  bool readInt(uint32_t &Val) {
     StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
-    assert (Str.empty() == false && "Unexpected memory buffer end!");
+    if (Str.empty()) {
+      errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n";
+      return false;
+    }
     Cursor += 4;
-    Result = *(const uint32_t *)(Str.data());
-    return Result;
+    Val = *(const uint32_t *)(Str.data());
+    return true;
   }
 
-  uint64_t readInt64() {
-    uint64_t Lo = readInt();
-    uint64_t Hi = readInt();
-    uint64_t Result = Lo | (Hi << 32);
-    return Result;
+  bool readInt64(uint64_t &Val) {
+    uint32_t Lo, Hi;
+    if (!readInt(Lo) || !readInt(Hi)) return false;
+    Val = ((uint64_t)Hi << 32) | Lo;
+    return true;
   }
 
-  StringRef readString() {
-    uint32_t Len = readInt() * 4;
-    StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len);
+  bool readString(StringRef &Str) {
+    uint32_t Len;
+    if (!readInt(Len)) return false;
+    Len *= 4;
+    if (Buffer->getBuffer().size() < Cursor+Len) {
+      errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n";
+      return false;
+    }
+    Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first;
     Cursor += Len;
-    return Str.split('\0').first;
+    return true;
   }
 
   uint64_t getCursor() const { return Cursor; }

Modified: llvm/trunk/lib/IR/GCOV.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/GCOV.cpp?rev=194635&r1=194634&r2=194635&view=diff
==============================================================================
--- llvm/trunk/lib/IR/GCOV.cpp (original)
+++ llvm/trunk/lib/IR/GCOV.cpp Wed Nov 13 18:07:15 2013
@@ -47,27 +47,34 @@ bool GCOVFile::read(GCOVBuffer &Buffer)
 
   if (isGCNOFile(Format)) {
     while (true) {
+      if (!Buffer.readFunctionTag()) break;
       GCOVFunction *GFun = new GCOVFunction();
       if (!GFun->read(Buffer, Format))
-        break;
+        return false;
       Functions.push_back(GFun);
     }
   }
   else if (isGCDAFile(Format)) {
     for (size_t i = 0, e = Functions.size(); i < e; ++i) {
-      bool ReadGCDA = Functions[i]->read(Buffer, Format);
-      (void)ReadGCDA;
-      assert(ReadGCDA && ".gcda data does not match .gcno data");
+      if (!Buffer.readFunctionTag()) {
+        errs() << "Unexpected number of functions.\n";
+        return false;
+      }
+      if (!Functions[i]->read(Buffer, Format))
+        return false;
     }
     if (Buffer.readObjectTag()) {
-      uint32_t Length = Buffer.readInt();
-      Buffer.readInt(); // checksum
-      Buffer.readInt(); // num
-      RunCount = Buffer.readInt();
+      uint32_t Length;
+      uint32_t Dummy;
+      if (!Buffer.readInt(Length)) return false;
+      if (!Buffer.readInt(Dummy)) return false; // checksum
+      if (!Buffer.readInt(Dummy)) return false; // num
+      if (!Buffer.readInt(RunCount)) return false;;
       Buffer.advanceCursor(Length-3);
     }
     while (Buffer.readProgramTag()) {
-      uint32_t Length = Buffer.readInt();
+      uint32_t Length;
+      if (!Buffer.readInt(Length)) return false;
       Buffer.advanceCursor(Length);
       ++ProgramCount;
     }
@@ -104,75 +111,103 @@ GCOVFunction::~GCOVFunction() {
 /// read - Read a function from the buffer. Return false if buffer cursor
 /// does not point to a function tag.
 bool GCOVFunction::read(GCOVBuffer &Buff, GCOV::GCOVFormat Format) {
-  if (!Buff.readFunctionTag())
-    return false;
-
-  Buff.readInt(); // Function header length
-  Ident = Buff.readInt(); 
-  Buff.readInt(); // Checksum #1
+  uint32_t Dummy;
+  if (!Buff.readInt(Dummy)) return false; // Function header length
+  if (!Buff.readInt(Ident)) return false;
+  if (!Buff.readInt(Dummy)) return false; // Checksum #1
   if (Format != GCOV::GCNO_402 && Format != GCOV::GCDA_402)
-    Buff.readInt(); // Checksum #2
+    if (!Buff.readInt(Dummy)) return false; // Checksum #2
+
+  if (!Buff.readString(Name)) return false;
 
-  Name = Buff.readString();
   if (Format == GCOV::GCNO_402 || Format == GCOV::GCNO_404)
-    Filename = Buff.readString();
+    if (!Buff.readString(Filename)) return false;
 
   if (Format == GCOV::GCDA_402 || Format == GCOV::GCDA_404) {
-    Buff.readArcTag();
-    uint32_t i = 0;
-    uint32_t Count = Buff.readInt() / 2;
+    if (!Buff.readArcTag()) {
+      errs() << "Arc tag not found.\n";
+      return false;
+    }
+    uint32_t Count;
+    if (!Buff.readInt(Count)) return false;
+    Count /= 2;
 
     // This for loop adds the counts for each block. A second nested loop is
     // required to combine the edge counts that are contained in the GCDA file.
-    for (uint32_t Line = 0; i < Count; ++Line) {
+    for (uint32_t Line = 0; Count > 0; ++Line) {
       GCOVBlock &Block = *Blocks[Line];
       for (size_t Edge = 0, End = Block.getNumEdges(); Edge < End; ++Edge) {
-        assert(i < Count && "Unexpected number of Edges!");
-        Block.addCount(Buff.readInt64());
-        ++i;
+        if (Count == 0) {
+          errs() << "Unexpected number of edges.\n";
+          return false;
+        }
+        uint64_t ArcCount;
+        if (!Buff.readInt64(ArcCount)) return false;
+        Block.addCount(ArcCount);
+        --Count;
       }
     }
     return true;
   }
 
-  LineNumber = Buff.readInt();
+  if (!Buff.readInt(LineNumber)) return false;
 
   // read blocks.
-  bool BlockTagFound = Buff.readBlockTag();
-  (void)BlockTagFound;
-  assert(BlockTagFound && "Block Tag not found!");
-  uint32_t BlockCount = Buff.readInt();
+  if (!Buff.readBlockTag()) {
+    errs() << "Block tag not found.\n";
+    return false;
+  }
+  uint32_t BlockCount;
+  if (!Buff.readInt(BlockCount)) return false;
   for (uint32_t i = 0, e = BlockCount; i != e; ++i) {
-    Buff.readInt(); // Block flags;
+    if (!Buff.readInt(Dummy)) return false; // Block flags;
     Blocks.push_back(new GCOVBlock(i));
   }
 
   // read edges.
   while (Buff.readEdgeTag()) {
-    uint32_t EdgeCount = (Buff.readInt() - 1) / 2;
-    uint32_t BlockNo = Buff.readInt();
-    assert(BlockNo < BlockCount && "Unexpected Block number!");
+    uint32_t EdgeCount;
+    if (!Buff.readInt(EdgeCount)) return false;
+    EdgeCount = (EdgeCount - 1) / 2;
+    uint32_t BlockNo;
+    if (!Buff.readInt(BlockNo)) return false;
+    if (BlockNo >= BlockCount) {
+      errs() << "Unexpected block number.\n";
+      return false;
+    }
     for (uint32_t i = 0, e = EdgeCount; i != e; ++i) {
-      Blocks[BlockNo]->addEdge(Buff.readInt());
-      Buff.readInt(); // Edge flag
+      uint32_t Dst;
+      if (!Buff.readInt(Dst)) return false;
+      Blocks[BlockNo]->addEdge(Dst);
+      if (!Buff.readInt(Dummy)) return false; // Edge flag
     }
   }
 
   // read line table.
   while (Buff.readLineTag()) {
-    uint32_t LineTableLength = Buff.readInt();
+    uint32_t LineTableLength;
+    if (!Buff.readInt(LineTableLength)) return false;
     uint32_t EndPos = Buff.getCursor() + LineTableLength*4;
-    uint32_t BlockNo = Buff.readInt();
-    assert(BlockNo < BlockCount && "Unexpected Block number!");
+    uint32_t BlockNo;
+    if (!Buff.readInt(BlockNo)) return false;
+    if (BlockNo >= BlockCount) {
+      errs() << "Unexpected block number.\n";
+      return false;
+    }
     GCOVBlock *Block = Blocks[BlockNo];
-    Buff.readInt(); // flag
+    if (!Buff.readInt(Dummy)) return false; // flag
     while (Buff.getCursor() != (EndPos - 4)) {
-      StringRef Filename = Buff.readString();
+      StringRef Filename;
+      if (!Buff.readString(Filename)) return false;
       if (Buff.getCursor() == (EndPos - 4)) break;
-      while (uint32_t L = Buff.readInt())
-        Block->addLine(Filename, L);
+      while (true) {
+        uint32_t Line;
+        if (!Buff.readInt(Line)) return false;
+        if (!Line) break;
+        Block->addLine(Filename, Line);
+      }
     }
-    Buff.readInt(); // flag
+    if (!Buff.readInt(Dummy)) return false; // flag
   }
   return true;
 }

Modified: llvm/trunk/test/tools/llvm-cov/llvm-cov.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/llvm-cov.test?rev=194635&r1=194634&r2=194635&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/llvm-cov.test (original)
+++ llvm/trunk/test/tools/llvm-cov/llvm-cov.test Wed Nov 13 18:07:15 2013
@@ -1,4 +1,8 @@
-RUN: cd %p/Inputs && llvm-cov -gcno=test.gcno -gcda=test.gcda \
+RUN: cd %p/Inputs
+
+RUN: llvm-cov -gcno=test.gcno -gcda=test.gcda \
 RUN:   | diff test.cpp.gcov -
 
+RUN: not llvm-cov -gcno=test_read_fail.gcno -gcda=test.gcda
+
 XFAIL: powerpc64, s390x, arm





More information about the llvm-commits mailing list