Commit message: None
CVE: CVE-2016-3881
CWE: CWE-119
Vulnerability description: 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.

Project: Android

static vpx_codec_err_t ctrl_get_bit_depth(vpx_codec_alg_priv_t *ctx,
                                          va_list args) {
 unsigned int *const bit_depth = va_arg(args, unsigned int *);
 VPxWorker *const worker = &ctx->frame_workers[ctx->next_output_worker_id];

 if (bit_depth) {
 if (worker) {
 FrameWorkerData *const frame_worker_data =
 (FrameWorkerData *)worker->data1;
 const VP9_COMMON *const cm = &frame_worker_data->pbi->common;
 *bit_depth = cm->bit_depth;
 return VPX_CODEC_OK;
 } else {
 return VPX_CODEC_ERROR;
 }
 }

 return VPX_CODEC_INVALID_PARAM;
}

Project: Android

static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) {
 if (ctx->frame_workers != NULL) {
 int i;
 for (i = 0; i < ctx->num_frame_workers; ++i) {
 VPxWorker *const worker = &ctx->frame_workers[i];
 FrameWorkerData *const frame_worker_data =
 (FrameWorkerData *)worker->data1;
      vpx_get_worker_interface()->end(worker);
      vp9_remove_common(&frame_worker_data->pbi->common);
#if CONFIG_VP9_POSTPROC
      vp9_free_postproc_buffers(&frame_worker_data->pbi->common);
#endif
      vp9_decoder_remove(frame_worker_data->pbi);
      vpx_free(frame_worker_data->scratch_buffer);
#if CONFIG_MULTITHREAD
      pthread_mutex_destroy(&frame_worker_data->stats_mutex);
      pthread_cond_destroy(&frame_worker_data->stats_cond);
#endif
      vpx_free(frame_worker_data);
 }
#if CONFIG_MULTITHREAD
    pthread_mutex_destroy(&ctx->buffer_pool->pool_mutex);
#endif
 }

 if (ctx->buffer_pool) {
    vp9_free_ref_frame_buffers(ctx->buffer_pool);
    vp9_free_internal_frame_buffers(&ctx->buffer_pool->int_frame_buffers);
 }

  vpx_free(ctx->frame_workers);
  vpx_free(ctx->buffer_pool);
  vpx_free(ctx);
 return VPX_CODEC_OK;
}

Project: Android

static int frame_worker_hook(void *arg1, void *arg2) {
 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)arg1;
 const uint8_t *data = frame_worker_data->data;
 (void)arg2;

  frame_worker_data->result =
      vp9_receive_compressed_data(frame_worker_data->pbi,
                                  frame_worker_data->data_size,
 &data);
  frame_worker_data->data_end = data;

 if (frame_worker_data->pbi->frame_parallel_decode) {
 if (frame_worker_data->result != 0 ||
        frame_worker_data->data + frame_worker_data->data_size - 1 > data) {
 VPxWorker *const worker = frame_worker_data->pbi->frame_worker_owner;
 BufferPool *const pool = frame_worker_data->pbi->common.buffer_pool;
      vp9_frameworker_lock_stats(worker);
      frame_worker_data->frame_context_ready = 1;
      lock_buffer_pool(pool);
      frame_worker_data->pbi->cur_buf->buf.corrupted = 1;
      unlock_buffer_pool(pool);
      frame_worker_data->pbi->need_resync = 1;
      vp9_frameworker_signal_stats(worker);
      vp9_frameworker_unlock_stats(worker);
 return 0;
 }
 } else if (frame_worker_data->result != 0) {
    frame_worker_data->pbi->cur_buf->buf.corrupted = 1;
    frame_worker_data->pbi->need_resync = 1;
 }
 return !frame_worker_data->result;
}