Code: sp<VBRISeeker> VBRISeeker::CreateFromSource(
 const sp<DataSource> &source, off64_t post_id3_pos) {
 off64_t pos = post_id3_pos;

 uint8_t header[4];
 ssize_t n = source->readAt(pos, header, sizeof(header));
 if (n < (ssize_t)sizeof(header)) {
 return NULL;
 }

 uint32_t tmp = U32_AT(&header[0]);
 size_t frameSize;
 int sampleRate;
 if (!GetMPEGAudioFrameSize(tmp, &frameSize, &sampleRate)) {
 return NULL;
 }

    pos += sizeof(header) + 32;

 uint8_t vbriHeader[26];
    n = source->readAt(pos, vbriHeader, sizeof(vbriHeader));
 if (n < (ssize_t)sizeof(vbriHeader)) {
 return NULL;
 }

 if (memcmp(vbriHeader, "VBRI", 4)) {
 return NULL;
 }

 size_t numFrames = U32_AT(&vbriHeader[14]);

 int64_t durationUs =
        numFrames * 1000000ll * (sampleRate >= 32000 ? 1152 : 576) / sampleRate;

    ALOGV("duration = %.2f secs", durationUs / 1E6);

 size_t numEntries = U16_AT(&vbriHeader[18]);
 size_t entrySize = U16_AT(&vbriHeader[22]);
 size_t scale = U16_AT(&vbriHeader[20]);

    ALOGV("%zu entries, scale=%zu, size_per_entry=%zu",
         numEntries,

          scale,
          entrySize);
 
     size_t totalEntrySize = numEntries * entrySize;
    uint8_t *buffer = new uint8_t[totalEntrySize];
 
     n = source->readAt(pos + sizeof(vbriHeader), buffer, totalEntrySize);
     if (n < (ssize_t)totalEntrySize) {
 delete[] buffer;
        buffer = NULL;


         return NULL;
     }
 
    sp<VBRISeeker> seeker = new VBRISeeker;
     seeker->mBasePos = post_id3_pos + frameSize;
 if (durationUs) {
        seeker->mDurationUs = durationUs;
 }

 off64_t offset = post_id3_pos;
 for (size_t i = 0; i < numEntries; ++i) {
 uint32_t numBytes;
 switch (entrySize) {
 case 1: numBytes = buffer[i]; break;
 case 2: numBytes = U16_AT(buffer + 2 * i); break;
 case 3: numBytes = U24_AT(buffer + 3 * i); break;
 default:
 {
                CHECK_EQ(entrySize, 4u);
                numBytes = U32_AT(buffer + 4 * i); break;
 }
 }

        numBytes *= scale;

        seeker->mSegments.push(numBytes);

        ALOGV("entry #%zu: %u offset %#016llx", i, numBytes, (long long)offset);
        offset += numBytes;
 }

 delete[] buffer;
    buffer = NULL;

    ALOGI("Found VBRI header.");

 return seeker;
}

Vulnerability Type: DoS 
CWE ID: 
Summary: A denial of service vulnerability in VBRISeeker.cpp in libstagefright in Mediaserver could enable a remote attacker to use a specially crafted file to cause a device hang or reboot. This issue is rated as High due to the possibility of remote denial of service. Product: Android. Versions: 4.4.4, 5.0.2, 5.1.1, 6.0, 6.0.1, 7.0, 7.1. Android ID: A-32577290.
Commit Message: Make VBRISeeker more robust

Bug: 32577290
Change-Id: I9bcc9422ae7dd3ae4a38df330c9dcd7ac4941ec8
(cherry picked from commit 7fdd36418e945cf6a500018632dfb0ed8cb1a343)
