Commit message: None
CVE: CVE-2014-7908
CWE: CWE-189
Vulnerability description: Multiple integer overflows in the CheckMov function in media/base/container_names.cc in Google Chrome before 39.0.2171.65 allow remote attackers to cause a denial of service or possibly have unspecified other impact via a large atom in (1) MPEG-4 or (2) QuickTime .mov data.

Project: Chrome

static bool AdvanceToStartCode(const uint8* buffer,
                               int buffer_size,
                               int* offset,
                               int bytes_needed,
                               int num_bits,
                               uint32 start_code) {
  DCHECK_GE(bytes_needed, 3);
  DCHECK_LE(num_bits, 24);  // Only supports up to 24 bits.

  uint32 bits_to_shift = 24 - num_bits;
  uint32 mask = (1 << num_bits) - 1;
  while (*offset + bytes_needed < buffer_size) {
    uint32 next = Read24(buffer + *offset);
    if (((next >> bits_to_shift) & mask) == start_code)
      return true;
    ++(*offset);
  }
  return false;
}

Project: Chrome

static bool CheckCaf(const uint8* buffer, int buffer_size) {
  RCHECK(buffer_size >= 52);
  BitReader reader(buffer, buffer_size);

  RCHECK(ReadBits(&reader, 32) == TAG('c', 'a', 'f', 'f'));

  RCHECK(ReadBits(&reader, 16) == 1);

  reader.SkipBits(16);

  RCHECK(ReadBits(&reader, 32) == TAG('d', 'e', 's', 'c'));
  RCHECK(ReadBits(&reader, 64) == 32);

  RCHECK(ReadBits(&reader, 64) != 0);

  RCHECK(ReadBits(&reader, 32) != 0);

  reader.SkipBits(32 + 32);

  RCHECK(ReadBits(&reader, 32) != 0);
  return true;
}

Project: Chrome

static bool CheckDts(const uint8* buffer, int buffer_size) {
  RCHECK(buffer_size > 11);

  int offset = 0;
  while (offset + 11 < buffer_size) {
    BitReader reader(buffer + offset, 11);

    RCHECK(ReadBits(&reader, 32) == 0x7ffe8001);

    reader.SkipBits(1 + 5);

    RCHECK(ReadBits(&reader, 1) == 0);  // CPF must be 0.

    RCHECK(ReadBits(&reader, 7) >= 5);

    int frame_size = ReadBits(&reader, 14);
    RCHECK(frame_size >= 95);

    reader.SkipBits(6);

    RCHECK(kSamplingFrequencyValid[ReadBits(&reader, 4)]);

    RCHECK(ReadBits(&reader, 5) <= 25);

    RCHECK(ReadBits(&reader, 1) == 0);

    reader.SkipBits(1 + 1 + 1 + 1);

    RCHECK(kExtAudioIdValid[ReadBits(&reader, 3)]);

    reader.SkipBits(1 + 1);

    RCHECK(ReadBits(&reader, 2) != 3);

    offset += frame_size + 1;
  }
  return true;
}

Project: Chrome

static bool CheckEac3(const uint8* buffer, int buffer_size) {

  RCHECK(buffer_size > 6);

  int offset = 0;
  while (offset + 6 < buffer_size) {
    BitReader reader(buffer + offset, 6);

    RCHECK(ReadBits(&reader, 16) == kAc3SyncWord);

    RCHECK(ReadBits(&reader, 2) != 3);

    reader.SkipBits(3);

    int frame_size = (ReadBits(&reader, 11) + 1) * 2;
    RCHECK(frame_size >= 7);

    reader.SkipBits(2 + 2 + 3 + 1);

    int bit_stream_id = ReadBits(&reader, 5);
    RCHECK(bit_stream_id >= 11 && bit_stream_id <= 16);

    offset += frame_size;
  }
  return true;
}

Project: Chrome

