void ServiceWorkerContainer::registerServiceWorkerImpl(ExecutionContext* executionContext, const KURL& rawScriptURL, const KURL& scope, PassOwnPtr<RegistrationCallbacks> callbacks)
{
    if (!m_provider) {
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeState, "Failed to register a ServiceWorker: The document is in an invalid state."));
        return;
    }

    RefPtr<SecurityOrigin> documentOrigin = executionContext->getSecurityOrigin();
    String errorMessage;
    if (!executionContext->isSecureContext(errorMessage)) {
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, errorMessage));
        return;
    }

    KURL pageURL = KURL(KURL(), documentOrigin->toString());
    if (!SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(pageURL.protocol())) {
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The URL protocol of the current origin ('" + documentOrigin->toString() + "') is not supported.")));
        return;
    }

    KURL scriptURL = rawScriptURL;
    scriptURL.removeFragmentIdentifier();
    if (!documentOrigin->canRequest(scriptURL)) {
        RefPtr<SecurityOrigin> scriptOrigin = SecurityOrigin::create(scriptURL);
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The origin of the provided scriptURL ('" + scriptOrigin->toString() + "') does not match the current origin ('" + documentOrigin->toString() + "').")));
        return;
    }
    if (!SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(scriptURL.protocol())) {
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The URL protocol of the script ('" + scriptURL.getString() + "') is not supported.")));
        return;
    }

    KURL patternURL = scope;
    patternURL.removeFragmentIdentifier();

    if (!documentOrigin->canRequest(patternURL)) {
        RefPtr<SecurityOrigin> patternOrigin = SecurityOrigin::create(patternURL);
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The origin of the provided scope ('" + patternOrigin->toString() + "') does not match the current origin ('" + documentOrigin->toString() + "').")));
        return;
    }
    if (!SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(patternURL.protocol())) {
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The URL protocol of the scope ('" + patternURL.getString() + "') is not supported.")));
        return;
    }

    WebString webErrorMessage;
    if (!m_provider->validateScopeAndScriptURL(patternURL, scriptURL, &webErrorMessage)) {
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeType, WebString::fromUTF8("Failed to register a ServiceWorker: " + webErrorMessage.utf8())));
         return;
     }

     m_provider->registerServiceWorker(patternURL, scriptURL, callbacks.leakPtr());
 }

The ServiceWorkerContainer::registerServiceWorkerImpl function in WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp in Blink, as used in Google Chrome before 51.0.2704.63, allows remote attackers to bypass the Content Security Policy (CSP) protection mechanism via a ServiceWorker registration.


void ServiceWorkerContainer::registerServiceWorkerImpl(ExecutionContext* executionContext, const KURL& rawScriptURL, const KURL& scope, PassOwnPtr<RegistrationCallbacks> callbacks)
{
    if (!m_provider) {
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeState, "Failed to register a ServiceWorker: The document is in an invalid state."));
        return;
    }

    RefPtr<SecurityOrigin> documentOrigin = executionContext->getSecurityOrigin();
    String errorMessage;
    if (!executionContext->isSecureContext(errorMessage)) {
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, errorMessage));
        return;
    }

    KURL pageURL = KURL(KURL(), documentOrigin->toString());
    if (!SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(pageURL.protocol())) {
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The URL protocol of the current origin ('" + documentOrigin->toString() + "') is not supported.")));
        return;
    }

    KURL scriptURL = rawScriptURL;
    scriptURL.removeFragmentIdentifier();
    if (!documentOrigin->canRequest(scriptURL)) {
        RefPtr<SecurityOrigin> scriptOrigin = SecurityOrigin::create(scriptURL);
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The origin of the provided scriptURL ('" + scriptOrigin->toString() + "') does not match the current origin ('" + documentOrigin->toString() + "').")));
        return;
    }
    if (!SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(scriptURL.protocol())) {
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The URL protocol of the script ('" + scriptURL.getString() + "') is not supported.")));
        return;
    }

    KURL patternURL = scope;
    patternURL.removeFragmentIdentifier();

    if (!documentOrigin->canRequest(patternURL)) {
        RefPtr<SecurityOrigin> patternOrigin = SecurityOrigin::create(patternURL);
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The origin of the provided scope ('" + patternOrigin->toString() + "') does not match the current origin ('" + documentOrigin->toString() + "').")));
        return;
    }
    if (!SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers(patternURL.protocol())) {
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The URL protocol of the scope ('" + patternURL.getString() + "') is not supported.")));
        return;
    }

    WebString webErrorMessage;
    if (!m_provider->validateScopeAndScriptURL(patternURL, scriptURL, &webErrorMessage)) {
        callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeType, WebString::fromUTF8("Failed to register a ServiceWorker: " + webErrorMessage.utf8())));
         return;
     }

    ContentSecurityPolicy* csp = executionContext->contentSecurityPolicy();
    if (csp) {
        if (!csp->allowWorkerContextFromSource(scriptURL, ContentSecurityPolicy::DidNotRedirect, ContentSecurityPolicy::SendReport)) {
            callbacks->onError(WebServiceWorkerError(WebServiceWorkerError::ErrorTypeSecurity, String("Failed to register a ServiceWorker: The provided scriptURL ('" + scriptURL.getString() + "') violates the Content Security Policy.")));
            return;
        }
    }

     m_provider->registerServiceWorker(patternURL, scriptURL, callbacks.leakPtr());
 }


void InputConnectionImpl::CommitText(const base::string16& text,
                                     int new_cursor_pos) {
  StartStateUpdateTimer();

  std::string error;
  if (!ime_engine_->ClearComposition(input_context_id_, &error))
    LOG(ERROR) << "ClearComposition failed: error=\"" << error << "\"";

  if (IsControlChar(text)) {
    SendControlKeyEvent(text);
    return;
  }

   if (!ime_engine_->CommitText(input_context_id_,
                                base::UTF16ToUTF8(text).c_str(), &error))
     LOG(ERROR) << "CommitText failed: error=\"" << error << "\"";
 }

The CPDF_DIBSource::CreateDecoder function in core/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp in PDFium, as used in Google Chrome before 51.0.2704.63, mishandles decoder-initialization failure, which allows remote attackers to cause a denial of service (out-of-bounds read) via a crafted PDF document.


void InputConnectionImpl::CommitText(const base::string16& text,
                                     int new_cursor_pos) {
  StartStateUpdateTimer();

  std::string error;
  if (!ime_engine_->ClearComposition(input_context_id_, &error))
    LOG(ERROR) << "ClearComposition failed: error=\"" << error << "\"";

  if (IsControlChar(text)) {
    SendControlKeyEvent(text);
    return;
  }

   if (!ime_engine_->CommitText(input_context_id_,
                                base::UTF16ToUTF8(text).c_str(), &error))
     LOG(ERROR) << "CommitText failed: error=\"" << error << "\"";
  composing_text_.clear();
 }


