From 84f1c37fc55c5a79511c8ddab9f891988c8bccd4 Mon Sep 17 00:00:00 2001 From: beveloper Date: Fri, 29 Oct 2004 20:22:23 +0000 Subject: [PATCH] Added a lot of checks to read slightly broken AVI files, as those created by Pinnacle Studio 9 for Windows, without problems. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9654 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../avi_reader/libOpenDML/OpenDMLParser.cpp | 65 ++++++++++++++++--- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLParser.cpp b/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLParser.cpp index eb36e34478..21c8b29077 100644 --- a/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLParser.cpp +++ b/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLParser.cpp @@ -133,12 +133,21 @@ OpenDMLParser::Parse(BPositionIO *source) uint32 temp; uint32 fourcc; uint32 size; + uint64 maxsize; + + maxsize = fSize - pos; + + if (maxsize < 13) { + ERROR("OpenDMLParser::Parse: remaining size too small for RIFF AVI chunk data at pos %lld\n", pos); + return false; + } if (sizeof(temp) != fSource->ReadAt(pos, &temp, sizeof(temp))) { ERROR("OpenDMLParser::Parse: read error at pos %llu\n", pos); return false; } pos += 4; + maxsize -= 4; fourcc = AVI_UINT32(temp); if (sizeof(temp) != fSource->ReadAt(pos, &temp, sizeof(temp))) { @@ -146,12 +155,21 @@ OpenDMLParser::Parse(BPositionIO *source) return false; } pos += 4; + maxsize -= 4; size = AVI_UINT32(temp); if (size == 0) { ERROR("OpenDMLParser::Parse: Error: chunk of size 0 found\n"); return false; } + + TRACE("OpenDMLParser::Parse: chunk '"FOURCC_FORMAT"', size = %lu, maxsize %Ld\n", FOURCC_PARAM(fourcc), size, maxsize); + + if (size > maxsize) { + ERROR("OpenDMLParser::Parse: Warning chunk '"FOURCC_FORMAT"', size = %lu extends beyond end of file\n", FOURCC_PARAM(fourcc), size); + ERROR("OpenDMLParser::Parse: Chunk at filepos %Ld truncated to %Ld, filesize %Ld\n", pos - 8, maxsize, fSize); + size = maxsize; + } if (fourcc == FOURCC('J','U','N','K')) { ERROR("OpenDMLParser::Parse: JUNK chunk ignored, size: %lu bytes\n", size); @@ -163,13 +181,13 @@ OpenDMLParser::Parse(BPositionIO *source) ERROR("OpenDMLParser::Parse: not a RIFF file\n"); return false; } else { - TRACE("OpenDMLParser::Parse: unknown chunk '"FOURCC_FORMAT"' (expected 'RIFF'), size = %lu ignored\n", FOURCC_PARAM(fourcc), size); + TRACE("OpenDMLParser::Parse: unknown chunk '"FOURCC_FORMAT"' (expected 'RIFF'), size = %lu ignored\n", FOURCC_PARAM(fourcc), size); goto cont; } } - TRACE("OpenDMLParser::Parse: RIFF chunk %d size: %lu bytes\n", riff_chunk_number, size); + TRACE("OpenDMLParser::Parse: it's a RIFF chunk!\n"); if (sizeof(temp) != fSource->ReadAt(pos, &temp, sizeof(temp))) { ERROR("OpenDMLParser::Parse: read error at pos %llu\n", pos); @@ -183,7 +201,7 @@ OpenDMLParser::Parse(BPositionIO *source) } if (fourcc != FOURCC('A','V','I',' ') && fourcc != FOURCC('A','V','I','X')) { - TRACE("OpenDMLParser::Parse: unknown chunk '"FOURCC_FORMAT"' , size = %lu ignored\n", FOURCC_PARAM(fourcc), size); + TRACE("OpenDMLParser::Parse: unknown RIFF subchunk '"FOURCC_FORMAT"' , size = %lu ignored, filepos %Ld, filesize %Ld\n", FOURCC_PARAM(fourcc), size, pos - 8, fSize); goto cont; } @@ -203,7 +221,12 @@ OpenDMLParser::ParseChunk_AVI(int number, uint64 start, uint32 size) TRACE("OpenDMLParser::ParseChunk_AVI\n"); uint64 pos = start; uint64 end = start + size; - + + if (size < 9) { + ERROR("OpenDMLParser::ParseChunk_AVI: chunk is to small at pos %llu\n", start); + return false; + } + while (pos < end) { uint32 temp; uint32 Chunkfcc; @@ -223,13 +246,20 @@ OpenDMLParser::ParseChunk_AVI(int number, uint64 start, uint32 size) pos += 4; Chunksize = AVI_UINT32(temp); - TRACE("OpenDMLParser::ParseChunk_AVI: chunk '"FOURCC_FORMAT"', size = %lu\n", FOURCC_PARAM(Chunkfcc), Chunksize); + uint32 maxsize = end - pos; + + TRACE("OpenDMLParser::ParseChunk_AVI: chunk '"FOURCC_FORMAT"', size = %lu, maxsize %lu\n", FOURCC_PARAM(Chunkfcc), Chunksize, maxsize); if (Chunksize == 0) { - ERROR("OpenDMLParser::ParseChunk_AVI: Error: chunk of size 0 found\n"); + ERROR("OpenDMLParser::ParseChunk_AVI: chunk '"FOURCC_FORMAT"' has size 0\n", FOURCC_PARAM(Chunkfcc)); return false; } + if (Chunksize > maxsize) { + TRACE("OpenDMLParser::ParseChunk_AVI: chunk '"FOURCC_FORMAT"', size = %lu too big, truncated to %lu\n", FOURCC_PARAM(Chunkfcc), Chunksize, maxsize); + Chunksize = maxsize; + } + if (Chunkfcc == FOURCC('L','I','S','T')) { if (!ParseChunk_LIST(pos, Chunksize)) return false; @@ -254,6 +284,11 @@ OpenDMLParser::ParseChunk_LIST(uint64 start, uint32 size) TRACE("OpenDMLParser::ParseChunk_LIST\n"); uint32 temp; uint32 fourcc; + + if (size < 5) { + ERROR("OpenDMLParser::ParseChunk_LIST: chunk is to small at pos %llu\n", start); + return false; + } if (sizeof(temp) != fSource->ReadAt(start, &temp, sizeof(temp))) { ERROR("OpenDMLParser::ParseChunk_LIST: read error at pos %llu\n", start); @@ -581,7 +616,7 @@ OpenDMLParser::ParseChunk_dmlh(uint64 start, uint32 size) fOdmlExtendedHeaderValid = true; TRACE("fOdmlExtendedHeader:\n"); - TRACE("total_frames = %ld\n", fOdmlExtendedHeader.total_frames); + TRACE("total_frames = %lu\n", fOdmlExtendedHeader.total_frames); return true; } @@ -604,6 +639,11 @@ OpenDMLParser::ParseList_generic(uint64 start, uint32 size) uint64 pos = start; uint64 end = start + size; + if (size < 9) { + ERROR("OpenDMLParser::ParseList_generic: list too small at pos %llu\n",pos); + return false; + } + while (pos < end) { uint32 temp; uint32 Chunkfcc; @@ -622,14 +662,21 @@ OpenDMLParser::ParseList_generic(uint64 start, uint32 size) } pos += 4; Chunksize = AVI_UINT32(temp); + + uint32 maxsize = end - pos; - TRACE("OpenDMLParser::ParseList_generic: chunk '"FOURCC_FORMAT"', size = %ld\n", FOURCC_PARAM(Chunkfcc), Chunksize); + TRACE("OpenDMLParser::ParseList_generic: chunk '"FOURCC_FORMAT"', size = %lu, maxsize = %lu\n", FOURCC_PARAM(Chunkfcc), Chunksize, maxsize); if (Chunksize == 0) { - ERROR("OpenDMLParser::ParseList_generic: Error: chunk of size 0 found\n"); + ERROR("OpenDMLParser::ParseList_generic: chunk '"FOURCC_FORMAT"' has size 0\n", FOURCC_PARAM(Chunkfcc)); return false; } + if (Chunksize > maxsize) { + TRACE("OpenDMLParser::ParseList_generic: chunk '"FOURCC_FORMAT"', size = %lu too big, truncated to %lu\n", FOURCC_PARAM(Chunkfcc), Chunksize, maxsize); + Chunksize = maxsize; + } + if (Chunkfcc == FOURCC('a','v','i','h')) { if (!ParseChunk_avih(pos, Chunksize)) return false;