Box::Box(BoxContext* aContext, uint64_t aOffset, const Box* aParent) : mContext(aContext), mParent(aParent) { uint8_t header[8]; MediaByteRange headerRange(aOffset, aOffset + sizeof(header)); if (mParent && !mParent->mRange.Contains(headerRange)) { return; } const MediaByteRange* byteRange; for (int i = 0; ; i++) { if (i == mContext->mByteRanges.Length()) { return; } byteRange = &mContext->mByteRanges[i]; if (byteRange->Contains(headerRange)) { break; } } size_t bytes; if (!mContext->mSource->CachedReadAt(aOffset, header, sizeof(header), &bytes) || bytes != sizeof(header)) { return; } uint64_t size = BigEndian::readUint32(header); if (size == 1) { uint8_t bigLength[8]; MediaByteRange bigLengthRange(headerRange.mEnd, headerRange.mEnd + sizeof(bigLength)); if ((mParent && !mParent->mRange.Contains(bigLengthRange)) || !byteRange->Contains(bigLengthRange) || !mContext->mSource->CachedReadAt(aOffset, bigLength, sizeof(bigLength), &bytes) || bytes != sizeof(bigLength)) { return; } size = BigEndian::readUint64(bigLength); mBodyOffset = bigLengthRange.mEnd; } else { mBodyOffset = headerRange.mEnd; } mType = BigEndian::readUint32(&header[4]); mChildOffset = mBodyOffset + BoxOffset(mType); MediaByteRange boxRange(aOffset, aOffset + size); if (mChildOffset > boxRange.mEnd || (mParent && !mParent->mRange.Contains(boxRange)) || !byteRange->Contains(boxRange)) { return; } mRange = boxRange; }
Box::Box(BoxContext* aContext, uint64_t aOffset, const Box* aParent) : mContext(aContext), mParent(aParent) { uint8_t header[8]; if (aOffset > INT64_MAX - sizeof(header)) { return; } MediaByteRange headerRange(aOffset, aOffset + sizeof(header)); if (mParent && !mParent->mRange.Contains(headerRange)) { return; } const MediaByteRange* byteRange; for (int i = 0; ; i++) { if (i == mContext->mByteRanges.Length()) { return; } byteRange = &mContext->mByteRanges[i]; if (byteRange->Contains(headerRange)) { break; } } size_t bytes; if (!mContext->mSource->CachedReadAt(aOffset, header, sizeof(header), &bytes) || bytes != sizeof(header)) { return; } uint64_t size = BigEndian::readUint32(header); if (size == 1) { uint8_t bigLength[8]; if (aOffset > INT64_MAX - sizeof(header) - sizeof(bigLength)) { return; } MediaByteRange bigLengthRange(headerRange.mEnd, headerRange.mEnd + sizeof(bigLength)); if ((mParent && !mParent->mRange.Contains(bigLengthRange)) || !byteRange->Contains(bigLengthRange) || !mContext->mSource->CachedReadAt(aOffset + sizeof(header), bigLength, sizeof(bigLength), &bytes) || bytes != sizeof(bigLength)) { return; } size = BigEndian::readUint64(bigLength); mBodyOffset = bigLengthRange.mEnd; } else if (size == 0) { // box extends to end of file. size = mContext->mByteRanges.LastElement().mEnd - aOffset; mBodyOffset = headerRange.mEnd; } else { mBodyOffset = headerRange.mEnd; } if (size > INT64_MAX) { return; } int64_t end = static_cast<int64_t>(aOffset) + static_cast<int64_t>(size); if (end < static_cast<int64_t>(aOffset)) { // Overflowed. return; } mType = BigEndian::readUint32(&header[4]); mChildOffset = mBodyOffset + BoxOffset(mType); MediaByteRange boxRange(aOffset, end); if (mChildOffset > boxRange.mEnd || (mParent && !mParent->mRange.Contains(boxRange)) || !byteRange->Contains(boxRange)) { return; } mRange = boxRange; }