status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len)
{
 const sp<ProcessState> proc(ProcessState::self());
 status_t err;
 const uint8_t *data = parcel->mData;
 const binder_size_t *objects = parcel->mObjects;
 size_t size = parcel->mObjectsSize;
 int startPos = mDataPos;
 int firstIndex = -1, lastIndex = -2;

 if (len == 0) {
 return NO_ERROR;
 }

 if ((offset > parcel->mDataSize)
 || (len > parcel->mDataSize)
 || (offset + len > parcel->mDataSize)) {
 return BAD_VALUE;
 }

     for (int i = 0; i < (int) size; i++) {
         size_t off = objects[i];
        if ((off >= offset) && (off < offset + len)) {
             if (firstIndex == -1) {
                 firstIndex = i;
             }
            lastIndex = i;
 }
 }
 int numObjects = lastIndex - firstIndex + 1;

 if ((mDataSize+len) > mDataCapacity) {
        err = growData(len);
 if (err != NO_ERROR) {
 return err;
 }
 }

    memcpy(mData + mDataPos, data + offset, len);
    mDataPos += len;
    mDataSize += len;

    err = NO_ERROR;

 if (numObjects > 0) {
 if (mObjectsCapacity < mObjectsSize + numObjects) {
 int newSize = ((mObjectsSize + numObjects)*3)/2;
 binder_size_t *objects =
 (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
 if (objects == (binder_size_t*)0) {
 return NO_MEMORY;
 }
            mObjects = objects;
            mObjectsCapacity = newSize;
 }

 int idx = mObjectsSize;
 for (int i = firstIndex; i <= lastIndex; i++) {
 size_t off = objects[i] - offset + startPos;
            mObjects[idx++] = off;
            mObjectsSize++;

            flat_binder_object* flat
 = reinterpret_cast<flat_binder_object*>(mData + off);
            acquire_object(proc, *flat, this);

 if (flat->type == BINDER_TYPE_FD) {
                flat->handle = dup(flat->handle);
                flat->cookie = 1;
                mHasFds = mFdsKnown = true;
 if (!mAllowFds) {
                    err = FDS_NOT_ALLOWED;
 }
 }
 }
 }

 return err;
}

The Parcel::appendFrom function in libs/binder/Parcel.cpp in Binder in Android before 5.1.1 LMY48M does not consider parcel boundaries during identification of binder objects in an append operation, which allows attackers to obtain a different application's privileges via a crafted application, aka internal bug 17312693.


status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len)
{
 const sp<ProcessState> proc(ProcessState::self());
 status_t err;
 const uint8_t *data = parcel->mData;
 const binder_size_t *objects = parcel->mObjects;
 size_t size = parcel->mObjectsSize;
 int startPos = mDataPos;
 int firstIndex = -1, lastIndex = -2;

 if (len == 0) {
 return NO_ERROR;
 }

 if ((offset > parcel->mDataSize)
 || (len > parcel->mDataSize)
 || (offset + len > parcel->mDataSize)) {
 return BAD_VALUE;
 }

     for (int i = 0; i < (int) size; i++) {
         size_t off = objects[i];
        if ((off >= offset) && (off + sizeof(flat_binder_object) <= offset + len)) {
             if (firstIndex == -1) {
                 firstIndex = i;
             }
            lastIndex = i;
 }
 }
 int numObjects = lastIndex - firstIndex + 1;

 if ((mDataSize+len) > mDataCapacity) {
        err = growData(len);
 if (err != NO_ERROR) {
 return err;
 }
 }

    memcpy(mData + mDataPos, data + offset, len);
    mDataPos += len;
    mDataSize += len;

    err = NO_ERROR;

 if (numObjects > 0) {
 if (mObjectsCapacity < mObjectsSize + numObjects) {
 int newSize = ((mObjectsSize + numObjects)*3)/2;
 binder_size_t *objects =
 (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
 if (objects == (binder_size_t*)0) {
 return NO_MEMORY;
 }
            mObjects = objects;
            mObjectsCapacity = newSize;
 }

 int idx = mObjectsSize;
 for (int i = firstIndex; i <= lastIndex; i++) {
 size_t off = objects[i] - offset + startPos;
            mObjects[idx++] = off;
            mObjectsSize++;

            flat_binder_object* flat
 = reinterpret_cast<flat_binder_object*>(mData + off);
            acquire_object(proc, *flat, this);

 if (flat->type == BINDER_TYPE_FD) {
                flat->handle = dup(flat->handle);
                flat->cookie = 1;
                mHasFds = mFdsKnown = true;
 if (!mAllowFds) {
                    err = FDS_NOT_ALLOWED;
 }
 }
 }
 }

 return err;
}


static EAS_RESULT Parse_wave (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U16 waveIndex)
{
    EAS_RESULT result;
    EAS_U32 temp;
    EAS_I32 size;
    EAS_I32 endChunk;
    EAS_I32 chunkPos;
    EAS_I32 wsmpPos = 0;
    EAS_I32 fmtPos = 0;
    EAS_I32 dataPos = 0;
    EAS_I32 dataSize = 0;
    S_WSMP_DATA *p;
 void *pSample;
    S_WSMP_DATA wsmp;

 /* seek to start of chunk */
    chunkPos = pos + 12;
 if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
 return result;

 /* get the chunk type */
 if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
 return result;

 /* make sure it is a wave chunk */
 if (temp != CHUNK_WAVE)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Offset in ptbl does not point to wave chunk\n"); */ }
 return EAS_ERROR_FILE_FORMAT;
 }

 /* read to end of chunk */
    pos = chunkPos;
    endChunk = pos + size;
 while (pos < endChunk)
 {
        chunkPos = pos;

 /* get the chunk type */
 if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
 return result;

 /* parse useful chunks */
 switch (temp)
 {
 case CHUNK_WSMP:
                wsmpPos = chunkPos + 8;
 break;

 case CHUNK_FMT:
                fmtPos = chunkPos + 8;
 break;

 case CHUNK_DATA:
                dataPos = chunkPos + 8;
                dataSize = size;
 break;

 default:
 break;
 }

     }

    if (dataSize > MAX_DLS_WAVE_SIZE)
     {
         return EAS_ERROR_SOUND_LIBRARY;
     }

 /* for first pass, use temporary variable */
 if (pDLSData->pDLS == NULL)
        p = &wsmp;
 else
        p = &pDLSData->wsmpData[waveIndex];

 /* set the defaults */
    p->fineTune = 0;
    p->unityNote = 60;
    p->gain = 0;
    p->loopStart = 0;
    p->loopLength = 0;

 /* must have a fmt chunk */
 if (!fmtPos)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS wave chunk has no fmt chunk\n"); */ }
 return EAS_ERROR_UNRECOGNIZED_FORMAT;
 }

 /* must have a data chunk */
 if (!dataPos)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS wave chunk has no data chunk\n"); */ }
 return EAS_ERROR_UNRECOGNIZED_FORMAT;
 }

 /* parse the wsmp chunk */
 if (wsmpPos)
 {
 if ((result = Parse_wsmp(pDLSData, wsmpPos, p)) != EAS_SUCCESS)
 return result;
 }

 /* parse the fmt chunk */
 if ((result = Parse_fmt(pDLSData, fmtPos, p)) != EAS_SUCCESS)
 return result;

 /* calculate the size of the wavetable needed. We need only half
     * the memory for 16-bit samples when in 8-bit mode, and we need
     * double the memory for 8-bit samples in 16-bit mode. For
     * unlooped samples, we may use ADPCM. If so, we need only 1/4
     * the memory.
     *
     * We also need to add one for looped samples to allow for
     * the first sample to be copied to the end of the loop.
     */

 /* use ADPCM encode for unlooped 16-bit samples if ADPCM is enabled */
 /*lint -e{506} -e{774} groundwork for future version to support 8 & 16 bit */
 if (bitDepth == 8)
 {
 if (p->bitsPerSample == 8)
            size = dataSize;
 else
 /*lint -e{704} use shift for performance */
            size = dataSize >> 1;
 if (p->loopLength)
            size++;
 }

 else
 {
 if (p->bitsPerSample == 16)
            size = dataSize;
 else
 /*lint -e{703} use shift for performance */
            size = dataSize << 1;
 if (p->loopLength)
            size += 2;
 }

 /* for first pass, add size to wave pool size and return */
 if (pDLSData->pDLS == NULL)
 {
        pDLSData->wavePoolSize += (EAS_U32) size;
 return EAS_SUCCESS;
 }

 /* allocate memory and read in the sample data */
    pSample = pDLSData->pDLS->pDLSSamples + pDLSData->wavePoolOffset;
    pDLSData->pDLS->pDLSSampleOffsets[waveIndex] = pDLSData->wavePoolOffset;
    pDLSData->pDLS->pDLSSampleLen[waveIndex] = (EAS_U32) size;
    pDLSData->wavePoolOffset += (EAS_U32) size;
 if (pDLSData->wavePoolOffset > pDLSData->wavePoolSize)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Wave pool exceeded allocation\n"); */ }
 return EAS_ERROR_SOUND_LIBRARY;
 }

 if ((result = Parse_data(pDLSData, dataPos, dataSize, p, pSample)) != EAS_SUCCESS)
 return result;

 return EAS_SUCCESS;
}

The Parse_wave function in arm-wt-22k/lib_src/eas_mdls.c in the Sonivox DLS-to-EAS converter in Android before 5.1.1 LMY48I does not reject a negative value for a certain size field, which allows remote attackers to execute arbitrary code or cause a denial of service (buffer overflow) via crafted XMF data, aka internal bug 21132860.


static EAS_RESULT Parse_wave (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U16 waveIndex)
{
    EAS_RESULT result;
    EAS_U32 temp;
    EAS_I32 size;
    EAS_I32 endChunk;
    EAS_I32 chunkPos;
    EAS_I32 wsmpPos = 0;
    EAS_I32 fmtPos = 0;
    EAS_I32 dataPos = 0;
    EAS_I32 dataSize = 0;
    S_WSMP_DATA *p;
 void *pSample;
    S_WSMP_DATA wsmp;

 /* seek to start of chunk */
    chunkPos = pos + 12;
 if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
 return result;

 /* get the chunk type */
 if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
 return result;

 /* make sure it is a wave chunk */
 if (temp != CHUNK_WAVE)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Offset in ptbl does not point to wave chunk\n"); */ }
 return EAS_ERROR_FILE_FORMAT;
 }

 /* read to end of chunk */
    pos = chunkPos;
    endChunk = pos + size;
 while (pos < endChunk)
 {
        chunkPos = pos;

 /* get the chunk type */
 if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
 return result;

 /* parse useful chunks */
 switch (temp)
 {
 case CHUNK_WSMP:
                wsmpPos = chunkPos + 8;
 break;

 case CHUNK_FMT:
                fmtPos = chunkPos + 8;
 break;

 case CHUNK_DATA:
                dataPos = chunkPos + 8;
                dataSize = size;
 break;

 default:
 break;
 }

     }

    if (dataSize < 0 || dataSize > MAX_DLS_WAVE_SIZE)
     {
         return EAS_ERROR_SOUND_LIBRARY;
     }

 /* for first pass, use temporary variable */
 if (pDLSData->pDLS == NULL)
        p = &wsmp;
 else
        p = &pDLSData->wsmpData[waveIndex];

 /* set the defaults */
    p->fineTune = 0;
    p->unityNote = 60;
    p->gain = 0;
    p->loopStart = 0;
    p->loopLength = 0;

 /* must have a fmt chunk */
 if (!fmtPos)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS wave chunk has no fmt chunk\n"); */ }
 return EAS_ERROR_UNRECOGNIZED_FORMAT;
 }

 /* must have a data chunk */
 if (!dataPos)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS wave chunk has no data chunk\n"); */ }
 return EAS_ERROR_UNRECOGNIZED_FORMAT;
 }

 /* parse the wsmp chunk */
 if (wsmpPos)
 {
 if ((result = Parse_wsmp(pDLSData, wsmpPos, p)) != EAS_SUCCESS)
 return result;
 }

 /* parse the fmt chunk */
 if ((result = Parse_fmt(pDLSData, fmtPos, p)) != EAS_SUCCESS)
 return result;

 /* calculate the size of the wavetable needed. We need only half
     * the memory for 16-bit samples when in 8-bit mode, and we need
     * double the memory for 8-bit samples in 16-bit mode. For
     * unlooped samples, we may use ADPCM. If so, we need only 1/4
     * the memory.
     *
     * We also need to add one for looped samples to allow for
     * the first sample to be copied to the end of the loop.
     */

 /* use ADPCM encode for unlooped 16-bit samples if ADPCM is enabled */
 /*lint -e{506} -e{774} groundwork for future version to support 8 & 16 bit */
 if (bitDepth == 8)
 {
 if (p->bitsPerSample == 8)
            size = dataSize;
 else
 /*lint -e{704} use shift for performance */
            size = dataSize >> 1;
 if (p->loopLength)
            size++;
 }

 else
 {
 if (p->bitsPerSample == 16)
            size = dataSize;
 else
 /*lint -e{703} use shift for performance */
            size = dataSize << 1;
 if (p->loopLength)
            size += 2;
 }

 /* for first pass, add size to wave pool size and return */
 if (pDLSData->pDLS == NULL)
 {
        pDLSData->wavePoolSize += (EAS_U32) size;
 return EAS_SUCCESS;
 }

 /* allocate memory and read in the sample data */
    pSample = pDLSData->pDLS->pDLSSamples + pDLSData->wavePoolOffset;
    pDLSData->pDLS->pDLSSampleOffsets[waveIndex] = pDLSData->wavePoolOffset;
    pDLSData->pDLS->pDLSSampleLen[waveIndex] = (EAS_U32) size;
    pDLSData->wavePoolOffset += (EAS_U32) size;
 if (pDLSData->wavePoolOffset > pDLSData->wavePoolSize)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Wave pool exceeded allocation\n"); */ }
 return EAS_ERROR_SOUND_LIBRARY;
 }

 if ((result = Parse_data(pDLSData, dataPos, dataSize, p, pSample)) != EAS_SUCCESS)
 return result;

 return EAS_SUCCESS;
}


status_t BnHDCP::onTransact(
 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
 switch (code) {
 case HDCP_SET_OBSERVER:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            sp<IHDCPObserver> observer =
                interface_cast<IHDCPObserver>(data.readStrongBinder());

            reply->writeInt32(setObserver(observer));
 return OK;
 }

 case HDCP_INIT_ASYNC:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

 const char *host = data.readCString();
 unsigned port = data.readInt32();

            reply->writeInt32(initAsync(host, port));
 return OK;
 }

 case HDCP_SHUTDOWN_ASYNC:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            reply->writeInt32(shutdownAsync());
 return OK;
 }

 case HDCP_GET_CAPS:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            reply->writeInt32(getCaps());
 return OK;
 }

         case HDCP_ENCRYPT:
         {
             size_t size = data.readInt32();

            void *inData = malloc(2 * size);
             void *outData = (uint8_t *)inData + size;

             data.read(inData, size);

 uint32_t streamCTR = data.readInt32();
 uint64_t inputCTR;
 status_t err = encrypt(inData, size, streamCTR, &inputCTR, outData);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt64(inputCTR);
                reply->write(outData, size);
 }

            free(inData);
            inData = outData = NULL;

 return OK;
 }

 case HDCP_ENCRYPT_NATIVE:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);
 size_t offset = data.readInt32();
 size_t size = data.readInt32();
 uint32_t streamCTR = data.readInt32();
 void *outData = malloc(size);
 uint64_t inputCTR;

 status_t err = encryptNative(graphicBuffer, offset, size,
                                         streamCTR, &inputCTR, outData);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt64(inputCTR);
                reply->write(outData, size);
 }

            free(outData);
            outData = NULL;

 return OK;
 }

         case HDCP_DECRYPT:
         {
             size_t size = data.readInt32();

            void *inData = malloc(2 * size);
             void *outData = (uint8_t *)inData + size;

             data.read(inData, size);

 uint32_t streamCTR = data.readInt32();
 uint64_t inputCTR = data.readInt64();
 status_t err = decrypt(inData, size, streamCTR, inputCTR, outData);

            reply->writeInt32(err);

 if (err == OK) {
                reply->write(outData, size);
 }

            free(inData);
            inData = outData = NULL;

 return OK;
 }

 default:
 return BBinder::onTransact(code, data, reply, flags);
 }
}