static bool CheckH261(const uint8* buffer, int buffer_size) {
  RCHECK(buffer_size > 16);

  int offset = 0;
  bool seen_start_code = false;
  while (true) {
    if (!AdvanceToStartCode(buffer, buffer_size, &offset, 4, 20, 0x10)) {
      return seen_start_code;
    }

    BitReader reader(buffer + offset, buffer_size - offset);
    RCHECK(ReadBits(&reader, 20) == 0x10);

    reader.SkipBits(5 + 6);

    int extra = ReadBits(&reader, 1);
    while (extra == 1) {
      if (!reader.SkipBits(8))
        return seen_start_code;
      if (!reader.ReadBits(1, &extra))
        return seen_start_code;
    }

    int next;
    if (!reader.ReadBits(16, &next))
      return seen_start_code;
    RCHECK(next == 1);

    seen_start_code = true;
    offset += 4;
  }
}

Project: Chrome

static bool CheckH264(const uint8* buffer, int buffer_size) {
  RCHECK(buffer_size > 4);

  int offset = 0;
  int parameter_count = 0;
  while (true) {
    if (!AdvanceToStartCode(buffer, buffer_size, &offset, 4, 24, 1)) {
      return parameter_count > 0;
    }

    BitReader reader(buffer + offset, 4);
    RCHECK(ReadBits(&reader, 24) == 1);

    RCHECK(ReadBits(&reader, 1) == 0);

    int nal_ref_idc = ReadBits(&reader, 2);
    int nal_unit_type = ReadBits(&reader, 5);

    switch (nal_unit_type) {
      case 5:  // Coded slice of an IDR picture.
        RCHECK(nal_ref_idc != 0);
        break;
      case 6:   // Supplemental enhancement information (SEI).
      case 9:   // Access unit delimiter.
      case 10:  // End of sequence.
      case 11:  // End of stream.
      case 12:  // Filler data.
        RCHECK(nal_ref_idc == 0);
        break;
      case 7:  // Sequence parameter set.
      case 8:  // Picture parameter set.
        ++parameter_count;
        break;
    }

    offset += 4;
  }
}

Project: Chrome

static bool CheckHls(const uint8* buffer, int buffer_size) {

  if (StartsWith(buffer, buffer_size, kHlsSignature)) {
    int offset = strlen(kHlsSignature);
    while (offset < buffer_size) {
      if (buffer[offset] == '#') {
        if (StartsWith(buffer + offset, buffer_size - offset, kHls1) ||
            StartsWith(buffer + offset, buffer_size - offset, kHls2) ||
            StartsWith(buffer + offset, buffer_size - offset, kHls3)) {
          return true;
        }
      }
      ++offset;
    }
  }
  return false;
}

Project: Chrome

static bool CheckMJpeg(const uint8* buffer, int buffer_size) {
  RCHECK(buffer_size >= 16);

  int offset = 0;
  int last_restart = -1;
  int num_codes = 0;
  while (offset + 5 < buffer_size) {
    RCHECK(buffer[offset] == 0xff);
    uint8 code = buffer[offset + 1];
    RCHECK(code >= 0xc0 || code == 1);

    if (code == 0xff) {
      ++offset;
      continue;
    }

    if (code == 0xd9)
      return true;

    if (code == 0xd8 || code == 1) {
      offset += 2;
    } else if (code >= 0xd0 && code <= 0xd7) {
      int restart = code & 0x07;
      if (last_restart >= 0)
        RCHECK(restart == (last_restart + 1) % 8);
      last_restart = restart;
      offset += 2;
    } else {
      int length = Read16(buffer + offset + 2) + 2;

      if (code == 0xda) {
        int number_components = buffer[offset + 4];
        RCHECK(length == 8 + 2 * number_components);

        offset += length;
        while (offset + 2 < buffer_size) {
          if (buffer[offset] == 0xff && buffer[offset + 1] != 0)
            break;
          ++offset;
        }
      } else {
        offset += length;
      }
    }
    ++num_codes;
  }
  return (num_codes > 1);
}

Project: Chrome

