Coverage Report

Created: 2026-03-31 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libavc/fuzzer/svc_dec_fuzzer.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Copyright (C) 2022 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
/**
21
 *******************************************************************************
22
 * @file
23
 *  svc_dec_fuzzer.cpp
24
 *
25
 * @brief
26
 *  Contains functions required for fuzzer tests
27
 *
28
 * @author
29
 *  Kishore
30
 *
31
 * @remarks
32
 *  None
33
 *
34
 *******************************************************************************
35
 */
36
37
#include <stddef.h>
38
#include <stdint.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <string.h>
42
43
#include <algorithm>
44
#include <memory>
45
46
#include "ih264_typedefs.h"
47
#include "ithread.h"
48
#include "iv.h"
49
#include "ivd.h"
50
51
#include "ih264d.h"
52
#include "isvcd.h"
53
54
#define NELEMENTS(x) (sizeof(x) / sizeof(x[0]))
55
939k
#define ivd_api_function isvcd_api_function
56
const IV_COLOR_FORMAT_T supportedColorFormats[] = {IV_YUV_420P,   IV_YUV_420SP_UV, IV_YUV_420SP_VU,
57
                                                   IV_YUV_422ILE, IV_RGB_565,      IV_RGBA_8888};
58
59
/* Decoder ignores invalid arch, i.e. for arm build, if SSSE3 is requested,
60
 * decoder defaults to a supported configuration. So same set of supported
61
 * architectures can be used in arm/arm64/x86 builds */
62
const IVD_ARCH_T supportedArchitectures[] = {
63
    ARCH_ARM_NONEON,  ARCH_ARM_A9Q,   ARCH_ARM_NEONINTR, ARCH_ARMV8_GENERIC,
64
    ARCH_X86_GENERIC, ARCH_X86_SSSE3, ARCH_X86_SSE42};
