blob: 2c639adf29404895e24bf148a953519420c0a36c [file] [log] [blame]
// 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;
}