buffer, parse: Fix overread on {d,q,}words

When read 2, 4, or 8 bytes from a bounded_buffer, we only
checked to see if the offset, not the whole span, was in bounds.

This results in an arbitrary memory read of up to 1, 3, or 7 bytes
when the offset is aligned with the very end of the buffer.
This commit is contained in:
William Woodruff 2018-09-20 10:57:22 -04:00
parent 11685390bb
commit 0f740c43ab
No known key found for this signature in database
GPG Key ID: 70F70A3979DDCED3
3 changed files with 17 additions and 5 deletions

View File

@ -133,7 +133,9 @@ enum pe_err {
PEERR_READ = 6,
PEERR_OPEN = 7,
PEERR_STAT = 8,
PEERR_MAGIC = 9
PEERR_MAGIC = 9,
PEERR_BUFFER = 10,
PEERR_ADDRESS = 11,
};
bool readByte(bounded_buffer *b, std::uint32_t offset, std::uint8_t &out);

View File

@ -86,10 +86,12 @@ struct buffer_detail {
bool readByte(bounded_buffer *b, std::uint32_t offset, std::uint8_t &out) {
if (b == nullptr) {
PE_ERR(PEERR_BUFFER);
return false;
}
if (offset >= b->bufLen) {
PE_ERR(PEERR_ADDRESS);
return false;
}
@ -101,10 +103,12 @@ bool readByte(bounded_buffer *b, std::uint32_t offset, std::uint8_t &out) {
bool readWord(bounded_buffer *b, std::uint32_t offset, std::uint16_t &out) {
if (b == nullptr) {
PE_ERR(PEERR_BUFFER);
return false;
}
if (offset >= b->bufLen) {
if (offset + 1 >= b->bufLen) {
PE_ERR(PEERR_ADDRESS);
return false;
}
@ -120,10 +124,12 @@ bool readWord(bounded_buffer *b, std::uint32_t offset, std::uint16_t &out) {
bool readDword(bounded_buffer *b, std::uint32_t offset, std::uint32_t &out) {
if (b == nullptr) {
PE_ERR(PEERR_BUFFER);
return false;
}
if (offset >= b->bufLen) {
if (offset + 3 >= b->bufLen) {
PE_ERR(PEERR_ADDRESS);
return false;
}
@ -139,10 +145,12 @@ bool readDword(bounded_buffer *b, std::uint32_t offset, std::uint32_t &out) {
bool readQword(bounded_buffer *b, std::uint32_t offset, std::uint64_t &out) {
if (b == nullptr) {
PE_ERR(PEERR_BUFFER);
return false;
}
if (offset >= b->bufLen) {
if (offset + 7 >= b->bufLen) {
PE_ERR(PEERR_ADDRESS);
return false;
}

View File

@ -136,7 +136,9 @@ static const char *pe_err_str[] = {"None",
"Unable to read data",
"Unable to open",
"Unable to stat",
"Bad magic"};
"Bad magic",
"Invalid buffer",
"Invalid address",};
std::uint32_t GetPEErr() {
return err;