Add experimental LibFuzzer cppcheck client

This commit is contained in:
Daniel Marjamäki 2019-03-21 20:05:55 +01:00
parent d204869d3d
commit 194631ff9c
2 changed files with 132 additions and 0 deletions

16
fuzzer-cli/Makefile Normal file
View File

@ -0,0 +1,16 @@
# a small client for fuzzers.
TARGET_NAME=cppcheck-fuzzing-client
CXX=clang++-6.0
CXXFLAGS=-std=c++11 -g -fsanitize=address,fuzzer
CPPCHECK_DIR=..
INCLUDE_DIR=-I ${CPPCHECK_DIR}/lib -I ${CPPCHECK_DIR}/externals/simplecpp -I ${CPPCHECK_DIR}/externals/tinyxml
SRC_FILES=main.cpp ${CPPCHECK_DIR}/externals/simplecpp/simplecpp.cpp ${CPPCHECK_DIR}/externals/tinyxml/tinyxml2.cpp ${CPPCHECK_DIR}/lib/*.cpp
all: ${TARGET_NAME}
${TARGET_NAME}:
${CXX} ${CXXFLAGS} -o ${TARGET_NAME} ${INCLUDE_DIR} ${SRC_FILES}
clean:
rm -f ${TARGET_NAME}

116
fuzzer-cli/main.cpp Normal file
View File

@ -0,0 +1,116 @@
#include <fstream>
#include <iostream>
#include <sstream>
#include <cstring>
#include "cppcheck.h"
constexpr int type = 1;
class CppcheckExecutor : public ErrorLogger {
private:
CppCheck cppcheck;
public:
CppcheckExecutor()
: ErrorLogger()
, cppcheck(*this, false) {
cppcheck.settings().addEnabled("all");
cppcheck.settings().inconclusive = true;
}
void run(const std::string &code) {
cppcheck.check("test.cpp", code);
}
void reportOut(const std::string &outmsg) { }
void reportErr(const ErrorLogger::ErrorMessage &msg) {}
void reportProgress(const std::string& filename,
const char stage[],
const unsigned int value) {}
};
static const char * const data0[] = {
"(", ")", "{", "}", "[", "]",
"<", "<=", "==", "!=", ">=", ">",
"+", "-", "*", "/", "%", "~", "&", "|", "^", "&&", "||", "++", "--", "=", "?", ":"
"name1", "name2", "name3", "name4", "name5", "name6",
"const", "void", "char", "int", "enum", "if", "else", "while", "for", "switch", "case", "default", "return", "continue", "break", "struct", "typedef",
";", ",",
"1", "0.1", "0xff", "-5", "\"abc\"", "'x'",
};
static const char * const data1[] = {
"(", ")", "[", "]", "{", "}",
"<", "<=", "==", "!=", ">=", ">",
"+", "-", "*", "/", "%", "~", "&", "|", "^", "&&", "||", "++", "--", "=", "?", ":",
"name1", "name2", "name3", "name4", "name5", "name6",
"const", "void", "char", "int", "enum", "if", "else", "while", "for", "switch", "case", "default", "return", "continue", "break", "struct", "typedef",
",", ";", "#", "##", ".", "->", "...",
"1", "0.1", "0xff", "-5", "\"abc\"", "'x'"
};
#define NUM(data) (sizeof(data)/sizeof(*data))
static void writeCode(std::ostream &ostr, int type, unsigned int *value, unsigned int *ones, const unsigned int min) {
static char par[20] = {' ',0};
static char parindex = 0;
const unsigned int num = (type == 0) ? NUM(data0) : NUM(data1);
const char * const * const data = (type == 0) ? data0 : data1;
while (*ones > min) {
unsigned char i = *value % num;
*value = *value / num;
*ones = *ones / num;
if (parindex < (sizeof(par)-1) && std::strchr("([{", *data[i]))
par[++parindex] = *data[i+1];
else if (std::strchr(")]}", *data[i])) {
while (parindex > 0 && par[parindex] != *data[i])
ostr << par[parindex--];
if (parindex > 0)
parindex--;
else
ostr << *data[i-1];
}
ostr << ' ' << data[i];
}
if (min == 0) {
while (parindex > 0)
ostr << par[parindex--];
}
}
std::string generateCode(const uint8_t *data, size_t dataSize) {
std::ostringstream ostr;
unsigned int value = 0;
unsigned int ones = 0;
for (size_t i = 0; i < dataSize; ++i) {
uint8_t c = data[i];
value = (value << 8) | c;
ones = (ones << 8) | 0xff;
writeCode(ostr, type, &value, &ones, 0x100);
}
writeCode(ostr, type, &value, &ones, 0);
std::string code;
switch (type) {
case 0:
code = ostr.str();
break;
case 1:
code = "void f() {\n x=" + ostr.str() + ";\n}";
break;
}
return code;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataSize) {
CppcheckExecutor cppcheckExecutor;
cppcheckExecutor.run(generateCode(data, dataSize));
return 0;
}