Code: long Segment::ParseNext(
    const Cluster* pCurr,
    const Cluster*& pResult,
    long long& pos,
    long& len)
{
    assert(pCurr);
    assert(!pCurr->EOS());
    assert(m_clusters);
 
    pResult = 0;
 
    if (pCurr->m_index >= 0)  //loaded (not merely preloaded)
    {
        assert(m_clusters[pCurr->m_index] == pCurr);
 
        const long next_idx = pCurr->m_index + 1;
 
        if (next_idx < m_clusterCount)
        {
            pResult = m_clusters[next_idx];
            return 0;  //success
        }
 
 
        const long result = LoadCluster(pos, len);
 
        if (result < 0)  //error or underflow
            return result;
 
        if (result > 0)  //no more clusters
        {
            return 1;
        }
 
        pResult = GetLast();
        return 0;  //success
     }
 
    assert(m_pos > 0);
 
    long long total, avail;
 
    long status = m_pReader->Length(&total, &avail);
 
    if (status < 0)  //error
        return status;
 
    assert((total < 0) || (avail <= total));
 
    const long long segment_stop = (m_size < 0) ? -1 : m_start + m_size;
 
 
    pos = pCurr->m_element_start;
 
    if (pCurr->m_element_size >= 0)
        pos += pCurr->m_element_size;
     else
    {
        if ((pos + 1) > avail)
        {
            len = 1;
            return E_BUFFER_NOT_FULL;
        }
 
        long long result = GetUIntLength(m_pReader, pos, len);
 
        if (result < 0)  //error
            return static_cast<long>(result);
 
        if (result > 0)  //weird
            return E_BUFFER_NOT_FULL;
 
        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
            return E_FILE_FORMAT_INVALID;
 
        if ((pos + len) > avail)
            return E_BUFFER_NOT_FULL;
        const long long id = ReadUInt(m_pReader, pos, len);
        if (id != 0x0F43B675)  //weird: not Cluster ID
            return -1;
        pos += len;  //consume ID
        if ((pos + 1) > avail)
        {
            len = 1;
            return E_BUFFER_NOT_FULL;
        }
        result = GetUIntLength(m_pReader, pos, len);
        if (result < 0)  //error
            return static_cast<long>(result);
        if (result > 0)  //weird
            return E_BUFFER_NOT_FULL;
        if ((segment_stop >= 0) && ((pos + len) > segment_stop))
            return E_FILE_FORMAT_INVALID;
        if ((pos + len) > avail)
            return E_BUFFER_NOT_FULL;
        const long long size = ReadUInt(m_pReader, pos, len);
        if (size < 0) //error
            return static_cast<long>(size);
        pos += len;  //consume size field
        const long long unknown_size = (1LL << (7 * len)) - 1;
        if (size == unknown_size)          //TODO: should never happen
            return E_FILE_FORMAT_INVALID;  //TODO: resolve this
        if ((segment_stop >= 0) && ((pos + size) > segment_stop))
            return E_FILE_FORMAT_INVALID;
        pos += size;  //consume payload (that is, the current cluster)
        assert((segment_stop < 0) || (pos <= segment_stop));
    }
    for (;;)
    {
        const long status = DoParseNext(pResult, pos, len);
        if (status <= 1)
            return status;
    }
 }

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 Segment::ParseNext(
  long long pos = pCurr->m_element_start;
 
  assert(m_size >= 0);  // TODO
  const long long stop = m_start + m_size;  // end of segment
 
  {
    long len;
 
    long long result = GetUIntLength(m_pReader, pos, len);
    assert(result == 0);
    assert((pos + len) <= stop);  // TODO
    if (result != 0)
      return NULL;
 
    const long long id = ReadUInt(m_pReader, pos, len);
    assert(id == 0x0F43B675);  // Cluster ID
    if (id != 0x0F43B675)
      return NULL;
 
    pos += len;  // consume ID
 
    // Read Size
    result = GetUIntLength(m_pReader, pos, len);
    assert(result == 0);  // TODO
    assert((pos + len) <= stop);  // TODO
 
    const long long size = ReadUInt(m_pReader, pos, len);
    assert(size > 0);  // TODO
    // assert((pCurr->m_size <= 0) || (pCurr->m_size == size));
 
    pos += len;  // consume length of size of element
    assert((pos + size) <= stop);  // TODO
 
    // Pos now points to start of payload

    pos += size;  // consume payload
  }

  long long off_next = 0;

  while (pos < stop) {
    long len;

    long long result = GetUIntLength(m_pReader, pos, len);
    assert(result == 0);
    assert((pos + len) <= stop);  // TODO
    if (result != 0)
      return NULL;

    const long long idpos = pos;  // pos of next (potential) cluster

    const long long id = ReadUInt(m_pReader, idpos, len);
    assert(id > 0);  // TODO

    pos += len;  // consume ID

    // Read Size
    result = GetUIntLength(m_pReader, pos, len);
    assert(result == 0);  // TODO
    assert((pos + len) <= stop);  // TODO

    const long long size = ReadUInt(m_pReader, pos, len);
    assert(size >= 0);  // TODO

    pos += len;  // consume length of size of element
    assert((pos + size) <= stop);  // TODO

    // Pos now points to start of payload

    if (size == 0)  // weird
      continue;

    if (id == 0x0F43B675) {  // Cluster ID
      const long long off_next_ = idpos - m_start;

      long long pos_;
      long len_;

      const long status = Cluster::HasBlockEntries(this, off_next_, pos_, len_);

      assert(status >= 0);

      if (status > 0) {
        off_next = off_next_;
        break;
      }
     }
 
    pos += size;  // consume payload
  }
 
  if (off_next <= 0)
    return 0;
 
  Cluster** const ii = m_clusters + m_clusterCount;
  Cluster** i = ii;
 
  Cluster** const jj = ii + m_clusterPreloadCount;
  Cluster** j = jj;
 
  while (i < j) {
    // INVARIANT:
    //[0, i) < pos_next
    //[i, j) ?
    //[j, jj)  > pos_next
 
    Cluster** const k = i + (j - i) / 2;
    assert(k < jj);
 
    Cluster* const pNext = *k;
    assert(pNext);
    assert(pNext->m_index < 0);
 
    // const long long pos_ = pNext->m_pos;
    // assert(pos_);
    // pos = pos_ * ((pos_ < 0) ? -1 : 1);
 
    pos = pNext->GetPosition();

    if (pos < off_next)
      i = k + 1;
    else if (pos > off_next)
      j = k;
     else
      return pNext;
  }
 
  assert(i == j);
 
  Cluster* const pNext = Cluster::Create(this, -1, off_next);
  assert(pNext);
 
  const ptrdiff_t idx_next = i - m_clusters;  // insertion position
 
  PreloadCluster(pNext, idx_next);
  assert(m_clusters);
  assert(idx_next < m_clusterSize);
  assert(m_clusters[idx_next] == pNext);
 
  return pNext;
 }
