Line | Count | Source (jump to first uncovered line) |
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 | | |
24 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
25 | 272k | { |
26 | 272k | int32_t i; |
27 | 272k | int32_t iBufPos = 0; |
28 | 272k | int32_t iEndOfStreamFlag; |
29 | 272k | int iLevelSetting = (int) WELS_LOG_QUIET; // disable logging while fuzzing |
30 | 272k | int32_t iSliceSize; |
31 | 272k | ISVCDecoder *pDecoder; |
32 | 272k | SDecodingParam sDecParam = {0}; |
33 | 272k | SBufferInfo sDstBufInfo; |
34 | 272k | std::unique_ptr<uint8_t[]> pBuf(new uint8_t[size + 4]); |
35 | 272k | uint8_t* pData[3] = {NULL}; |
36 | 272k | uint8_t uiStartCode[4] = {0, 0, 0, 1}; |
37 | | |
38 | 272k | memcpy(pBuf.get(), data, size); |
39 | 272k | memcpy(pBuf.get() + size, &uiStartCode[0], 4); |
40 | 272k | memset(&sDstBufInfo, 0, sizeof(SBufferInfo)); |
41 | | |
42 | | // TODO: is this the best/fastest ERROR_CON to use? |
43 | 272k | sDecParam.eEcActiveIdc = ERROR_CON_SLICE_COPY; |
44 | | // TODO: should we also fuzz VIDEO_BITSTREAM_SVC? |
45 | 272k | sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC; |
46 | | |
47 | 272k | WelsCreateDecoder (&pDecoder); |
48 | 272k | pDecoder->Initialize (&sDecParam); |
49 | 272k | pDecoder->SetOption (DECODER_OPTION_TRACE_LEVEL, &iLevelSetting); |
50 | | |
51 | 29.0M | while (1) { |
52 | 29.0M | if (iBufPos >= size) { |
53 | 272k | iEndOfStreamFlag = 1; |
54 | 272k | if (iEndOfStreamFlag) |
55 | 272k | pDecoder->SetOption (DECODER_OPTION_END_OF_STREAM, (void*)&iEndOfStreamFlag); |
56 | 272k | break; |
57 | 272k | } |
58 | | |
59 | 1.94G | for (i = 0; i < size; i++) { |
60 | 1.94G | if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1 |
61 | 1.94G | && i > 0) || (pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 1 && i > 0)) { |
62 | 28.7M | break; |
63 | 28.7M | } |
64 | 1.94G | } |
65 | 28.7M | iSliceSize = i; |
66 | 28.7M | if (iSliceSize < 4) { |
67 | 11.2M | if (iSliceSize == 0) { |
68 | | // I don't think this should happen but let's just avoid the hang |
69 | 0 | goto label_cleanup; |
70 | 0 | } |
71 | 11.2M | iBufPos += iSliceSize; |
72 | 11.2M | continue; |
73 | 11.2M | } |
74 | | |
75 | 17.5M | pDecoder->DecodeFrameNoDelay (pBuf.get() + iBufPos, iSliceSize, pData, &sDstBufInfo); |
76 | 17.5M | iBufPos += iSliceSize; |
77 | 17.5M | } |
78 | | |
79 | 272k | label_cleanup: |
80 | 272k | pDecoder->Uninitialize (); |
81 | 272k | WelsDestroyDecoder (pDecoder); |
82 | | |
83 | 272k | return 0; |
84 | 272k | } |