зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1406503 - P5. Do not ignore small flac packets. r=jwwang
A FLAC packet may have a size as small as 11 bytes. We should parse as much data as we can and not make assumptions on when to stop early. MozReview-Commit-ID: 9skvwbt15MY --HG-- extra : rebase_source : e428ba40fb71a4607af5d3be7f7d61ae98631522
This commit is contained in:
Родитель
241e778f48
Коммит
14413d23f3
|
@ -44,11 +44,9 @@ public:
|
|||
// From https://xiph.org/flac/format.html#frame_header
|
||||
// A valid header is one that can be decoded without error and that has a
|
||||
// valid CRC.
|
||||
// aPacket must points to a buffer that is at least FLAC_MAX_FRAME_HEADER_SIZE
|
||||
// bytes.
|
||||
bool Parse(const uint8_t* aPacket)
|
||||
bool Parse(const uint8_t* aPacket, size_t aBytes)
|
||||
{
|
||||
mp4_demuxer::BitReader br(aPacket, FLAC_MAX_FRAME_HEADER_SIZE * 8);
|
||||
mp4_demuxer::BitReader br(aPacket, aBytes * 8);
|
||||
|
||||
// Frame sync code.
|
||||
if ((br.ReadBits(15) & 0x7fff) != 0x7ffc) {
|
||||
|
@ -230,27 +228,32 @@ public:
|
|||
// mandatorily set to 0, so we need to find either of 0xfffc or 0xfffd 2-bytes
|
||||
// signature. We first use a bitmask to see if 0xfc or 0xfd is present. And if
|
||||
// so we check for the whole signature.
|
||||
// aData must be pointing to a buffer at least
|
||||
// aLength + FLAC_MAX_FRAME_HEADER_SIZE bytes.
|
||||
int64_t FindNext(const uint8_t* aData, const uint32_t aLength)
|
||||
{
|
||||
// The non-variable size of a FLAC header is 32 bits followed by variable
|
||||
// size data and a 8 bits CRC.
|
||||
// There's no need to read the last 4 bytes, it can never make a complete
|
||||
// header.
|
||||
if (aLength < 4) {
|
||||
return -1;
|
||||
}
|
||||
uint32_t modOffset = aLength % 4;
|
||||
uint32_t i, j;
|
||||
|
||||
for (i = 0; i < modOffset; i++) {
|
||||
if ((BigEndian::readUint16(aData + i) & 0xfffe) == 0xfff8) {
|
||||
if (mHeader.Parse(aData + i)) {
|
||||
if (mHeader.Parse(aData + i, aLength - i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < aLength; i += 4) {
|
||||
for (; i < aLength - 4; i += 4) {
|
||||
uint32_t x = BigEndian::readUint32(aData + i);
|
||||
if (((x & ~(x + 0x01010101)) & 0x80808080)) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
if ((BigEndian::readUint16(aData + i + j) & 0xfffe) == 0xfff8) {
|
||||
if (mHeader.Parse(aData + i + j)) {
|
||||
if (mHeader.Parse(aData + i + j, aLength - i - j)) {
|
||||
return i + j;
|
||||
}
|
||||
}
|
||||
|
@ -282,15 +285,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
if (read < FLAC_MAX_FRAME_HEADER_SIZE) {
|
||||
// Assume that we can't have a valid frame in such small content, we
|
||||
// must have reached EOS.
|
||||
// So we're done.
|
||||
mEOS = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t bufSize = read + innerOffset - FLAC_MAX_FRAME_HEADER_SIZE;
|
||||
const size_t bufSize = read + innerOffset;
|
||||
int64_t foundOffset =
|
||||
FindNext(reinterpret_cast<uint8_t*>(buffer.Elements()), bufSize);
|
||||
|
||||
|
@ -299,9 +294,19 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
if (read < BUFFER_SIZE) {
|
||||
// Nothing more to try on as we had reached EOS during the previous
|
||||
// read.
|
||||
mEOS = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Scan the next block;
|
||||
offset += bufSize;
|
||||
buffer.RemoveElementsAt(0, bufSize);
|
||||
// We rewind a bit to re-try what could have been an incomplete packet.
|
||||
// The maximum size of a FLAC header being FLAC_MAX_FRAME_HEADER_SIZE so
|
||||
// we need to retry just after that amount.
|
||||
offset += bufSize - (FLAC_MAX_FRAME_HEADER_SIZE + 1);
|
||||
buffer.RemoveElementsAt(0, bufSize - (FLAC_MAX_FRAME_HEADER_SIZE + 1));
|
||||
innerOffset = buffer.Length();
|
||||
} while (offset - originalOffset < FLAC_MAX_FRAME_SIZE);
|
||||
|
||||
|
@ -1046,12 +1051,12 @@ FlacTrackDemuxer::TimeAtEnd()
|
|||
/* static */ bool
|
||||
FlacDemuxer::FlacSniffer(const uint8_t* aData, const uint32_t aLength)
|
||||
{
|
||||
if (aLength < FLAC_MAX_FRAME_HEADER_SIZE) {
|
||||
if (aLength < FLAC_MIN_FRAME_SIZE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
flac::Frame frame;
|
||||
return frame.FindNext(aData, aLength - FLAC_MAX_FRAME_HEADER_SIZE) >= 0;
|
||||
return frame.FindNext(aData, aLength) >= 0;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
Загрузка…
Ссылка в новой задаче