\version \$Id: KaxBlock.cpp 1265 2007-01-14 17:20:35Z mosu $
\author Steve Lhomme <robux4 @ users.sf.net>
\author Julien Coloos <suiryc @ users.sf.net>
+ \author Moritz Bunkus <moritz@bunkus.org>
*/
#include <cassert>
//#include <streams.h>
+#include "ebml/MemReadIOCallback.h"
+#include "ebml/SafeReadIOCallback.h"
#include "matroska/KaxBlock.h"
#include "matroska/KaxContexts.h"
#include "matroska/KaxBlockData.h"
FirstFrameLocation = input.getFilePointer(); // will be updated accordingly below
+ SetValueIsSet(false);
+
+ try {
if (ReadFully == SCOPE_ALL_DATA) {
Result = EbmlBinary::ReadData(input, ReadFully);
- binary *cursor = EbmlBinary::GetBuffer();
+ if (Result != GetSize())
+ throw SafeReadIOCallback::EndOfStreamX(GetSize() - Result);
+
+ binary *BufferStart = EbmlBinary::GetBuffer();
+
+ SafeReadIOCallback Mem(*this);
uint8 BlockHeadSize = 4;
// update internal values
- TrackNumber = *cursor++;
+ TrackNumber = Mem.GetUInt8();
if ((TrackNumber & 0x80) == 0) {
// there is extra data
if ((TrackNumber & 0x40) == 0) {
// We don't support track numbers that large !
- return Result;
+ throw SafeReadIOCallback::EndOfStreamX(0);
}
TrackNumber = (TrackNumber & 0x3F) << 8;
- TrackNumber += *cursor++;
+ TrackNumber += Mem.GetUInt8();
BlockHeadSize++;
} else {
TrackNumber &= 0x7F;
}
- big_int16 b16;
- b16.Eval(cursor);
- LocalTimecode = int16(b16);
+ LocalTimecode = int16(Mem.GetUInt16BE());
bLocalTimecodeUsed = true;
- cursor += 2;
+ uint8 Flags = Mem.GetUInt8();
if (EbmlId(*this) == EBML_ID(KaxSimpleBlock)) {
- bIsKeyframe = (*cursor & 0x80) != 0;
- bIsDiscardable = (*cursor & 0x01) != 0;
+ bIsKeyframe = (Flags & 0x80) != 0;
+ bIsDiscardable = (Flags & 0x01) != 0;
}
- mInvisible = (*cursor & 0x08) >> 3;
- mLacing = LacingType((*cursor++ & 0x06) >> 1);
+ mInvisible = (Flags & 0x08) >> 3;
+ mLacing = LacingType((Flags & 0x06) >> 1);
// put all Frames in the list
if (mLacing == LACING_NONE) {
- FirstFrameLocation += cursor - EbmlBinary::GetBuffer();
- DataBuffer * soloFrame = new DataBuffer(cursor, GetSize() - BlockHeadSize);
+ FirstFrameLocation += Mem.GetPosition();
+ DataBuffer * soloFrame = new DataBuffer(BufferStart + Mem.GetPosition(), GetSize() - BlockHeadSize);
myBuffers.push_back(soloFrame);
SizeList.resize(1);
SizeList[0] = GetSize() - BlockHeadSize;
} else {
// read the number of frames in the lace
uint32 LastBufferSize = GetSize() - BlockHeadSize - 1; // 1 for number of frame
- uint8 FrameNum = *cursor++; // number of frames in the lace - 1
+ uint8 FrameNum = Mem.GetUInt8(); // number of frames in the lace - 1
// read the list of frame sizes
uint8 Index;
int32 FrameSize;
for (Index=0; Index<FrameNum; Index++) {
// get the size of the frame
FrameSize = 0;
+ uint8 Value;
do {
- FrameSize += uint8(*cursor);
+ Value = Mem.GetUInt8();
+ FrameSize += Value;
LastBufferSize--;
- } while (*cursor++ == 0xFF);
+ } while (Value == 0xFF);
SizeList[Index] = FrameSize;
LastBufferSize -= FrameSize;
}
break;
case LACING_EBML:
SizeRead = LastBufferSize;
- FrameSize = ReadCodedSizeValue(cursor, SizeRead, SizeUnknown);
+ FrameSize = ReadCodedSizeValue(BufferStart + Mem.GetPosition(), SizeRead, SizeUnknown);
SizeList[0] = FrameSize;
- cursor += SizeRead;
+ Mem.Skip(SizeRead);
LastBufferSize -= FrameSize + SizeRead;
for (Index=1; Index<FrameNum; Index++) {
// get the size of the frame
SizeRead = LastBufferSize;
- FrameSize += ReadCodedSizeSignedValue(cursor, SizeRead, SizeUnknown);
+ FrameSize += ReadCodedSizeSignedValue(BufferStart + Mem.GetPosition(), SizeRead, SizeUnknown);
SizeList[Index] = FrameSize;
- cursor += SizeRead;
+ Mem.Skip(SizeRead);
LastBufferSize -= FrameSize + SizeRead;
}
if (Index <= FrameNum) // Safety check if FrameNum == 0
assert(0);
}
- FirstFrameLocation += cursor - EbmlBinary::GetBuffer();
+ FirstFrameLocation += Mem.GetPosition();
for (Index=0; Index<=FrameNum; Index++) {
- DataBuffer * lacedFrame = new DataBuffer(cursor, SizeList[Index]);
+ DataBuffer * lacedFrame = new DataBuffer(BufferStart + Mem.GetPosition(), SizeList[Index]);
myBuffers.push_back(lacedFrame);
- cursor += SizeList[Index];
+ Mem.Skip(SizeList[Index]);
}
}
+
+ binary *BufferEnd = BufferStart + GetSize();
+ size_t NumFrames = myBuffers.size();
+
+ // Sanity checks for frame pointers and boundaries.
+ for (size_t Index = 0; Index < NumFrames; ++Index) {
+ binary *FrameStart = myBuffers[Index]->Buffer();
+ binary *FrameEnd = FrameStart + myBuffers[Index]->Size();
+ binary *ExpectedEnd = (Index + 1) < NumFrames ? myBuffers[Index + 1]->Buffer() : BufferEnd;
+
+ if ((FrameStart < BufferStart) || (FrameEnd > BufferEnd) || (FrameEnd != ExpectedEnd))
+ throw SafeReadIOCallback::EndOfStreamX(0);
+ }
+
SetValueIsSet();
- }
- else if (ReadFully == SCOPE_PARTIAL_DATA) {
+ } else if (ReadFully == SCOPE_PARTIAL_DATA) {
binary _TempHead[5];
Result = input.read(_TempHead, 5);
+ if (Result != 5)
+ throw SafeReadIOCallback::EndOfStreamX(0);
binary *cursor = _TempHead;
binary *_tmpBuf;
uint8 BlockHeadSize = 4;
Result = GetSize();
}
+ } catch (SafeReadIOCallback::EndOfStreamX &) {
+ SetValueIsSet(false);
+
+ std::memset(EbmlBinary::GetBuffer(), 0, GetSize());
+ myBuffers.clear();
+ SizeList.clear();
+ Timecode = 0;
+ LocalTimecode = 0;
+ TrackNumber = 0;
+ bLocalTimecodeUsed = false;
+ FirstFrameLocation = 0;
+
+ return 0;
+ }
+
return Result;
}