vsk created this revision.
vsk added reviewers: rsmith, benlangmuir.
vsk added a subscriber: cfe-commits.

If we try to read a corrupt pch, we can easily assert-fail or trigger invalid
memory accesses when manipulating ASTReader::RecordData objects. This problem
is easy enough to diagnose when assertions are enabled, but can cause trouble
otherwise.

Emit an error diagnostic when we detect a bad RecordData access.

http://reviews.llvm.org/D17299

Files:
  include/clang/Serialization/ASTReader.h
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTReaderDecl.cpp
  lib/Serialization/ASTReaderStmt.cpp

Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -2575,7 +2575,7 @@
   unsigned PrevNumStmts = StmtStack.size();
 #endif
 
-  RecordData Record;
+  RecordData Record(this);
   unsigned Idx;
   ASTStmtReader Reader(*this, F, Cursor, Record, Idx);
   Stmt::EmptyShell Empty;
Index: lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- lib/Serialization/ASTReaderDecl.cpp
+++ lib/Serialization/ASTReaderDecl.cpp
@@ -3129,7 +3129,7 @@
   Deserializing ADecl(this);
 
   DeclsCursor.JumpToBit(Loc.Offset);
-  RecordData Record;
+  RecordData Record(this);
   unsigned Code = DeclsCursor.ReadCode();
   unsigned Idx = 0;
   ASTDeclReader Reader(*this, *Loc.F, ID, RawLocation, Record,Idx);
@@ -3408,7 +3408,7 @@
       llvm::BitstreamCursor &Cursor = F->DeclsCursor;
       SavedStreamPosition SavedPosition(Cursor);
       Cursor.JumpToBit(Offset);
-      RecordData Record;
+      RecordData Record(this);
       unsigned Code = Cursor.ReadCode();
       unsigned RecCode = Cursor.readRecord(Code, Record);
       (void)RecCode;
@@ -3452,7 +3452,7 @@
   SavedStreamPosition SavedPosition(Cursor);
   Cursor.JumpToBit(LocalOffset);
 
-  RecordData Record;
+  RecordData Record(this);
   unsigned Code = Cursor.ReadCode();
   unsigned RecCode = Cursor.readRecord(Code, Record);
   (void)RecCode;
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -988,7 +988,7 @@
   SavedStreamPosition SavedPosition(Cursor);
   Cursor.JumpToBit(Offset);
 
-  RecordData Record;
+  RecordData Record(this);
   StringRef Blob;
   unsigned Code = Cursor.ReadCode();
   unsigned RecCode = Cursor.readRecord(Code, Record, &Blob);
@@ -1024,7 +1024,7 @@
   SavedStreamPosition SavedPosition(Cursor);
   Cursor.JumpToBit(Offset);
 
-  RecordData Record;
+  RecordData Record(this);
   StringRef Blob;
   unsigned Code = Cursor.ReadCode();
   unsigned RecCode = Cursor.readRecord(Code, Record, &Blob);
@@ -1130,7 +1130,7 @@
     return true;
   }
 
