2016-04-30 01:22:58 +08:00
|
|
|
//===- 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.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-07-30 04:56:36 +08:00
|
|
|
#include "llvm/DebugInfo/MSF/StreamReader.h"
|
2016-05-26 04:37:03 +08:00
|
|
|
|
2016-07-30 04:56:36 +08:00
|
|
|
#include "llvm/DebugInfo/MSF/MSFError.h"
|
|
|
|
#include "llvm/DebugInfo/MSF/StreamRef.h"
|
2016-04-30 01:22:58 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
2016-07-23 03:56:05 +08:00
|
|
|
using namespace llvm::msf;
|
2016-04-30 01:22:58 +08:00
|
|
|
|
2016-07-29 03:12:28 +08:00
|
|
|
StreamReader::StreamReader(ReadableStreamRef S) : Stream(S), Offset(0) {}
|
2016-04-30 01:22:58 +08:00
|
|
|
|
2016-06-10 13:09:12 +08:00
|
|
|
Error StreamReader::readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer) {
|
|
|
|
if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))
|
|
|
|
return EC;
|
|
|
|
Offset += Buffer.size();
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2016-05-28 13:21:57 +08:00
|
|
|
Error StreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
|
2016-05-27 09:54:44 +08:00
|
|
|
if (auto EC = Stream.readBytes(Offset, Size, Buffer))
|
|
|
|
return EC;
|
|
|
|
Offset += Size;
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2016-10-21 02:31:19 +08:00
|
|
|
Error StreamReader::readInteger(uint8_t &Dest) {
|
|
|
|
const uint8_t *P;
|
|
|
|
if (auto EC = readObject(P))
|
|
|
|
return EC;
|
|
|
|
Dest = *P;
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2016-05-27 09:54:44 +08:00
|
|
|
Error StreamReader::readInteger(uint16_t &Dest) {
|
|
|
|
const support::ulittle16_t *P;
|
|
|
|
if (auto EC = readObject(P))
|
|
|
|
return EC;
|
|
|
|
Dest = *P;
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2016-05-07 04:51:57 +08:00
|
|
|
Error StreamReader::readInteger(uint32_t &Dest) {
|
2016-05-27 09:54:44 +08:00
|
|
|
const support::ulittle32_t *P;
|
|
|
|
if (auto EC = readObject(P))
|
2016-04-30 01:22:58 +08:00
|
|
|
return EC;
|
2016-05-27 09:54:44 +08:00
|
|
|
Dest = *P;
|
2016-05-07 04:51:57 +08:00
|
|
|
return Error::success();
|
2016-04-30 01:22:58 +08:00
|
|
|
}
|
|
|
|
|
2016-10-21 02:31:19 +08:00
|
|
|
Error StreamReader::readInteger(uint64_t &Dest) {
|
|
|
|
const support::ulittle64_t *P;
|
|
|
|
if (auto EC = readObject(P))
|
|
|
|
return EC;
|
|
|
|
Dest = *P;
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
Error StreamReader::readInteger(int8_t &Dest) {
|
|
|
|
const int8_t *P;
|
|
|
|
if (auto EC = readObject(P))
|
|
|
|
return EC;
|
|
|
|
Dest = *P;
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
Error StreamReader::readInteger(int16_t &Dest) {
|
|
|
|
const support::little16_t *P;
|
|
|
|
if (auto EC = readObject(P))
|
|
|
|
return EC;
|
|
|
|
Dest = *P;
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
Error StreamReader::readInteger(int32_t &Dest) {
|
|
|
|
const support::little32_t *P;
|
|
|
|
if (auto EC = readObject(P))
|
|
|
|
return EC;
|
|
|
|
Dest = *P;
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
Error StreamReader::readInteger(int64_t &Dest) {
|
|
|
|
const support::little64_t *P;
|
|
|
|
if (auto EC = readObject(P))
|
|
|
|
return EC;
|
|
|
|
Dest = *P;
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2016-05-27 09:54:44 +08:00
|
|
|
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;
|
2016-04-30 01:22:58 +08:00
|
|
|
do {
|
2016-05-27 09:54:44 +08:00
|
|
|
if (auto EC = readObject(C))
|
2016-05-07 04:51:57 +08:00
|
|
|
return EC;
|
2016-05-27 09:54:44 +08:00
|
|
|
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;
|
2016-05-28 13:21:57 +08:00
|
|
|
if (auto EC = readBytes(Data, Length))
|
2016-05-27 09:54:44 +08:00
|
|
|
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);
|
2016-05-07 04:51:57 +08:00
|
|
|
return Error::success();
|
2016-04-30 01:22:58 +08:00
|
|
|
}
|
2016-05-03 08:28:21 +08:00
|
|
|
|
2016-05-27 09:54:44 +08:00
|
|
|
Error StreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
|
|
|
|
ArrayRef<uint8_t> Bytes;
|
2016-05-28 13:21:57 +08:00
|
|
|
if (auto EC = readBytes(Bytes, Length))
|
2016-05-03 08:28:21 +08:00
|
|
|
return EC;
|
2016-05-27 09:54:44 +08:00
|
|
|
Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2016-07-29 03:12:28 +08:00
|
|
|
Error StreamReader::readStreamRef(ReadableStreamRef &Ref) {
|
2016-05-27 09:54:44 +08:00
|
|
|
return readStreamRef(Ref, bytesRemaining());
|
|
|
|
}
|
|
|
|
|
2016-07-29 03:12:28 +08:00
|
|
|
Error StreamReader::readStreamRef(ReadableStreamRef &Ref, uint32_t Length) {
|
2016-05-27 09:54:44 +08:00
|
|
|
if (bytesRemaining() < Length)
|
2016-07-30 04:56:36 +08:00
|
|
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
[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.
llvm-svn: 271570
2016-06-03 03:51:48 +08:00
|
|
|
Ref = Stream.slice(Offset, Length);
|
2016-05-03 08:28:21 +08:00
|
|
|
Offset += Length;
|
2016-05-07 04:51:57 +08:00
|
|
|
return Error::success();
|
2016-05-03 08:28:21 +08:00
|
|
|
}
|
2016-10-21 02:31:19 +08:00
|
|
|
|
|
|
|
Error StreamReader::skip(uint32_t Amount) {
|
|
|
|
if (Amount > bytesRemaining())
|
|
|
|
return make_error<MSFError>(msf_error_code::insufficient_buffer);
|
|
|
|
Offset += Amount;
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t StreamReader::peek() const {
|
|
|
|
ArrayRef<uint8_t> Buffer;
|
|
|
|
auto EC = Stream.readBytes(Offset, 1, Buffer);
|
|
|
|
assert(!EC && "Cannot peek an empty buffer!");
|
|
|
|
llvm::consumeError(std::move(EC));
|
|
|
|
return Buffer[0];
|
|
|
|
}
|