[llvm] r271570 - [codeview] Fix a nasty use after free.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 2 12:51:49 PDT 2016


Author: zturner
Date: Thu Jun  2 14:51:48 2016
New Revision: 271570

URL: http://llvm.org/viewvc/llvm-project?rev=271570&view=rev
Log:
[codeview] Fix a nasty use after free.

StreamRef was designed to be a thin wrapper over an abstract
stream interface that could itself be treated the same as any
other stream interface.  For this reason, it inherited publicly
from StreamInterface, and stored a StreamInterface* internally.

But StreamRef was also designed to be lightweight and easily
copyable, similar to ArrayRef.  This led to two misuses of
the classes.

1) When creating a StreamRef A from another StreamRef B, it was
   possible to end up with A storing a pointer to B, even when
   B was a temporary object, leading to use after free.
2) The above situation could be repeated ad nauseum, so that
   A stores a pointer to B, which itself stores a pointer to
   another StreamRef C, and so on and so on, creating an
   unnecessarily level of nesting depth.

This patch removes the public inheritance relationship between
StreamRef and StreamInterface, making it so that we can never
accidentally convert a StreamRef to a StreamInterface.

Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/StreamReader.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/StreamRef.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/ModInfo.h
    llvm/trunk/lib/DebugInfo/CodeView/StreamReader.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h?rev=271570&r1=271569&r2=271570&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h Thu Jun  2 14:51:48 2016
@@ -27,7 +27,7 @@ template <typename Kind> struct CVRecord
 };
 
 template <typename Kind> struct VarStreamArrayExtractor<CVRecord<Kind>> {
-  Error operator()(const StreamInterface &Stream, uint32_t &Len,
+  Error operator()(StreamRef Stream, uint32_t &Len,
                    CVRecord<Kind> &Item) const {
     const RecordPrefix *Prefix = nullptr;
     StreamReader Reader(Stream);

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h?rev=271570&r1=271569&r2=271570&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/StreamArray.h Thu Jun  2 14:51:48 2016
@@ -29,8 +29,7 @@ template <typename T> struct VarStreamAr
   // with the following method implemented.  On output return `Len` should
   // contain the number of bytes to consume from the stream, and `Item` should
   // be initialized with the proper value.
-  Error operator()(const StreamInterface &Stream, uint32_t &Len,
-                   T &Item) const = delete;
+  Error operator()(StreamRef Stream, uint32_t &Len, T &Item) const = delete;
 };
 
 /// VarStreamArray represents an array of variable length records backed by a

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/StreamReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/StreamReader.h?rev=271570&r1=271569&r2=271570&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/StreamReader.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/StreamReader.h Thu Jun  2 14:51:48 2016
@@ -26,7 +26,7 @@ class StreamRef;
 
 class StreamReader {
 public:
-  StreamReader(const StreamInterface &S);
+  StreamReader(StreamRef Stream);
 
   Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
   Error readInteger(uint16_t &Dest);
@@ -72,7 +72,7 @@ public:
       return make_error<CodeViewError>(cv_error_code::corrupt_record);
     if (Offset + Length > Stream.getLength())
       return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
-    StreamRef View(Stream, Offset, Length);
+    StreamRef View = Stream.slice(Offset, Length);
     Array = FixedStreamArray<T>(View);
     Offset += Length;
     return Error::success();
@@ -84,7 +84,7 @@ public:
   uint32_t bytesRemaining() const { return getLength() - getOffset(); }
 
 private:
-  const StreamInterface &Stream;
+  StreamRef Stream;
   uint32_t Offset;
 };
 } // namespace codeview

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/StreamRef.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/StreamRef.h?rev=271570&r1=271569&r2=271570&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/StreamRef.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/StreamRef.h Thu Jun  2 14:51:48 2016
@@ -16,7 +16,7 @@
 namespace llvm {
 namespace codeview {
 
-class StreamRef : public StreamInterface {
+class StreamRef : private StreamInterface {
 public:
   StreamRef() : Stream(nullptr), ViewOffset(0), Length(0) {}
   StreamRef(const StreamInterface &Stream)
@@ -50,6 +50,10 @@ public:
     return StreamRef(*Stream, ViewOffset, N);
   }
 
+  StreamRef slice(uint32_t Offset, uint32_t Len) const {
+    return drop_front(Offset).keep_front(Len);
+  }
+
   bool operator==(const StreamRef &Other) const {
     if (Stream != Other.Stream)
       return false;

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/ModInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/ModInfo.h?rev=271570&r1=271569&r2=271570&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/ModInfo.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/ModInfo.h Thu Jun  2 14:51:48 2016
@@ -64,7 +64,7 @@ struct ModuleInfoEx {
 
 namespace codeview {
 template <> struct VarStreamArrayExtractor<pdb::ModInfo> {
-  Error operator()(const StreamInterface &Stream, uint32_t &Length,
+  Error operator()(StreamRef Stream, uint32_t &Length,
                    pdb::ModInfo &Info) const {
     if (auto EC = pdb::ModInfo::initialize(Stream, Info))
       return EC;

Modified: llvm/trunk/lib/DebugInfo/CodeView/StreamReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/StreamReader.cpp?rev=271570&r1=271569&r2=271570&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/StreamReader.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/StreamReader.cpp Thu Jun  2 14:51:48 2016
@@ -15,7 +15,7 @@
 using namespace llvm;
 using namespace llvm::codeview;
 
-StreamReader::StreamReader(const StreamInterface &S) : Stream(S), Offset(0) {}
+StreamReader::StreamReader(StreamRef Stream) : Stream(Stream), Offset(0) {}
 
 Error StreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
   if (auto EC = Stream.readBytes(Offset, Size, Buffer))
@@ -80,7 +80,7 @@ Error StreamReader::readStreamRef(Stream
 Error StreamReader::readStreamRef(StreamRef &Ref, uint32_t Length) {
   if (bytesRemaining() < Length)
     return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
-  Ref = StreamRef(Stream, Offset, Length);
+  Ref = Stream.slice(Offset, Length);
   Offset += Length;
   return Error::success();
 }




More information about the llvm-commits mailing list