static bool CheckMpeg2ProgramStream(const uint8* buffer, int buffer_size) {
  RCHECK(buffer_size > 14);

  int offset = 0;
  while (offset + 14 < buffer_size) {
    BitReader reader(buffer + offset, 14);

    RCHECK(ReadBits(&reader, 24) == 1);
    RCHECK(ReadBits(&reader, 8) == PACK_START_CODE);

    int mpeg_version = ReadBits(&reader, 2);
    if (mpeg_version == 0) {
      RCHECK(ReadBits(&reader, 2) == 2);
    } else {
      RCHECK(mpeg_version == 1);
    }

    reader.SkipBits(3);

    RCHECK(ReadBits(&reader, 1) == 1);

    reader.SkipBits(15);

    RCHECK(ReadBits(&reader, 1) == 1);

    reader.SkipBits(15);

    RCHECK(ReadBits(&reader, 1) == 1);

    if (mpeg_version == 0) {
      RCHECK(ReadBits(&reader, 1) == 1);

      reader.SkipBits(22);

      RCHECK(ReadBits(&reader, 1) == 1);

      offset += 12;
    } else {
      reader.SkipBits(22);

      RCHECK(ReadBits(&reader, 2) == 3);

      reader.SkipBits(5);

      int pack_stuffing_length = ReadBits(&reader, 3);
      offset += 14 + pack_stuffing_length;
    }

    while (offset + 6 < buffer_size && Read24(buffer + offset) == 1) {
      int stream_id = buffer[offset + 3];

      if (mpeg_version == 0)
        RCHECK(stream_id != 0xbc && stream_id < 0xf0);
      else
        RCHECK(stream_id != 0xfc && stream_id != 0xfd && stream_id != 0xfe);

      if (stream_id == PACK_START_CODE)  // back to outer loop.
        break;
      if (stream_id == PROGRAM_END_CODE)  // end of stream.
        return true;

      int pes_length = Read16(buffer + offset + 4);
      RCHECK(pes_length > 0);
      offset = offset + 6 + pes_length;
    }
  }
  return true;
}

Project: Chrome

static bool CheckMpeg2TransportStream(const uint8* buffer, int buffer_size) {
  RCHECK(buffer_size >= 250);  // Want more than 1 packet to check.

  int offset = 0;
  int packet_length = -1;
  while (buffer[offset] != kMpeg2SyncWord && offset < 20) {
    ++offset;
  }

  while (offset + 6 < buffer_size) {
    BitReader reader(buffer + offset, 6);

    RCHECK(ReadBits(&reader, 8) == kMpeg2SyncWord);

    reader.SkipBits(1 + 1 + 1);

    int pid = ReadBits(&reader, 13);
    RCHECK(pid < 3 || pid > 15);

    reader.SkipBits(2);

    int adaptation_field_control = ReadBits(&reader, 2);
    RCHECK(adaptation_field_control != 0);

    if (adaptation_field_control >= 2) {
      reader.SkipBits(4);

      int adaptation_field_length = ReadBits(&reader, 8);
      if (adaptation_field_control == 2)
        RCHECK(adaptation_field_length == 183);
      else
        RCHECK(adaptation_field_length <= 182);
    }

    if (packet_length < 0) {
      if (buffer[offset + 188] == kMpeg2SyncWord)
        packet_length = 188;
      else if (buffer[offset + 192] == kMpeg2SyncWord)
        packet_length = 192;
      else if (buffer[offset + 204] == kMpeg2SyncWord)
        packet_length = 204;
      else
        packet_length = 208;
    }
    offset += packet_length;
  }
  return true;
}

Project: Chrome

static bool CheckSrt(const uint8* buffer, int buffer_size) {
  RCHECK(buffer_size > 20);

  int offset = StartsWith(buffer, buffer_size, UTF8_BYTE_ORDER_MARK) ? 3 : 0;
  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 100));
  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, '\n', '\r'));

  while (VerifyCharacters(buffer, buffer_size, &offset, '\n', '\r')) {}
  --offset;  // Since VerifyCharacters() gobbled up the next non-CR/LF.

  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 100));
  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ':', 0));
  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 2));
  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ':', 0));
  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 2));
  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ',', '.'));
  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 3));
  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ' ', 0));
  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, '-', 0));
  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, '-', 0));
  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, '>', 0));
  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ' ', 0));
  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 100));
  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ':', 0));
  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 2));
  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ':', 0));
  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 2));
  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ',', '.'));
  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 3));
  return true;
}

Project: Chrome

