1 // TODO: This should be moved to the openh264 repo.
2
3 #include <stddef.h>
4 #include <stdint.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include <memory>
10
11 #include "codec_def.h"
12 #include "codec_app_def.h"
13 #include "codec_api.h"
14 #include "read_config.h"
15 #include "typedefs.h"
16 #include "measure_time.h"
17
18 /*
19 * To build locally:
20 * CC=clang CXX=clang++ CFLAGS="-fsanitize=address,fuzzer-no-link -g" CXXFLAGS="-fsanitize=address,fuzzer-no-link -g" LDFLAGS="-fsanitize=address,fuzzer-no-link" make -j$(nproc) USE_ASM=No BUILDTYPE=Debug libraries
21 * clang++ -o decoder_fuzzer -fsanitize=address -g -O1 -I./codec/api/svc -I./codec/console/common/inc -I./codec/common/inc -L. -lFuzzer -lstdc++ decoder_fuzzer.cpp libopenh264.a
22 */
23
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)24 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
25 {
26 int32_t i;
27 int32_t iBufPos = 0;
28 int32_t iEndOfStreamFlag;
29 int iLevelSetting = (int) WELS_LOG_QUIET; // disable logging while fuzzing
30 int32_t iSliceSize;
31 ISVCDecoder *pDecoder;
32 SDecodingParam sDecParam = {0};
33 SBufferInfo sDstBufInfo;
34 std::unique_ptr<uint8_t[]> pBuf(new uint8_t[size + 4]);
35 uint8_t* pData[3] = {NULL};
36 uint8_t uiStartCode[4] = {0, 0, 0, 1};
37
38 memcpy(pBuf.get(), data, size);
39 memcpy(pBuf.get() + size, &uiStartCode[0], 4);
40 memset(&sDstBufInfo, 0, sizeof(SBufferInfo));
41
42 // TODO: is this the best/fastest ERROR_CON to use?
43 sDecParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
44 // TODO: should we also fuzz VIDEO_BITSTREAM_SVC?
45 sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
46
47 WelsCreateDecoder (&pDecoder);
48 pDecoder->Initialize (&sDecParam);
49 pDecoder->SetOption (DECODER_OPTION_TRACE_LEVEL, &iLevelSetting);
50
51 while (1) {
52 if (iBufPos >= size) {
53 iEndOfStreamFlag = 1;
54 if (iEndOfStreamFlag)
55 pDecoder->SetOption (DECODER_OPTION_END_OF_STREAM, (void*)&iEndOfStreamFlag);
56 break;
57 }
58
59 for (i = 0; i < size; i++) {
60 if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1
61 && i > 0) || (pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 1 && i > 0)) {
62 break;
63 }
64 }
65 iSliceSize = i;
66 if (iSliceSize < 4) {
67 if (iSliceSize == 0) {
68 // I don't think this should happen but let's just avoid the hang
69 goto label_cleanup;
70 }
71 iBufPos += iSliceSize;
72 continue;
73 }
74
75 pDecoder->DecodeFrameNoDelay (pBuf.get() + iBufPos, iSliceSize, pData, &sDstBufInfo);
76 iBufPos += iSliceSize;
77 }
78
79 label_cleanup:
80 pDecoder->Uninitialize ();
81 WelsDestroyDecoder (pDecoder);
82
83 return 0;
84 }
85