Multiple integer overflows in the BnHDCP::onTransact function in media/libmedia/IHDCP.cpp in libstagefright in Android before 5.1.1 LMY48I allow attackers to execute arbitrary code via a crafted application that uses HDCP encryption, leading to a heap-based buffer overflow, aka internal bug 20222489.


status_t BnHDCP::onTransact(
 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
 switch (code) {
 case HDCP_SET_OBSERVER:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            sp<IHDCPObserver> observer =
                interface_cast<IHDCPObserver>(data.readStrongBinder());

            reply->writeInt32(setObserver(observer));
 return OK;
 }

 case HDCP_INIT_ASYNC:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

 const char *host = data.readCString();
 unsigned port = data.readInt32();

            reply->writeInt32(initAsync(host, port));
 return OK;
 }

 case HDCP_SHUTDOWN_ASYNC:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            reply->writeInt32(shutdownAsync());
 return OK;
 }

 case HDCP_GET_CAPS:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            reply->writeInt32(getCaps());
 return OK;
 }

         case HDCP_ENCRYPT:
         {
             size_t size = data.readInt32();
            size_t bufSize = 2 * size;

            // watch out for overflow
            void *inData = NULL;
            if (bufSize > size) {
                inData = malloc(bufSize);
            }

            if (inData == NULL) {
                reply->writeInt32(ERROR_OUT_OF_RANGE);
                return OK;
            }

             void *outData = (uint8_t *)inData + size;

             data.read(inData, size);

 uint32_t streamCTR = data.readInt32();
 uint64_t inputCTR;
 status_t err = encrypt(inData, size, streamCTR, &inputCTR, outData);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt64(inputCTR);
                reply->write(outData, size);
 }

            free(inData);
            inData = outData = NULL;

 return OK;
 }

 case HDCP_ENCRYPT_NATIVE:
 {
            CHECK_INTERFACE(IHDCP, data, reply);

            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);
 size_t offset = data.readInt32();
 size_t size = data.readInt32();
 uint32_t streamCTR = data.readInt32();
 void *outData = malloc(size);
 uint64_t inputCTR;

 status_t err = encryptNative(graphicBuffer, offset, size,
                                         streamCTR, &inputCTR, outData);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt64(inputCTR);
                reply->write(outData, size);
 }

            free(outData);
            outData = NULL;

 return OK;
 }

         case HDCP_DECRYPT:
         {
             size_t size = data.readInt32();
            size_t bufSize = 2 * size;

            // watch out for overflow
            void *inData = NULL;
            if (bufSize > size) {
                inData = malloc(bufSize);
            }

            if (inData == NULL) {
                reply->writeInt32(ERROR_OUT_OF_RANGE);
                return OK;
            }

             void *outData = (uint8_t *)inData + size;

             data.read(inData, size);

 uint32_t streamCTR = data.readInt32();
 uint64_t inputCTR = data.readInt64();
 status_t err = decrypt(inData, size, streamCTR, inputCTR, outData);

            reply->writeInt32(err);

 if (err == OK) {
                reply->write(outData, size);
 }

            free(inData);
            inData = outData = NULL;

 return OK;
 }

 default:
 return BBinder::onTransact(code, data, reply, flags);
 }
}


 virtual ssize_t readAt(off64_t offset, void *buffer, size_t size) {
 Parcel data, reply;
        data.writeInterfaceToken(
 IMediaHTTPConnection::getInterfaceDescriptor());

        data.writeInt64(offset);
        data.writeInt32(size);

 status_t err = remote()->transact(READ_AT, data, &reply);
 if (err != OK) {
            ALOGE("remote readAt failed");
 return UNKNOWN_ERROR;
 }

 int32_t exceptionCode = reply.readExceptionCode();

 if (exceptionCode) {

             return UNKNOWN_ERROR;
         }

        int32_t len = reply.readInt32();

        if (len > 0) {
            memcpy(buffer, mMemory->pointer(), len);
         }

         return len;
     }

Buffer overflow in the readAt function in BpMediaHTTPConnection in media/libmedia/IMediaHTTPConnection.cpp in the mediaserver service in Android before 5.1.1 LMY48I allows attackers to execute arbitrary code via a crafted application, aka internal bug 19400722.


 virtual ssize_t readAt(off64_t offset, void *buffer, size_t size) {
 Parcel data, reply;
        data.writeInterfaceToken(
 IMediaHTTPConnection::getInterfaceDescriptor());

        data.writeInt64(offset);
        data.writeInt32(size);

 status_t err = remote()->transact(READ_AT, data, &reply);
 if (err != OK) {
            ALOGE("remote readAt failed");
 return UNKNOWN_ERROR;
 }

 int32_t exceptionCode = reply.readExceptionCode();

 if (exceptionCode) {

             return UNKNOWN_ERROR;
         }

        size_t len = reply.readInt32();

        if (len > size) {
            ALOGE("requested %zu, got %zu", size, len);
            return ERROR_OUT_OF_RANGE;
         }
        if (len > mMemory->size()) {
            ALOGE("got %zu, but memory has %zu", len, mMemory->size());
            return ERROR_OUT_OF_RANGE;
        }

        memcpy(buffer, mMemory->pointer(), len);

         return len;
     }


status_t ESDS::parseESDescriptor(size_t offset, size_t size) {
 if (size < 3) {
 return ERROR_MALFORMED;
 }

    offset += 2; // skip ES_ID
    size -= 2;

 unsigned streamDependenceFlag = mData[offset] & 0x80;
 unsigned URL_Flag = mData[offset] & 0x40;
 unsigned OCRstreamFlag = mData[offset] & 0x20;

 ++offset;

     --size;

     if (streamDependenceFlag) {
         offset += 2;
         size -= 2;
     }

 if (URL_Flag) {
 if (offset >= size) {

             return ERROR_MALFORMED;
         }
         unsigned URLlength = mData[offset];
         offset += URLlength + 1;
         size -= URLlength + 1;
     }

     if (OCRstreamFlag) {
         offset += 2;
         size -= 2;

 if ((offset >= size || mData[offset] != kTag_DecoderConfigDescriptor)
 && offset - 2 < size
 && mData[offset - 2] == kTag_DecoderConfigDescriptor) {
            offset -= 2;
            size += 2;

            ALOGW("Found malformed 'esds' atom, ignoring missing OCR_ES_Id.");
 }
 }

 if (offset >= size) {
 return ERROR_MALFORMED;
 }

 uint8_t tag;
 size_t sub_offset, sub_size;
 status_t err = skipDescriptorHeader(
            offset, size, &tag, &sub_offset, &sub_size);

 if (err != OK) {
 return err;
 }

 if (tag != kTag_DecoderConfigDescriptor) {
 return ERROR_MALFORMED;
 }

    err = parseDecoderConfigDescriptor(sub_offset, sub_size);

 return err;
}

Multiple integer underflows in the ESDS::parseESDescriptor function in ESDS.cpp in libstagefright in Android before 5.1.1 LMY48I allow remote attackers to execute arbitrary code via crafted ESDS atoms, aka internal bug 20139950, a related issue to CVE-2015-4493.


status_t ESDS::parseESDescriptor(size_t offset, size_t size) {
 if (size < 3) {
 return ERROR_MALFORMED;
 }

    offset += 2; // skip ES_ID
    size -= 2;

 unsigned streamDependenceFlag = mData[offset] & 0x80;
 unsigned URL_Flag = mData[offset] & 0x40;
 unsigned OCRstreamFlag = mData[offset] & 0x20;

 ++offset;

     --size;

     if (streamDependenceFlag) {
        if (size < 2)
            return ERROR_MALFORMED;
         offset += 2;
         size -= 2;
     }

 if (URL_Flag) {
 if (offset >= size) {

             return ERROR_MALFORMED;
         }
         unsigned URLlength = mData[offset];
        if (URLlength >= size)
            return ERROR_MALFORMED;
         offset += URLlength + 1;
         size -= URLlength + 1;
     }

     if (OCRstreamFlag) {
        if (size < 2)
            return ERROR_MALFORMED;
         offset += 2;
         size -= 2;

 if ((offset >= size || mData[offset] != kTag_DecoderConfigDescriptor)
 && offset - 2 < size
 && mData[offset - 2] == kTag_DecoderConfigDescriptor) {
            offset -= 2;
            size += 2;

            ALOGW("Found malformed 'esds' atom, ignoring missing OCR_ES_Id.");
 }
 }

 if (offset >= size) {
 return ERROR_MALFORMED;
 }

 uint8_t tag;
 size_t sub_offset, sub_size;
 status_t err = skipDescriptorHeader(
            offset, size, &tag, &sub_offset, &sub_size);

 if (err != OK) {
 return err;
 }

 if (tag != kTag_DecoderConfigDescriptor) {
 return ERROR_MALFORMED;
 }

    err = parseDecoderConfigDescriptor(sub_offset, sub_size);

 return err;
}


static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
 if (parcel == NULL) {
 SkDebugf("-------- unparcel parcel is NULL\n");
 return NULL;
 }

    android::Parcel* p = android::parcelForJavaObject(env, parcel);

 const bool        isMutable = p->readInt32() != 0;
 const SkColorType colorType = (SkColorType)p->readInt32();
 const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
 const int         width = p->readInt32();
 const int         height = p->readInt32();
 const int         rowBytes = p->readInt32();
 const int         density = p->readInt32();

 if (kN32_SkColorType != colorType &&
            kRGB_565_SkColorType != colorType &&
            kARGB_4444_SkColorType != colorType &&
            kIndex_8_SkColorType != colorType &&
            kAlpha_8_SkColorType != colorType) {
 SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);

         return NULL;
     }

    SkBitmap* bitmap = new SkBitmap;

    bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType), rowBytes);

     SkColorTable* ctable = NULL;
     if (colorType == kIndex_8_SkColorType) {
         int count = p->readInt32();
         if (count > 0) {
             size_t size = count * sizeof(SkPMColor);
             const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
             ctable = new SkColorTable(src, count);
         }
     }

    jbyteArray buffer = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable);
     if (NULL == buffer) {
         SkSafeUnref(ctable);
        delete bitmap;
         return NULL;
     }

 SkSafeUnref(ctable);

 size_t size = bitmap->getSize();

    android::Parcel::ReadableBlob blob;

     android::status_t status = p->readBlob(size, &blob);
     if (status) {
         doThrowRE(env, "Could not read bitmap from parcel blob.");
        delete bitmap;
         return NULL;
     }

    bitmap->lockPixels();
    memcpy(bitmap->getPixels(), blob.data(), size);
    bitmap->unlockPixels();

     blob.release();

    return GraphicsJNI::createBitmap(env, bitmap, buffer, getPremulBitmapCreateFlags(isMutable),
            NULL, NULL, density);
 }

