Code: long AudioTrack::Parse(
    Segment* pSegment,
    const Info& info,
    long long element_start,
    long long element_size,
    AudioTrack*& pResult)
{
    if (pResult)
        return -1;
 
    if (info.type != Track::kAudio)
        return -1;
 
    IMkvReader* const pReader = pSegment->m_pReader;
 
    const Settings& s = info.settings;
    assert(s.start >= 0);
    assert(s.size >= 0);
 
    long long pos = s.start;
    assert(pos >= 0);
 
    const long long stop = pos + s.size;
 
    double rate = 8000.0;  // MKV default
    long long channels = 1;
    long long bit_depth = 0;
 
    while (pos < stop)
    {
        long long id, size;
 
        long status = ParseElementHeader(
                                pReader,
                                pos,
                                stop,
                                id,
                                size);
 
        if (status < 0)  //error
            return status;
 
        if (id == 0x35)  //Sample Rate
        {
            status = UnserializeFloat(pReader, pos, size, rate);
 
            if (status < 0)
                return status;
 
            if (rate <= 0)
                return E_FILE_FORMAT_INVALID;
        }
        else if (id == 0x1F)  //Channel Count
        {
            channels = UnserializeUInt(pReader, pos, size);
 
            if (channels <= 0)
                return E_FILE_FORMAT_INVALID;
        }
        else if (id == 0x2264)  //Bit Depth
        {
            bit_depth = UnserializeUInt(pReader, pos, size);
 
            if (bit_depth <= 0)
                return E_FILE_FORMAT_INVALID;
        }
 
        pos += size;  //consume payload
        assert(pos <= stop);
     }
 
    assert(pos == stop);
 
    AudioTrack* const pTrack = new (std::nothrow) AudioTrack(pSegment,
                                                             element_start,
                                                             element_size);
 
    if (pTrack == NULL)
        return -1;  //generic error
 
    const int status = info.Copy(pTrack->m_info);
 
     if (status)
    {
        delete pTrack;
        return status;
    }
    pTrack->m_rate = rate;
    pTrack->m_channels = channels;
    pTrack->m_bitDepth = bit_depth;
 
     pResult = pTrack;
    return 0;  //success
 }

Commit Message: libwebm: Pull from upstream

Rolling mkvparser from upstream. Primarily for fixing a bug on parsing
failures with certain Opus WebM files.

Upstream commit hash of this pull: 574045edd4ecbeb802ee3f1d214b5510269852ae

The diff is so huge because there were some style clean ups upstream.
But it was ensured that there were no breaking changes when the style
clean ups was done upstream.

Change-Id: Ib6e907175484b4b0ae1b55ab39522ea3188ad039
CWE ID: CWE-119
long AudioTrack::Parse(
    if (status < 0)  // error
      return status;
 
    if (size == 0)  // weird
      continue;
 
    if (id == 0x2E)  // TrackEntry ID
      ++count;
 
    pos += size;  // consume payload
    assert(pos <= stop);
  }
 
  assert(pos == stop);
 
  if (count <= 0)
    return 0;  // success
 
  m_trackEntries = new (std::nothrow) Track* [count];
 
  if (m_trackEntries == NULL)
    return -1;
 
  m_trackEntriesEnd = m_trackEntries;
 
  pos = m_start;
 
  while (pos < stop) {
    const long long element_start = pos;
 
    long long id, payload_size;
 
    const long status =
        ParseElementHeader(pReader, pos, stop, id, payload_size);
 
    if (status < 0)  // error
      return status;
 
    if (payload_size == 0)  // weird
      continue;
 
    const long long payload_stop = pos + payload_size;
    assert(payload_stop <= stop);  // checked in ParseElement

    const long long element_size = payload_stop - element_start;

    if (id == 0x2E) {  // TrackEntry ID
      Track*& pTrack = *m_trackEntriesEnd;
      pTrack = NULL;

      const long status = ParseTrackEntry(pos, payload_size, element_start,
                                          element_size, pTrack);

      if (status)
        return status;

      if (pTrack)
        ++m_trackEntriesEnd;
     }
 
    pos = payload_stop;
    assert(pos <= stop);
  }
 
  assert(pos == stop);
 
  return 0;  // success
}
 
unsigned long Tracks::GetTracksCount() const {
  const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries;
  assert(result >= 0);

  return static_cast<unsigned long>(result);
}

