Coverage Report

Created: 2025-11-29 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libavc/fuzzer/mvc_dec_fuzzer.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Copyright (C) 2019 The Android Open Source Project
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at:
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 *****************************************************************************
18
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19
 */
20
#include <cstdio>
21
#include <cstdlib>
22
#include <cstring>
23
#include <algorithm>
24
25
#ifdef __cplusplus
26
extern "C"
27
{
28
#include "ih264_typedefs.h"
29
#include "imvcd.h"
30
}
31
#endif
32
33
15.0k
#define MAX_NUM_VIEWS 6
34
35
15.0k
#define NUM_COMPONENTS 3
36
37
#define NELEMENTS(x) (sizeof(x) / sizeof(x[0]))
38
39
typedef enum ARG_OFFSETS_T
40
{
41
    OFFSET_COLOR_FORMAT = 6,
42
    OFFSET_NUM_CORES,
43
    OFFSET_ARCH,
44
    /* Should be the last entry */
45
    OFFSET_MAX,
46
} ARG_OFFSETS_T;
47
48
static const IV_COLOR_FORMAT_T supportedColorFormats[] = {IV_YUV_420P};
49
static const IVD_ARCH_T supportedArchitectures[] = {ARCH_ARM_NEONINTR, ARCH_X86_GENERIC,
50
                                                    ARCH_X86_SSSE3, ARCH_X86_SSE42};
51
static const int kMaxNumDecodeCalls = 1000;
52
static const int kSupportedColorFormats = NELEMENTS(supportedColorFormats);
53
static const int kSupportedArchitectures = NELEMENTS(supportedArchitectures);
54
static const int kMaxCores = 3;
55
56
static inline void *mvcd_aligned_malloc(void *pv_ctxt, WORD32 alignment, WORD32 i4_size)
57
826k
{
58
826k
    void *buf = nullptr;
59
826k
    (void) pv_ctxt;
60
61
826k
    if(0 != posix_memalign(&buf, alignment, i4_size))
62
0
    {
63
0
        return nullptr;
64
0
    }
65
66
826k
    return buf;
67
826k
}
68
69
static inline void mvcd_aligned_free(void *pv_ctxt, void *pv_buf)
70
826k
{
71
826k
    (void) pv_ctxt;
72
826k
    free(pv_buf);
73
826k
}
74
75
class Codec
76
{
77
   public:
78
    Codec(IV_COLOR_FORMAT_T colorFormat, size_t numCores);
79
    ~Codec();
80
81
    void resetCodec();
82
    WORD32 allocFrame();
83
    void freeFrame();
84
    IV_API_CALL_STATUS_T decodeHeader(const uint8_t *data, size_t size);
85
    IV_API_CALL_STATUS_T decodeFrame(const uint8_t *data, size_t size, size_t *bytesConsumed);
86
    void setArchitecture(IVD_ARCH_T arch);
87
    void setBufInfo();
88
    void setCores();
89
90
567k
    ivd_out_bufdesc_t *getOutBuf() { return &mOutBufHandle; }
91
92
136k
    iv_yuv_buf_t *getViewDispBuf(UWORD16 u2_view_id = 0) { return &as_view_disp_bufs[u2_view_id]; }
93
94
30.1k
    UWORD32 getNumViews() { return mBufInfo.s_mvc_buf_info.u2_num_views; }
95
96
0
    iv_obj_t *getCodecHandle() { return mCodec; }
97
98
   private:
99
    iv_obj_t *mCodec;
100
    ivd_out_bufdesc_t mOutBufHandle;
101
    iv_yuv_buf_t as_view_disp_bufs[MAX_NUM_VIEWS];
102
    imvcd_get_buf_info_op_t mBufInfo;
103
    IV_COLOR_FORMAT_T mColorFormat;
104
    size_t mNumCores;
105
    uint32_t mWidth;
106
    uint32_t mHeight;
107
};
108
109
Codec::Codec(IV_COLOR_FORMAT_T colorFormat, size_t numCores)
110
45.3k
    : mCodec(nullptr), mColorFormat(colorFormat), mNumCores(numCores), mWidth(0), mHeight(0)