Integer overflow in the Bitmap_createFromParcel function in core/jni/android/graphics/Bitmap.cpp in Android before 5.1.1 LMY48I allows attackers to cause a denial of service (system_server crash) or obtain sensitive system_server memory-content information via a crafted application that leverages improper unmarshalling of bitmaps, aka internal bug 19666945.


static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
 if (parcel == NULL) {
 SkDebugf("-------- unparcel parcel is NULL\n");
 return NULL;
 }

    android::Parcel* p = android::parcelForJavaObject(env, parcel);

 const bool        isMutable = p->readInt32() != 0;
 const SkColorType colorType = (SkColorType)p->readInt32();
 const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
 const int         width = p->readInt32();
 const int         height = p->readInt32();
 const int         rowBytes = p->readInt32();
 const int         density = p->readInt32();

 if (kN32_SkColorType != colorType &&
            kRGB_565_SkColorType != colorType &&
            kARGB_4444_SkColorType != colorType &&
            kIndex_8_SkColorType != colorType &&
            kAlpha_8_SkColorType != colorType) {
 SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);

         return NULL;
     }

    SkAutoTDelete<SkBitmap> bitmap(new SkBitmap);

    if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType), rowBytes)) {
        return NULL;
    }

     SkColorTable* ctable = NULL;
     if (colorType == kIndex_8_SkColorType) {
         int count = p->readInt32();
        if (count < 0 || count > 256) {
            // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
            // inclusive.
            return NULL;
        }
         if (count > 0) {
             size_t size = count * sizeof(SkPMColor);
             const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
            if (src == NULL) {
                return NULL;
            }
             ctable = new SkColorTable(src, count);
         }
     }

    jbyteArray buffer = GraphicsJNI::allocateJavaPixelRef(env, bitmap.get(), ctable);
     if (NULL == buffer) {
         SkSafeUnref(ctable);
         return NULL;
     }

 SkSafeUnref(ctable);

 size_t size = bitmap->getSize();

    android::Parcel::ReadableBlob blob;

     android::status_t status = p->readBlob(size, &blob);
     if (status) {
         doThrowRE(env, "Could not read bitmap from parcel blob.");
         return NULL;
     }

    bitmap->lockPixels();
    memcpy(bitmap->getPixels(), blob.data(), size);
    bitmap->unlockPixels();

     blob.release();

    return GraphicsJNI::createBitmap(env, bitmap.detach(), buffer,
            getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
 }


status_t SampleIterator::seekTo(uint32_t sampleIndex) {
    ALOGV("seekTo(%d)", sampleIndex);

 if (sampleIndex >= mTable->mNumSampleSizes) {
 return ERROR_END_OF_STREAM;
 }

 if (mTable->mSampleToChunkOffset < 0
 || mTable->mChunkOffsetOffset < 0
 || mTable->mSampleSizeOffset < 0
 || mTable->mTimeToSampleCount == 0) {

 return ERROR_MALFORMED;
 }

 if (mInitialized && mCurrentSampleIndex == sampleIndex) {
 return OK;
 }

 if (!mInitialized || sampleIndex < mFirstChunkSampleIndex) {
        reset();
 }

 if (sampleIndex >= mStopChunkSampleIndex) {
 status_t err;
 if ((err = findChunkRange(sampleIndex)) != OK) {
            ALOGE("findChunkRange failed");
 return err;
 }
 }

    CHECK(sampleIndex < mStopChunkSampleIndex);

 if (mSamplesPerChunk == 0) {
        ALOGE("b/22802344");
 return ERROR_MALFORMED;
 }

 uint32_t chunk =
 (sampleIndex - mFirstChunkSampleIndex) / mSamplesPerChunk

         + mFirstChunk;

     if (!mInitialized || chunk != mCurrentChunkIndex) {
        mCurrentChunkIndex = chunk;
         status_t err;
         if ((err = getChunkOffset(chunk, &mCurrentChunkOffset)) != OK) {
             ALOGE("getChunkOffset return error");
 return err;
 }

        mCurrentChunkSampleSizes.clear();

         uint32_t firstChunkSampleIndex =
             mFirstChunkSampleIndex
                + mSamplesPerChunk * (mCurrentChunkIndex - mFirstChunk);

         for (uint32_t i = 0; i < mSamplesPerChunk; ++i) {
             size_t sampleSize;
             if ((err = getSampleSizeDirect(
                             firstChunkSampleIndex + i, &sampleSize)) != OK) {
                 ALOGE("getSampleSizeDirect return error");
                 return err;
             }

             mCurrentChunkSampleSizes.push(sampleSize);
         }
     }

     uint32_t chunkRelativeSampleIndex =
 (sampleIndex - mFirstChunkSampleIndex) % mSamplesPerChunk;

    mCurrentSampleOffset = mCurrentChunkOffset;
 for (uint32_t i = 0; i < chunkRelativeSampleIndex; ++i) {
        mCurrentSampleOffset += mCurrentChunkSampleSizes[i];
 }

    mCurrentSampleSize = mCurrentChunkSampleSizes[chunkRelativeSampleIndex];
 if (sampleIndex < mTTSSampleIndex) {
        mTimeToSampleIndex = 0;
        mTTSSampleIndex = 0;
        mTTSSampleTime = 0;
        mTTSCount = 0;
        mTTSDuration = 0;
 }

 status_t err;
 if ((err = findSampleTimeAndDuration(
            sampleIndex, &mCurrentSampleTime, &mCurrentSampleDuration)) != OK) {
        ALOGE("findSampleTime return error");
 return err;
 }

    mCurrentSampleIndex = sampleIndex;

    mInitialized = true;

 return OK;
}

An information disclosure vulnerability in libstagefright in Mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, 6.x before 2016-11-01, and 7.0 before 2016-11-01 could enable a local malicious application to access data outside of its permission levels. This issue is rated as Moderate because it could be used to access sensitive data without permission. Android ID: A-31091777.


status_t SampleIterator::seekTo(uint32_t sampleIndex) {
    ALOGV("seekTo(%d)", sampleIndex);

 if (sampleIndex >= mTable->mNumSampleSizes) {
 return ERROR_END_OF_STREAM;
 }

 if (mTable->mSampleToChunkOffset < 0
 || mTable->mChunkOffsetOffset < 0
 || mTable->mSampleSizeOffset < 0
 || mTable->mTimeToSampleCount == 0) {

 return ERROR_MALFORMED;
 }

 if (mInitialized && mCurrentSampleIndex == sampleIndex) {
 return OK;
 }

 if (!mInitialized || sampleIndex < mFirstChunkSampleIndex) {
        reset();
 }

 if (sampleIndex >= mStopChunkSampleIndex) {
 status_t err;
 if ((err = findChunkRange(sampleIndex)) != OK) {
            ALOGE("findChunkRange failed");
 return err;
 }
 }

    CHECK(sampleIndex < mStopChunkSampleIndex);

 if (mSamplesPerChunk == 0) {
        ALOGE("b/22802344");
 return ERROR_MALFORMED;
 }

 uint32_t chunk =
 (sampleIndex - mFirstChunkSampleIndex) / mSamplesPerChunk

         + mFirstChunk;

     if (!mInitialized || chunk != mCurrentChunkIndex) {
         status_t err;
         if ((err = getChunkOffset(chunk, &mCurrentChunkOffset)) != OK) {
             ALOGE("getChunkOffset return error");
 return err;
 }

        mCurrentChunkSampleSizes.clear();

         uint32_t firstChunkSampleIndex =
             mFirstChunkSampleIndex
                + mSamplesPerChunk * (chunk - mFirstChunk);

         for (uint32_t i = 0; i < mSamplesPerChunk; ++i) {
             size_t sampleSize;
             if ((err = getSampleSizeDirect(
                             firstChunkSampleIndex + i, &sampleSize)) != OK) {
                 ALOGE("getSampleSizeDirect return error");
                mCurrentChunkSampleSizes.clear();
                 return err;
             }

             mCurrentChunkSampleSizes.push(sampleSize);
         }

        mCurrentChunkIndex = chunk;
     }

     uint32_t chunkRelativeSampleIndex =
 (sampleIndex - mFirstChunkSampleIndex) % mSamplesPerChunk;

    mCurrentSampleOffset = mCurrentChunkOffset;
 for (uint32_t i = 0; i < chunkRelativeSampleIndex; ++i) {
        mCurrentSampleOffset += mCurrentChunkSampleSizes[i];
 }

    mCurrentSampleSize = mCurrentChunkSampleSizes[chunkRelativeSampleIndex];
 if (sampleIndex < mTTSSampleIndex) {
        mTimeToSampleIndex = 0;
        mTTSSampleIndex = 0;
        mTTSSampleTime = 0;
        mTTSCount = 0;
        mTTSDuration = 0;
 }

 status_t err;
 if ((err = findSampleTimeAndDuration(
            sampleIndex, &mCurrentSampleTime, &mCurrentSampleDuration)) != OK) {
        ALOGE("findSampleTime return error");
 return err;
 }

    mCurrentSampleIndex = sampleIndex;

    mInitialized = true;

 return OK;
}


int vp9_alloc_context_buffers(VP9_COMMON *cm, int width, int height) {
 int new_mi_size;

  vp9_set_mb_mi(cm, width, height);
  new_mi_size = cm->mi_stride * calc_mi_size(cm->mi_rows);
 if (cm->mi_alloc_size < new_mi_size) {
    cm->free_mi(cm);
 if (cm->alloc_mi(cm, new_mi_size))
 goto fail;
 }

 if (cm->seg_map_alloc_size < cm->mi_rows * cm->mi_cols) {
    free_seg_map(cm);
 if (alloc_seg_map(cm, cm->mi_rows * cm->mi_cols))
 goto fail;
 }

 if (cm->above_context_alloc_cols < cm->mi_cols) {
    vpx_free(cm->above_context);
    cm->above_context = (ENTROPY_CONTEXT *)vpx_calloc(
 2 * mi_cols_aligned_to_sb(cm->mi_cols) * MAX_MB_PLANE,
 sizeof(*cm->above_context));
 if (!cm->above_context) goto fail;

    vpx_free(cm->above_seg_context);
    cm->above_seg_context = (PARTITION_CONTEXT *)vpx_calloc(
        mi_cols_aligned_to_sb(cm->mi_cols), sizeof(*cm->above_seg_context));
 if (!cm->above_seg_context) goto fail;
    cm->above_context_alloc_cols = cm->mi_cols;
 }

   return 0;

  fail:
   vp9_free_context_buffers(cm);
   return 1;
 }

A remote denial of service vulnerability in libvpx in Mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, and 6.x before 2016-11-01 could enable an 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. Android ID: A-30593752.