-  RecordData Record;
+  RecordData Record(this);
   while (true) {
     llvm::BitstreamEntry E = SLocEntryCursor.advanceSkippingSubblocks();
     
@@ -1209,7 +1209,7 @@
   auto ReadBuffer = [this](
       BitstreamCursor &SLocEntryCursor,
       StringRef Name) -> std::unique_ptr<llvm::MemoryBuffer> {
-    RecordData Record;
+    RecordData Record(this);
     StringRef Blob;
     unsigned Code = SLocEntryCursor.ReadCode();
     unsigned RecCode = SLocEntryCursor.readRecord(Code, Record, &Blob);
@@ -1242,7 +1242,7 @@
     return true;
   }
   
-  RecordData Record;
+  RecordData Record(this);
   StringRef Blob;
   switch (SLocEntryCursor.readRecord(Entry.ID, Record, &Blob)) {
   default:
@@ -1410,7 +1410,7 @@
   SavedStreamPosition SavedPosition(Stream);
 
   Stream.JumpToBit(Offset);
-  RecordData Record;
+  RecordData Record(this);
   SmallVector<IdentifierInfo*, 16> MacroArgs;
   MacroInfo *Macro = nullptr;
 
@@ -1656,7 +1656,7 @@
     BitstreamCursor Cursor = MacroCursor;
     Cursor.JumpToBit(I->MacroStartOffset);
 
-    RecordData Record;
+    RecordData Record(this);
     while (true) {
       llvm::BitstreamEntry E = Cursor.advanceSkippingSubblocks();
       
@@ -1798,7 +1798,7 @@
   // We expect to see a sequence of PP_MODULE_MACRO records listing exported
   // macros, followed by a PP_MACRO_DIRECTIVE_HISTORY record with the complete
   // macro histroy.
-  RecordData Record;
+  RecordData Record(this);
   while (true) {
     llvm::BitstreamEntry Entry =
         Cursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd);
@@ -1898,7 +1898,7 @@
   Cursor.JumpToBit(F.InputFileOffsets[ID-1]);
 
   unsigned Code = Cursor.ReadCode();
-  RecordData Record;
+  RecordData Record(this);
   StringRef Blob;
 
   unsigned Result = Cursor.readRecord(Code, Record, &Blob);
@@ -2090,7 +2090,7 @@
     return Failure;
 
   // Read all of the records in the options block.
-  RecordData Record;
+  RecordData Record(nullptr);
   ASTReadResult Result = Success;
   while (1) {
     llvm::BitstreamEntry Entry = Stream.advance();
@@ -2176,7 +2176,7 @@
   }
 
   // Read all of the records and blocks in the control block.
-  RecordData Record;
+  RecordData Record(this);
   unsigned NumInputs = 0;
   unsigned NumUserInputs = 0;
   while (1) {
@@ -2453,7 +2453,7 @@
   }
 
   // Read all of the records and blocks for the AST file.
-  RecordData Record;
+  RecordData Record(this);
   while (1) {
     llvm::BitstreamEntry Entry = Stream.advance();
     
@@ -3888,7 +3888,7 @@
 ASTReader::ASTReadResult ASTReader::ReadExtensionBlock(ModuleFile &F) {
   BitstreamCursor &Stream = F.Stream;
 
-  RecordData Record;
+  RecordData Record(this);
   while (true) {
     llvm::BitstreamEntry Entry = Stream.advance();
     switch (Entry.Kind) {
@@ -4087,7 +4087,7 @@
     return 0;
 
   // Scan for SIGNATURE inside the control block.
-  ASTReader::RecordData Record;
+  ASTReader::RecordData Record(nullptr);
   while (1) {
     llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
     if (Entry.Kind == llvm::BitstreamEntry::EndBlock ||
@@ -4133,7 +4133,7 @@
   }
 
   // Scan for ORIGINAL_FILE inside the control block.
-  RecordData Record;
+  RecordData Record(nullptr);
   while (1) {
     llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
     if (Entry.Kind == llvm::BitstreamEntry::EndBlock)
@@ -4230,7 +4230,7 @@
   bool NeedsImports = Listener.needsImportVisitation();
   BitstreamCursor InputFilesCursor;
 
-  RecordData Record;
+  RecordData Record(nullptr);
   std::string ModuleDir;
   bool DoneWithControlBlock = false;
   while (!DoneWithControlBlock) {
@@ -4323,7 +4323,7 @@
         Cursor.JumpToBit(InputFileOffs[I]);
 
         unsigned Code = Cursor.ReadCode();
-        RecordData Record;
+        RecordData Record(nullptr);
         StringRef Blob;
         bool shouldContinue = false;
         switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) {
@@ -4430,7 +4430,7 @@
   ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
   bool First = true;
   Module *CurrentModule = nullptr;
-  RecordData Record;
+  RecordData Record(this);
   while (true) {
     llvm::BitstreamEntry Entry = F.Stream.advanceSkippingSubblocks();
     
@@ -4895,7 +4895,7 @@
                     ReadSourceLocation(M, PPOffs.End));
   PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
   StringRef Blob;
-  RecordData Record;
+  RecordData Record(this);
   PreprocessorDetailRecordTypes RecType =
     (PreprocessorDetailRecordTypes)M.PreprocessorDetailCursor.readRecord(
                                           Entry.ID, Record, &Blob);
@@ -5207,7 +5207,7 @@
 
   unsigned Idx = 0;
   DeclsCursor.JumpToBit(Loc.Offset);
-  RecordData Record;
+  RecordData Record(this);
   unsigned Code = DeclsCursor.ReadCode();
   switch ((TypeCode)DeclsCursor.readRecord(Code, Record)) {
   case TYPE_EXT_QUAL: {
@@ -6318,7 +6318,7 @@
   Cursor.JumpToBit(Loc.Offset);
   ReadingKindTracker ReadingKind(Read_Decl, *this);
 
-  RecordData Record;
+  RecordData Record(this);
   unsigned Code = Cursor.ReadCode();
   unsigned RecCode = Cursor.readRecord(Code, Record);
   if (RecCode != DECL_CXX_CTOR_INITIALIZERS) {
@@ -6348,7 +6348,7 @@
   SavedStreamPosition SavedPosition(Cursor);
   Cursor.JumpToBit(Loc.Offset);
   ReadingKindTracker ReadingKind(Read_Decl, *this);
-  RecordData Record;
+  RecordData Record(this);
   unsigned Code = Cursor.ReadCode();
   unsigned RecCode = Cursor.readRecord(Code, Record);
   if (RecCode != DECL_CXX_BASE_SPECIFIERS) {
@@ -8234,7 +8234,7 @@
     serialization::ModuleFile &F = *I->second;
     SavedStreamPosition SavedPosition(Cursor);
 
-    RecordData Record;
+    RecordData Record(this);
     while (true) {
       llvm::BitstreamEntry Entry =
         Cursor.advanceSkippingSubblocks(BitstreamCursor::AF_DontPopBlockAtEnd);
Index: include/clang/Serialization/ASTReader.h
===================================================================
--- include/clang/Serialization/ASTReader.h
+++ include/clang/Serialization/ASTReader.h
@@ -317,7 +317,31 @@
     public ExternalSLocEntrySource
 {
 public:
-  typedef SmallVector<uint64_t, 64> RecordData;
+  class RecordData : public SmallVector<uint64_t, 64> {
+  public:
+    RecordData(ASTReader *AR) : AR(AR) {}
+
+    reference operator[](size_type idx) {
+      if (AR && idx >= size()) {
+        AR->Error("Malformed record data, invalid access");
+        return Poison;
+      }
+      return SmallVector<uint64_t, 64>::operator[](idx);
+    }
+
+    const_reference operator[](size_type idx) const {
+      if (AR && idx >= size()) {
+        AR->Error("Malformed record data, invalid access");
+        return Poison;
+      }
+      return SmallVector<uint64_t, 64>::operator[](idx);
+    }
+
+  private:
+    ASTReader *AR;
+    uint64_t Poison;
+  };
+
   typedef SmallVectorImpl<uint64_t> RecordDataImpl;
 
   /// \brief The result of reading the control block of an AST file, which
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to