65
66
enum
67
{
68
    OFFSET_COLOR_FORMAT = 6,
69
    OFFSET_NUM_CORES,
70
    OFFSET_ARCH,
71
    OFFSET_TGT_LAYER,
72
    /* Should be the last entry */
73
    OFFSET_MAX,
74
};
75
76
const static int kMaxNumDecodeCalls = 100;
77
const static int kSupportedColorFormats = NELEMENTS(supportedColorFormats);
78
const static int kSupportedArchitectures = NELEMENTS(supportedArchitectures);
79
const static int kMaxCores = 4;
80
const static int kMaxTgtLayer = 2;
81
void *iv_aligned_malloc(void *ctxt, WORD32 alignment, WORD32 size)
82
3.93M
{
83
3.93M
    void *buf = NULL;
84
3.93M
    (void) ctxt;
85
3.93M
    if(0 != posix_memalign(&buf, alignment, size))
86
0
    {
87
0
        return NULL;
88
0
    }
89
3.93M
    return buf;
90
3.93M
}
91
92
void iv_aligned_free(void *ctxt, void *buf)
93
3.93M
{
94
3.93M
    (void) ctxt;
95
3.93M
    free(buf);
96
3.93M
}
97
98
class Codec
99
{
100
   public:
101
    Codec(IV_COLOR_FORMAT_T colorFormat, size_t numCores);
102
    ~Codec();
103
104
    void createCodec();
105
    void deleteCodec();
106
    void resetCodec();
107
    void setCores();
108
    void allocFrame();
109
    void freeFrame();
110
    void decodeHeader(const uint8_t *data, size_t size);
111
    IV_API_CALL_STATUS_T decodeFrame(const uint8_t *data, size_t size, size_t *bytesConsumed);
112
    void setParams(IVD_VIDEO_DECODE_MODE_T mode);
113
    void setArchitecture(IVD_ARCH_T arch);
114
    void setTgtLayer(size_t tgtLayer);
115
116
   private:
117
    IV_COLOR_FORMAT_T mColorFormat;
118
    size_t mNumCores;
119
    iv_obj_t *mCodec;
120
    ivd_out_bufdesc_t mOutBufHandle;
121
    uint32_t mWidth;
122
    uint32_t mHeight;
123
};
124
125
Codec::Codec(IV_COLOR_FORMAT_T colorFormat, size_t numCores)
126
27.6k
{
127
27.6k
    mColorFormat = colorFormat;
128
27.6k
    mNumCores = numCores;
129
27.6k
    mCodec = nullptr;
130
27.6k
    mWidth = 0;
131
27.6k
    mHeight = 0;
132
133
27.6k
    memset(&mOutBufHandle, 0, sizeof(mOutBufHandle));
134
27.6k
}
135
136
36.2k
Codec::~Codec() {}
137
void Codec::createCodec()
138
23.7k
{
139
23.7k
    IV_API_CALL_STATUS_T ret;
140
23.7k
    ih264d_create_ip_t create_ip{};
141
23.7k
    ih264d_create_op_t create_op{};
142
23.7k
    void *fxns = (void *) &ivd_api_function;
143
144
23.7k
    create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
145
23.7k
    create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0;
146
23.7k
    create_ip.s_ivd_create_ip_t.e_output_format = mColorFormat;
147
23.7k
    create_ip.s_ivd_create_ip_t.pf_aligned_alloc = iv_aligned_malloc;
148
23.7k
    create_ip.s_ivd_create_ip_t.pf_aligned_free = iv_aligned_free;
149
23.7k
    create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL;
150
23.7k
    create_ip.s_ivd_create_ip_t.u4_size = sizeof(ih264d_create_ip_t);
151
23.7k
    create_op.s_ivd_create_op_t.u4_size = sizeof(ih264d_create_op_t);
152
153
23.7k
    ret = ivd_api_function(NULL, (void *) &create_ip, (void *) &create_op);
154
23.7k
    if(ret != IV_SUCCESS)
155
17
    {
156
17
        return;
157
17
    }
158
23.7k
    mCodec = (iv_obj_t *) create_op.s_ivd_create_op_t.pv_handle;
159
23.7k
    mCodec->pv_fxns = fxns;
160
23.7k
    mCodec->u4_size = sizeof(iv_obj_t);
161
23.7k
}
162
163
void Codec::deleteCodec()
164
23.7k
{
165
23.7k
    ivd_delete_ip_t delete_ip{};
166
23.7k
    ivd_delete_op_t delete_op{};
167
168
23.7k
    delete_ip.e_cmd = IVD_CMD_DELETE;
169
23.7k
    delete_ip.u4_size = sizeof(ivd_delete_ip_t);
170
23.7k
    delete_op.u4_size = sizeof(ivd_delete_op_t);
171
172
23.7k
    ivd_api_function(mCodec, (void *) &delete_ip, (void *) &delete_op);
173
23.7k
}
174
175
void Codec::resetCodec()
176
6.13k
{
177
6.13k
    ivd_ctl_reset_ip_t s_ctl_ip{};
178
6.13k
    ivd_ctl_reset_op_t s_ctl_op{};
179
180
6.13k
    s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
181
6.13k
    s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET;
182
6.13k
    s_ctl_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
183
6.13k
    s_ctl_op.u4_size = sizeof(ivd_ctl_reset_op_t);
184
185
6.13k
    ivd_api_function(mCodec, (void *) &s_ctl_ip, (void *) &s_ctl_op);
186
6.13k
}
187
188
void Codec::setCores()
189
27.6k
{
190
27.6k
    ih264d_ctl_set_num_cores_ip_t s_ctl_ip{};
191
27.6k
    ih264d_ctl_set_num_cores_op_t s_ctl_op{};
192
193
27.6k
    s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
194
27.6k
    s_ctl_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T) IH264D_CMD_CTL_SET_NUM_CORES;
