ソースを参照

Lagom: Add fuzz testing for LibJS using libFuzzer (#1692)

Note: clang only (see https://llvm.org/docs/LibFuzzer.html)

- add FuzzJs which will run the LibJS parser on random javascript inputs
- added a basic dictionary of javascript tokens

To use fuzzer:
CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -DENABLE_FUZZER_SANITIZER=1 ..
Fuzzers/FuzzJs -dict=../Fuzzers/FuzzJs.dict
Paul Redmond 5 年 前
コミット
7291d5c86f

+ 10 - 0
Meta/Lagom/CMakeLists.txt

@@ -24,6 +24,12 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
         set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=undefined")
     endif()
 
+    option(ENABLE_FUZZER_SANITIZER "Enable fuzzer sanitizer testing in clang" FALSE)
+    if (ENABLE_FUZZER_SANITIZER)
+        add_definitions(-fsanitize=fuzzer -fno-omit-frame-pointer)
+        set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=fuzzer-no-link")
+    endif()
+
     set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
     set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
     set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
@@ -57,3 +63,7 @@ add_executable(js ../../Userland/js.cpp)
 target_link_libraries(js lagom)
 target_link_libraries(js stdc++)
 target_link_libraries(js pthread)
+
+if (ENABLE_FUZZER_SANITIZER)
+    add_subdirectory(Fuzzers)
+endif()

+ 9 - 0
Meta/Lagom/Fuzzers/CMakeLists.txt

@@ -0,0 +1,9 @@
+add_executable(FuzzJs FuzzJs.cpp)
+target_compile_options(FuzzJs
+    PRIVATE $<$<C_COMPILER_ID:Clang>:-g -O1 -fsanitize=fuzzer>
+    )
+
+target_link_libraries(FuzzJs
+    PUBLIC lagom
+    PRIVATE $<$<C_COMPILER_ID:Clang>:-fsanitize=fuzzer>
+    )

+ 14 - 0
Meta/Lagom/Fuzzers/FuzzJs.cpp

@@ -0,0 +1,14 @@
+#include <AK/StringView.h>
+#include <LibJS/Lexer.h>
+#include <LibJS/Parser.h>
+#include <stddef.h>
+#include <stdint.h>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+    auto js = AK::StringView(static_cast<const unsigned char*>(data), size);
+    auto lexer = JS::Lexer(js);
+    auto parser = JS::Parser(lexer);
+    parser.parse_program();
+    return 0;
+}

+ 107 - 0
Meta/Lagom/Fuzzers/FuzzJs.dict

@@ -0,0 +1,107 @@
+#
+# AFL dictionary for JavaScript
+# -----------------------------
+#
+# Contains basic reserved keywords and syntax building blocks.
+#
+# Created by Michal Zalewski <lcamtuf@google.com>
+#
+
+keyword_arguments="arguments"
+keyword_break="break"
+keyword_case="case"
+keyword_catch="catch"
+keyword_const="const"
+keyword_continue="continue"
+keyword_debugger="debugger"
+keyword_decodeURI="decodeURI"
+keyword_default="default"
+keyword_delete="delete"
+keyword_do="do"
+keyword_else="else"
+keyword_escape="escape"
+keyword_eval="eval"
+keyword_export="export"
+keyword_finally="finally"
+keyword_for="for (a=0;a<2;a++)"
+keyword_function="function"
+keyword_if="if"
+keyword_in="in"
+keyword_instanceof="instanceof"
+keyword_isNaN="isNaN"
+keyword_let="let"
+keyword_new="new"
+keyword_parseInt="parseInt"
+keyword_return="return"
+keyword_switch="switch"
+keyword_this="this"
+keyword_throw="throw"
+keyword_try="try"
+keyword_typeof="typeof"
+keyword_var="var"
+keyword_void="void"
+keyword_while="while"
+keyword_with="with"
+
+misc_1=" 1"
+misc_a="a"
+misc_array=" [1]"
+misc_assign=" a=1"
+misc_code_block=" {1}"
+misc_colon_num=" 1:"
+misc_colon_string=" 'a':"
+misc_comma=" ,"
+misc_comment_block=" /* */"
+misc_comment_line=" //"
+misc_cond=" 1?2:3"
+misc_dec=" --"
+misc_div=" /"
+misc_equals=" ="
+misc_fn=" a()"
+misc_identical=" ==="
+misc_inc=" ++"
+misc_minus=" -"
+misc_modulo=" %"
+misc_parentheses=" ()"
+misc_parentheses_1=" (1)"
+misc_parentheses_1x4=" (1,1,1,1)"
+misc_parentheses_a=" (a)"
+misc_period="."
+misc_plus=" +"
+misc_plus_assign=" +="
+misc_regex=" /a/g"
+misc_rol=" <<<"
+misc_semicolon=" ;"
+misc_serialized_object=" {'a': 1}"
+misc_string=" 'a'"
+misc_unicode=" '\\u0001'"
+
+object_Array=" Array"
+object_Boolean=" Boolean"
+object_Date=" Date"
+object_Function=" Function"
+object_Infinity=" Infinity"
+object_Int8Array=" Int8Array"
+object_Math=" Math"
+object_NaN=" NaN"
+object_Number=" Number"
+object_Object=" Object"
+object_RegExp=" RegExp"
+object_String=" String"
+object_Symbol=" Symbol"
+object_false=" false"
+object_null=" null"
+object_true=" true"
+
+prop_charAt=".charAt"
+prop_concat=".concat"
+prop_constructor=".constructor"
+prop_destructor=".destructor"
+prop_length=".length"
+prop_match=".match"
+prop_proto=".__proto__"
+prop_prototype=".prototype"
+prop_slice=".slice"
+prop_toCode=".toCode"
+prop_toString=".toString"
+prop_valueOf=".valueOf"