mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-26 06:48:51 -04:00

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. llvm-svn: 271570
87 lines
2.5 KiB
C++
87 lines
2.5 KiB
C++
//===- StreamReader.cpp - Reads bytes and objects from a stream -----------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/DebugInfo/CodeView/StreamReader.h"
|
|
|
|
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
|
|
#include "llvm/DebugInfo/CodeView/StreamRef.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::codeview;
|
|
|
|
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))
|
|
return EC;
|
|
Offset += Size;
|
|
return Error::success();
|
|
}
|
|
|
|
Error StreamReader::readInteger(uint16_t &Dest) {
|
|
const support::ulittle16_t *P;
|
|
if (auto EC = readObject(P))
|
|
return EC;
|
|
Dest = *P;
|
|
return Error::success();
|
|
}
|
|
|
|
Error StreamReader::readInteger(uint32_t &Dest) {
|
|
const support::ulittle32_t *P;
|
|
if (auto EC = readObject(P))
|
|
return EC;
|
|
Dest = *P;
|
|
return Error::success();
|
|
}
|
|
|
|
Error StreamReader::readZeroString(StringRef &Dest) {
|
|
uint32_t Length = 0;
|
|
// First compute the length of the string by reading 1 byte at a time.
|
|
uint32_t OriginalOffset = getOffset();
|
|
const char *C;
|
|
do {
|
|
if (auto EC = readObject(C))
|
|
return EC;
|
|
if (*C != '\0')
|
|
++Length;
|
|
} while (*C != '\0');
|
|
// Now go back and request a reference for that many bytes.
|
|
uint32_t NewOffset = getOffset();
|
|
setOffset(OriginalOffset);
|
|
|
|
ArrayRef<uint8_t> Data;
|
|
if (auto EC = readBytes(Data, Length))
|
|
return EC;
|
|
Dest = StringRef(reinterpret_cast<const char *>(Data.begin()), Data.size());
|
|
|
|
// Now set the offset back to where it was after we calculated the length.
|
|
setOffset(NewOffset);
|
|
return Error::success();
|
|
}
|
|
|
|
Error StreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
|
|
ArrayRef<uint8_t> Bytes;
|
|
if (auto EC = readBytes(Bytes, Length))
|
|
return EC;
|
|
Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
|
|
return Error::success();
|
|
}
|
|
|
|
Error StreamReader::readStreamRef(StreamRef &Ref) {
|
|
return readStreamRef(Ref, bytesRemaining());
|
|
}
|
|
|
|
Error StreamReader::readStreamRef(StreamRef &Ref, uint32_t Length) {
|
|
if (bytesRemaining() < Length)
|
|
return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
|
|
Ref = Stream.slice(Offset, Length);
|
|
Offset += Length;
|
|
return Error::success();
|
|
}
|