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  | 9.24k  | { | 
26  | 9.24k  |   int32_t i;  | 
27  | 9.24k  |   int32_t iBufPos = 0;  | 
28  | 9.24k  |   int32_t iEndOfStreamFlag;  | 
29  | 9.24k  |   int iLevelSetting = (int) WELS_LOG_QUIET; // disable logging while fuzzing  | 
30  | 9.24k  |   int32_t iSliceSize;  | 
31  | 9.24k  |   ISVCDecoder *pDecoder;  | 
32  | 9.24k  |   SDecodingParam sDecParam = {0}; | 
33  | 9.24k  |   SBufferInfo sDstBufInfo;  | 
34  | 9.24k  |   std::unique_ptr<uint8_t[]> pBuf(new uint8_t[size + 4]);  | 
35  | 9.24k  |   uint8_t* pData[3] = {NULL}; | 
36  | 9.24k  |   uint8_t uiStartCode[4] = {0, 0, 0, 1}; | 
37  |  |  | 
38  | 9.24k  |   memcpy(pBuf.get(), data, size);  | 
39  | 9.24k  |   memcpy(pBuf.get() + size, &uiStartCode[0], 4);  | 
40  | 9.24k  |   memset(&sDstBufInfo, 0, sizeof(SBufferInfo));  | 
41  |  |  | 
42  |  |   // TODO: is this the best/fastest ERROR_CON to use?  | 
43  | 9.24k  |   sDecParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;  | 
44  |  |   // TODO: should we also fuzz VIDEO_BITSTREAM_SVC?  | 
45  | 9.24k  |   sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;  | 
46  |  |     | 
47  | 9.24k  |   WelsCreateDecoder (&pDecoder);  | 
48  | 9.24k  |   pDecoder->Initialize (&sDecParam);  | 
49  | 9.24k  |   pDecoder->SetOption (DECODER_OPTION_TRACE_LEVEL, &iLevelSetting);  | 
50  |  |  | 
51  | 1.50M  |   while (1) { | 
52  | 1.50M  |     if (iBufPos >= size) { | 
53  | 9.24k  |       iEndOfStreamFlag = 1;  | 
54  | 9.24k  |       if (iEndOfStreamFlag)  | 
55  | 9.24k  |         pDecoder->SetOption (DECODER_OPTION_END_OF_STREAM, (void*)&iEndOfStreamFlag);  | 
56  | 9.24k  |       break;  | 
57  | 9.24k  |     }  | 
58  |  |  | 
59  | 1.14G  |     for (i = 0; i < size; i++) { | 
60  | 1.14G  |       if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1  | 
61  | 1.14G  |           && i > 0) || (pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 1 && i > 0)) { | 
62  | 1.49M  |         break;  | 
63  | 1.49M  |       }  | 
64  | 1.14G  |     }  | 
65  | 1.49M  |     iSliceSize = i;  | 
66  | 1.49M  |     if (iSliceSize < 4) { | 
67  | 747k  |       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  | 747k  |       iBufPos += iSliceSize;  | 
72  | 747k  |       continue;  | 
73  | 747k  |     }  | 
74  |  |  | 
75  | 750k  |     pDecoder->DecodeFrameNoDelay (pBuf.get() + iBufPos, iSliceSize, pData, &sDstBufInfo);  | 
76  | 750k  |     iBufPos += iSliceSize;  | 
77  | 750k  |   }  | 
78  |  |  | 
79  | 9.24k  | label_cleanup:  | 
80  | 9.24k  |   pDecoder->Uninitialize ();  | 
81  | 9.24k  |   WelsDestroyDecoder (pDecoder);  | 
82  |  |  | 
83  | 9.24k  |   return 0;  | 
84  | 9.24k  | }  |