195
27.6k
    s_ctl_ip.u4_num_cores = mNumCores;
196
27.6k
    s_ctl_ip.u4_size = sizeof(ih264d_ctl_set_num_cores_ip_t);
197
27.6k
    s_ctl_op.u4_size = sizeof(ih264d_ctl_set_num_cores_op_t);
198
199
27.6k
    ivd_api_function(mCodec, (void *) &s_ctl_ip, (void *) &s_ctl_op);
200
27.6k
}
201
202
void Codec::setTgtLayer(size_t TgtLayer)
203
23.3k
{
204
23.3k
    isvcd_set_target_layer_ip_t s_ctl_set_target_layer_ip{};
205
23.3k
    isvcd_set_target_layer_op_t s_ctl_set_target_layer_op{};
206
207
23.3k
    s_ctl_set_target_layer_ip.e_cmd = IVD_CMD_VIDEO_CTL;
208
23.3k
    s_ctl_set_target_layer_ip.e_sub_cmd =
209
23.3k
        (IVD_CONTROL_API_COMMAND_TYPE_T) ISVCD_CMD_CTL_SET_TGT_LAYER;
210
23.3k
    s_ctl_set_target_layer_ip.u1_tgt_priority_id = 63;
211
23.3k
    s_ctl_set_target_layer_ip.u1_tgt_temp_id = 7;
212
23.3k
    s_ctl_set_target_layer_ip.u1_tgt_quality_id = 0;
213
23.3k
    s_ctl_set_target_layer_ip.u1_tgt_dep_id = TgtLayer;
214
23.3k
    s_ctl_set_target_layer_ip.u4_size = sizeof(isvcd_set_target_layer_ip_t);
215
23.3k
    s_ctl_set_target_layer_op.u4_size = sizeof(isvcd_set_target_layer_op_t);
216
217
23.3k
    ivd_api_function(mCodec, (void *) &s_ctl_set_target_layer_ip,
218
23.3k
                     (void *) &s_ctl_set_target_layer_op);
219
23.3k
}
220
221
void Codec::setParams(IVD_VIDEO_DECODE_MODE_T mode)
222
47.5k
{
223
47.5k
    ivd_ctl_set_config_ip_t s_ctl_ip{};
224
47.5k
    ivd_ctl_set_config_op_t s_ctl_op{};
225
226
47.5k
    s_ctl_ip.u4_disp_wd = 0;
227
47.5k
    s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE;
228
47.5k
    s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
229
47.5k
    s_ctl_ip.e_vid_dec_mode = mode;
230
47.5k
    s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
231
47.5k
    s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
232
47.5k
    s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
233
47.5k
    s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
234
235
47.5k
    ivd_api_function(mCodec, (void *) &s_ctl_ip, (void *) &s_ctl_op);
236
47.5k
}
237
238
void Codec::setArchitecture(IVD_ARCH_T arch)
239
27.6k
{
240
27.6k
    ih264d_ctl_set_processor_ip_t s_ctl_ip{};
241
27.6k
    ih264d_ctl_set_processor_op_t s_ctl_op{};
242
243
27.6k
    s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
244
27.6k
    s_ctl_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T) IH264D_CMD_CTL_SET_PROCESSOR;
245
27.6k
    s_ctl_ip.u4_arch = arch;
246
27.6k
    s_ctl_ip.u4_soc = SOC_GENERIC;
247
27.6k
    s_ctl_ip.u4_size = sizeof(ih264d_ctl_set_processor_ip_t);
248
27.6k
    s_ctl_op.u4_size = sizeof(ih264d_ctl_set_processor_op_t);
249
250
27.6k
    ivd_api_function(mCodec, (void *) &s_ctl_ip, (void *) &s_ctl_op);
