diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fa8dc2..17c657e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,12 @@ set(CMAKE_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_INCLUDE_PATH} include(SetBuildParallelLevel) include(SetHardwareArch) +if (ENABLE_LAPI_TESTS) + include(LibFuzzer) + SetLibFuzzerPath(FUZZER_NO_MAIN_LIBRARY) + SetLibFuzzerObjDir(LibFuzzerObjDir) +endif() + if (USE_LUA AND NOT LUA_VERSION) set(LUA_VERSION "master") endif() diff --git a/cmake/BuildLua.cmake b/cmake/BuildLua.cmake index b9e27c5..d1a39c3 100644 --- a/cmake/BuildLua.cmake +++ b/cmake/BuildLua.cmake @@ -65,6 +65,7 @@ macro(build_lua LUA_VERSION) # `io.popen()` is not supported by default, it is enabled # by `LUA_USE_POSIX` flag. Required by a function `random_locale()`. set(CFLAGS "${CFLAGS} -DLUA_USE_POSIX") + set(LDFLAGS "${LDFLAGS} -lstdc++") endif() include(ExternalProject) @@ -90,6 +91,7 @@ macro(build_lua LUA_VERSION) BUILD_COMMAND cd && make -j CC=${CMAKE_C_COMPILER} CFLAGS=${CFLAGS} LDFLAGS=${LDFLAGS} + LF_PATH=${LibFuzzerObjDir} INSTALL_COMMAND "" BUILD_BYPRODUCTS ${LUA_LIBRARY} ${LUA_EXECUTABLE} diff --git a/cmake/BuildLuaJIT.cmake b/cmake/BuildLuaJIT.cmake index 28630f2..e8ccae5 100644 --- a/cmake/BuildLuaJIT.cmake +++ b/cmake/BuildLuaJIT.cmake @@ -88,6 +88,7 @@ macro(build_luajit LJ_VERSION) # CMake option LUAJIT_FRIENDLY_MODE in luzer requires # LUAJIT_ENABLE_CHECKHOOK. set(CFLAGS "${CFLAGS} -DLUAJIT_ENABLE_CHECKHOOK") + set(LDFLAGS "${LDFLAGS} -lstdc++") endif() include(ExternalProject) @@ -116,6 +117,7 @@ macro(build_luajit LJ_VERSION) CFLAGS=${CFLAGS} LDFLAGS=${LDFLAGS} HOST_CFLAGS=-fno-sanitize=undefined + LF_PATH=${LibFuzzerObjDir} -C src INSTALL_COMMAND "" diff --git a/cmake/BuildLuzer.cmake b/cmake/BuildLuzer.cmake index 833204b..dd68036 100644 --- a/cmake/BuildLuzer.cmake +++ b/cmake/BuildLuzer.cmake @@ -34,7 +34,7 @@ endif() ExternalProject_Add(bundled-luzer GIT_REPOSITORY https://github.com/ligurio/luzer - GIT_TAG fc4a32fe98f1da8b07f74a35f40b678692e7152b + GIT_TAG e4624477735961457f562423ef2ba9afa51ba170 GIT_PROGRESS TRUE GIT_SHALLOW FALSE SOURCE_DIR ${LUZER_DIR}/source diff --git a/cmake/LibFuzzer.cmake b/cmake/LibFuzzer.cmake new file mode 100644 index 0000000..a763d32 --- /dev/null +++ b/cmake/LibFuzzer.cmake @@ -0,0 +1,62 @@ +# The function sets the given variable in a parent scope to a +# string with hardware architecture name and this name should +# match to hardware architecture name used in a library name of +# libclang_rt.fuzzer_no_main: aarch64, x86_64, i386. +function(SetHwArchString outvar) + set(${outvar} ${CMAKE_SYSTEM_PROCESSOR} PARENT_SCOPE) +endfunction() + +# The function sets the given variable in a parent scope to a +# value with path to libclang_rt.fuzzer_no_main [1] library. +# The function raises a fatal message if C compiler is not Clang. +# +# $ clang-15 -print-file-name=libclang_rt.fuzzer_no_main-x86_64.a +# $ /usr/lib/llvm-15/lib/clang/15.0.7/lib/linux/libclang_rt.fuzzer_no_main-x86_64.a +# +# 1. https://llvm.org/docs/LibFuzzer.html#using-libfuzzer-as-a-library +function(SetLibFuzzerPath outvar) + if (NOT CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "C compiler is not a Clang") + endif () + + SetHwArchString(HW_ARCH) + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(lib_name "libclang_rt.fuzzer_no_main-${HW_ARCH}.a") + else() + message(FATAL_ERROR "Unsupported system: ${CMAKE_SYSTEM_NAME}") + endif() + + execute_process(COMMAND ${CMAKE_C_COMPILER} "-print-file-name=${lib_name}" + RESULT_VARIABLE CMD_ERROR + OUTPUT_VARIABLE CMD_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if (CMD_ERROR) + message(FATAL_ERROR "${CMD_ERROR}") + endif() + + if(NOT EXISTS ${CMD_OUTPUT}) + message(FATAL_ERROR "${lib_name} was not found.") + endif() + + set(${outvar} ${CMD_OUTPUT} PARENT_SCOPE) +endfunction() + +# The function unpack libFuzzer archive located at +# to a directory and return a path to a directory +# with libFuzzer's object files. +function(SetLibFuzzerObjDir outvar) + set(LibFuzzerDir ${PROJECT_BINARY_DIR}/libFuzzer_unpacked) + file(MAKE_DIRECTORY ${LibFuzzerDir}) + SetLibFuzzerPath(LibFuzzerPath) + execute_process( + COMMAND ${CMAKE_AR} x ${LibFuzzerPath} --output ${LibFuzzerDir} + RESULT_VARIABLE CMD_ERROR + OUTPUT_VARIABLE CMD_OUTPUT + WORKING_DIRECTORY ${LibFuzzerDir} + ) + if (CMD_ERROR) + message(FATAL_ERROR "${CMD_ERROR}") + endif() + set(${outvar} ${LibFuzzerDir} PARENT_SCOPE) +endfunction() diff --git a/patches/luajit-v2.1.patch b/patches/luajit-v2.1.patch index 2ee1561..a97e91e 100644 --- a/patches/luajit-v2.1.patch +++ b/patches/luajit-v2.1.patch @@ -1,5 +1,32 @@ +diff --git a/src/Makefile b/src/Makefile +index 969bf289..23c4264b 100644 +--- a/src/Makefile ++++ b/src/Makefile +@@ -514,6 +514,10 @@ LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \ + lib_buffer.o + LJLIB_C= $(LJLIB_O:.o=.c) + ++ifneq ($(LF_PATH),) ++LIBFUZZER_O= $(shell find $(LF_PATH) -maxdepth 1 -name '*.o') ++endif ++ + LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \ + lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \ + lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \ +@@ -748,9 +752,9 @@ $(LUAJIT_SO): $(LJVMCORE_O) + $(Q)$(TARGET_LD) $(TARGET_ASHLDFLAGS) -o $@ $(LJVMCORE_DYNO) $(TARGET_ALIBS) + $(Q)$(TARGET_STRIP) $@ + +-$(LUAJIT_T): $(TARGET_O) $(LUAJIT_O) $(TARGET_DEP) ++$(LUAJIT_T): $(TARGET_O) $(LUAJIT_O) $(TARGET_DEP) $(LIBFUZZER_O) + $(E) "LINK $@" +- $(Q)$(TARGET_LD) $(TARGET_ALDFLAGS) -o $@ $(LUAJIT_O) $(TARGET_O) $(TARGET_ALIBS) ++ $(Q)$(TARGET_LD) $(TARGET_ALDFLAGS) -o $@ $(LUAJIT_O) $(TARGET_O) $(TARGET_ALIBS) $(LIBFUZZER_O) + $(Q)$(TARGET_STRIP) $@ + $(E) "OK Successfully built LuaJIT" + diff --git a/src/host/buildvm.c b/src/host/buildvm.c -index ec99e501..d23530c4 100644 +index 24db75f4..021e7dbe 100644 --- a/src/host/buildvm.c +++ b/src/host/buildvm.c @@ -35,6 +35,10 @@ @@ -14,7 +41,7 @@ index ec99e501..d23530c4 100644 /* DynASM glue definitions. */ diff --git a/src/lj_buf.h b/src/lj_buf.h -index 744e5747..ea299472 100644 +index 15a04250..ef701256 100644 --- a/src/lj_buf.h +++ b/src/lj_buf.h @@ -165,6 +165,13 @@ LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c); @@ -32,7 +59,7 @@ index 744e5747..ea299472 100644 { return (char *)memcpy(p, q, len) + len; diff --git a/src/lj_carith.c b/src/lj_carith.c -index 9bea0a33..046dea4c 100644 +index b09812c6..98128daa 100644 --- a/src/lj_carith.c +++ b/src/lj_carith.c @@ -159,6 +159,11 @@ static int carith_ptr(lua_State *L, CTState *cts, CDArith *ca, MMS mm) @@ -48,7 +75,7 @@ index 9bea0a33..046dea4c 100644 { if (ctype_isnum(ca->ct[0]->info) && ca->ct[0]->size <= 8 && diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c -index ce78505b..bc9d64f3 100644 +index 456c04b2..4edfa742 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c @@ -260,6 +260,11 @@ LJFOLDF(kfold_numcomp) @@ -64,10 +91,10 @@ index ce78505b..bc9d64f3 100644 { switch (op) { diff --git a/src/lj_parse.c b/src/lj_parse.c -index 5a44f8db..bfe044a8 100644 +index 832f6bf4..7d0390e4 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c -@@ -934,6 +934,11 @@ static void bcemit_binop(FuncState *fs, BinOpr op, ExpDesc *e1, ExpDesc *e2) +@@ -935,6 +935,11 @@ static void bcemit_binop(FuncState *fs, BinOpr op, ExpDesc *e1, ExpDesc *e2) } /* Emit unary operator. */ @@ -80,7 +107,7 @@ index 5a44f8db..bfe044a8 100644 { if (op == BC_NOT) { diff --git a/src/lj_snap.c b/src/lj_snap.c -index 6fda08ba..c7f51d7d 100644 +index d0d28c81..c8d5ffcc 100644 --- a/src/lj_snap.c +++ b/src/lj_snap.c @@ -763,6 +763,13 @@ static void snap_restoreval(jit_State *J, GCtrace *T, ExitState *ex, @@ -98,7 +125,7 @@ index 6fda08ba..c7f51d7d 100644 static void snap_restoredata(jit_State *J, GCtrace *T, ExitState *ex, SnapNo snapno, BloomFilter rfilt, diff --git a/src/lj_str.c b/src/lj_str.c -index cfdaec6f..88f9c765 100644 +index f34d6d95..806c67db 100644 --- a/src/lj_str.c +++ b/src/lj_str.c @@ -13,6 +13,15 @@ @@ -118,7 +145,7 @@ index cfdaec6f..88f9c765 100644 /* Ordered compare of strings. Assumes string data is 4-byte aligned. */ diff --git a/src/lj_strfmt.c b/src/lj_strfmt.c -index 909255db..ef9bd4f9 100644 +index 0936298d..32e93c42 100644 --- a/src/lj_strfmt.c +++ b/src/lj_strfmt.c @@ -99,6 +99,11 @@ retlit: diff --git a/patches/puc-rio-lua.patch b/patches/puc-rio-lua.patch index f25b584..2598a82 100644 --- a/patches/puc-rio-lua.patch +++ b/patches/puc-rio-lua.patch @@ -1,5 +1,5 @@ diff --git a/makefile b/makefile -index 8674519f..17dabfa8 100644 +index 8674519f..1773b0eb 100644 --- a/makefile +++ b/makefile @@ -39,7 +39,7 @@ CWARNSC= -Wdeclaration-after-statement \ @@ -26,3 +26,17 @@ index 8674519f..17dabfa8 100644 AR= ar rc RANLIB= ranlib RM= rm -f +@@ -96,9 +96,12 @@ CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \ + AUX_O= lauxlib.o + LIB_O= lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o lstrlib.o \ + lutf8lib.o loadlib.o lcorolib.o linit.o ++ifneq ($(LF_PATH),) ++LF_O= $(shell find $(LF_PATH) -maxdepth 1 -name '*.o') ++endif + + LUA_T= lua +-LUA_O= lua.o ++LUA_O= lua.o $(LF_O) + + + ALL_T= $(CORE_T) $(LUA_T) diff --git a/tests/lapi/CMakeLists.txt b/tests/lapi/CMakeLists.txt index 8f2836d..0f95643 100644 --- a/tests/lapi/CMakeLists.txt +++ b/tests/lapi/CMakeLists.txt @@ -16,6 +16,13 @@ lapi_tests_make_lua_path(LUA_PATH ${CMAKE_CURRENT_SOURCE_DIR}/?.lua ) +list(APPEND TEST_ENV + "LUA_PATH=${LUA_PATH}" + "LUA_CPATH=${LUA_CPATH}" + ASAN_OPTIONS=detect_odr_violation=0 + LD_DYNAMIC_WEAK=1 +) + function(create_test) cmake_parse_arguments( FUZZ @@ -45,7 +52,7 @@ function(create_test) ) set_tests_properties(${test_name} PROPERTIES LABELS "lapi" - ENVIRONMENT "LUA_PATH=${LUA_PATH};LUA_CPATH=${LUA_CPATH};ASAN_OPTIONS=detect_odr_violation=0;LD_DYNAMIC_WEAK=1" + ENVIRONMENT "${TEST_ENV}" DEPENDS ${LUA_EXECUTABLE} ${LUZER_LIBRARY} ) endfunction()