1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include <cstddef>
16#include <cstdint>
17#include "native_avcodec_videodecoder.h"
18#include "native_averrors.h"
19#include "native_avcodec_base.h"
20#include "videodec_sample.h"
21using namespace std;
22using namespace OHOS;
23using namespace OHOS::Media;
24#define FUZZ_PROJECT_NAME "hwdecoder_fuzzer"
25
26static VDecFuzzSample *g_vDecSample = nullptr;
27constexpr uint32_t DEFAULT_WIDTH = 1920;
28constexpr uint32_t DEFAULT_HEIGHT = 1080;
29constexpr uint32_t SPS_SIZE = 0x19;
30constexpr uint32_t PPS_SIZE = 0x05;
31constexpr uint32_t START_CODE_SIZE = 4;
32constexpr uint8_t SPS[SPS_SIZE + START_CODE_SIZE] = {0x00, 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x28, 0xAC,
33                                                     0xB4, 0x03, 0xC0, 0x11, 0x3F, 0x2E, 0x02, 0x20, 0x00,
34                                                     0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x07, 0x81, 0xE3,
35                                                     0x06, 0x54};
36constexpr uint8_t PPS[PPS_SIZE + START_CODE_SIZE] = {0x00, 0x00, 0x00, 0x01, 0x68, 0xEF, 0x0F, 0x2C, 0x8B};
37bool g_isSurfMode = true;
38
39void RunNormalDecoder()
40{
41    VDecFuzzSample *vDecSample = new VDecFuzzSample();
42    vDecSample->defaultWidth = DEFAULT_WIDTH;
43    vDecSample->defaultHeight = DEFAULT_HEIGHT;
44    vDecSample->CreateVideoDecoder();
45    vDecSample->ConfigureVideoDecoder();
46    vDecSample->SetVideoDecoderCallback();
47    vDecSample->StartVideoDecoder();
48    vDecSample->WaitForEOS();
49    delete vDecSample;
50
51    vDecSample = new VDecFuzzSample();
52    vDecSample->isSurfMode = true;
53    vDecSample->defaultWidth = DEFAULT_WIDTH;
54    vDecSample->defaultHeight = DEFAULT_HEIGHT;
55    vDecSample->CreateVideoDecoder();
56    vDecSample->ConfigureVideoDecoder();
57    vDecSample->SetVideoDecoderCallback();
58    vDecSample->StartVideoDecoder();
59    vDecSample->WaitForEOS();
60    delete vDecSample;
61}
62
63bool g_needRunNormalDecoder = true;
64namespace OHOS {
65bool HwdecoderFuzzTest(const uint8_t *data, size_t size)
66{
67    if (size < sizeof(int32_t)) {
68        return false;
69    }
70    if (g_needRunNormalDecoder) {
71        g_needRunNormalDecoder = false;
72        RunNormalDecoder();
73    }
74    int32_t data_ = *reinterpret_cast<const int32_t *>(data);
75    if (!g_vDecSample) {
76        g_vDecSample = new VDecFuzzSample();
77        g_vDecSample->defaultWidth = DEFAULT_WIDTH;
78        g_vDecSample->defaultHeight = DEFAULT_HEIGHT;
79        g_vDecSample->CreateVideoDecoder();
80        g_vDecSample->ConfigureVideoDecoder();
81        g_vDecSample->SetVideoDecoderCallback();
82        g_vDecSample->Start();
83        g_vDecSample->InputFuncFUZZ(SPS, SPS_SIZE + START_CODE_SIZE);
84        g_vDecSample->InputFuncFUZZ(PPS, PPS_SIZE + START_CODE_SIZE);
85    }
86    OH_AVErrCode ret = g_vDecSample->InputFuncFUZZ(data, size);
87    g_vDecSample->SetParameter(data_);
88    if (ret == AV_ERR_NO_MEMORY) {
89        g_vDecSample->Flush();
90        g_vDecSample->Stop();
91        g_vDecSample->Reset();
92        delete g_vDecSample;
93        g_vDecSample = nullptr;
94        return false;
95    }
96    return true;
97}
98} // namespace OHOS
99
100/* Fuzzer entry point */
101extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
102{
103    /* Run your code on data */
104    OHOS::HwdecoderFuzzTest(data, size);
105    return 0;
106}
107