long Tracks::ParseTrackEntry(long long track_start, long long track_size,
                             long long element_start, long long element_size,
                             Track*& pResult) const {
  if (pResult)
    return -1;

  IMkvReader* const pReader = m_pSegment->m_pReader;

  long long pos = track_start;
  const long long track_stop = track_start + track_size;

  Track::Info info;

  info.type = 0;
  info.number = 0;
  info.uid = 0;
  info.defaultDuration = 0;

  Track::Settings v;
  v.start = -1;
  v.size = -1;

  Track::Settings a;
  a.start = -1;
  a.size = -1;

  Track::Settings e;  // content_encodings_settings;
  e.start = -1;
  e.size = -1;

  long long lacing = 1;  // default is true

  while (pos < track_stop) {
    long long id, size;

    const long status = ParseElementHeader(pReader, pos, track_stop, id, size);

    if (status < 0)  // error
      return status;

    if (size < 0)
      return E_FILE_FORMAT_INVALID;

    const long long start = pos;

    if (id == 0x60) {  // VideoSettings ID
      v.start = start;
      v.size = size;
    } else if (id == 0x61) {  // AudioSettings ID
      a.start = start;
      a.size = size;
    } else if (id == 0x2D80) {  // ContentEncodings ID
      e.start = start;
      e.size = size;
    } else if (id == 0x33C5) {  // Track UID
      if (size > 8)
        return E_FILE_FORMAT_INVALID;

      info.uid = 0;

      long long pos_ = start;
      const long long pos_end = start + size;

      while (pos_ != pos_end) {
        unsigned char b;

        const int status = pReader->Read(pos_, 1, &b);

        if (status)
          return status;

        info.uid <<= 8;
        info.uid |= b;

        ++pos_;
      }
    } else if (id == 0x57) {  // Track Number
      const long long num = UnserializeUInt(pReader, pos, size);

      if ((num <= 0) || (num > 127))
        return E_FILE_FORMAT_INVALID;

      info.number = static_cast<long>(num);
    } else if (id == 0x03) {  // Track Type
      const long long type = UnserializeUInt(pReader, pos, size);

      if ((type <= 0) || (type > 254))
        return E_FILE_FORMAT_INVALID;

      info.type = static_cast<long>(type);
    } else if (id == 0x136E) {  // Track Name
      const long status =
          UnserializeString(pReader, pos, size, info.nameAsUTF8);

      if (status)
        return status;
    } else if (id == 0x02B59C) {  // Track Language
      const long status = UnserializeString(pReader, pos, size, info.language);

      if (status)
        return status;
    } else if (id == 0x03E383) {  // Default Duration
      const long long duration = UnserializeUInt(pReader, pos, size);

      if (duration < 0)
        return E_FILE_FORMAT_INVALID;

      info.defaultDuration = static_cast<unsigned long long>(duration);
    } else if (id == 0x06) {  // CodecID
      const long status = UnserializeString(pReader, pos, size, info.codecId);

      if (status)
        return status;
    } else if (id == 0x1C) {  // lacing
      lacing = UnserializeUInt(pReader, pos, size);

      if ((lacing < 0) || (lacing > 1))
        return E_FILE_FORMAT_INVALID;
    } else if (id == 0x23A2) {  // Codec Private
      delete[] info.codecPrivate;
      info.codecPrivate = NULL;
      info.codecPrivateSize = 0;

      const size_t buflen = static_cast<size_t>(size);

      if (buflen) {
        typedef unsigned char* buf_t;

        const buf_t buf = new (std::nothrow) unsigned char[buflen];

        if (buf == NULL)
          return -1;

        const int status = pReader->Read(pos, static_cast<long>(buflen), buf);

        if (status) {
          delete[] buf;
          return status;
        }

        info.codecPrivate = buf;
        info.codecPrivateSize = buflen;
      }
    } else if (id == 0x058688) {  // Codec Name
      const long status =
          UnserializeString(pReader, pos, size, info.codecNameAsUTF8);

      if (status)
        return status;
    } else if (id == 0x16AA) {  // Codec Delay
      info.codecDelay = UnserializeUInt(pReader, pos, size);
    } else if (id == 0x16BB) {  // Seek Pre Roll
      info.seekPreRoll = UnserializeUInt(pReader, pos, size);
    }

    pos += size;  // consume payload
    assert(pos <= track_stop);
  }

  assert(pos == track_stop);

  if (info.number <= 0)  // not specified
    return E_FILE_FORMAT_INVALID;

  if (GetTrackByNumber(info.number))
    return E_FILE_FORMAT_INVALID;

  if (info.type <= 0)  // not specified
    return E_FILE_FORMAT_INVALID;

  info.lacing = (lacing > 0) ? true : false;

  if (info.type == Track::kVideo) {
    if (v.start < 0)
      return E_FILE_FORMAT_INVALID;

    if (a.start >= 0)
      return E_FILE_FORMAT_INVALID;

    info.settings = v;

    VideoTrack* pTrack = NULL;

    const long status = VideoTrack::Parse(m_pSegment, info, element_start,
                                          element_size, pTrack);
 
     if (status)
      return status;
 
     pResult = pTrack;
    assert(pResult);

    if (e.start >= 0)
      pResult->ParseContentEncodingsEntry(e.start, e.size);
  } else if (info.type == Track::kAudio) {
    if (a.start < 0)
      return E_FILE_FORMAT_INVALID;

    if (v.start >= 0)
      return E_FILE_FORMAT_INVALID;

    info.settings = a;

    AudioTrack* pTrack = NULL;

    const long status = AudioTrack::Parse(m_pSegment, info, element_start,
                                          element_size, pTrack);

    if (status)
      return status;

    pResult = pTrack;
    assert(pResult);

    if (e.start >= 0)
      pResult->ParseContentEncodingsEntry(e.start, e.size);
  } else {
    // neither video nor audio - probably metadata or subtitles

    if (a.start >= 0)
      return E_FILE_FORMAT_INVALID;

    if (v.start >= 0)
      return E_FILE_FORMAT_INVALID;

    if (e.start >= 0)
      return E_FILE_FORMAT_INVALID;

    info.settings.start = -1;
    info.settings.size = 0;

    Track* pTrack = NULL;

    const long status =
        Track::Create(m_pSegment, info, element_start, element_size, pTrack);

    if (status)
      return status;

    pResult = pTrack;
    assert(pResult);
  }

  return 0;  // success
 }