111
45.3k
{
112
45.3k
    imvcd_create_ip_t s_create_ip;
113
45.3k
    imvcd_create_op_t s_create_op;
114
115
45.3k
    s_create_ip.s_ivd_ip.e_cmd = IVD_CMD_CREATE;
116
45.3k
    s_create_ip.s_ivd_ip.e_output_format = colorFormat;
117
45.3k
    s_create_ip.s_ivd_ip.pf_aligned_alloc = mvcd_aligned_malloc;
118
45.3k
    s_create_ip.s_ivd_ip.pf_aligned_free = mvcd_aligned_free;
119
45.3k
    s_create_ip.s_ivd_ip.u4_share_disp_buf = 0;
120
45.3k
    s_create_ip.s_ivd_ip.pv_mem_ctxt = nullptr;
121
122
45.3k
    s_create_ip.s_ivd_ip.u4_size = sizeof(s_create_ip.s_ivd_ip);
123
45.3k
    s_create_op.s_ivd_op.u4_size = sizeof(s_create_op.s_ivd_op);
124
125
45.3k
    imvcd_api_function(NULL, &s_create_ip, &s_create_op);
126
127
45.3k
    mCodec = static_cast<iv_obj_t *>(s_create_op.s_ivd_op.pv_handle);
128
129
45.3k
    setCores();
130
131
45.3k
    memset(getOutBuf(), 0, sizeof(getOutBuf()[0]));
132
45.3k
}
133
134
Codec::~Codec()
135
53.9k
{
136
53.9k
    imvcd_delete_ip_t s_delete_ip;
137
53.9k
    imvcd_delete_op_t s_delete_op;
138
139
53.9k
    s_delete_ip.s_ivd_ip.e_cmd = IVD_CMD_DELETE;
140
141
53.9k
    s_delete_ip.s_ivd_ip.u4_size = sizeof(s_delete_ip.s_ivd_ip);
142
53.9k
    s_delete_op.s_ivd_op.u4_size = sizeof(s_delete_op.s_ivd_op);
143
144
53.9k
    imvcd_api_function(mCodec, &s_delete_ip, &s_delete_op);
145
53.9k
}
146
147
void Codec::setCores()
148
45.3k
{
149
45.3k
    imvcd_set_num_cores_ip_t s_ctl_ip;
150
45.3k
    imvcd_set_num_cores_op_t s_ctl_op;
151
152
45.3k
    s_ctl_ip.u4_size = sizeof(s_ctl_ip);
153
45.3k
    s_ctl_op.u4_size = sizeof(s_ctl_op);
154
45.3k
    s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
155
45.3k
    s_ctl_ip.e_sub_cmd = static_cast<IVD_CONTROL_API_COMMAND_TYPE_T>(IMVCD_CTL_SET_NUM_CORES);
156
45.3k
    s_ctl_ip.u4_num_cores = mNumCores;
157
158
45.3k
    imvcd_api_function(mCodec, &s_ctl_ip, &s_ctl_op);
159
45.3k
}
160
161
void Codec::setArchitecture(IVD_ARCH_T e_arch)
162
45.3k
{
163
45.3k
    imvcd_set_arch_ip_t s_ctl_ip;
164
45.3k
    imvcd_set_arch_op_t s_ctl_op;
165
166
45.3k
    s_ctl_ip.u4_size = sizeof(s_ctl_ip);
167
45.3k
    s_ctl_op.u4_size = sizeof(s_ctl_op);
168
45.3k
    s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
169
45.3k
    s_ctl_ip.e_sub_cmd = static_cast<IVD_CONTROL_API_COMMAND_TYPE_T>(IMVCD_CTL_SET_PROCESSOR);
170
45.3k
    s_ctl_ip.e_arch = e_arch;
171
45.3k
    s_ctl_ip.e_soc = SOC_GENERIC;
172
173
45.3k
    imvcd_api_function(mCodec, &s_ctl_ip, &s_ctl_op);
174
45.3k
}
175
176
void Codec::setBufInfo()
177
15.0k
{
178
15.0k
    imvcd_get_buf_info_ip_t s_ctl_ip;
179
15.0k
    imvcd_get_buf_info_op_t s_ctl_op;
180
181
15.0k
    s_ctl_ip.s_ivd_ip.u4_size = sizeof(s_ctl_ip.s_ivd_ip);
182
15.0k
    s_ctl_op.s_ivd_op.u4_size = sizeof(s_ctl_op.s_ivd_op);
183
15.0k
    s_ctl_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_CTL;
184
15.0k
    s_ctl_ip.s_ivd_ip.e_sub_cmd =
185
15.0k
        static_cast<IVD_CONTROL_API_COMMAND_TYPE_T>(IVD_CMD_CTL_GETBUFINFO);
186
187
15.0k
    imvcd_api_function(mCodec, &s_ctl_ip, &s_ctl_op);
188
189
15.0k
    mBufInfo = s_ctl_op;
190
15.0k
}
191
192
WORD32 Codec::allocFrame()
193
15.0k
{
194
15.0k
    if(getNumViews() > MAX_NUM_VIEWS)
195
0
    {
196
0
        return IV_FAIL;
197
0
    }
198
199
15.0k
    if(mBufInfo.s_ivd_op.u4_min_num_out_bufs < (NUM_COMPONENTS * getNumViews()))
200
0
    {
201
0
        return IV_FAIL;
202
0
    }
203
204
15.0k
    getOutBuf()->u4_num_bufs = mBufInfo.s_ivd_op.u4_min_num_out_bufs;
205
206
61.1k
    for(UWORD32 i = 0; i < getOutBuf()->u4_num_bufs; i++)
207
46.0k
    {
208
46.0k
        getOutBuf()->u4_min_out_buf_size[i] = mBufInfo.s_ivd_op.u4_min_out_buf_size[i];
209
46.0k
        getOutBuf()->pu1_bufs[i] =
210
46.0k
            (UWORD8 *) mvcd_aligned_malloc(nullptr, 16, mBufInfo.s_ivd_op.u4_min_out_buf_size[i]);
211
212
46.0k
        if(getOutBuf()->pu1_bufs[i] == nullptr)
213
0
        {
214
0
            return IV_FAIL;
215
0
        }
216
46.0k
    }
217
218
15.0k
    return IV_SUCCESS;
219
15.0k
}
220
221
void Codec::freeFrame()
222
93.1k
{
223
259k
    for(UWORD32 i = 0; i < getOutBuf()->u4_num_bufs; i++)
224
166k
    {
225
166k
        if(getOutBuf()->pu1_bufs[i])
226
166k
        {
227
166k
            mvcd_aligned_free(nullptr, getOutBuf()->pu1_bufs[i]);
228
166k
            getOutBuf()->pu1_bufs[i] = nullptr;
229
166k
        }
230
166k
    }
231
93.1k
}
232
233
static void sendDecodeSignal(iv_obj_t *psCodec, IVD_VIDEO_DECODE_MODE_T eDecMode)
234
136k
{
235
136k
    imvcd_set_config_ip_t s_ctl_ip;
236
136k
    imvcd_set_config_op_t s_ctl_op;
237
238
136k
    s_ctl_ip.s_ivd_ip.u4_size = sizeof(s_ctl_ip.s_ivd_ip);
239
136k
    s_ctl_op.s_ivd_op.u4_size = sizeof(s_ctl_op.s_ivd_op);
240
136k
    s_ctl_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_CTL;
241
136k
    s_ctl_ip.s_ivd_ip.e_sub_cmd =
242
136k
        static_cast<IVD_CONTROL_API_COMMAND_TYPE_T>(IVD_CMD_CTL_SETPARAMS);
243
244
136k
    s_ctl_ip.s_ivd_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
245
136k
    s_ctl_ip.s_ivd_ip.e_frm_skip_mode = IVD_SKIP_NONE;
246
136k
    s_ctl_ip.s_ivd_ip.e_vid_dec_mode = eDecMode;
247
248
136k
    imvcd_api_function(psCodec, &s_ctl_ip, &s_ctl_op);
249
136k
}
250
251
IV_API_CALL_STATUS_T Codec::decodeHeader(const uint8_t *data, size_t size)
252
17.6k
{
253
17.6k
    IV_API_CALL_STATUS_T ret;
254
255
17.6k
    WORD32 numBytesRemaining = size;
256
257
17.6k
    sendDecodeSignal(mCodec, IVD_DECODE_HEADER);
258
259
17.6k
    while(size > 0)
260
17.6k
    {
261
17.6k
        imvcd_video_decode_ip_t s_video_decode_ip;
262
17.6k
        imvcd_video_decode_op_t s_video_decode_op;
263
264
17.6k
        UWORD32 u4_num_bytes_dec = 0;
265
266
17.6k
        memset(&s_video_decode_ip, 0, sizeof(s_video_decode_ip));
267
17.6k
        memset(&s_video_decode_op, 0, sizeof(s_video_decode_op));
268
269
17.6k
        s_video_decode_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
270
17.6k
        s_video_decode_ip.s_ivd_ip.u4_ts = 0;
271
17.6k
        s_video_decode_ip.s_ivd_ip.pv_stream_buffer =
272
17.6k
            static_cast<void *>(const_cast<uint8_t *>(data));
273
17.6k
        s_video_decode_ip.s_ivd_ip.u4_num_Bytes = numBytesRemaining;
274
17.6k
        s_video_decode_ip.s_ivd_ip.s_out_buffer = getOutBuf()[0];
275
17.6k
        s_video_decode_op.ps_view_disp_bufs = getViewDispBuf();
276
277
17.6k
        s_video_decode_ip.s_ivd_ip.u4_size = sizeof(s_video_decode_ip.s_ivd_ip);
278
17.6k
        s_video_decode_op.s_ivd_op.u4_size = sizeof(s_video_decode_op.s_ivd_op);
279
280
17.6k
        ret = imvcd_api_function(mCodec, &s_video_decode_ip, &s_video_decode_op);
281
282
17.6k
        if(IV_SUCCESS != ret)
283
2.54k
        {
284
2.54k
            return IV_FAIL;
285
2.54k
        }
286
287
15.0k
        u4_num_bytes_dec = s_video_decode_op.s_ivd_op.u4_num_bytes_consumed;
288
289
15.0k
        data += u4_num_bytes_dec;
290
15.0k
        numBytesRemaining -= u4_num_bytes_dec;
291
15.0k
        mWidth = s_video_decode_op.s_ivd_op.u4_pic_wd;
292
15.0k
        mHeight = s_video_decode_op.s_ivd_op.u4_pic_ht;
293
294
        /* Break after successful header decode */
295
15.0k
        if(mWidth && mHeight)
296
15.0k
        {
297
15.0k
            break;
298
15.0k
        }
299
15.0k
    }
300
301
    /* if width / height are invalid, set them to defaults */
302
15.0k
    if(!mWidth)
303
0
    {
304
0
        mWidth = 1920;
305
0
    }
306
307
15.0k
    if(!mHeight)
308
0
    {
309
0
        mHeight = 1080;
310
0
    }
311
312
15.0k
    setBufInfo();
313
314
15.0k
    return IV_SUCCESS;
315
17.6k
}
316
317
IV_API_CALL_STATUS_T Codec::decodeFrame(const uint8_t *data, size_t size, size_t *bytesConsumed)
318
119k
{
319
119k
    imvcd_video_decode_ip_t s_video_decode_ip;
320
119k
    imvcd_video_decode_op_t s_video_decode_op;
321
322
119k
    IV_API_CALL_STATUS_T ret;
323
324
119k
    memset(&s_video_decode_ip, 0, sizeof(s_video_decode_ip));
325
119k
    memset(&s_video_decode_op, 0, sizeof(s_video_decode_op));
326
327
119k
    sendDecodeSignal(mCodec, IVD_DECODE_FRAME);
328
329
119k
    s_video_decode_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
330
119k
    s_video_decode_ip.s_ivd_ip.u4_ts = 0;
331
119k
    s_video_decode_ip.s_ivd_ip.pv_stream_buffer = static_cast<void *>(const_cast<uint8_t *>(data));
332
119k
    s_video_decode_ip.s_ivd_ip.u4_num_Bytes = size;
333
119k
    s_video_decode_ip.s_ivd_ip.s_out_buffer = getOutBuf()[0];
334
119k
    s_video_decode_op.ps_view_disp_bufs = getViewDispBuf();
335
336
119k
    s_video_decode_ip.s_ivd_ip.u4_size = sizeof(s_video_decode_ip.s_ivd_ip);
337
119k
    s_video_decode_op.s_ivd_op.u4_size = sizeof(s_video_decode_op.s_ivd_op);
338
339
119k
    ret = imvcd_api_function(mCodec, &s_video_decode_ip, &s_video_decode_op);
340
341
119k
    bytesConsumed[0] = s_video_decode_op.s_ivd_op.u4_num_bytes_consumed;
342
343
119k
    if(s_video_decode_op.s_ivd_op.u4_pic_wd && s_video_decode_op.s_ivd_op.u4_pic_ht &&
344
108k
       ((mWidth != s_video_decode_op.s_ivd_op.u4_pic_wd) ||
345
108k
        (mHeight != s_video_decode_op.s_ivd_op.u4_pic_ht)))
346
0
    {
347
0
        mWidth = s_video_decode_op.s_ivd_op.u4_pic_wd;
348
0
        mHeight = s_video_decode_op.s_ivd_op.u4_pic_ht;
349
0
        freeFrame();
350
0
        allocFrame();
351
0
    }
352
353
119k
    return ret;
354
119k
}
355
356
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
357
17.6k
{
358
17.6k
    if(size < 1)
359
0
    {
360
0
        return 0;
361
0
    }
362
363
17.6k
    WORD32 ret;
364
365
17.6k
    size_t colorFormatOfst = std::min((size_t) OFFSET_COLOR_FORMAT, size - 1);
366
17.6k
    size_t numCoresOfst = std::min((size_t) OFFSET_NUM_CORES, size - 1);
367
17.6k
    size_t architectureOfst = std::min((size_t) OFFSET_ARCH, size - 1);
368
17.6k
    size_t architectureIdx = data[architectureOfst] % kSupportedArchitectures;
369
17.6k
    size_t colorFormatIdx = data[colorFormatOfst] % kSupportedColorFormats;
370
17.6k
    uint32_t numCores = (data[numCoresOfst] % kMaxCores) + 1;
371
17.6k
    uint32_t numDecodeCalls = 0;
372
373
17.6k
    IVD_ARCH_T arch = (IVD_ARCH_T) supportedArchitectures[architectureIdx];
374
17.6k
    IV_COLOR_FORMAT_T colorFormat = (IV_COLOR_FORMAT_T) (supportedColorFormats[colorFormatIdx]);
375
376
17.6k
    Codec cCodec = Codec(colorFormat, numCores);
377
378
17.6k
    cCodec.setArchitecture(arch);
379
380
17.6k
    ret = cCodec.decodeHeader(data, size);
381
382
17.6k
    if(IV_SUCCESS != ret)
383
2.54k
    {
384
2.54k
        return 0;
385
2.54k
    }
386
387
15.0k
    ret = cCodec.allocFrame();
388
389
15.0k
    if(IV_SUCCESS != ret)
390
0
    {
391
0
        cCodec.freeFrame();
392
393
0
        return 0;
394
0
    }
395
396
123k
    while((size > 0) && (numDecodeCalls < kMaxNumDecodeCalls))
397
119k
    {
398
119k
        size_t bytesConsumed;
399
400
119k
        IV_API_CALL_STATUS_T ret = cCodec.decodeFrame(data, size, &bytesConsumed);
401
402
119k
        if(ret != IV_SUCCESS)
403
10.4k
        {
404
10.4k
            break;
405
10.4k
        }
406
407
108k
        bytesConsumed = std::min(size, bytesConsumed);
408
108k
        data += bytesConsumed;
409
108k
        size -= bytesConsumed;
410
108k
        numDecodeCalls++;
411
108k
    }
412
413
15.0k
    cCodec.freeFrame();
414
415
15.0k
    return 0;
416
15.0k
}