diff --git a/test/fuzzer/afl_fuzzer.cc b/test/fuzzer/afl_fuzzer.cc index 93afdef276..a4d87cc405 100644 --- a/test/fuzzer/afl_fuzzer.cc +++ b/test/fuzzer/afl_fuzzer.cc @@ -20,7 +20,7 @@ #include "src/actions/transformations/transformation.h" /** - * for i in $(ls -l src/actions/transformations/*.h | awk {'print $9'}); do echo "#include \"$i\""; done; + * for i in $(find src/actions/transformations -name '*.h'); do echo "#include \"$i\""; done; * */ #include "src/actions/transformations/base64_decode.h" @@ -64,7 +64,7 @@ /** - * for i in $(ls -l src/operators/*.h | awk {'print $9'}); do echo "#include \"$i\""; done; + * for i in $(find src/operators -name '*.h'); do echo "#include \"$i\""; done; * */ #include "src/operators/begins_with.h" @@ -122,13 +122,41 @@ using namespace modsecurity; #include #include +/** +* __AFL_LOOP is provided by afl-clang-fast. When the harness is built with a +* plain compiler it is absent, so define a single-shot fallback: the binary +* reads stdin once and exits. This keeps the harness compilable (and therefore +* checkable) without afl++ installed. +*/ +#ifndef __AFL_LOOP +inline int afl_loop_fallback() { + static bool consumed = false; + if (consumed) { + return 0; + } + consumed = true; + return 1; +} +#define __AFL_LOOP(x) afl_loop_fallback() +#endif + inline void op_test(const std::string &opName, const std::string &s) { Operator *op = Operator::instantiate(opName, ""); op->init("", nullptr); - op->evaluate(nullptr, nullptr, s, nullptr); + op->evaluate(nullptr, nullptr, s); delete op; } +template +inline void tfn_test(const std::string &tfnName, const std::string &s, + const Transaction *t) { + T tfn(tfnName); + // transform() rewrites in place, so each transformation gets its own copy + // of the fuzzer input rather than the output of the previous one. + std::string value(s); + tfn.transform(value, t); +} + int main(int argc, char** argv) { uint8_t buf[128]; @@ -141,8 +169,12 @@ int main(int argc, char** argv) { // (re-) initialize the library and read new input memset(buf, 0, 128); read_bytes = read(STDIN_FILENO, buf, 128); + if (read_bytes <= 0) { + continue; + } - std::string currentString = std::string(read_bytes, 128); + std::string currentString(reinterpret_cast(buf), + read_bytes); const std::string& s = currentString; #if 0 std::string z = lastString; @@ -158,52 +190,52 @@ int main(int argc, char** argv) { /** * Transformations, generated by: * - * for i in $(grep "class " -Ri src/actions/transformations/* | grep " :" | grep -v "InstantCache" | awk {'print $2'}); do echo $i *$(echo $i | awk '{print tolower($0)}') = new $i\(\"$i\"\)\; $(echo $i | awk '{print tolower($0)}')-\>evaluate\(s, NULL\)\; delete $(echo $i | awk '{print tolower($0)}')\;; done; + * for i in $(grep "class " -Ri src/actions/transformations | grep " :" | grep -v "InstantCache" | awk {'print $2'}); do echo tfn_test\<$i\>\(\"$i\", s, t\)\;; done; * */ -Base64Decode *base64decode = new Base64Decode("Base64Decode"); base64decode->evaluate(s, NULL); delete base64decode; -Base64DecodeExt *base64decodeext = new Base64DecodeExt("Base64DecodeExt"); base64decodeext->evaluate(s, NULL); delete base64decodeext; -Base64Encode *base64encode = new Base64Encode("Base64Encode"); base64encode->evaluate(s, NULL); delete base64encode; -CmdLine *cmdline = new CmdLine("CmdLine"); cmdline->evaluate(s, NULL); delete cmdline; -CompressWhitespace *compresswhitespace = new CompressWhitespace("CompressWhitespace"); compresswhitespace->evaluate(s, NULL); delete compresswhitespace; -CssDecode *cssdecode = new CssDecode("CssDecode"); cssdecode->evaluate(s, NULL); delete cssdecode; -EscapeSeqDecode *escapeseqdecode = new EscapeSeqDecode("EscapeSeqDecode"); escapeseqdecode->evaluate(s, NULL); delete escapeseqdecode; -HexDecode *hexdecode = new HexDecode("HexDecode"); hexdecode->evaluate(s, NULL); delete hexdecode; -HexEncode *hexencode = new HexEncode("HexEncode"); hexencode->evaluate(s, NULL); delete hexencode; -HtmlEntityDecode *htmlentitydecode = new HtmlEntityDecode("HtmlEntityDecode"); htmlentitydecode->evaluate(s, NULL); delete htmlentitydecode; -JsDecode *jsdecode = new JsDecode("JsDecode"); jsdecode->evaluate(s, NULL); delete jsdecode; -Length *length = new Length("Length"); length->evaluate(s, NULL); delete length; -LowerCase *lowercase = new LowerCase("LowerCase"); lowercase->evaluate(s, NULL); delete lowercase; -Md5 *md5 = new Md5("Md5"); md5->evaluate(s, NULL); delete md5; -None *none = new None("None"); none->evaluate(s, NULL); delete none; -NormalisePath *normalisepath = new NormalisePath("NormalisePath"); normalisepath->evaluate(s, NULL); delete normalisepath; -NormalisePathWin *normalisepathwin = new NormalisePathWin("NormalisePathWin"); normalisepathwin->evaluate(s, NULL); delete normalisepathwin; -ParityEven7bit *parityeven7bit = new ParityEven7bit("ParityEven7bit"); parityeven7bit->evaluate(s, NULL); delete parityeven7bit; -ParityOdd7bit *parityodd7bit = new ParityOdd7bit("ParityOdd7bit"); parityodd7bit->evaluate(s, NULL); delete parityodd7bit; -ParityZero7bit *parityzero7bit = new ParityZero7bit("ParityZero7bit"); parityzero7bit->evaluate(s, NULL); delete parityzero7bit; -RemoveComments *removecomments = new RemoveComments("RemoveComments"); removecomments->evaluate(s, NULL); delete removecomments; -RemoveCommentsChar *removecommentschar = new RemoveCommentsChar("RemoveCommentsChar"); removecommentschar->evaluate(s, NULL); delete removecommentschar; -RemoveNulls *removenulls = new RemoveNulls("RemoveNulls"); removenulls->evaluate(s, NULL); delete removenulls; -RemoveWhitespace *removewhitespace = new RemoveWhitespace("RemoveWhitespace"); removewhitespace->evaluate(s, NULL); delete removewhitespace; -ReplaceComments *replacecomments = new ReplaceComments("ReplaceComments"); replacecomments->evaluate(s, NULL); delete replacecomments; -ReplaceNulls *replacenulls = new ReplaceNulls("ReplaceNulls"); replacenulls->evaluate(s, NULL); delete replacenulls; -Sha1 *sha1 = new Sha1("Sha1"); sha1->evaluate(s, NULL); delete sha1; -SqlHexDecode *sqlhexdecode = new SqlHexDecode("SqlHexDecode"); sqlhexdecode->evaluate(s, NULL); delete sqlhexdecode; -Transformation *transformation = new Transformation("Transformation"); transformation->evaluate(s, NULL); delete transformation; -Trim *trim = new Trim("Trim"); trim->evaluate(s, NULL); delete trim; -TrimLeft *trimleft = new TrimLeft("TrimLeft"); trimleft->evaluate(s, NULL); delete trimleft; -TrimRight *trimright = new TrimRight("TrimRight"); trimright->evaluate(s, NULL); delete trimright; -UpperCase *uppercase = new UpperCase("UpperCase"); uppercase->evaluate(s, NULL); delete uppercase; -UrlDecode *urldecode = new UrlDecode("UrlDecode"); urldecode->evaluate(s, NULL); delete urldecode; -UrlDecodeUni *urldecodeuni = new UrlDecodeUni("UrlDecodeUni"); urldecodeuni->evaluate(s, NULL); delete urldecodeuni; -UrlEncode *urlencode = new UrlEncode("UrlEncode"); urlencode->evaluate(s, NULL); delete urlencode; -Utf8ToUnicode *utf8tounicode = new Utf8ToUnicode("Utf8ToUnicode"); utf8tounicode->evaluate(s, NULL); delete utf8tounicode; +tfn_test("Base64Decode", s, t); +tfn_test("Base64DecodeExt", s, t); +tfn_test("Base64Encode", s, t); +tfn_test("CmdLine", s, t); +tfn_test("CompressWhitespace", s, t); +tfn_test("CssDecode", s, t); +tfn_test("EscapeSeqDecode", s, t); +tfn_test("HexDecode", s, t); +tfn_test("HexEncode", s, t); +tfn_test("HtmlEntityDecode", s, t); +tfn_test("JsDecode", s, t); +tfn_test("Length", s, t); +tfn_test("LowerCase", s, t); +tfn_test("Md5", s, t); +tfn_test("None", s, t); +tfn_test("NormalisePath", s, t); +tfn_test("NormalisePathWin", s, t); +tfn_test("ParityEven7bit", s, t); +tfn_test("ParityOdd7bit", s, t); +tfn_test("ParityZero7bit", s, t); +tfn_test("RemoveComments", s, t); +tfn_test("RemoveCommentsChar", s, t); +tfn_test("RemoveNulls", s, t); +tfn_test("RemoveWhitespace", s, t); +tfn_test("ReplaceComments", s, t); +tfn_test("ReplaceNulls", s, t); +tfn_test("Sha1", s, t); +tfn_test("SqlHexDecode", s, t); +tfn_test("Transformation", s, t); +tfn_test("Trim", s, t); +tfn_test("TrimLeft", s, t); +tfn_test("TrimRight", s, t); +tfn_test("UpperCase", s, t); +tfn_test("UrlDecode", s, t); +tfn_test("UrlDecodeUni", s, t); +tfn_test("UrlEncode", s, t); +tfn_test("Utf8ToUnicode", s, t); /** * Operators, generated by: * - * for i in $(grep "class " -Ri src/operators/* | grep " :" | awk {'print $2'}); do echo $i *$(echo $i | awk '{print tolower($0)}') = new $i\(\"$i\", z, false\)\; $(echo $i | awk '{print tolower($0)}')-\>evaluate\(t, s\)\; delete $(echo $i | awk '{print tolower($0)}')\;; done; + * for i in $(grep "class " -Ri src/operators | grep " :" | awk {'print $2'}); do echo $i *$(echo $i | awk '{print tolower($0)}') = new $i\(\"$i\", z, false\)\; $(echo $i | awk '{print tolower($0)}')-\>evaluate\(t, s\)\; delete $(echo $i | awk '{print tolower($0)}')\;; done; * */ op_test("BeginsWith", s);