85 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			85 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| // TODO: This should be moved to the openh264 repo.
 | |
| 
 | |
| #include <stddef.h>
 | |
| #include <stdint.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #include <memory>
 | |
| 
 | |
| #include "codec_def.h"
 | |
| #include "codec_app_def.h"
 | |
| #include "codec_api.h"
 | |
| #include "read_config.h"
 | |
| #include "typedefs.h"
 | |
| #include "measure_time.h"
 | |
| 
 | |
| /*
 | |
|  * To build locally:
 | |
|  * 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
 | |
|  * 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
 | |
|  */
 | |
| 
 | |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 | |
| {
 | |
|   int32_t i;
 | |
|   int32_t iBufPos = 0;
 | |
|   int32_t iEndOfStreamFlag;
 | |
|   int iLevelSetting = (int) WELS_LOG_QUIET; // disable logging while fuzzing
 | |
|   int32_t iSliceSize;
 | |
|   ISVCDecoder *pDecoder;
 | |
|   SDecodingParam sDecParam = {0};
 | |
|   SBufferInfo sDstBufInfo;
 | |
|   std::unique_ptr<uint8_t[]> pBuf(new uint8_t[size + 4]);
 | |
|   uint8_t* pData[3] = {NULL};
 | |
|   uint8_t uiStartCode[4] = {0, 0, 0, 1};
 | |
| 
 | |
|   memcpy(pBuf.get(), data, size);
 | |
|   memcpy(pBuf.get() + size, &uiStartCode[0], 4);
 | |
|   memset(&sDstBufInfo, 0, sizeof(SBufferInfo));
 | |
| 
 | |
|   // TODO: is this the best/fastest ERROR_CON to use?
 | |
|   sDecParam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
 | |
|   // TODO: should we also fuzz VIDEO_BITSTREAM_SVC?
 | |
|   sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
 | |
|   
 | |
|   WelsCreateDecoder (&pDecoder);
 | |
|   pDecoder->Initialize (&sDecParam);
 | |
|   pDecoder->SetOption (DECODER_OPTION_TRACE_LEVEL, &iLevelSetting);
 | |
| 
 | |
|   while (1) {
 | |
|     if (iBufPos >= size) {
 | |
|       iEndOfStreamFlag = 1;
 | |
|       if (iEndOfStreamFlag)
 | |
|         pDecoder->SetOption (DECODER_OPTION_END_OF_STREAM, (void*)&iEndOfStreamFlag);
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < size; i++) {
 | |
|       if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1
 | |
|           && i > 0) || (pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 1 && i > 0)) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     iSliceSize = i;
 | |
|     if (iSliceSize < 4) {
 | |
|       if (iSliceSize == 0) {
 | |
|         // I don't think this should happen but let's just avoid the hang
 | |
|         goto label_cleanup;
 | |
|       }
 | |
|       iBufPos += iSliceSize;
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     pDecoder->DecodeFrameNoDelay (pBuf.get() + iBufPos, iSliceSize, pData, &sDstBufInfo);
 | |
|     iBufPos += iSliceSize;
 | |
|   }
 | |
| 
 | |
| label_cleanup:
 | |
|   pDecoder->Uninitialize ();
 | |
|   WelsDestroyDecoder (pDecoder);
 | |
| 
 | |
|   return 0;
 | |
| }
 |