static bool CheckVC1(const uint8* buffer, int buffer_size) {

  RCHECK(buffer_size >= 24);

  if (buffer[0] == 0xc5 &&
      Read32(buffer + 4) == 0x04 &&
      Read32(buffer + 20) == 0x0c) {
    BitReader reader(buffer + 8, 12);

    int profile = ReadBits(&reader, 4);
    if (profile == 0 || profile == 4) {  // simple or main
      reader.SkipBits(3 + 5 + 1);

      RCHECK(ReadBits(&reader, 1) == 0);

      reader.SkipBits(1);

      RCHECK(ReadBits(&reader, 1) == 1);

      reader.SkipBits(1 + 1 + 2 + 1);

      RCHECK(ReadBits(&reader, 1) == 0);

      reader.SkipBits(1 + 1 + 1 + 3 + 2 + 1);

      RCHECK(ReadBits(&reader, 1) == 1);

    } else {
      RCHECK(profile == 12);  // Other profile values not allowed.
      RCHECK(ReadBits(&reader, 28) == 0);
    }

    RCHECK(ReadBits(&reader, 32) <= 8192);
    RCHECK(ReadBits(&reader, 32) <= 8192);
    return true;
  }

  int offset = 0;
  int sequence_start_code = 0;
  int frame_start_code = 0;
  while (true) {
    if (!AdvanceToStartCode(buffer, buffer_size, &offset, 5, 24, 1)) {
      return (sequence_start_code > 0 && frame_start_code > 0);
    }

    BitReader reader(buffer + offset, 5);
    RCHECK(ReadBits(&reader, 24) == 1);

    switch (ReadBits(&reader, 8)) {
      case VC1_SEQUENCE_START_CODE: {
        ++sequence_start_code;
        switch (ReadBits(&reader, 2)) {
          case 0:  // simple
          case 1:  // main
            RCHECK(ReadBits(&reader, 2) == 0);
            break;
          case 2:  // complex
            return false;
          case 3:  // advanced
            RCHECK(ReadBits(&reader, 3) <= 4);  // Verify level = 0..4
            RCHECK(ReadBits(&reader, 2) == 1);  // Verify colordiff_format = 1
            break;
        }
        break;
      }

      case VC1_ENTRY_POINT_START_CODE:
        RCHECK(sequence_start_code > 0);
        break;

      case VC1_FRAME_START_CODE:
        ++frame_start_code;
        break;
    }
    offset += 5;
  }
}

Project: Chrome

static bool CheckWebm(const uint8* buffer, int buffer_size) {
  RCHECK(buffer_size > 12);

  BitReader reader(buffer, buffer_size);

  RCHECK(GetElementId(&reader) == 0x1a45dfa3);

  int header_size = GetVint(&reader);
  RCHECK(reader.bits_available() / 8 >= header_size);

  while (reader.bits_available() > 0) {
    int tag = GetElementId(&reader);
    int tagsize = GetVint(&reader);
    switch (tag) {
      case 0x4286:  // EBMLVersion
      case 0x42f7:  // EBMLReadVersion
      case 0x42f2:  // EBMLMaxIdLength
      case 0x42f3:  // EBMLMaxSizeLength
      case 0x4287:  // DocTypeVersion
      case 0x4285:  // DocTypeReadVersion
      case 0xec:    // void
      case 0xbf:    // CRC32
        RCHECK(reader.SkipBits(tagsize * 8));
        break;

      case 0x4282:  // EBMLDocType
        switch (ReadBits(&reader, 32)) {
          case TAG('w', 'e', 'b', 'm') :
            return true;
          case TAG('m', 'a', 't', 'r') :
            return (ReadBits(&reader, 32) == TAG('o', 's', 'k', 'a'));
        }
        return false;

      default:  // Unrecognized tag
        return false;
    }
  }
  return false;
}

Project: Chrome

