Add experimental LibFuzzer cppcheck client
This commit is contained in:
parent
d204869d3d
commit
194631ff9c
|
@ -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}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue