llvm.org GIT mirror llvm / 7f1badc
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271570 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 4 years ago
6 changed file(s) with 13 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
2626 };
2727
2828 template struct VarStreamArrayExtractor> {
29 Error operator()(const StreamInterface &Stream, uint32_t &Len,
29 Error operator()(StreamRef Stream, uint32_t &Len,
3030 CVRecord &Item) const {
3131 const RecordPrefix *Prefix = nullptr;
3232 StreamReader Reader(Stream);
2828 // with the following method implemented. On output return `Len` should
2929 // contain the number of bytes to consume from the stream, and `Item` should
3030 // be initialized with the proper value.
31 Error operator()(const StreamInterface &Stream, uint32_t &Len,
32 T &Item) const = delete;
31 Error operator()(StreamRef Stream, uint32_t &Len, T &Item) const = delete;
3332 };
3433
3534 /// VarStreamArray represents an array of variable length records backed by a
2525
2626 class StreamReader {
2727 public:
28 StreamReader(const StreamInterface &S);
28 StreamReader(StreamRef Stream);
2929
3030 Error readBytes(ArrayRef &Buffer, uint32_t Size);
3131 Error readInteger(uint16_t &Dest);
7171 return make_error(cv_error_code::corrupt_record);
7272 if (Offset + Length > Stream.getLength())
7373 return make_error(cv_error_code::insufficient_buffer);
74 StreamRef View(Stream, Offset, Length);
74 StreamRef View = Stream.slice(Offset, Length);
7575 Array = FixedStreamArray(View);
7676 Offset += Length;
7777 return Error::success();
8383 uint32_t bytesRemaining() const { return getLength() - getOffset(); }
8484
8585 private:
86 const StreamInterface &Stream;
86 StreamRef Stream;
8787 uint32_t Offset;
8888 };
8989 } // namespace codeview
1515 namespace llvm {
1616 namespace codeview {
1717
18 class StreamRef : public StreamInterface {
18 class StreamRef : private StreamInterface {
1919 public:
2020 StreamRef() : Stream(nullptr), ViewOffset(0), Length(0) {}
2121 StreamRef(const StreamInterface &Stream)
4949 return StreamRef(*Stream, ViewOffset, N);
5050 }
5151
52 StreamRef slice(uint32_t Offset, uint32_t Len) const {
53 return drop_front(Offset).keep_front(Len);
54 }
55
5256 bool operator==(const StreamRef &Other) const {
5357 if (Stream != Other.Stream)
5458 return false;
6363
6464 namespace codeview {
6565 template <> struct VarStreamArrayExtractor {
66 Error operator()(const StreamInterface &Stream, uint32_t &Length,
66 Error operator()(StreamRef Stream, uint32_t &Length,
6767 pdb::ModInfo &Info) const {
6868 if (auto EC = pdb::ModInfo::initialize(Stream, Info))
6969 return EC;
1414 using namespace llvm;
1515 using namespace llvm::codeview;
1616
17 StreamReader::StreamReader(const StreamInterface &S) : Stream(S), Offset(0) {}
17 StreamReader::StreamReader(StreamRef Stream) : Stream(Stream), Offset(0) {}
1818
1919 Error StreamReader::readBytes(ArrayRef &Buffer, uint32_t Size) {
2020 if (auto EC = Stream.readBytes(Offset, Size, Buffer))
7979 Error StreamReader::readStreamRef(StreamRef &Ref, uint32_t Length) {
8080 if (bytesRemaining() < Length)
8181 return make_error(cv_error_code::insufficient_buffer);
82 Ref = StreamRef(Stream, Offset, Length);
82 Ref = Stream.slice(Offset, Length);
8383 Offset += Length;
8484 return Error::success();
8585 }