int vp9_alloc_context_buffers(VP9_COMMON *cm, int width, int height) {
 int new_mi_size;

  vp9_set_mb_mi(cm, width, height);
  new_mi_size = cm->mi_stride * calc_mi_size(cm->mi_rows);
 if (cm->mi_alloc_size < new_mi_size) {
    cm->free_mi(cm);
 if (cm->alloc_mi(cm, new_mi_size))
 goto fail;
 }

 if (cm->seg_map_alloc_size < cm->mi_rows * cm->mi_cols) {
    free_seg_map(cm);
 if (alloc_seg_map(cm, cm->mi_rows * cm->mi_cols))
 goto fail;
 }

 if (cm->above_context_alloc_cols < cm->mi_cols) {
    vpx_free(cm->above_context);
    cm->above_context = (ENTROPY_CONTEXT *)vpx_calloc(
 2 * mi_cols_aligned_to_sb(cm->mi_cols) * MAX_MB_PLANE,
 sizeof(*cm->above_context));
 if (!cm->above_context) goto fail;

    vpx_free(cm->above_seg_context);
    cm->above_seg_context = (PARTITION_CONTEXT *)vpx_calloc(
        mi_cols_aligned_to_sb(cm->mi_cols), sizeof(*cm->above_seg_context));
 if (!cm->above_seg_context) goto fail;
    cm->above_context_alloc_cols = cm->mi_cols;
 }

   return 0;

  fail:
  vp9_set_mb_mi(cm, 0, 0);
   vp9_free_context_buffers(cm);
   return 1;
 }


status_t MediaHTTP::connect(
 const char *uri,
 const KeyedVector<String8, String8> *headers,
 off64_t /* offset */) {
 if (mInitCheck != OK) {
 return mInitCheck;
 }

 KeyedVector<String8, String8> extHeaders;
 if (headers != NULL) {
        extHeaders = *headers;
 }

 if (extHeaders.indexOfKey(String8("User-Agent")) < 0) {

         extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str()));
     }

    bool success = mHTTPConnection->connect(uri, &extHeaders);

     mLastHeaders = extHeaders;
    mLastURI = uri;

     mCachedSizeValid = false;

     if (success) {
        AString sanitized = uriDebugString(uri);
         mName = String8::format("MediaHTTP(%s)", sanitized.c_str());
     }

 return success ? OK : UNKNOWN_ERROR;
}

A remote code execution vulnerability in libstagefright in Mediaserver in Android 7.0 before 2016-11-01 could enable an attacker using a specially crafted file to cause memory corruption during media file and data processing. This issue is rated as Critical due to the possibility of remote code execution within the context of the Mediaserver process. Android ID: A-31373622.


status_t MediaHTTP::connect(
 const char *uri,
 const KeyedVector<String8, String8> *headers,
 off64_t /* offset */) {
 if (mInitCheck != OK) {
 return mInitCheck;
 }

 KeyedVector<String8, String8> extHeaders;
 if (headers != NULL) {
        extHeaders = *headers;
 }

 if (extHeaders.indexOfKey(String8("User-Agent")) < 0) {

         extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str()));
     }

    mLastURI = uri;
    // reconnect() calls with uri == old mLastURI.c_str(), which gets zapped
    // as part of the above assignment. Ensure no accidental later use.
    uri = NULL;

    bool success = mHTTPConnection->connect(mLastURI.c_str(), &extHeaders);

     mLastHeaders = extHeaders;

     mCachedSizeValid = false;

     if (success) {
        AString sanitized = uriDebugString(mLastURI);
         mName = String8::format("MediaHTTP(%s)", sanitized.c_str());
     }

 return success ? OK : UNKNOWN_ERROR;
}


 status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
                                              uint32_t cmdSize,
                                              void *pCmdData,
 uint32_t *replySize,
 void *pReplyData)
{
 Mutex::Autolock _l(mLock);
    ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);

 if (mState == DESTROYED || mEffectInterface == NULL) {
 return NO_INIT;
 }
 if (mStatus != NO_ERROR) {
 return mStatus;
 }
 if (cmdCode == EFFECT_CMD_GET_PARAM &&
 (*replySize < sizeof(effect_param_t) ||
 ((effect_param_t *)pCmdData)->psize > *replySize - sizeof(effect_param_t))) {

         android_errorWriteLog(0x534e4554, "29251553");
         return -EINVAL;
     }
     status_t status = (*mEffectInterface)->command(mEffectInterface,
                                                    cmdCode,
                                                    cmdSize,
                                                   pCmdData,
                                                   replySize,
                                                   pReplyData);
 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
 uint32_t size = (replySize == NULL) ? 0 : *replySize;
 for (size_t i = 1; i < mHandles.size(); i++) {
 EffectHandle *h = mHandles[i];
 if (h != NULL && !h->destroyed_l()) {
                h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
 }
 }
 }
 return status;
}

services/audioflinger/Effects.cpp in mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, 6.x before 2016-10-01, and 7.0 before 2016-10-01 does not validate EFFECT_CMD_SET_PARAM and EFFECT_CMD_SET_PARAM_DEFERRED commands, which allows attackers to obtain sensitive information via a crafted application, aka internal bug 30204301.


 status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
                                              uint32_t cmdSize,
                                              void *pCmdData,
 uint32_t *replySize,
 void *pReplyData)
{
 Mutex::Autolock _l(mLock);
    ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);

 if (mState == DESTROYED || mEffectInterface == NULL) {
 return NO_INIT;
 }
 if (mStatus != NO_ERROR) {
 return mStatus;
 }
 if (cmdCode == EFFECT_CMD_GET_PARAM &&
 (*replySize < sizeof(effect_param_t) ||
 ((effect_param_t *)pCmdData)->psize > *replySize - sizeof(effect_param_t))) {

         android_errorWriteLog(0x534e4554, "29251553");
         return -EINVAL;
     }
    if ((cmdCode == EFFECT_CMD_SET_PARAM
            || cmdCode == EFFECT_CMD_SET_PARAM_DEFERRED) &&  // DEFERRED not generally used
        (sizeof(effect_param_t) > cmdSize
            || ((effect_param_t *)pCmdData)->psize > cmdSize
                                                     - sizeof(effect_param_t)
            || ((effect_param_t *)pCmdData)->vsize > cmdSize
                                                     - sizeof(effect_param_t)
                                                     - ((effect_param_t *)pCmdData)->psize
            || roundUpDelta(((effect_param_t *)pCmdData)->psize, (uint32_t)sizeof(int)) >
                                                     cmdSize
                                                     - sizeof(effect_param_t)
                                                     - ((effect_param_t *)pCmdData)->psize
                                                     - ((effect_param_t *)pCmdData)->vsize)) {
        android_errorWriteLog(0x534e4554, "30204301");
        return -EINVAL;
    }
     status_t status = (*mEffectInterface)->command(mEffectInterface,
                                                    cmdCode,
                                                    cmdSize,
                                                   pCmdData,
                                                   replySize,
                                                   pReplyData);
 if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
 uint32_t size = (replySize == NULL) ? 0 : *replySize;
 for (size_t i = 1; i < mHandles.size(); i++) {
 EffectHandle *h = mHandles[i];
 if (h != NULL && !h->destroyed_l()) {
                h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
 }
 }
 }
 return status;
}


status_t MediaPlayerService::Client::setNextPlayer(const sp<IMediaPlayer>& player) {

     ALOGV("setNextPlayer");
     Mutex::Autolock l(mLock);
     sp<Client> c = static_cast<Client*>(player.get());
     mNextClient = c;

     if (c != NULL) {
 if (mAudioOutput != NULL) {
            mAudioOutput->setNextOutput(c->mAudioOutput);
 } else if ((mPlayer != NULL) && !mPlayer->hardwareOutput()) {
            ALOGE("no current audio output");
 }

 if ((mPlayer != NULL) && (mNextClient->getPlayer() != NULL)) {
            mPlayer->setNextPlayer(mNextClient->getPlayer());
 }
 }

 return OK;
}

media/libmediaplayerservice/MediaPlayerService.cpp in mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, 6.x before 2016-10-01, and 7.0 before 2016-10-01 does not validate a certain static_cast operation, which allows attackers to gain privileges via a crafted application, aka internal bug 30204103.


status_t MediaPlayerService::Client::setNextPlayer(const sp<IMediaPlayer>& player) {

     ALOGV("setNextPlayer");
     Mutex::Autolock l(mLock);
     sp<Client> c = static_cast<Client*>(player.get());
    if (!mService->hasClient(c)) {
      return BAD_VALUE;
    }

     mNextClient = c;

     if (c != NULL) {
 if (mAudioOutput != NULL) {
            mAudioOutput->setNextOutput(c->mAudioOutput);
 } else if ((mPlayer != NULL) && !mPlayer->hardwareOutput()) {
            ALOGE("no current audio output");
 }

 if ((mPlayer != NULL) && (mNextClient->getPlayer() != NULL)) {
            mPlayer->setNextPlayer(mNextClient->getPlayer());
 }
 }

 return OK;
}


static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)

 {
     const char *perm = "add";

    if (uid >= AID_APP) {
         return 0; /* Don't allow apps to register services */
     }

 return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
}

cmds/servicemanager/service_manager.c in ServiceManager in Android 5.0.x before 5.0.2, 5.1.x before 5.1.1, 6.x before 2016-10-01, and 7.0 before 2016-10-01 does not properly restrict service registration, which allows attackers to gain privileges via a crafted application, aka internal bug 29431260.


static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)

 {
     const char *perm = "add";

    if (multiuser_get_app_id(uid) >= AID_APP) {
         return 0; /* Don't allow apps to register services */
     }

 return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
}