MediaContainerName DetermineContainer(const uint8* buffer, int buffer_size) {
  DCHECK(buffer);

  if (CheckMov(buffer, buffer_size))
    return CONTAINER_MOV;

  MediaContainerName result = LookupContainerByFirst4(buffer, buffer_size);
  if (result != CONTAINER_UNKNOWN)
    return result;

  if (CheckMpeg2ProgramStream(buffer, buffer_size))
    return CONTAINER_MPEG2PS;
  if (CheckMpeg2TransportStream(buffer, buffer_size))
    return CONTAINER_MPEG2TS;
  if (CheckMJpeg(buffer, buffer_size))
    return CONTAINER_MJPEG;
  if (CheckDV(buffer, buffer_size))
    return CONTAINER_DV;
  if (CheckH261(buffer, buffer_size))
    return CONTAINER_H261;
  if (CheckH263(buffer, buffer_size))
    return CONTAINER_H263;
  if (CheckH264(buffer, buffer_size))
    return CONTAINER_H264;
  if (CheckMpeg4BitStream(buffer, buffer_size))
    return CONTAINER_MPEG4BS;
  if (CheckVC1(buffer, buffer_size))
    return CONTAINER_VC1;
  if (CheckSrt(buffer, buffer_size))
    return CONTAINER_SRT;
  if (CheckGsm(buffer, buffer_size))
    return CONTAINER_GSM;

  int offset = 1;  // No need to start at byte 0 due to First4 check.
  if (AdvanceToStartCode(buffer, buffer_size, &offset, 4, 16, kAc3SyncWord)) {
    if (CheckAc3(buffer + offset, buffer_size - offset))
      return CONTAINER_AC3;
    if (CheckEac3(buffer + offset, buffer_size - offset))
      return CONTAINER_EAC3;
  }

  return CONTAINER_UNKNOWN;
}

Project: Chrome

static int GetElementId(BitReader* reader) {
  if (reader->bits_available() >= 8) {
    int num_bits_to_read = 0;
    static int prefix[] = { 0x80, 0x4000, 0x200000, 0x10000000 };
    for (int i = 0; i < 4; ++i) {
      num_bits_to_read += 7;
      if (ReadBits(reader, 1) == 1) {
        if (reader->bits_available() < num_bits_to_read)
          break;
        return ReadBits(reader, num_bits_to_read) | prefix[i];
      }
    }
  }
  return -1;
}

Project: Chrome

static int GetMp3HeaderSize(const uint8* buffer, int buffer_size) {
  DCHECK_GE(buffer_size, 9);
  int size = ((buffer[6] & 0x7f) << 21) + ((buffer[7] & 0x7f) << 14) +
             ((buffer[8] & 0x7f) << 7) + (buffer[9] & 0x7f) + 10;
  if (buffer[5] & 0x10)  // Footer added?
    size += 10;
  return size;
}

Project: Chrome

static uint64 GetVint(BitReader* reader) {
  if (reader->bits_available() >= 8) {
    int num_bits_to_read = 0;
    for (int i = 0; i < 8; ++i) {
      num_bits_to_read += 7;
      if (ReadBits(reader, 1) == 1) {
        if (reader->bits_available() < num_bits_to_read)
          break;
        return ReadBits(reader, num_bits_to_read);
      }
    }
  }
  return (reader->bits_available() / 8) + 2;
}

Project: Chrome

