Fix handling AVC config errors leading to crashes
See https://github.com/Martchus/tageditor/issues/60
This commit is contained in:
parent
31e8741db0
commit
bcf00b0df5
|
@ -21,11 +21,9 @@ namespace TagParser {
|
||||||
/*!
|
/*!
|
||||||
* \brief Parses the AVC configuration using the specified \a reader.
|
* \brief Parses the AVC configuration using the specified \a reader.
|
||||||
* \throws Throws TruncatedDataException() when the config size exceeds the specified \a maxSize.
|
* \throws Throws TruncatedDataException() when the config size exceeds the specified \a maxSize.
|
||||||
* \todo Implement logging/reporting parsing errors.
|
|
||||||
*/
|
*/
|
||||||
void AvcConfiguration::parse(BinaryReader &reader, std::uint64_t maxSize, Diagnostics &diag)
|
void AvcConfiguration::parse(BinaryReader &reader, std::uint64_t maxSize, Diagnostics &diag)
|
||||||
{
|
{
|
||||||
CPP_UTILITIES_UNUSED(diag)
|
|
||||||
if (maxSize < 7) {
|
if (maxSize < 7) {
|
||||||
throw TruncatedDataException();
|
throw TruncatedDataException();
|
||||||
}
|
}
|
||||||
|
@ -38,12 +36,14 @@ void AvcConfiguration::parse(BinaryReader &reader, std::uint64_t maxSize, Diagno
|
||||||
naluSizeLength = (reader.readByte() & 0x03) + 1;
|
naluSizeLength = (reader.readByte() & 0x03) + 1;
|
||||||
|
|
||||||
// read SPS info entries
|
// read SPS info entries
|
||||||
std::uint8_t entryCount = reader.readByte() & 0x0f;
|
std::uint8_t spsEntryCount = reader.readByte() & 0x0f;
|
||||||
spsInfos.reserve(entryCount);
|
std::uint8_t ignoredSpsEntries = 0;
|
||||||
for (; entryCount; --entryCount) {
|
spsInfos.reserve(spsEntryCount);
|
||||||
|
for (; spsEntryCount; --spsEntryCount) {
|
||||||
if (maxSize < SpsInfo::minSize) {
|
if (maxSize < SpsInfo::minSize) {
|
||||||
throw TruncatedDataException();
|
throw TruncatedDataException();
|
||||||
}
|
}
|
||||||
|
auto error = false;
|
||||||
try {
|
try {
|
||||||
spsInfos.emplace_back().parse(
|
spsInfos.emplace_back().parse(
|
||||||
reader, maxSize > numeric_limits<std::uint32_t>::max() ? numeric_limits<std::uint32_t>::max() : static_cast<std::uint32_t>(maxSize));
|
reader, maxSize > numeric_limits<std::uint32_t>::max() ? numeric_limits<std::uint32_t>::max() : static_cast<std::uint32_t>(maxSize));
|
||||||
|
@ -51,21 +51,26 @@ void AvcConfiguration::parse(BinaryReader &reader, std::uint64_t maxSize, Diagno
|
||||||
if (spsInfos.back().size > (maxSize - SpsInfo::minSize)) {
|
if (spsInfos.back().size > (maxSize - SpsInfo::minSize)) {
|
||||||
throw; // sps info looks bigger than bytes to read
|
throw; // sps info looks bigger than bytes to read
|
||||||
}
|
}
|
||||||
spsInfos.pop_back(); // sps info exceeds denoted size
|
error = true; // sps info exceeds denoted size
|
||||||
} catch (const Failure &) {
|
} catch (const Failure &) {
|
||||||
spsInfos.pop_back();
|
error = true;
|
||||||
// TODO: log parsing error
|
|
||||||
}
|
}
|
||||||
maxSize -= spsInfos.back().size;
|
maxSize -= spsInfos.back().size;
|
||||||
|
if (error) {
|
||||||
|
spsInfos.pop_back();
|
||||||
|
++ignoredSpsEntries;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// read PPS info entries
|
// read PPS info entries
|
||||||
entryCount = reader.readByte();
|
std::uint8_t ppsEntryCount = reader.readByte();
|
||||||
ppsInfos.reserve(entryCount);
|
std::uint8_t ignoredPpsEntries = 0;
|
||||||
for (; entryCount; --entryCount) {
|
ppsInfos.reserve(ppsEntryCount);
|
||||||
|
for (; ppsEntryCount; --ppsEntryCount) {
|
||||||
if (maxSize < PpsInfo::minSize) {
|
if (maxSize < PpsInfo::minSize) {
|
||||||
throw TruncatedDataException();
|
throw TruncatedDataException();
|
||||||
}
|
}
|
||||||
|
auto error = false;
|
||||||
try {
|
try {
|
||||||
ppsInfos.emplace_back().parse(
|
ppsInfos.emplace_back().parse(
|
||||||
reader, maxSize > numeric_limits<std::uint32_t>::max() ? numeric_limits<std::uint32_t>::max() : static_cast<std::uint32_t>(maxSize));
|
reader, maxSize > numeric_limits<std::uint32_t>::max() ? numeric_limits<std::uint32_t>::max() : static_cast<std::uint32_t>(maxSize));
|
||||||
|
@ -73,12 +78,23 @@ void AvcConfiguration::parse(BinaryReader &reader, std::uint64_t maxSize, Diagno
|
||||||
if (ppsInfos.back().size > (maxSize - PpsInfo::minSize)) {
|
if (ppsInfos.back().size > (maxSize - PpsInfo::minSize)) {
|
||||||
throw; // pps info looks bigger than bytes to read
|
throw; // pps info looks bigger than bytes to read
|
||||||
}
|
}
|
||||||
ppsInfos.pop_back(); // pps info exceeds denoted size
|
error = true; // pps info exceeds denoted size
|
||||||
} catch (const Failure &) {
|
} catch (const Failure &) {
|
||||||
ppsInfos.pop_back();
|
error = true;
|
||||||
// TODO: log parsing error
|
|
||||||
}
|
}
|
||||||
maxSize -= ppsInfos.back().size;
|
maxSize -= ppsInfos.back().size;
|
||||||
|
if (error) {
|
||||||
|
ppsInfos.pop_back();
|
||||||
|
++ignoredPpsEntries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// log parsing errors
|
||||||
|
if (ignoredSpsEntries || ignoredPpsEntries) {
|
||||||
|
diag.emplace_back(DiagLevel::Debug,
|
||||||
|
argsToString(
|
||||||
|
"Ignored ", ignoredSpsEntries, " SPS entries and ", ignoredPpsEntries, " PPS entries. This AVC config is likely just not supported."),
|
||||||
|
"parsing AVC config");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore remaining data
|
// ignore remaining data
|
||||||
|
|
|
@ -234,7 +234,7 @@ void PpsInfo::parse(BinaryReader &reader, std::uint32_t maxSize)
|
||||||
// read general values
|
// read general values
|
||||||
bitReader.skipBits(1); // zero bit
|
bitReader.skipBits(1); // zero bit
|
||||||
if (bitReader.readBits<std::uint8_t>(5) != 8) { // nal unit type
|
if (bitReader.readBits<std::uint8_t>(5) != 8) { // nal unit type
|
||||||
throw InvalidDataException();
|
throw NotImplementedException();
|
||||||
}
|
}
|
||||||
id = bitReader.readUnsignedExpGolombCodedBits<ugolomb>();
|
id = bitReader.readUnsignedExpGolombCodedBits<ugolomb>();
|
||||||
spsId = bitReader.readUnsignedExpGolombCodedBits<ugolomb>();
|
spsId = bitReader.readUnsignedExpGolombCodedBits<ugolomb>();
|
||||||
|
|
Loading…
Reference in New Issue