• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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