static MediaContainerName LookupContainerByFirst4(const uint8* buffer,
                                                  int buffer_size) {
  if (buffer_size < 12)
    return CONTAINER_UNKNOWN;

  uint32 first4 = Read32(buffer);
  switch (first4) {
    case 0x1a45dfa3:
      if (CheckWebm(buffer, buffer_size))
        return CONTAINER_WEBM;
      break;

    case 0x3026b275:
      if (StartsWith(buffer,
                     buffer_size,
                     kAsfSignature,
                     sizeof(kAsfSignature))) {
        return CONTAINER_ASF;
      }
      break;

    case TAG('#','!','A','M'):
      if (StartsWith(buffer, buffer_size, kAmrSignature))
        return CONTAINER_AMR;
      break;

    case TAG('#','E','X','T'):
      if (CheckHls(buffer, buffer_size))
        return CONTAINER_HLS;
      break;

    case TAG('.','R','M','F'):
      if (buffer[4] == 0 && buffer[5] == 0)
        return CONTAINER_RM;
      break;

    case TAG('.','r','a','\xfd'):
      return CONTAINER_RM;

    case TAG('B','I','K','b'):
    case TAG('B','I','K','d'):
    case TAG('B','I','K','f'):
    case TAG('B','I','K','g'):
    case TAG('B','I','K','h'):
    case TAG('B','I','K','i'):
      if (CheckBink(buffer, buffer_size))
        return CONTAINER_BINK;
      break;

    case TAG('c','a','f','f'):
      if (CheckCaf(buffer, buffer_size))
        return CONTAINER_CAF;
      break;

    case TAG('D','E','X','A'):
      if (buffer_size > 15 &&
          Read16(buffer + 11) <= 2048 &&
          Read16(buffer + 13) <= 2048) {
        return CONTAINER_DXA;
      }
      break;

    case TAG('D','T','S','H'):
      if (Read32(buffer + 4) == TAG('D','H','D','R'))
        return CONTAINER_DTSHD;
      break;

    case 0x64a30100:
    case 0x64a30200:
    case 0x64a30300:
    case 0x64a30400:
    case 0x0001a364:
    case 0x0002a364:
    case 0x0003a364:
      if (Read32(buffer + 4) != 0 && Read32(buffer + 8) != 0)
        return CONTAINER_IRCAM;
      break;

    case TAG('f','L','a','C'):
      return CONTAINER_FLAC;

    case TAG('F','L','V',0):
    case TAG('F','L','V',1):
    case TAG('F','L','V',2):
    case TAG('F','L','V',3):
    case TAG('F','L','V',4):
      if (buffer[5] == 0 && Read32(buffer + 5) > 8)
        return CONTAINER_FLV;
      break;

    case TAG('F','O','R','M'):
      switch (Read32(buffer + 8)) {
        case TAG('A','I','F','F'):
        case TAG('A','I','F','C'):
          return CONTAINER_AIFF;
      }
      break;

    case TAG('M','A','C',' '):
      return CONTAINER_APE;

    case TAG('O','N','2',' '):
      if (Read32(buffer + 8) == TAG('O','N','2','f'))
        return CONTAINER_AVI;
      break;

    case TAG('O','g','g','S'):
      if (buffer[5] <= 7)
        return CONTAINER_OGG;
      break;

    case TAG('R','F','6','4'):
      if (buffer_size > 16 && Read32(buffer + 12) == TAG('d','s','6','4'))
        return CONTAINER_WAV;
      break;

    case TAG('R','I','F','F'):
      switch (Read32(buffer + 8)) {
        case TAG('A','V','I',' '):
        case TAG('A','V','I','X'):
        case TAG('A','V','I','\x19'):
        case TAG('A','M','V',' '):
          return CONTAINER_AVI;
        case TAG('W','A','V','E'):
          return CONTAINER_WAV;
      }
      break;

    case TAG('[','S','c','r'):
      if (StartsWith(buffer, buffer_size, kAssSignature))
        return CONTAINER_ASS;
      break;

    case TAG('\xef','\xbb','\xbf','['):
      if (StartsWith(buffer, buffer_size, kAssBomSignature))
        return CONTAINER_ASS;
      break;

    case 0x7ffe8001:
    case 0xfe7f0180:
    case 0x1fffe800:
    case 0xff1f00e8:
      if (CheckDts(buffer, buffer_size))
        return CONTAINER_DTS;
      break;

    case 0xb7d80020:
      if (StartsWith(buffer,
                     buffer_size,
                     kWtvSignature,
                     sizeof(kWtvSignature))) {
        return CONTAINER_WTV;
      }
      break;
  }

  uint32 first3 = first4 & 0xffffff00;
  switch (first3) {
    case TAG('C','W','S',0):
    case TAG('F','W','S',0):
      return CONTAINER_SWF;

    case TAG('I','D','3',0):
      if (CheckMp3(buffer, buffer_size, true))
        return CONTAINER_MP3;
      break;
  }

  uint32 first2 = Read16(buffer);
  switch (first2) {
    case kAc3SyncWord:
      if (CheckAc3(buffer, buffer_size))
        return CONTAINER_AC3;
      if (CheckEac3(buffer, buffer_size))
        return CONTAINER_EAC3;
      break;

    case 0xfff0:
    case 0xfff1:
    case 0xfff8:
    case 0xfff9:
      if (CheckAac(buffer, buffer_size))
        return CONTAINER_AAC;
      break;
  }

  if (CheckMp3(buffer, buffer_size, false))
    return CONTAINER_MP3;

  return CONTAINER_UNKNOWN;
}

