lib/nbt: Fix memory leak in case of parsing error
parent
6e57a86338
commit
25d7806f6d
|
@ -1176,6 +1176,7 @@ namespace NBT {
|
|||
// FIXME: memory leak when returning errors
|
||||
ErrorOr<std::vector<Tag::Generic*>> deserializeRawListContents(uint8_t data[], uint64_t dataSize, uint64_t initialPosition, uint64_t* processedDataSize) {
|
||||
std::vector<Tag::Generic*> contents;
|
||||
ErrorOr<std::vector<Tag::Generic*>> returnValue;
|
||||
// get contained data length by reading it manually because
|
||||
// the function that does it normally can't deal with
|
||||
// headerless tags
|
||||
|
@ -1183,6 +1184,8 @@ namespace NBT {
|
|||
// add one byte to position to skip the type byte
|
||||
ErrorOr<int32_t> elementCount = Helper::readInt32(data, dataSize, initialPosition+1);
|
||||
if (elementCount.isError) {
|
||||
// this is before the creation of any pointers so we can just return
|
||||
// without using the returnError label at the end of this function
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, elementCount.errorCode);
|
||||
}
|
||||
|
||||
|
@ -1202,14 +1205,10 @@ namespace NBT {
|
|||
for (int32_t i=0; i<elementCount.value; i++) {
|
||||
ErrorOr<int8_t> nextInt = Helper::readInt8(data, dataSize, initialPosition+*processedDataSize);
|
||||
if (nextInt.isError) {
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, nextInt.errorCode);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, nextInt.errorCode);
|
||||
goto returnError;
|
||||
}
|
||||
contents.push_back(new Tag::Int8("", nextInt.value));
|
||||
// The below code would produce a warning on GCC and Clang
|
||||
// about the computed value not being used. While this does
|
||||
// apply inside this function, it is ultimately not true
|
||||
// as the pointer is used both inside and outside of the
|
||||
// function.
|
||||
*processedDataSize += 1;
|
||||
}
|
||||
break;
|
||||
|
@ -1218,7 +1217,8 @@ namespace NBT {
|
|||
for (int32_t i=0; i<elementCount.value; i++) {
|
||||
ErrorOr<int16_t> nextInt = Helper::readInt16(data, dataSize, initialPosition+*processedDataSize);
|
||||
if (nextInt.isError) {
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, nextInt.errorCode);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, nextInt.errorCode);
|
||||
goto returnError;
|
||||
}
|
||||
contents.push_back(new Tag::Int16("", nextInt.value));
|
||||
*processedDataSize += 2;
|
||||
|
@ -1229,7 +1229,8 @@ namespace NBT {
|
|||
for (int32_t i=0; i<elementCount.value; i++) {
|
||||
ErrorOr<int32_t> nextInt = Helper::readInt32(data, dataSize, initialPosition+*processedDataSize);
|
||||
if (nextInt.isError) {
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, nextInt.errorCode);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, nextInt.errorCode);
|
||||
goto returnError;
|
||||
}
|
||||
contents.push_back(new Tag::Int32("", nextInt.value));
|
||||
*processedDataSize += 4;
|
||||
|
@ -1240,7 +1241,8 @@ namespace NBT {
|
|||
for (int32_t i=0; i<elementCount.value; i++) {
|
||||
ErrorOr<float> nextFloat = Helper::readFloat(data, dataSize, initialPosition+*processedDataSize);
|
||||
if (nextFloat.isError) {
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, nextFloat.errorCode);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, nextFloat.errorCode);
|
||||
goto returnError;
|
||||
}
|
||||
contents.push_back(new Tag::Float("", nextFloat.value));
|
||||
*processedDataSize += 4;
|
||||
|
@ -1251,7 +1253,8 @@ namespace NBT {
|
|||
for (int32_t i=0; i<elementCount.value; i++) {
|
||||
ErrorOr<int64_t> nextInt = Helper::readInt64(data, dataSize, initialPosition+*processedDataSize);
|
||||
if (nextInt.isError) {
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, nextInt.errorCode);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, nextInt.errorCode);
|
||||
goto returnError;
|
||||
}
|
||||
contents.push_back(new Tag::Int64("", nextInt.value));
|
||||
*processedDataSize += 8;
|
||||
|
@ -1262,7 +1265,8 @@ namespace NBT {
|
|||
for (int32_t i=0; i<elementCount.value; i++) {
|
||||
ErrorOr<double> nextDouble = Helper::readDouble(data, dataSize, initialPosition+*processedDataSize);
|
||||
if (nextDouble.isError) {
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, nextDouble.errorCode);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, nextDouble.errorCode);
|
||||
goto returnError;
|
||||
}
|
||||
contents.push_back(new Tag::Double("", nextDouble.value));
|
||||
*processedDataSize += 8;
|
||||
|
@ -1273,7 +1277,8 @@ namespace NBT {
|
|||
for (int32_t i=0; i<elementCount.value; i++) {
|
||||
ErrorOr<std::vector<int8_t>> nextArray = Helper::readInt8Array(data, dataSize, initialPosition+*processedDataSize);
|
||||
if (nextArray.isError) {
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, nextArray.errorCode);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, nextArray.errorCode);
|
||||
goto returnError;
|
||||
}
|
||||
contents.push_back(new Tag::Int8Array("", nextArray.value));
|
||||
*processedDataSize += (uint64_t) nextArray.value.size();
|
||||
|
@ -1284,7 +1289,8 @@ namespace NBT {
|
|||
for (int32_t i=0; i<elementCount.value; i++) {
|
||||
ErrorOr<tiny_utf8::string> nextString = Helper::readString(data, dataSize, initialPosition+*processedDataSize);
|
||||
if (nextString.isError) {
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, nextString.errorCode);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, nextString.errorCode);
|
||||
goto returnError;
|
||||
}
|
||||
contents.push_back(new Tag::String("", nextString.value));
|
||||
// this cannot be an error because it just got read
|
||||
|
@ -1301,7 +1307,8 @@ namespace NBT {
|
|||
ErrorOr<std::vector<Tag::Generic*>> nextListContents = deserializeRawListContents(data, dataSize, initialPosition+*processedDataSize, containedDataSize);
|
||||
if (nextListContents.isError) {
|
||||
delete containedDataSize;
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, nextListContents.errorCode);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, nextListContents.errorCode);
|
||||
goto returnError;
|
||||
}
|
||||
contents.push_back(new Tag::List("", nextListContents.value));
|
||||
*processedDataSize += *containedDataSize;
|
||||
|
@ -1316,7 +1323,8 @@ namespace NBT {
|
|||
ErrorOr<std::vector<Tag::Generic*>> nextCompoundData = deserialize(data, dataSize, initialPosition+*processedDataSize, containedDataSize);
|
||||
if (nextCompoundData.isError) {
|
||||
delete containedDataSize;
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, nextCompoundData.errorCode);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, nextCompoundData.errorCode);
|
||||
goto returnError;
|
||||
}
|
||||
contents.push_back(new Tag::Compound("", nextCompoundData.value));
|
||||
*processedDataSize += *containedDataSize;
|
||||
|
@ -1328,7 +1336,8 @@ namespace NBT {
|
|||
for (int32_t i=0; i<elementCount.value; i++) {
|
||||
ErrorOr<std::vector<int32_t>> nextArray = Helper::readInt32Array(data, dataSize, initialPosition+*processedDataSize);
|
||||
if (nextArray.isError) {
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, nextArray.errorCode);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, nextArray.errorCode);
|
||||
goto returnError;
|
||||
}
|
||||
contents.push_back(new Tag::Int32Array("", nextArray.value));
|
||||
*processedDataSize += (uint64_t) nextArray.value.size() * 4;
|
||||
|
@ -1339,7 +1348,8 @@ namespace NBT {
|
|||
for (int32_t i=0; i<elementCount.value; i++) {
|
||||
ErrorOr<std::vector<int64_t>> nextArray = Helper::readInt64Array(data, dataSize, initialPosition+*processedDataSize);
|
||||
if (nextArray.isError) {
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, nextArray.errorCode);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, nextArray.errorCode);
|
||||
goto returnError;
|
||||
}
|
||||
contents.push_back(new Tag::Int64Array("", nextArray.value));
|
||||
*processedDataSize += (uint64_t) nextArray.value.size() * 8;
|
||||
|
@ -1347,9 +1357,16 @@ namespace NBT {
|
|||
break;
|
||||
}
|
||||
default:
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(true, ErrorCodes::INVALID_TYPE);
|
||||
returnValue = ErrorOr<std::vector<Tag::Generic*>>(true, ErrorCodes::INVALID_TYPE);
|
||||
goto returnError;
|
||||
}
|
||||
return ErrorOr<std::vector<Tag::Generic*>>(contents);
|
||||
|
||||
returnError:
|
||||
for (uint64_t i=0; i<contents.size(); i++) {
|
||||
delete contents.at(i);
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
// comment about blindly passing up error codes applies here
|
||||
|
|
Loading…
Reference in New Issue