status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
 return allocateOutputBuffersFromNativeWindow();
 }

 if ((mFlags & kEnableGrallocUsageProtected) && portIndex == kPortIndexOutput) {
        ALOGE("protected output buffers must be stent to an ANativeWindow");
 return PERMISSION_DENIED;
 }

 status_t err = OK;
 if ((mFlags & kStoreMetaDataInVideoBuffers)
 && portIndex == kPortIndexInput) {
        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
 if (err != OK) {
            ALOGE("Storing meta data in video buffers is not supported");
 return err;
 }
 }

    OMX_PARAM_PORTDEFINITIONTYPE def;
 InitOMXParams(&def);
    def.nPortIndex = portIndex;

    err = mOMX->getParameter(
            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));

 if (err != OK) {
 return err;
 }

    CODEC_LOGV("allocating %u buffers of size %u on %s port",
            def.nBufferCountActual, def.nBufferSize,
            portIndex == kPortIndexInput ? "input" : "output");

 if (def.nBufferSize != 0 && def.nBufferCountActual > SIZE_MAX / def.nBufferSize) {
 return BAD_VALUE;
 }
 size_t totalSize = def.nBufferCountActual * def.nBufferSize;
    mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");

     for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
         sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
        CHECK(mem.get() != NULL);

         BufferInfo info;
         info.mData = NULL;
        info.mSize = def.nBufferSize;

        IOMX::buffer_id buffer;
 if (portIndex == kPortIndexInput
 && ((mQuirks & kRequiresAllocateBufferOnInputPorts)
 || (mFlags & kUseSecureInputBuffers))) {
 if (mOMXLivesLocally) {
                mem.clear();

                err = mOMX->allocateBuffer(
                        mNode, portIndex, def.nBufferSize, &buffer,
 &info.mData);
 } else {
                err = mOMX->allocateBufferWithBackup(
                        mNode, portIndex, mem, &buffer, mem->size());
 }
 } else if (portIndex == kPortIndexOutput
 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
 if (mOMXLivesLocally) {
                mem.clear();

                err = mOMX->allocateBuffer(
                        mNode, portIndex, def.nBufferSize, &buffer,
 &info.mData);
 } else {
                err = mOMX->allocateBufferWithBackup(
                        mNode, portIndex, mem, &buffer, mem->size());
 }
 } else {
            err = mOMX->useBuffer(mNode, portIndex, mem, &buffer, mem->size());
 }

 if (err != OK) {
            ALOGE("allocate_buffer_with_backup failed");
 return err;
 }

 if (mem != NULL) {
            info.mData = mem->pointer();
 }

        info.mBuffer = buffer;
        info.mStatus = OWNED_BY_US;
        info.mMem = mem;
        info.mMediaBuffer = NULL;

 if (portIndex == kPortIndexOutput) {
            LOG_ALWAYS_FATAL_IF((mOMXLivesLocally
 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)
 && (mQuirks & kDefersOutputBufferAllocation)),
 "allocateBuffersOnPort cannot defer buffer allocation");

            info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
            info.mMediaBuffer->setObserver(this);
 }

        mPortBuffers[portIndex].push(info);

        CODEC_LOGV("allocated buffer %u on %s port", buffer,
             portIndex == kPortIndexInput ? "input" : "output");
 }

 if (portIndex == kPortIndexOutput) {

        sp<MetaData> meta = mSource->getFormat();
 int32_t delay = 0;
 if (!meta->findInt32(kKeyEncoderDelay, &delay)) {
            delay = 0;
 }
 int32_t padding = 0;
 if (!meta->findInt32(kKeyEncoderPadding, &padding)) {
            padding = 0;
 }
 int32_t numchannels = 0;
 if (delay + padding) {
 if (mOutputFormat->findInt32(kKeyChannelCount, &numchannels)) {
 size_t frameSize = numchannels * sizeof(int16_t);
 if (mSkipCutBuffer != NULL) {
 size_t prevbuffersize = mSkipCutBuffer->size();
 if (prevbuffersize != 0) {
                        ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbuffersize);
 }
 }
                mSkipCutBuffer = new SkipCutBuffer(delay * frameSize, padding * frameSize);
 }
 }
 }

 if (portIndex == kPortIndexInput && (mFlags & kUseSecureInputBuffers)) {
 Vector<MediaBuffer *> buffers;
 for (size_t i = 0; i < def.nBufferCountActual; ++i) {
 const BufferInfo &info = mPortBuffers[kPortIndexInput].itemAt(i);

 MediaBuffer *mbuf = new MediaBuffer(info.mData, info.mSize);
            buffers.push(mbuf);
 }

 status_t err = mSource->setBuffers(buffers);

 if (err != OK) {
 for (size_t i = 0; i < def.nBufferCountActual; ++i) {
                buffers.editItemAt(i)->release();
 }
            buffers.clear();

            CODEC_LOGE(
 "Codec requested to use secure input buffers but "
 "upstream source didn't support that.");

 return err;
 }
 }

 return OK;
}

OMXCodec.cpp in libstagefright in mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, 6.x before 2016-09-01, and 7.0 before 2016-09-01 does not validate a certain pointer, which allows remote attackers to cause a denial of service (device hang or reboot) via a crafted media file, aka internal bug 29421811.


status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
 if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
 return allocateOutputBuffersFromNativeWindow();
 }

 if ((mFlags & kEnableGrallocUsageProtected) && portIndex == kPortIndexOutput) {
        ALOGE("protected output buffers must be stent to an ANativeWindow");
 return PERMISSION_DENIED;
 }

 status_t err = OK;
 if ((mFlags & kStoreMetaDataInVideoBuffers)
 && portIndex == kPortIndexInput) {
        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
 if (err != OK) {
            ALOGE("Storing meta data in video buffers is not supported");
 return err;
 }
 }

    OMX_PARAM_PORTDEFINITIONTYPE def;
 InitOMXParams(&def);
    def.nPortIndex = portIndex;

    err = mOMX->getParameter(
            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));

 if (err != OK) {
 return err;
 }

    CODEC_LOGV("allocating %u buffers of size %u on %s port",
            def.nBufferCountActual, def.nBufferSize,
            portIndex == kPortIndexInput ? "input" : "output");

 if (def.nBufferSize != 0 && def.nBufferCountActual > SIZE_MAX / def.nBufferSize) {
 return BAD_VALUE;
 }
 size_t totalSize = def.nBufferCountActual * def.nBufferSize;
    mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");

     for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
         sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
        if (mem == NULL || mem->pointer() == NULL) {
            return NO_MEMORY;
        }

         BufferInfo info;
         info.mData = NULL;
        info.mSize = def.nBufferSize;

        IOMX::buffer_id buffer;
 if (portIndex == kPortIndexInput
 && ((mQuirks & kRequiresAllocateBufferOnInputPorts)
 || (mFlags & kUseSecureInputBuffers))) {
 if (mOMXLivesLocally) {
                mem.clear();

                err = mOMX->allocateBuffer(
                        mNode, portIndex, def.nBufferSize, &buffer,
 &info.mData);
 } else {
                err = mOMX->allocateBufferWithBackup(
                        mNode, portIndex, mem, &buffer, mem->size());
 }
 } else if (portIndex == kPortIndexOutput
 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
 if (mOMXLivesLocally) {
                mem.clear();

                err = mOMX->allocateBuffer(
                        mNode, portIndex, def.nBufferSize, &buffer,
 &info.mData);
 } else {
                err = mOMX->allocateBufferWithBackup(
                        mNode, portIndex, mem, &buffer, mem->size());
 }
 } else {
            err = mOMX->useBuffer(mNode, portIndex, mem, &buffer, mem->size());
 }

 if (err != OK) {
            ALOGE("allocate_buffer_with_backup failed");
 return err;
 }

 if (mem != NULL) {
            info.mData = mem->pointer();
 }

        info.mBuffer = buffer;
        info.mStatus = OWNED_BY_US;
        info.mMem = mem;
        info.mMediaBuffer = NULL;

 if (portIndex == kPortIndexOutput) {
            LOG_ALWAYS_FATAL_IF((mOMXLivesLocally
 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)
 && (mQuirks & kDefersOutputBufferAllocation)),
 "allocateBuffersOnPort cannot defer buffer allocation");

            info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
            info.mMediaBuffer->setObserver(this);
 }

        mPortBuffers[portIndex].push(info);

        CODEC_LOGV("allocated buffer %u on %s port", buffer,
             portIndex == kPortIndexInput ? "input" : "output");
 }

 if (portIndex == kPortIndexOutput) {

        sp<MetaData> meta = mSource->getFormat();
 int32_t delay = 0;
 if (!meta->findInt32(kKeyEncoderDelay, &delay)) {
            delay = 0;
 }
 int32_t padding = 0;
 if (!meta->findInt32(kKeyEncoderPadding, &padding)) {
            padding = 0;
 }
 int32_t numchannels = 0;
 if (delay + padding) {
 if (mOutputFormat->findInt32(kKeyChannelCount, &numchannels)) {
 size_t frameSize = numchannels * sizeof(int16_t);
 if (mSkipCutBuffer != NULL) {
 size_t prevbuffersize = mSkipCutBuffer->size();
 if (prevbuffersize != 0) {
                        ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbuffersize);
 }
 }
                mSkipCutBuffer = new SkipCutBuffer(delay * frameSize, padding * frameSize);
 }
 }
 }

 if (portIndex == kPortIndexInput && (mFlags & kUseSecureInputBuffers)) {
 Vector<MediaBuffer *> buffers;
 for (size_t i = 0; i < def.nBufferCountActual; ++i) {
 const BufferInfo &info = mPortBuffers[kPortIndexInput].itemAt(i);

 MediaBuffer *mbuf = new MediaBuffer(info.mData, info.mSize);
            buffers.push(mbuf);
 }

 status_t err = mSource->setBuffers(buffers);

 if (err != OK) {
 for (size_t i = 0; i < def.nBufferCountActual; ++i) {
                buffers.editItemAt(i)->release();
 }
            buffers.clear();

            CODEC_LOGE(
 "Codec requested to use secure input buffers but "
 "upstream source didn't support that.");

 return err;
 }
 }

 return OK;
}


void close_all_sockets(atransport* t) {
    asocket* s;

 /* this is a little gross, but since s->close() *will* modify
    ** the list out from under you, your options are limited.
    */
    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);

 restart:
     for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
         if (s->transport == t || (s->peer && s->peer->transport == t)) {
            local_socket_close(s);
             goto restart;
         }
     }
}

The Java Debug Wire Protocol (JDWP) implementation in adb/sockets.cpp in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, and 6.x before 2016-09-01 mishandles socket close operations, which allows attackers to gain privileges via a crafted application, aka internal bug 28347842.


void close_all_sockets(atransport* t) {
    asocket* s;

 /* this is a little gross, but since s->close() *will* modify
    ** the list out from under you, your options are limited.
    */
    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);

 restart:
     for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
         if (s->transport == t || (s->peer && s->peer->transport == t)) {
            s->close(s);
             goto restart;
         }
     }
}


static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
 unsigned int data_sz,
 vpx_codec_stream_info_t *si,
 int *is_intra_only,

                                                 vpx_decrypt_cb decrypt_cb,
                                                 void *decrypt_state) {
   int intra_only_flag = 0;
  uint8_t clear_buffer[9];

   if (data + data_sz <= data)
     return VPX_CODEC_INVALID_PARAM;

  si->is_kf = 0;
  si->w = si->h = 0;

 if (decrypt_cb) {
    data_sz = VPXMIN(sizeof(clear_buffer), data_sz);
    decrypt_cb(decrypt_state, data, clear_buffer, data_sz);

     data = clear_buffer;
   }

   {
     int show_frame;
     int error_resilient;
 struct vpx_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
 const int frame_marker = vpx_rb_read_literal(&rb, 2);
 const BITSTREAM_PROFILE profile = vp9_read_profile(&rb);

 if (frame_marker != VP9_FRAME_MARKER)
 return VPX_CODEC_UNSUP_BITSTREAM;

     if (profile >= MAX_PROFILES)
       return VPX_CODEC_UNSUP_BITSTREAM;

    if ((profile >= 2 && data_sz <= 1) || data_sz < 1)
      return VPX_CODEC_UNSUP_BITSTREAM;
     if (vpx_rb_read_bit(&rb)) {  // show an existing frame
       vpx_rb_read_literal(&rb, 3);  // Frame buffer to show.
       return VPX_CODEC_OK;
     }

    if (data_sz <= 8)
       return VPX_CODEC_UNSUP_BITSTREAM;

     si->is_kf = !vpx_rb_read_bit(&rb);
    show_frame = vpx_rb_read_bit(&rb);
    error_resilient = vpx_rb_read_bit(&rb);

 if (si->is_kf) {
 if (!vp9_read_sync_code(&rb))
 return VPX_CODEC_UNSUP_BITSTREAM;

 if (!parse_bitdepth_colorspace_sampling(profile, &rb))
 return VPX_CODEC_UNSUP_BITSTREAM;
      vp9_read_frame_size(&rb, (int *)&si->w, (int *)&si->h);
 } else {
      intra_only_flag = show_frame ? 0 : vpx_rb_read_bit(&rb);

      rb.bit_offset += error_resilient ? 0 : 2; // reset_frame_context

 if (intra_only_flag) {
 if (!vp9_read_sync_code(&rb))
 return VPX_CODEC_UNSUP_BITSTREAM;
 if (profile > PROFILE_0) {
 if (!parse_bitdepth_colorspace_sampling(profile, &rb))
 return VPX_CODEC_UNSUP_BITSTREAM;
 }
        rb.bit_offset += REF_FRAMES; // refresh_frame_flags
        vp9_read_frame_size(&rb, (int *)&si->w, (int *)&si->h);
 }
 }
 }
 if (is_intra_only != NULL)
 *is_intra_only = intra_only_flag;
 return VPX_CODEC_OK;
}