251
27.6k
}
252
253
void Codec::freeFrame()
254
70.9k
{
255
186k
    for(unsigned int i = 0; i < mOutBufHandle.u4_num_bufs; i++)
256
115k
    {
257
115k
        if(mOutBufHandle.pu1_bufs[i])
258
115k
        {
259
115k
            iv_aligned_free(NULL, mOutBufHandle.pu1_bufs[i]);
260
115k
            mOutBufHandle.pu1_bufs[i] = nullptr;
261
115k
        }
262
115k
    }
263
70.9k
}
264
265
void Codec::allocFrame()
266
43.3k
{
267
43.3k
    size_t sizes[4] = {0};
268
43.3k
    UWORD32 num_bufs = 0;
269
270
43.3k
    freeFrame();
271
272
43.3k
    memset(&mOutBufHandle, 0, sizeof(mOutBufHandle));
273
274
43.3k
    switch(mColorFormat)
275
43.3k
    {
276
13.2k
        case IV_YUV_420SP_UV:
277
13.2k
            [[fallthrough]];
278
25.5k
        case IV_YUV_420SP_VU:
279
25.5k
            sizes[0] = mWidth * mHeight;
280
25.5k
            sizes[1] = mWidth * mHeight >> 1;
281
25.5k
            num_bufs = 2;
282
25.5k
            break;
283
137
        case IV_YUV_422ILE:
284
137
            sizes[0] = mWidth * mHeight * 2;
285
137
            num_bufs = 1;
286
137
            break;
287
214
        case IV_RGB_565:
288
214
            sizes[0] = mWidth * mHeight * 2;
289
214
            num_bufs = 1;
290
214
            break;
291
6
        case IV_RGBA_8888:
292
6
            sizes[0] = mWidth * mHeight * 4;
293
6
            num_bufs = 1;
294
6
            break;
295
17.4k
        case IV_YUV_420P:
296
17.4k
            [[fallthrough]];
297
17.4k
        default:
298
17.4k
            sizes[0] = mWidth * mHeight;
299
17.4k
            sizes[1] = mWidth * mHeight >> 2;
300
17.4k
            sizes[2] = mWidth * mHeight >> 2;
301
17.4k
            num_bufs = 3;
302
17.4k
            break;
303
43.3k
    }
304
43.3k
    mOutBufHandle.u4_num_bufs = num_bufs;
305
147k
    for(UWORD32 i = 0; i < num_bufs; i++)
306
103k
    {
307
103k
        mOutBufHandle.u4_min_out_buf_size[i] = sizes[i];
308
103k
        mOutBufHandle.pu1_bufs[i] = (UWORD8 *) iv_aligned_malloc(NULL, 16, sizes[i]);
309
103k
    }
310
43.3k
}
311
312
void Codec::decodeHeader(const uint8_t *data, size_t size)
313
23.7k
{
314
23.7k
    setParams(IVD_DECODE_HEADER);
315
23.7k
    size_t numDecodeCalls = 0;
316
527k
    while(size > 0 && numDecodeCalls < kMaxNumDecodeCalls)
317
504k
    {
318
504k
        IV_API_CALL_STATUS_T ret;
319
504k
        isvcd_video_decode_ip_t s_video_decode_ip;
320
504k
        isvcd_video_decode_op_t s_video_decode_op;
321
504k
        size_t bytes_consumed;
322
504k
        memset(&s_video_decode_ip, 0, sizeof(s_video_decode_ip));
323
504k
        memset(&s_video_decode_op, 0, sizeof(s_video_decode_op));
324
325
504k
        s_video_decode_ip.s_ivd_video_decode_ip_t.e_cmd = IVD_CMD_VIDEO_DECODE;
326
504k
        s_video_decode_ip.s_ivd_video_decode_ip_t.u4_ts = 0;
327
504k
        s_video_decode_ip.s_ivd_video_decode_ip_t.pv_stream_buffer = (void *) data;
328
504k
        s_video_decode_ip.s_ivd_video_decode_ip_t.u4_num_Bytes = size;
329
504k
        s_video_decode_ip.s_ivd_video_decode_ip_t.u4_size = sizeof(s_video_decode_ip);
330
504k
        s_video_decode_op.s_ivd_video_decode_op_t.u4_size = sizeof(s_video_decode_op);
331
332
504k
        ret = ivd_api_function(mCodec, (void *) &s_video_decode_ip, (void *) &s_video_decode_op);
333
504k
        (void(ret));
334
504k
        bytes_consumed = s_video_decode_op.s_ivd_video_decode_op_t.u4_num_bytes_consumed;
335
        /* If no bytes are consumed, then consume 4 bytes to ensure fuzzer proceeds
336
         * to feed next data */
337
504k
        if(!bytes_consumed) bytes_consumed = 4;
338
339
504k
        bytes_consumed = std::min(size, bytes_consumed);
340
341
504k
        data += bytes_consumed;
342
504k
        size -= bytes_consumed;
343
504k
        numDecodeCalls++;
344
345
504k
        mWidth = std::min(s_video_decode_op.s_ivd_video_decode_op_t.u4_pic_wd, (UWORD32) 10240);
346
504k
        mHeight = std::min(s_video_decode_op.s_ivd_video_decode_op_t.u4_pic_ht, (UWORD32) 10240);
347
348
        /* Break after successful header decode */
349
504k
        if(mWidth && mHeight)
350
348
        {
351
348
            break;
352
348
        }
353
504k
    }
354
    /* if width / height are invalid, set them to defaults */
355
23.7k
    if(!mWidth) mWidth = 1920;
356
23.7k
    if(!mHeight) mHeight = 1088;
357
23.7k
}
358
359
IV_API_CALL_STATUS_T Codec::decodeFrame(const uint8_t *data, size_t size, size_t *bytesConsumed)
360
225k
{
361
225k
    IV_API_CALL_STATUS_T ret;
362
225k
    isvcd_video_decode_ip_t s_video_decode_ip{};
363
225k
    isvcd_video_decode_op_t s_video_decode_op{};
364
365
225k
    s_video_decode_ip.s_ivd_video_decode_ip_t.e_cmd = IVD_CMD_VIDEO_DECODE;
366
225k
    s_video_decode_ip.s_ivd_video_decode_ip_t.u4_ts = 0;
367
225k
    s_video_decode_ip.s_ivd_video_decode_ip_t.pv_stream_buffer = (void *) data;
368
225k
    s_video_decode_ip.s_ivd_video_decode_ip_t.u4_num_Bytes = size;
369
225k
    s_video_decode_ip.s_ivd_video_decode_ip_t.u4_size = sizeof(s_video_decode_ip);
370
225k
    s_video_decode_ip.s_ivd_video_decode_ip_t.s_out_buffer = mOutBufHandle;
371
372
225k
    s_video_decode_op.s_ivd_video_decode_op_t.u4_size = sizeof(s_video_decode_op);
373
225k
    s_video_decode_op.s_ivd_video_decode_op_t.u4_num_bytes_consumed = 0;
374
225k
    s_video_decode_op.s_ivd_video_decode_op_t.u4_pic_wd = 0;
375
225k
    s_video_decode_op.s_ivd_video_decode_op_t.u4_pic_ht = 0;
376
377
225k
    ret = ivd_api_function(mCodec, (void *) &s_video_decode_ip, (void *) &s_video_decode_op);
378
379
    /* In case of change in resolution, reset codec and feed the same data again
380
     */
381
225k
    if(IVD_RES_CHANGED == (s_video_decode_op.s_ivd_video_decode_op_t.u4_error_code & 0xFF))
382
6.13k
    {
383
6.13k
        resetCodec();
384
6.13k
        ret = ivd_api_function(mCodec, (void *) &s_video_decode_ip, (void *) &s_video_decode_op);
385
6.13k
    }
386
225k
    *bytesConsumed = s_video_decode_op.s_ivd_video_decode_op_t.u4_num_bytes_consumed;
387
388
    /* If no bytes are consumed, then consume 4 bytes to ensure fuzzer proceeds
389
     * to feed next data */
390
225k
    if(!*bytesConsumed)
391
46.2k
    {
392
46.2k
        *bytesConsumed = 4;
393
46.2k
    }
394
225k
    if(s_video_decode_op.s_ivd_video_decode_op_t.u4_pic_wd &&
395
106k
       s_video_decode_op.s_ivd_video_decode_op_t.u4_pic_ht &&
396
106k
       (mWidth != s_video_decode_op.s_ivd_video_decode_op_t.u4_pic_wd ||
397
87.5k
        mHeight != s_video_decode_op.s_ivd_video_decode_op_t.u4_pic_ht))
398
19.5k
    {
399
19.5k
        mWidth = std::min(s_video_decode_op.s_ivd_video_decode_op_t.u4_pic_wd, (UWORD32) 10240);
400
19.5k
        mHeight = std::min(s_video_decode_op.s_ivd_video_decode_op_t.u4_pic_ht, (UWORD32) 10240);
401
19.5k
        allocFrame();
402
19.5k
    }
403
404
225k
    return ret;
405
225k
}
406
407
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
408
23.7k
{
409
23.7k
    if(size < 1)
410
0
    {
411
0
        return 0;
412
0
    }
413
23.7k
    size_t colorFormatOfst = std::min((size_t) OFFSET_COLOR_FORMAT, size - 1);
414
23.7k
    size_t numCoresOfst = std::min((size_t) OFFSET_NUM_CORES, size - 1);
415
23.7k
    size_t architectureOfst = std::min((size_t) OFFSET_ARCH, size - 1);
416
23.7k
    size_t architectureIdx = data[architectureOfst] % kSupportedArchitectures;
417
23.7k
    IVD_ARCH_T arch = (IVD_ARCH_T) supportedArchitectures[architectureIdx];
418
23.7k
    size_t colorFormatIdx = data[colorFormatOfst] % kSupportedColorFormats;
419
23.7k
    IV_COLOR_FORMAT_T colorFormat = (IV_COLOR_FORMAT_T) (supportedColorFormats[colorFormatIdx]);
420
23.7k
    uint32_t numCores = (data[numCoresOfst] % kMaxCores) + 1;
421
422
23.7k
    size_t numTgtLayerOfst = std::min((size_t) OFFSET_TGT_LAYER, size - 1);
423
23.7k
    uint32_t tgtLayer = (data[numTgtLayerOfst] % kMaxTgtLayer);
424
425
23.7k
    size_t numDecodeCalls = 0;
426
23.7k
    Codec *codec = new Codec(colorFormat, numCores);
427
23.7k
    codec->createCodec();
428
23.7k
    codec->setArchitecture(arch);
429
23.7k
    codec->setCores();
430
23.7k
    codec->setTgtLayer(tgtLayer);
431
23.7k
    codec->decodeHeader(data, size);
432
23.7k
    codec->setParams(IVD_DECODE_FRAME);
433
23.7k
    codec->allocFrame();
434
435
249k
    while(size > 0 && numDecodeCalls < kMaxNumDecodeCalls)
436
225k
    {
437
225k
        IV_API_CALL_STATUS_T ret;
438
225k
        size_t bytesConsumed;
439
225k
        ret = codec->decodeFrame(data, size, &bytesConsumed);
440
225k
        (void(ret));
441
225k
        bytesConsumed = std::min(size, bytesConsumed);
442
225k
        data += bytesConsumed;
443
225k
        size -= bytesConsumed;
444
225k
        numDecodeCalls++;
445
225k
    }
446
447
23.7k
    codec->freeFrame();
448
23.7k
    codec->deleteCodec();
449
23.7k
    delete codec;
450
23.7k
    return 0;
451
23.7k
}