Project: Chrome

static int Read16(const uint8* p) {
  return p[0] << 8 | p[1];
}

Project: Chrome

static uint32 Read24(const uint8* p) {
  return p[0] << 16 | p[1] << 8 | p[2];
}

Project: Chrome

static uint32 Read32(const uint8* p) {
  return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
}

Project: Chrome

static uint32 Read32LE(const uint8* p) {
  return p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
}

Project: Chrome

static uint64 ReadBits(BitReader* reader, int num_bits) {
  DCHECK_GE(reader->bits_available(), num_bits);
  DCHECK((num_bits > 0) && (num_bits <= 64));
  uint64 value;
  reader->ReadBits(num_bits, &value);
  return value;
}

Project: Chrome

static bool StartsWith(const uint8* buffer,
                       size_t buffer_size,
                       const char* prefix) {
  size_t prefix_size = strlen(prefix);
  return (prefix_size <= buffer_size &&
          memcmp(buffer, prefix, prefix_size) == 0);
}

Project: Chrome

static bool StartsWith(const uint8* buffer,
                       size_t buffer_size,
                       const uint8* prefix,
                       size_t prefix_size) {
  return (prefix_size <= buffer_size &&
          memcmp(buffer, prefix, prefix_size) == 0);
}

Project: Chrome

static bool ValidMpegAudioFrameHeader(const uint8* header,
                                      int header_size,
                                      int* framesize) {
  DCHECK_GE(header_size, 4);
  *framesize = 0;
  BitReader reader(header, 4);  // Header can only be 4 bytes long.

  RCHECK(ReadBits(&reader, 11) == 0x7ff);

  int version = ReadBits(&reader, 2);
  RCHECK(version != 1);  // Reserved.

  int layer = ReadBits(&reader, 2);
  RCHECK(layer != 0);

  reader.SkipBits(1);

  int bitrate_index = ReadBits(&reader, 4);
  RCHECK(bitrate_index != 0xf);

  int sampling_index = ReadBits(&reader, 2);
  RCHECK(sampling_index != 3);

  int padding = ReadBits(&reader, 1);

  int sampling_rate = kSampleRateTable[version][sampling_index];
  int bitrate;
  if (version == VERSION_1) {
    if (layer == LAYER_1)
      bitrate = kBitRateTableV1L1[bitrate_index];
    else if (layer == LAYER_2)
      bitrate = kBitRateTableV1L2[bitrate_index];
    else
      bitrate = kBitRateTableV1L3[bitrate_index];
  } else {
    if (layer == LAYER_1)
      bitrate = kBitRateTableV2L1[bitrate_index];
    else
      bitrate = kBitRateTableV2L23[bitrate_index];
  }
  if (layer == LAYER_1)
    *framesize = ((12000 * bitrate) / sampling_rate + padding) * 4;
  else
    *framesize = (144000 * bitrate) / sampling_rate + padding;
  return (bitrate > 0 && sampling_rate > 0);
}

Project: Chrome

static inline bool VerifyCharacters(const uint8* buffer,
                                    int buffer_size,
                                    int* offset,
                                    char c1,
                                    char c2) {
  RCHECK(*offset < buffer_size);
  char c = static_cast<char>(buffer[(*offset)++]);
  return (c == c1 || (c == c2 && c2 != 0));
}

Project: Chrome

static bool VerifyNumber(const uint8* buffer,
                         int buffer_size,
                         int* offset,
                         int max_digits) {
  RCHECK(*offset < buffer_size);

  while (isspace(buffer[*offset])) {
    ++(*offset);
    RCHECK(*offset < buffer_size);
  }

  int numSeen = 0;
  while (--max_digits >= 0 && isdigit(buffer[*offset])) {
    ++numSeen;
    ++(*offset);
    if (*offset >= buffer_size)
      return true;  // Out of space but seen a digit.
  }

  return (numSeen > 0);
}