lib/nbt: Return correct error code from read functions (fixes #17)

Soda
BodgeMaster 2022-08-27 22:35:10 +02:00
parent cdd17045d1
commit 629c999336
2 changed files with 39 additions and 20 deletions

View File

@ -38,17 +38,19 @@
namespace NBT { namespace NBT {
namespace helper { namespace helper {
ErrorOr<int8_t> readInt8(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) { ErrorOr<int8_t> readInt8(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
if (dataSize<currentPosition+1) return ErrorOr<int8_t>(true, ErrorCodes::OUT_OF_RANGE); if (currentPosition>=dataSize) return ErrorOr<int8_t>(true, ErrorCodes::OUT_OF_RANGE);
return ErrorOr<int8_t>((int8_t) data[currentPosition]); return ErrorOr<int8_t>((int8_t) data[currentPosition]);
} }
ErrorOr<int16_t> readInt16(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) { ErrorOr<int16_t> readInt16(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
if (dataSize<currentPosition+2) return ErrorOr<int16_t>(true, ErrorCodes::OUT_OF_RANGE); if (currentPosition>=dataSize) return ErrorOr<int16_t>(true, ErrorCodes::OUT_OF_RANGE);
if (dataSize<currentPosition+2) return ErrorOr<int16_t>(true, ErrorCodes::OVERRUN);
return ErrorOr<int16_t>((int16_t) ((static_cast<int16_t>(data[currentPosition]) << 8) | static_cast<int16_t>(data[currentPosition+1]))); return ErrorOr<int16_t>((int16_t) ((static_cast<int16_t>(data[currentPosition]) << 8) | static_cast<int16_t>(data[currentPosition+1])));
} }
ErrorOr<int32_t> readInt32(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) { ErrorOr<int32_t> readInt32(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
if (dataSize<currentPosition+4) return ErrorOr<int32_t>(true, ErrorCodes::OUT_OF_RANGE); if (currentPosition>=dataSize) return ErrorOr<int32_t>(true, ErrorCodes::OUT_OF_RANGE);
if (dataSize<currentPosition+4) return ErrorOr<int32_t>(true, ErrorCodes::OVERRUN);
return ErrorOr<int32_t>((int32_t) ( return ErrorOr<int32_t>((int32_t) (
(static_cast<int32_t>(data[currentPosition ]) << 24) | (static_cast<int32_t>(data[currentPosition ]) << 24) |
(static_cast<int32_t>(data[currentPosition+1]) << 16) | (static_cast<int32_t>(data[currentPosition+1]) << 16) |
@ -58,7 +60,8 @@ namespace NBT {
} }
ErrorOr<int64_t> readInt64(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) { ErrorOr<int64_t> readInt64(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
if (dataSize<currentPosition+8) return ErrorOr<int64_t>(true, ErrorCodes::OUT_OF_RANGE); if (currentPosition>=dataSize) return ErrorOr<int64_t>(true, ErrorCodes::OUT_OF_RANGE);
if (dataSize<currentPosition+8) return ErrorOr<int64_t>(true, ErrorCodes::OVERRUN);
return ErrorOr<int64_t>((int64_t) ( return ErrorOr<int64_t>((int64_t) (
(static_cast<int64_t>(data[currentPosition ]) << 56) | (static_cast<int64_t>(data[currentPosition ]) << 56) |
(static_cast<int64_t>(data[currentPosition+1]) << 48) | (static_cast<int64_t>(data[currentPosition+1]) << 48) |
@ -132,9 +135,14 @@ namespace NBT {
} }
ErrorOr<std::vector<int8_t>> readInt8Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) { ErrorOr<std::vector<int8_t>> readInt8Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
// get size prefix
ErrorOr<int32_t> size = readInt32(data, dataSize, currentPosition); ErrorOr<int32_t> size = readInt32(data, dataSize, currentPosition);
if (size.isError) return ErrorOr<std::vector<int8_t>>(true, size.errorCode); if (size.isError) {
// It is okay to pass up the error code here without further
// processing because both OVERRUN and OUT_OF_RANGE errors will
// still apply.
return ErrorOr<std::vector<int8_t>>(true, size.errorCode);
}
// get content // get content
if (currentPosition+4+size.value > dataSize) return ErrorOr<std::vector<int8_t>>(true, ErrorCodes::OVERRUN); if (currentPosition+4+size.value > dataSize) return ErrorOr<std::vector<int8_t>>(true, ErrorCodes::OVERRUN);
@ -146,12 +154,12 @@ namespace NBT {
} }
ErrorOr<tiny_utf8::string> readString(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) { ErrorOr<tiny_utf8::string> readString(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
if(currentPosition > dataSize){
return ErrorOr<tiny_utf8::string>(true, ErrorCodes::OVERRUN);
}
ErrorOr<int16_t> stringSize = readInt16(data, dataSize, currentPosition); ErrorOr<int16_t> stringSize = readInt16(data, dataSize, currentPosition);
if (stringSize.isError) { if (stringSize.isError) {
// It is okay to pass up the error code here without further
// processing because both OVERRUN and OUT_OF_RANGE errors will
// still apply.
return ErrorOr<tiny_utf8::string>(true, stringSize.errorCode); return ErrorOr<tiny_utf8::string>(true, stringSize.errorCode);
} }
if (currentPosition + (uint64_t) stringSize.value + 2 > dataSize) { if (currentPosition + (uint64_t) stringSize.value + 2 > dataSize) {
@ -166,9 +174,14 @@ namespace NBT {
} }
ErrorOr<std::vector<int32_t>> readInt32Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) { ErrorOr<std::vector<int32_t>> readInt32Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
// get size prefix
ErrorOr<int32_t> size = readInt32(data, dataSize, currentPosition); ErrorOr<int32_t> size = readInt32(data, dataSize, currentPosition);
if (size.isError) return ErrorOr<std::vector<int32_t>>(true, size.errorCode); if (size.isError) {
// It is okay to pass up the error code here without further
// processing because both OVERRUN and OUT_OF_RANGE errors will
// still apply.
return ErrorOr<std::vector<int32_t>>(true, size.errorCode);
}
// get content // get content
if (currentPosition+4+(size.value*4) > dataSize) return ErrorOr<std::vector<int32_t>>(true, ErrorCodes::OVERRUN); if (currentPosition+4+(size.value*4) > dataSize) return ErrorOr<std::vector<int32_t>>(true, ErrorCodes::OVERRUN);
@ -182,9 +195,14 @@ namespace NBT {
} }
ErrorOr<std::vector<int64_t>> readInt64Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) { ErrorOr<std::vector<int64_t>> readInt64Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
// get size prefix
ErrorOr<int32_t> size = readInt32(data, dataSize, currentPosition); ErrorOr<int32_t> size = readInt32(data, dataSize, currentPosition);
if (size.isError) return ErrorOr<std::vector<int64_t>>(true, size.errorCode); if (size.isError) {
// It is okay to pass up the error code here without further
// processing because both OVERRUN and OUT_OF_RANGE errors will
// still apply.
return ErrorOr<std::vector<int64_t>>(true, size.errorCode);
}
// get content // get content
if (currentPosition+4+(size.value*8) > dataSize) return ErrorOr<std::vector<int64_t>>(true, ErrorCodes::OVERRUN); if (currentPosition+4+(size.value*8) > dataSize) return ErrorOr<std::vector<int64_t>>(true, ErrorCodes::OVERRUN);
@ -389,7 +407,7 @@ namespace NBT {
// feature as compound tags and lists need to be dealt with // feature as compound tags and lists need to be dealt with
// separately to avoid unnecessarily long and complex code. // separately to avoid unnecessarily long and complex code.
// //
// Regardinng lists specifically: The size of some lists can can // Regarding lists specifically: The size of some lists can can
// be determined easily by looking at the contained data type and // be determined easily by looking at the contained data type and
// size information but cases like string lists or compound lists // size information but cases like string lists or compound lists
// are significantly more difficult to deal with. Parsing their // are significantly more difficult to deal with. Parsing their

View File

@ -86,7 +86,7 @@ int main(){
// partially out of bounds // partially out of bounds
currentPosition = 9; currentPosition = 9;
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true); ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE); ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// fully out of bounds // fully out of bounds
currentPosition = 10; currentPosition = 10;
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true); ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true);
@ -122,7 +122,7 @@ int main(){
// partially out of bounds // partially out of bounds
currentPosition = 7; currentPosition = 7;
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true); ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE); ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// fully out of bounds // fully out of bounds
currentPosition = 10; currentPosition = 10;
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true); ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true);
@ -164,7 +164,7 @@ int main(){
// partially out of bounds // partially out of bounds
currentPosition = 3; currentPosition = 3;
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true); ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE); ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// fully out of bounds // fully out of bounds
currentPosition = 10; currentPosition = 10;
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true); ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true);
@ -226,7 +226,7 @@ int main(){
// read with size partially out of bounds // read with size partially out of bounds
currentPosition = 114; currentPosition = 114;
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true); ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE); ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// read out of bounds // read out of bounds
currentPosition = 200; currentPosition = 200;
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true); ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
@ -282,7 +282,7 @@ int main(){
// read with size partially out of bounds // read with size partially out of bounds
currentPosition = 114; currentPosition = 114;
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true); ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE); ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// read out of bounds // read out of bounds
currentPosition = 200; currentPosition = 200;
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true); ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
@ -347,7 +347,7 @@ int main(){
// read with size partially out of bounds // read with size partially out of bounds
currentPosition = 114; currentPosition = 114;
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true); ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE); ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// read out of bounds // read out of bounds
currentPosition = 200; currentPosition = 200;
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true); ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
@ -537,6 +537,7 @@ int main(){
javaStdString[0] = '1'; javaStdString[0] = '1';
ASSERT(NBT::helper::readString(reinterpret_cast<uint8_t*>(javaStdString.data()), javaStdString.size(), 0).errorCode == ErrorCodes::OVERRUN); ASSERT(NBT::helper::readString(reinterpret_cast<uint8_t*>(javaStdString.data()), javaStdString.size(), 0).errorCode == ErrorCodes::OVERRUN);
ASSERT(NBT::helper::readString(reinterpret_cast<uint8_t*>(javaStdString.data()), javaStdString.size(), javaStdString.size()).errorCode == ErrorCodes::OUT_OF_RANGE);
//reading data from the blob at the top of this file //reading data from the blob at the top of this file
currentPositionInBlob = 0x1cf; currentPositionInBlob = 0x1cf;