The decoder_peek_si_internal function in vp9/vp9_dx_iface.c in libvpx in mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, 6.x before 2016-09-01, and 7.0 before 2016-09-01 allows remote attackers to cause a denial of service (buffer over-read, and device hang or reboot) via a crafted media file, aka internal bug 30013856.


static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
 unsigned int data_sz,
 vpx_codec_stream_info_t *si,
 int *is_intra_only,

                                                 vpx_decrypt_cb decrypt_cb,
                                                 void *decrypt_state) {
   int intra_only_flag = 0;
  uint8_t clear_buffer[10];

   if (data + data_sz <= data)
     return VPX_CODEC_INVALID_PARAM;

  si->is_kf = 0;
  si->w = si->h = 0;

 if (decrypt_cb) {
    data_sz = VPXMIN(sizeof(clear_buffer), data_sz);
    decrypt_cb(decrypt_state, data, clear_buffer, data_sz);

     data = clear_buffer;
   }

  // A maximum of 6 bits are needed to read the frame marker, profile and
  // show_existing_frame.
  if (data_sz < 1)
    return VPX_CODEC_UNSUP_BITSTREAM;

   {
     int show_frame;
     int error_resilient;
 struct vpx_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
 const int frame_marker = vpx_rb_read_literal(&rb, 2);
 const BITSTREAM_PROFILE profile = vp9_read_profile(&rb);

 if (frame_marker != VP9_FRAME_MARKER)
 return VPX_CODEC_UNSUP_BITSTREAM;

     if (profile >= MAX_PROFILES)
       return VPX_CODEC_UNSUP_BITSTREAM;

     if (vpx_rb_read_bit(&rb)) {  // show an existing frame
      // If profile is > 2 and show_existing_frame is true, then at least 1 more
      // byte (6+3=9 bits) is needed.
      if (profile > 2 && data_sz < 2)
        return VPX_CODEC_UNSUP_BITSTREAM;
       vpx_rb_read_literal(&rb, 3);  // Frame buffer to show.
       return VPX_CODEC_OK;
     }

    // For the rest of the function, a maximum of 9 more bytes are needed
    // (computed by taking the maximum possible bits needed in each case). Note
    // that this has to be updated if we read any more bits in this function.
    if (data_sz < 10)
       return VPX_CODEC_UNSUP_BITSTREAM;

     si->is_kf = !vpx_rb_read_bit(&rb);
    show_frame = vpx_rb_read_bit(&rb);
    error_resilient = vpx_rb_read_bit(&rb);

 if (si->is_kf) {
 if (!vp9_read_sync_code(&rb))
 return VPX_CODEC_UNSUP_BITSTREAM;

 if (!parse_bitdepth_colorspace_sampling(profile, &rb))
 return VPX_CODEC_UNSUP_BITSTREAM;
      vp9_read_frame_size(&rb, (int *)&si->w, (int *)&si->h);
 } else {
      intra_only_flag = show_frame ? 0 : vpx_rb_read_bit(&rb);

      rb.bit_offset += error_resilient ? 0 : 2; // reset_frame_context

 if (intra_only_flag) {
 if (!vp9_read_sync_code(&rb))
 return VPX_CODEC_UNSUP_BITSTREAM;
 if (profile > PROFILE_0) {
 if (!parse_bitdepth_colorspace_sampling(profile, &rb))
 return VPX_CODEC_UNSUP_BITSTREAM;
 }
        rb.bit_offset += REF_FRAMES; // refresh_frame_flags
        vp9_read_frame_size(&rb, (int *)&si->w, (int *)&si->h);
 }
 }
 }
 if (is_intra_only != NULL)
 *is_intra_only = intra_only_flag;
 return VPX_CODEC_OK;
}


EAS_RESULT DLSParser (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_DLSLIB_HANDLE *ppDLS)
{
    EAS_RESULT result;
    SDLS_SYNTHESIZER_DATA dls;
    EAS_U32 temp;
    EAS_I32 pos;
    EAS_I32 chunkPos;
    EAS_I32 size;
    EAS_I32 instSize;
    EAS_I32 rgnPoolSize;
    EAS_I32 artPoolSize;
    EAS_I32 waveLenSize;
    EAS_I32 endDLS;
    EAS_I32 wvplPos;
    EAS_I32 wvplSize;
    EAS_I32 linsPos;
    EAS_I32 linsSize;
    EAS_I32 ptblPos;
    EAS_I32 ptblSize;
 void *p;

 /* zero counts and pointers */
    EAS_HWMemSet(&dls, 0, sizeof(dls));

 /* save file handle and hwInstData to save copying pointers around */
    dls.hwInstData = hwInstData;
    dls.fileHandle = fileHandle;

 /* NULL return value in case of error */
 *ppDLS = NULL;

 /* seek to start of DLS and read in RIFF tag and set processor endian flag */
 if ((result = EAS_HWFileSeek(dls.hwInstData, dls.fileHandle, offset)) != EAS_SUCCESS)
 return result;
 if ((result = EAS_HWReadFile(dls.hwInstData, dls.fileHandle, &temp, sizeof(temp), &size)) != EAS_SUCCESS)
 return result;

 /* check for processor endian-ness */
    dls.bigEndian = (temp == CHUNK_RIFF);

 /* first chunk should be DLS */
    pos = offset;
 if ((result = NextChunk(&dls, &pos, &temp, &size)) != EAS_SUCCESS)
 return result;
 if (temp != CHUNK_DLS)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected DLS chunk, got %08lx\n", temp); */ }
 return EAS_ERROR_FILE_FORMAT;
 }

 /* no instrument or wavepool chunks */
    linsSize = wvplSize = ptblSize = linsPos = wvplPos = ptblPos = 0;

 /* scan the chunks in the DLS list */
    endDLS = offset + size;
    pos = offset + 12;
 while (pos < endDLS)
 {
        chunkPos = pos;

 /* get the next chunk type */
 if ((result = NextChunk(&dls, &pos, &temp, &size)) != EAS_SUCCESS)
 return result;

 /* parse useful chunks */
 switch (temp)
 {
 case CHUNK_CDL:
 if ((result = Parse_cdl(&dls, size, &temp)) != EAS_SUCCESS)
 return result;
 if (!temp)
 return EAS_ERROR_UNRECOGNIZED_FORMAT;
 break;

 case CHUNK_LINS:
                linsPos = chunkPos + 12;
                linsSize = size - 4;
 break;

 case CHUNK_WVPL:
                wvplPos = chunkPos + 12;
                wvplSize = size - 4;
 break;

 case CHUNK_PTBL:
                ptblPos = chunkPos + 8;
                ptblSize = size - 4;
 break;

 default:
 break;
 }
 }

 /* must have a lins chunk */
 if (linsSize == 0)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No lins chunk found"); */ }
 return EAS_ERROR_UNRECOGNIZED_FORMAT;
 }

 /* must have a wvpl chunk */
 if (wvplSize == 0)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No wvpl chunk found"); */ }
 return EAS_ERROR_UNRECOGNIZED_FORMAT;
 }

 /* must have a ptbl chunk */
 if ((ptblSize == 0) || (ptblSize > DLS_MAX_WAVE_COUNT * sizeof(POOLCUE) + sizeof(POOLTABLE)))
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No ptbl chunk found"); */ }
 return EAS_ERROR_UNRECOGNIZED_FORMAT;
 }

 /* pre-parse the wave pool chunk */
 if ((result = Parse_ptbl(&dls, ptblPos, wvplPos, wvplSize)) != EAS_SUCCESS)
 return result;

 /* limit check  */
 if ((dls.waveCount == 0) || (dls.waveCount > DLS_MAX_WAVE_COUNT))
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #waves [%u]\n", dls.waveCount); */ }
 return EAS_ERROR_FILE_FORMAT;
 }

 /* allocate memory for wsmp data */
    dls.wsmpData = EAS_HWMalloc(dls.hwInstData, (EAS_I32) (sizeof(S_WSMP_DATA) * dls.waveCount));
 if (dls.wsmpData == NULL)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc for wsmp data failed\n"); */ }
 return EAS_ERROR_MALLOC_FAILED;
 }
    EAS_HWMemSet(dls.wsmpData, 0, (EAS_I32) (sizeof(S_WSMP_DATA) * dls.waveCount));

 /* pre-parse the lins chunk */
    result = Parse_lins(&dls, linsPos, linsSize);
 if (result == EAS_SUCCESS)
 {

 /* limit check  */
 if ((dls.regionCount == 0) || (dls.regionCount > DLS_MAX_REGION_COUNT))
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #regions [%u]\n", dls.regionCount); */ }
 return EAS_ERROR_FILE_FORMAT;
 }

 /* limit check  */
 if ((dls.artCount == 0) || (dls.artCount > DLS_MAX_ART_COUNT))
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #articulations [%u]\n", dls.regionCount); */ }
 return EAS_ERROR_FILE_FORMAT;
 }

 /* limit check  */
 if ((dls.instCount == 0) || (dls.instCount > DLS_MAX_INST_COUNT))
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #instruments [%u]\n", dls.instCount); */ }
 return EAS_ERROR_FILE_FORMAT;
 }

 /* Allocate memory for the converted DLS data */
 /* calculate size of instrument data */
        instSize = (EAS_I32) (sizeof(S_PROGRAM) * dls.instCount);

 /* calculate size of region pool */
        rgnPoolSize = (EAS_I32) (sizeof(S_DLS_REGION) * dls.regionCount);

 /* calculate size of articulation pool, add one for default articulation */
        dls.artCount++;
        artPoolSize = (EAS_I32) (sizeof(S_DLS_ARTICULATION) * dls.artCount);

 /* calculate size of wave length and offset arrays */
        waveLenSize = (EAS_I32) (dls.waveCount * sizeof(EAS_U32));

 /* calculate final memory size */
        size = (EAS_I32) sizeof(S_EAS) + instSize + rgnPoolSize + artPoolSize + (2 * waveLenSize) + (EAS_I32) dls.wavePoolSize;
 if (size <= 0) {
 return EAS_ERROR_FILE_FORMAT;
 }

 /* allocate the main EAS chunk */
        dls.pDLS = EAS_HWMalloc(dls.hwInstData, size);
 if (dls.pDLS == NULL)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc failed for DLS memory allocation size %ld\n", size); */ }
 return EAS_ERROR_MALLOC_FAILED;
 }
        EAS_HWMemSet(dls.pDLS, 0, size);
        dls.pDLS->refCount = 1;
        p = PtrOfs(dls.pDLS, sizeof(S_EAS));

 /* setup pointer to programs */
        dls.pDLS->numDLSPrograms = (EAS_U16) dls.instCount;
        dls.pDLS->pDLSPrograms = p;
        p = PtrOfs(p, instSize);

 /* setup pointer to regions */
        dls.pDLS->pDLSRegions = p;
        dls.pDLS->numDLSRegions = (EAS_U16) dls.regionCount;
        p = PtrOfs(p, rgnPoolSize);

 /* setup pointer to articulations */
        dls.pDLS->numDLSArticulations = (EAS_U16) dls.artCount;
        dls.pDLS->pDLSArticulations = p;
        p = PtrOfs(p, artPoolSize);

 /* setup pointer to wave length table */
        dls.pDLS->numDLSSamples = (EAS_U16) dls.waveCount;
        dls.pDLS->pDLSSampleLen = p;
        p = PtrOfs(p, waveLenSize);

 /* setup pointer to wave offsets table */
        dls.pDLS->pDLSSampleOffsets = p;
        p = PtrOfs(p, waveLenSize);

 /* setup pointer to wave pool */
        dls.pDLS->pDLSSamples = p;

 /* clear filter flag */
        dls.filterUsed = EAS_FALSE;

 /* parse the wave pool and load samples */
        result = Parse_ptbl(&dls, ptblPos, wvplPos, wvplSize);

     }

     /* create the default articulation */
    Convert_art(&dls, &defaultArt, 0);
    dls.artCount = 1;

     /* parse the lins chunk and load instruments */
     dls.regionCount = dls.instCount = 0;
 if (result == EAS_SUCCESS)
        result = Parse_lins(&dls, linsPos, linsSize);

 /* clean up any temporary objects that were allocated */
 if (dls.wsmpData)
        EAS_HWFree(dls.hwInstData, dls.wsmpData);

 /* if successful, return a pointer to the EAS collection */
 if (result == EAS_SUCCESS)
 {
 *ppDLS = dls.pDLS;
#ifdef _DEBUG_DLS
 DumpDLS(dls.pDLS);
#endif
 }

 /* something went wrong, deallocate the EAS collection */
 else
 DLSCleanup(dls.hwInstData, dls.pDLS);

 return result;
}

