// Copyright (c) 2012 The WebM project authors. All Rights Reserved.//// Use of this source code is governed by a BSD-style license// that can be found in the LICENSE file in the root of the source// tree. An additional intellectual property rights grant can be found// in the file PATENTS. All contributing project authors may// be found in the AUTHORS file in the root of the source tree. #include "mkvparser.hpp"#include <cassert>#include <cstring>#include <new>#include <climits> #ifdef _MSC_VER// Disable MSVC warnings that suggest making code non-portable.#pragma warning(disable : 4996)#endif mkvparser::IMkvReader::~IMkvReader() {} void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision) { major = 1; minor = 0; build = 0; revision = 28;} long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len) { assert(pReader); assert(pos >= 0); int status; //#ifdef _DEBUG // long long total, available; // status = pReader->Length(&total, &available); // assert(status >= 0); // assert((total < 0) || (available <= total)); // assert(pos < available); // assert((available - pos) >= 1); //assume here max u-int len is 8 //#endif len = 1; unsigned char b; status = pReader->Read(pos, 1, &b); if (status < 0) // error or underflow return status; if (status > 0) // interpreted as "underflow" return E_BUFFER_NOT_FULL; if (b == 0) // we can't handle u-int values larger than 8 bytes return E_FILE_FORMAT_INVALID; unsigned char m = 0x80; while (!(b & m)) { m >>= 1; ++len; } //#ifdef _DEBUG // assert((available - pos) >= len); //#endif long long result = b & (~m); ++pos; for (int i = 1; i < len; ++i) { status = pReader->Read(pos, 1, &b); if (status < 0) { len = 1; return status; } if (status > 0) { len = 1; return E_BUFFER_NOT_FULL; } result <<= 8; result |= b; ++pos; } return result;} long long mkvparser::GetUIntLength(IMkvReader* pReader, long long pos, long& len) { assert(pReader); assert(pos >= 0); long long total, available; int status = pReader->Length(&total, &available); assert(status >= 0); assert((total < 0) || (available <= total)); len = 1; if (pos >= available) return pos; // too few bytes available unsigned char b; status = pReader->Read(pos, 1, &b); if (status < 0) return status; assert(status == 0); if (b == 0) // we can't handle u-int values larger than 8 bytes return E_FILE_FORMAT_INVALID; unsigned char m = 0x80; while (!(b & m)) { m >>= 1; ++len; } return 0; // success} long long mkvparser::UnserializeUInt(IMkvReader* pReader, long long pos, long long size) { assert(pReader); assert(pos >= 0); if ((size <= 0) || (size > 8)) return E_FILE_FORMAT_INVALID; long long result = 0; for (long long i = 0; i < size; ++i) { unsigned char b; const long status = pReader->Read(pos, 1, &b); if (status < 0) return status; result <<= 8; result |= b; ++pos; } return result;} long mkvparser::UnserializeFloat(IMkvReader* pReader, long long pos, long long size_, double& result) { assert(pReader); assert(pos >= 0); if ((size_ != 4) && (size_ != 8)) return E_FILE_FORMAT_INVALID; const long size = static_cast<long>(size_); unsigned char buf[8]; const int status = pReader->Read(pos, size, buf); if (status < 0) // error return status; if (size == 4) { union { float f; unsigned long ff; }; ff = 0; for (int i = 0;;) { ff |= buf[i]; if (++i >= 4) break; ff <<= 8; } result = f; } else { assert(size == 8); union { double d; unsigned long long dd; }; dd = 0; for (int i = 0;;) { dd |= buf[i]; if (++i >= 8) break; dd <<= 8; } result = d; } return 0;} long mkvparser::UnserializeInt(IMkvReader* pReader, long long pos, long size, long long& result) { assert(pReader); assert(pos >= 0); assert(size > 0); assert(size <= 8); { signed char b; const long status = pReader->Read(pos, 1, (unsigned char*)&b); if (status < 0) return status; result = b; ++pos; } for (long i = 1; i < size; ++i) { unsigned char b; const long status = pReader->Read(pos, 1, &b); if (status < 0) return status; result <<= 8; result |= b; ++pos; } return 0; // success} long mkvparser::UnserializeString(IMkvReader* pReader, long long pos, long long size_, char*& str) { delete[] str; str = NULL; if (size_ >= LONG_MAX) // we need (size+1) chars return E_FILE_FORMAT_INVALID; const long size = static_cast<long>(size_); str = new (std::nothrow) char[size + 1]; if (str == NULL) return -1; unsigned char* const buf = reinterpret_cast<unsigned char*>(str); const long status = pReader->Read(pos, size, buf); if (status) { delete[] str; str = NULL; return status; } str[size] = '\0'; return 0; // success} long mkvparser::ParseElementHeader(IMkvReader* pReader, long long& pos, long long stop, long long& id, long long& size) { if ((stop >= 0) && (pos >= stop)) return E_FILE_FORMAT_INVALID; long len; id = ReadUInt(pReader, pos, len); if (id < 0) return E_FILE_FORMAT_INVALID; pos += len; // consume id if ((stop >= 0) && (pos >= stop)) return E_FILE_FORMAT_INVALID; size = ReadUInt(pReader, pos, len); if (size < 0) return E_FILE_FORMAT_INVALID; pos += len; // consume length of size // pos now designates payload if ((stop >= 0) && ((pos + size) > stop)) return E_FILE_FORMAT_INVALID; return 0; // success} bool mkvparser::Match(IMkvReader* pReader, long long& pos, unsigned long id_, long long& val) { assert(pReader); assert(pos >= 0); long long total, available; const long status = pReader->Length(&total, &available); assert(status >= 0); assert((total < 0) || (available <= total)); if (status < 0) return false; long len; const long long id = ReadUInt(pReader, pos, len); assert(id >= 0); assert(len > 0); assert(len <= 8); assert((pos + len) <= available); if ((unsigned long)id != id_) return false; pos += len; // consume id const long long size = ReadUInt(pReader, pos, len); assert(size >= 0); assert(size <= 8); assert(len > 0); assert(len <= 8); assert((pos + len) <= available); pos += len; // consume length of size of payload val = UnserializeUInt(pReader, pos, size); assert(val >= 0); pos += size; // consume size of payload return true;} bool mkvparser::Match(IMkvReader* pReader, long long& pos, unsigned long id_, unsigned char*& buf, size_t& buflen) { assert(pReader); assert(pos >= 0); long long total, available; long status = pReader->Length(&total, &available); assert(status >= 0); assert((total < 0) || (available <= total)); if (status < 0) return false; long len; const long long id = ReadUInt(pReader, pos, len); assert(id >= 0); assert(len > 0); assert(len <= 8); assert((pos + len) <= available); if ((unsigned long)id != id_) return false; pos += len; // consume id const long long size_ = ReadUInt(pReader, pos, len); assert(size_ >= 0); assert(len > 0); assert(len <= 8); assert((pos + len) <= available); pos += len; // consume length of size of payload assert((pos + size_) <= available); const long buflen_ = static_cast<long>(size_); buf = new (std::nothrow) unsigned char[buflen_]; assert(buf); // TODO status = pReader->Read(pos, buflen_, buf); assert(status == 0); // TODO buflen = buflen_; pos += size_; // consume size of payload return true;} namespace mkvparser { EBMLHeader::EBMLHeader() : m_docType(NULL) { Init(); } EBMLHeader::~EBMLHeader() { delete[] m_docType; } void EBMLHeader::Init() { m_version = 1; m_readVersion = 1; m_maxIdLength = 4; m_maxSizeLength = 8; if (m_docType) { delete[] m_docType; m_docType = NULL; } m_docTypeVersion = 1; m_docTypeReadVersion = 1;} long long EBMLHeader::Parse(IMkvReader* pReader, long long& pos) { assert(pReader); long long total, available; long status = pReader->Length(&total, &available); if (status < 0) // error return status; pos = 0; long long end = (available >= 1024) ? 1024 : available; for (;;) { unsigned char b = 0; while (pos < end) { status = pReader->Read(pos, 1, &b); if (status < 0) // error return status; if (b == 0x1A) break; ++pos; } if (b != 0x1A) { if (pos >= 1024) return E_FILE_FORMAT_INVALID; // don't bother looking anymore if ((total >= 0) && ((total - available) < 5)) return E_FILE_FORMAT_INVALID; return available + 5; // 5 = 4-byte ID + 1st byte of size } if ((total >= 0) && ((total - pos) < 5)) return E_FILE_FORMAT_INVALID; if ((available - pos) < 5) return pos + 5; // try again later long len; const long long result = ReadUInt(pReader, pos, len); if (result < 0) // error return result; if (result == 0x0A45DFA3) { // EBML Header ID pos += len; // consume ID break; } ++pos; // throw away just the 0x1A byte, and try again } // pos designates start of size field // get length of size field long len; long long result = GetUIntLength(pReader, pos, len); if (result < 0) // error return result;Lines 1–500 of 8358. Load more
// Copyright (c) 2012 The WebM project authors. All Rights Reserved. // // Use of this source code is governed by a BSD-style license // that can be found in the LICENSE file in the root of the source // tree. An additional intellectual property rights grant can be found // in the file PATENTS. All contributing project authors may // be found in the AUTHORS file in the root of the source tree. #include "mkvparser.hpp" #include <cassert> #include <cstring> #include <new> #include <climits> #ifdef _MSC_VER // Disable MSVC warnings that suggest making code non-portable. #pragma warning(disable : 4996) #endif mkvparser::IMkvReader::~IMkvReader() {} void mkvparser::GetVersion(int& major, int& minor, int& build, int& revision) { major = 1; minor = 0; build = 0; revision = 28; } long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len) { assert(pReader); assert(pos >= 0); int status; //#ifdef _DEBUG // long long total, available; // status = pReader->Length(&total, &available); // assert(status >= 0); // assert((total < 0) || (available <= total)); // assert(pos < available); // assert((available - pos) >= 1); //assume here max u-int len is 8 //#endif len = 1; unsigned char b; status = pReader->Read(pos, 1, &b); if (status < 0) // error or underflow return status; if (status > 0) // interpreted as "underflow" return E_BUFFER_NOT_FULL; if (b == 0) // we can't handle u-int values larger than 8 bytes return E_FILE_FORMAT_INVALID; unsigned char m = 0x80; while (!(b & m)) { m >>= 1; ++len; } //#ifdef _DEBUG // assert((available - pos) >= len); //#endif long long result = b & (~m); ++pos; for (int i = 1; i < len; ++i) { status = pReader->Read(pos, 1, &b); if (status < 0) { len = 1; return status; } if (status > 0) { len = 1; return E_BUFFER_NOT_FULL; } result <<= 8; result |= b; ++pos; } return result; } long long mkvparser::GetUIntLength(IMkvReader* pReader, long long pos, long& len) { assert(pReader); assert(pos >= 0); long long total, available; int status = pReader->Length(&total, &available); assert(status >= 0); assert((total < 0) || (available <= total)); len = 1; if (pos >= available) return pos; // too few bytes available unsigned char b; status = pReader->Read(pos, 1, &b); if (status < 0) return status; assert(status == 0); if (b == 0) // we can't handle u-int values larger than 8 bytes return E_FILE_FORMAT_INVALID; unsigned char m = 0x80; while (!(b & m)) { m >>= 1; ++len; } return 0; // success } long long mkvparser::UnserializeUInt(IMkvReader* pReader, long long pos, long long size) { assert(pReader); assert(pos >= 0); if ((size <= 0) || (size > 8)) return E_FILE_FORMAT_INVALID; long long result = 0; for (long long i = 0; i < size; ++i) { unsigned char b; const long status = pReader->Read(pos, 1, &b); if (status < 0) return status; result <<= 8; result |= b; ++pos; } return result; } long mkvparser::UnserializeFloat(IMkvReader* pReader, long long pos, long long size_, double& result) { assert(pReader); assert(pos >= 0); if ((size_ != 4) && (size_ != 8)) return E_FILE_FORMAT_INVALID; const long size = static_cast<long>(size_); unsigned char buf[8]; const int status = pReader->Read(pos, size, buf); if (status < 0) // error return status; if (size == 4) { union { float f; unsigned long ff; }; ff = 0; for (int i = 0;;) { ff |= buf[i]; if (++i >= 4) break; ff <<= 8; } result = f; } else { assert(size == 8); union { double d; unsigned long long dd; }; dd = 0; for (int i = 0;;) { dd |= buf[i]; if (++i >= 8) break; dd <<= 8; } result = d; } return 0; } long mkvparser::UnserializeInt(IMkvReader* pReader, long long pos, long size, long long& result) { assert(pReader); assert(pos >= 0); assert(size > 0); assert(size <= 8); { signed char b; const long status = pReader->Read(pos, 1, (unsigned char*)&b); if (status < 0) return status; result = b; ++pos; } for (long i = 1; i < size; ++i) { unsigned char b; const long status = pReader->Read(pos, 1, &b); if (status < 0) return status; result <<= 8; result |= b; ++pos; } return 0; // success } long mkvparser::UnserializeString(IMkvReader* pReader, long long pos, long long size_, char*& str) { delete[] str; str = NULL; if (size_ >= LONG_MAX) // we need (size+1) chars return E_FILE_FORMAT_INVALID; const long size = static_cast<long>(size_); str = new (std::nothrow) char[size + 1]; if (str == NULL) return -1; unsigned char* const buf = reinterpret_cast<unsigned char*>(str); const long status = pReader->Read(pos, size, buf); if (status) { delete[] str; str = NULL; return status; } str[size] = '\0'; return 0; // success } long mkvparser::ParseElementHeader(IMkvReader* pReader, long long& pos, long long stop, long long& id, long long& size) { if ((stop >= 0) && (pos >= stop)) return E_FILE_FORMAT_INVALID; long len; id = ReadUInt(pReader, pos, len); if (id < 0) return E_FILE_FORMAT_INVALID; pos += len; // consume id if ((stop >= 0) && (pos >= stop)) return E_FILE_FORMAT_INVALID; size = ReadUInt(pReader, pos, len); if (size < 0) return E_FILE_FORMAT_INVALID; pos += len; // consume length of size // pos now designates payload if ((stop >= 0) && ((pos + size) > stop)) return E_FILE_FORMAT_INVALID; return 0; // success } bool mkvparser::Match(IMkvReader* pReader, long long& pos, unsigned long id_, long long& val) { assert(pReader); assert(pos >= 0); long long total, available; const long status = pReader->Length(&total, &available); assert(status >= 0); assert((total < 0) || (available <= total)); if (status < 0) return false; long len; const long long id = ReadUInt(pReader, pos, len); assert(id >= 0); assert(len > 0); assert(len <= 8); assert((pos + len) <= available); if ((unsigned long)id != id_) return false; pos += len; // consume id const long long size = ReadUInt(pReader, pos, len); assert(size >= 0); assert(size <= 8); assert(len > 0); assert(len <= 8); assert((pos + len) <= available); pos += len; // consume length of size of payload val = UnserializeUInt(pReader, pos, size); assert(val >= 0); pos += size; // consume size of payload return true; } bool mkvparser::Match(IMkvReader* pReader, long long& pos, unsigned long id_, unsigned char*& buf, size_t& buflen) { assert(pReader); assert(pos >= 0); long long total, available; long status = pReader->Length(&total, &available); assert(status >= 0); assert((total < 0) || (available <= total)); if (status < 0) return false; long len; const long long id = ReadUInt(pReader, pos, len); assert(id >= 0); assert(len > 0); assert(len <= 8); assert((pos + len) <= available); if ((unsigned long)id != id_) return false; pos += len; // consume id const long long size_ = ReadUInt(pReader, pos, len); assert(size_ >= 0); assert(len > 0); assert(len <= 8); assert((pos + len) <= available); pos += len; // consume length of size of payload assert((pos + size_) <= available); const long buflen_ = static_cast<long>(size_); buf = new (std::nothrow) unsigned char[buflen_]; assert(buf); // TODO status = pReader->Read(pos, buflen_, buf); assert(status == 0); // TODO buflen = buflen_; pos += size_; // consume size of payload return true; } namespace mkvparser { EBMLHeader::EBMLHeader() : m_docType(NULL) { Init(); } EBMLHeader::~EBMLHeader() { delete[] m_docType; } void EBMLHeader::Init() { m_version = 1; m_readVersion = 1; m_maxIdLength = 4; m_maxSizeLength = 8; if (m_docType) { delete[] m_docType; m_docType = NULL; } m_docTypeVersion = 1; m_docTypeReadVersion = 1; } long long EBMLHeader::Parse(IMkvReader* pReader, long long& pos) { assert(pReader); long long total, available; long status = pReader->Length(&total, &available); if (status < 0) // error return status; pos = 0; long long end = (available >= 1024) ? 1024 : available; for (;;) { unsigned char b = 0; while (pos < end) { status = pReader->Read(pos, 1, &b); if (status < 0) // error return status; if (b == 0x1A) break; ++pos; } if (b != 0x1A) { if (pos >= 1024) return E_FILE_FORMAT_INVALID; // don't bother looking anymore if ((total >= 0) && ((total - available) < 5)) return E_FILE_FORMAT_INVALID; return available + 5; // 5 = 4-byte ID + 1st byte of size } if ((total >= 0) && ((total - pos) < 5)) return E_FILE_FORMAT_INVALID; if ((available - pos) < 5) return pos + 5; // try again later long len; const long long result = ReadUInt(pReader, pos, len); if (result < 0) // error return result; if (result == 0x0A45DFA3) { // EBML Header ID pos += len; // consume ID break; } ++pos; // throw away just the 0x1A byte, and try again } // pos designates start of size field // get length of size field long len; long long result = GetUIntLength(pReader, pos, len); if (result < 0) // error return result;