/** * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #ifdef TEST_ARM32 #include #include "../includes/common.h" #include #include #include #include "vpx/vp8dx.h" #include "vpx/vpx_decoder.h" #include "vpx_ports/mem_ops.h" #define IVF_FILE_HDR_SZ 32 #define IVF_FRAME_HDR_SZ (4 + 8) /* 4 byte size + 8 byte timestamp */ FILE *fp = nullptr; void exitHandler(void) { if (fp) { fclose(fp); } } bool testInProgress = false; struct sigaction new_action, old_action; void sigabrt_handler(int32_t signum, siginfo_t *info, void* context) { if (testInProgress && info->si_signo == SIGABRT) { (*old_action.sa_sigaction)(signum, info, context); return; } _exit(EXIT_FAILURE); } #endif int32_t main(int32_t argc, char **argv) { (void)argc; (void)argv; #ifdef TEST_ARM32 atexit(exitHandler); sigemptyset(&new_action.sa_mask); new_action.sa_flags = SA_SIGINFO; new_action.sa_sigaction = sigabrt_handler; sigaction(SIGABRT, &new_action, &old_action); FAIL_CHECK(argc >= 2); fp = fopen(argv[1], "rb"); FAIL_CHECK(fp); fseek(fp, 0, SEEK_END); size_t size = ftell(fp); fseek(fp, 0, SEEK_SET); FAIL_CHECK(size > IVF_FILE_HDR_SZ); std::vector buffer(size); FAIL_CHECK(fread((void *)buffer.data(), sizeof(uint8_t), size, fp) == size); vpx_codec_ctx_t codec; vpx_codec_dec_cfg_t cfg; memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t)); cfg.threads = 1; FAIL_CHECK(vpx_codec_dec_init(&codec, &vpx_codec_vp8_dx_algo, &cfg, 0) == VPX_CODEC_OK); uint8_t *data = buffer.data(); data += IVF_FILE_HDR_SZ; size -= IVF_FILE_HDR_SZ; while (size > IVF_FRAME_HDR_SZ) { size_t frame_size = mem_get_le32(data); size -= IVF_FRAME_HDR_SZ; data += IVF_FRAME_HDR_SZ; frame_size = std::min(size, frame_size); testInProgress = true; vpx_codec_decode(&codec, data, frame_size, nullptr, 0); testInProgress = false; vpx_codec_iter_t iter = nullptr; vpx_image_t *img = nullptr; while ((img = vpx_codec_get_frame(&codec, &iter)) != nullptr) { if (img->d_w > img->w || img->d_h > img->h) { return EXIT_VULNERABLE; } } data += frame_size; size -= frame_size; } vpx_codec_destroy(&codec); #endif return EXIT_SUCCESS; }