arm-wt-22k/lib_src/eas_mdls.c in mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, and 6.x before 2016-09-01 allows remote attackers to cause a denial of service (NULL pointer dereference, and device hang or reboot) via a crafted media file, aka internal bug 29770686.


EAS_RESULT DLSParser (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_DLSLIB_HANDLE *ppDLS)
{
    EAS_RESULT result;
    SDLS_SYNTHESIZER_DATA dls;
    EAS_U32 temp;
    EAS_I32 pos;
    EAS_I32 chunkPos;
    EAS_I32 size;
    EAS_I32 instSize;
    EAS_I32 rgnPoolSize;
    EAS_I32 artPoolSize;
    EAS_I32 waveLenSize;
    EAS_I32 endDLS;
    EAS_I32 wvplPos;
    EAS_I32 wvplSize;
    EAS_I32 linsPos;
    EAS_I32 linsSize;
    EAS_I32 ptblPos;
    EAS_I32 ptblSize;
 void *p;

 /* zero counts and pointers */
    EAS_HWMemSet(&dls, 0, sizeof(dls));

 /* save file handle and hwInstData to save copying pointers around */
    dls.hwInstData = hwInstData;
    dls.fileHandle = fileHandle;

 /* NULL return value in case of error */
 *ppDLS = NULL;

 /* seek to start of DLS and read in RIFF tag and set processor endian flag */
 if ((result = EAS_HWFileSeek(dls.hwInstData, dls.fileHandle, offset)) != EAS_SUCCESS)
 return result;
 if ((result = EAS_HWReadFile(dls.hwInstData, dls.fileHandle, &temp, sizeof(temp), &size)) != EAS_SUCCESS)
 return result;

 /* check for processor endian-ness */
    dls.bigEndian = (temp == CHUNK_RIFF);

 /* first chunk should be DLS */
    pos = offset;
 if ((result = NextChunk(&dls, &pos, &temp, &size)) != EAS_SUCCESS)
 return result;
 if (temp != CHUNK_DLS)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected DLS chunk, got %08lx\n", temp); */ }
 return EAS_ERROR_FILE_FORMAT;
 }

 /* no instrument or wavepool chunks */
    linsSize = wvplSize = ptblSize = linsPos = wvplPos = ptblPos = 0;

 /* scan the chunks in the DLS list */
    endDLS = offset + size;
    pos = offset + 12;
 while (pos < endDLS)
 {
        chunkPos = pos;

 /* get the next chunk type */
 if ((result = NextChunk(&dls, &pos, &temp, &size)) != EAS_SUCCESS)
 return result;

 /* parse useful chunks */
 switch (temp)
 {
 case CHUNK_CDL:
 if ((result = Parse_cdl(&dls, size, &temp)) != EAS_SUCCESS)
 return result;
 if (!temp)
 return EAS_ERROR_UNRECOGNIZED_FORMAT;
 break;

 case CHUNK_LINS:
                linsPos = chunkPos + 12;
                linsSize = size - 4;
 break;

 case CHUNK_WVPL:
                wvplPos = chunkPos + 12;
                wvplSize = size - 4;
 break;

 case CHUNK_PTBL:
                ptblPos = chunkPos + 8;
                ptblSize = size - 4;
 break;

 default:
 break;
 }
 }

 /* must have a lins chunk */
 if (linsSize == 0)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No lins chunk found"); */ }
 return EAS_ERROR_UNRECOGNIZED_FORMAT;
 }

 /* must have a wvpl chunk */
 if (wvplSize == 0)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No wvpl chunk found"); */ }
 return EAS_ERROR_UNRECOGNIZED_FORMAT;
 }

 /* must have a ptbl chunk */
 if ((ptblSize == 0) || (ptblSize > DLS_MAX_WAVE_COUNT * sizeof(POOLCUE) + sizeof(POOLTABLE)))
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No ptbl chunk found"); */ }
 return EAS_ERROR_UNRECOGNIZED_FORMAT;
 }

 /* pre-parse the wave pool chunk */
 if ((result = Parse_ptbl(&dls, ptblPos, wvplPos, wvplSize)) != EAS_SUCCESS)
 return result;

 /* limit check  */
 if ((dls.waveCount == 0) || (dls.waveCount > DLS_MAX_WAVE_COUNT))
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #waves [%u]\n", dls.waveCount); */ }
 return EAS_ERROR_FILE_FORMAT;
 }

 /* allocate memory for wsmp data */
    dls.wsmpData = EAS_HWMalloc(dls.hwInstData, (EAS_I32) (sizeof(S_WSMP_DATA) * dls.waveCount));
 if (dls.wsmpData == NULL)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc for wsmp data failed\n"); */ }
 return EAS_ERROR_MALLOC_FAILED;
 }
    EAS_HWMemSet(dls.wsmpData, 0, (EAS_I32) (sizeof(S_WSMP_DATA) * dls.waveCount));

 /* pre-parse the lins chunk */
    result = Parse_lins(&dls, linsPos, linsSize);
 if (result == EAS_SUCCESS)
 {

 /* limit check  */
 if ((dls.regionCount == 0) || (dls.regionCount > DLS_MAX_REGION_COUNT))
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #regions [%u]\n", dls.regionCount); */ }
 return EAS_ERROR_FILE_FORMAT;
 }

 /* limit check  */
 if ((dls.artCount == 0) || (dls.artCount > DLS_MAX_ART_COUNT))
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #articulations [%u]\n", dls.regionCount); */ }
 return EAS_ERROR_FILE_FORMAT;
 }

 /* limit check  */
 if ((dls.instCount == 0) || (dls.instCount > DLS_MAX_INST_COUNT))
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #instruments [%u]\n", dls.instCount); */ }
 return EAS_ERROR_FILE_FORMAT;
 }

 /* Allocate memory for the converted DLS data */
 /* calculate size of instrument data */
        instSize = (EAS_I32) (sizeof(S_PROGRAM) * dls.instCount);

 /* calculate size of region pool */
        rgnPoolSize = (EAS_I32) (sizeof(S_DLS_REGION) * dls.regionCount);

 /* calculate size of articulation pool, add one for default articulation */
        dls.artCount++;
        artPoolSize = (EAS_I32) (sizeof(S_DLS_ARTICULATION) * dls.artCount);

 /* calculate size of wave length and offset arrays */
        waveLenSize = (EAS_I32) (dls.waveCount * sizeof(EAS_U32));

 /* calculate final memory size */
        size = (EAS_I32) sizeof(S_EAS) + instSize + rgnPoolSize + artPoolSize + (2 * waveLenSize) + (EAS_I32) dls.wavePoolSize;
 if (size <= 0) {
 return EAS_ERROR_FILE_FORMAT;
 }

 /* allocate the main EAS chunk */
        dls.pDLS = EAS_HWMalloc(dls.hwInstData, size);
 if (dls.pDLS == NULL)
 {
 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc failed for DLS memory allocation size %ld\n", size); */ }
 return EAS_ERROR_MALLOC_FAILED;
 }
        EAS_HWMemSet(dls.pDLS, 0, size);
        dls.pDLS->refCount = 1;
        p = PtrOfs(dls.pDLS, sizeof(S_EAS));

 /* setup pointer to programs */
        dls.pDLS->numDLSPrograms = (EAS_U16) dls.instCount;
        dls.pDLS->pDLSPrograms = p;
        p = PtrOfs(p, instSize);

 /* setup pointer to regions */
        dls.pDLS->pDLSRegions = p;
        dls.pDLS->numDLSRegions = (EAS_U16) dls.regionCount;
        p = PtrOfs(p, rgnPoolSize);

 /* setup pointer to articulations */
        dls.pDLS->numDLSArticulations = (EAS_U16) dls.artCount;
        dls.pDLS->pDLSArticulations = p;
        p = PtrOfs(p, artPoolSize);

 /* setup pointer to wave length table */
        dls.pDLS->numDLSSamples = (EAS_U16) dls.waveCount;
        dls.pDLS->pDLSSampleLen = p;
        p = PtrOfs(p, waveLenSize);

 /* setup pointer to wave offsets table */
        dls.pDLS->pDLSSampleOffsets = p;
        p = PtrOfs(p, waveLenSize);

 /* setup pointer to wave pool */
        dls.pDLS->pDLSSamples = p;

 /* clear filter flag */
        dls.filterUsed = EAS_FALSE;

 /* parse the wave pool and load samples */
        result = Parse_ptbl(&dls, ptblPos, wvplPos, wvplSize);

     }

     /* create the default articulation */
    if (dls.pDLS) {
        Convert_art(&dls, &defaultArt, 0);
        dls.artCount = 1;
    }

     /* parse the lins chunk and load instruments */
     dls.regionCount = dls.instCount = 0;
 if (result == EAS_SUCCESS)
        result = Parse_lins(&dls, linsPos, linsSize);

 /* clean up any temporary objects that were allocated */
 if (dls.wsmpData)
        EAS_HWFree(dls.hwInstData, dls.wsmpData);

 /* if successful, return a pointer to the EAS collection */
 if (result == EAS_SUCCESS)
 {
 *ppDLS = dls.pDLS;
#ifdef _DEBUG_DLS
 DumpDLS(dls.pDLS);
#endif
 }

 /* something went wrong, deallocate the EAS collection */
 else
 DLSCleanup(dls.hwInstData, dls.pDLS);

 return result;
}