diff --git a/CMakeLists.txt b/CMakeLists.txt index 331c749..838f78f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,11 @@ project( LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 20) +include(CMakePushCheckState) +include(CheckCXXCompilerFlag) +include(CheckIncludeFileCXX) +include(CheckCXXSourceCompiles) + set(DEFAULT_BUILD_TYPE "Release") if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) @@ -28,7 +33,55 @@ add_compile_options( -fPIC -fdata-sections -ffunction-sections - -fno-omit-frame-pointer) + -fno-omit-frame-pointer + -g) + +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + add_link_options("-Wno-unused-command-line-argument") + find_program(LLVM_OBJCOPY llvm-objcopy) + if(LLVM_OBJCOPY) + set(CMAKE_OBJCOPY + ${LLVM_OBJCOPY} + CACHE FILEPATH "path to objcopy binary" FORCE) + endif() +endif() + +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + add_compile_options("-Wno-maybe-uninitialized") +endif() + +set(full_relro_flags "-pie;LINKER:-z,relro,-z,now,-z,noexecstack") +cmake_push_check_state() +list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${full_relro_flags}) +check_cxx_source_compiles("int main(){}" HAS_FULL_RELRO FAIL_REGEX "warning:") +if(HAS_FULL_RELRO) + add_link_options(${full_relro_flags}) +endif() +cmake_pop_check_state() + +if(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL + arm64) + add_compile_options(-mbranch-protection=standard) +else() + add_compile_options(-fcf-protection) + set(rewrite_endbr_flags "-fuse-ld=mold;LINKER:-z,rewrite-endbr") + cmake_push_check_state() + list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${rewrite_endbr_flags}) + check_cxx_source_compiles("int main(){}" HAS_REWRITE_ENDBR FAIL_REGEX + "warning:") + if(HAS_REWRITE_ENDBR) + add_link_options(${rewrite_endbr_flags}) + endif() + cmake_pop_check_state() +endif() + +set(version_script_flags + LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/linker.map) +cmake_push_check_state() +list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${version_script_flags}) +check_cxx_source_compiles("int main(){}" HAS_VERSION_SCRIPT FAIL_REGEX + "warning:") +cmake_pop_check_state() if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) add_compile_options(-mavx) @@ -37,6 +90,16 @@ if(CMAKE_SYSTEM_NAME STREQUAL Linux) add_link_options(LINKER:--gc-sections) endif() +# This is encouraged according to +# https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq +include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/valgrind) + +if(HAS_VERSION_SCRIPT) + target_link_options( + ${PROJECT_NAME} PRIVATE + LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/linker.map) +endif() + add_subdirectory(third_party) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") @@ -93,9 +156,12 @@ if(NOT APPLE) "Proceeding with all symbols global in static library") endif() +set(TEST_FLAGS -Wall -Wextra -Wunreachable-code -Wpedantic -UNDEBUG) + add_executable(mytest src/test.cpp) target_include_directories(mytest PRIVATE include) target_link_libraries(mytest PRIVATE ${PROJECT_NAME} doctest nanobench simdjson) +target_compile_options(mytest PRIVATE ${TEST_FLAGS}) doctest_discover_tests(mytest) include(CMakePushCheckState) @@ -109,7 +175,7 @@ if(HAS_LIB_FUZZER) add_executable(fuzz src/fuzz.cpp src/lib.cpp) target_include_directories(fuzz PRIVATE include) target_link_libraries(fuzz PRIVATE simdjson) - target_compile_options(fuzz PRIVATE -fsanitize=fuzzer) + target_compile_options(fuzz PRIVATE -fsanitize=fuzzer ${TEST_FLAGS}) target_link_options(fuzz PRIVATE -fsanitize=fuzzer) endif() diff --git a/src/callbacks.h b/src/callbacks.h index 396ed0b..a00a334 100644 --- a/src/callbacks.h +++ b/src/callbacks.h @@ -34,12 +34,12 @@ inline WeaselJsonCallbacks noopCallbacks() { result.on_begin_object = +[](void *) {}; result.on_end_object = +[](void *) {}; result.on_begin_string = +[](void *) {}; - result.on_string_data = +[](void *, const char *buf, int len) {}; + result.on_string_data = +[](void *, const char *, int) {}; result.on_end_string = +[](void *) {}; result.on_begin_array = +[](void *) {}; result.on_end_array = +[](void *) {}; result.on_begin_number = +[](void *) {}; - result.on_number_data = +[](void *, const char *buf, int len) {}; + result.on_number_data = +[](void *, const char *, int) {}; result.on_end_number = +[](void *) {}; result.on_true_literal = +[](void *) {}; result.on_false_literal = +[](void *) {}; diff --git a/src/parser3.h b/src/parser3.h index 5e564a2..b7e8c04 100644 --- a/src/parser3.h +++ b/src/parser3.h @@ -550,7 +550,7 @@ inline PRESERVE_NONE WeaselJsonStatus n_string_following_escape(Parser3 *self) { case 'n': case 'r': case 't': - *self->writeBuf++ = tables.unescape[*self->buf++]; + *self->writeBuf++ = tables.unescape[uint8_t(*self->buf++)]; self->pop(); if (auto s = self->push({N_STRING2})) { return s; diff --git a/src/test.cpp b/src/test.cpp index 9073050..3a41931 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -153,7 +153,7 @@ void testStreaming(std::string const &json) { { auto copy = json; auto *parser = WeaselJsonParser_create(1024, &c, &streaming); - for (int i = 0; i < copy.size(); ++i) { + for (size_t i = 0; i < copy.size(); ++i) { REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == WeaselJson_AGAIN); } @@ -179,7 +179,7 @@ TEST_CASE("parser3") { { auto copy = json; auto *parser = WeaselJsonParser_create(1024, &c, &state); - for (int i = 0; i < copy.size(); ++i) { + for (size_t i = 0; i < copy.size(); ++i) { REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == WeaselJson_AGAIN); } @@ -189,7 +189,7 @@ TEST_CASE("parser3") { { std::string copy = "{\"x\": [], \"y\": {}}"; auto *parser = WeaselJsonParser_create(1024, &c, &state); - for (int i = 0; i < copy.size(); ++i) { + for (size_t i = 0; i < copy.size(); ++i) { REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == WeaselJson_AGAIN); } @@ -201,7 +201,7 @@ TEST_CASE("parser3") { auto c = noopCallbacks(); std::string copy = "{\"a\":\"a"; auto *parser = WeaselJsonParser_create(1024, &c, &state); - for (int i = 0; i < copy.size(); ++i) { + for (size_t i = 0; i < copy.size(); ++i) { REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == WeaselJson_AGAIN); } @@ -212,7 +212,7 @@ TEST_CASE("parser3") { auto c = noopCallbacks(); std::string copy = "["; auto *parser = WeaselJsonParser_create(1024, &c, &state); - for (int i = 0; i < copy.size(); ++i) { + for (size_t i = 0; i < copy.size(); ++i) { REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == WeaselJson_AGAIN); } @@ -236,7 +236,7 @@ void doTestUnescapingUtf8(std::string const &escaped, }; auto *parser = WeaselJsonParser_create(1024, &c, &result); auto copy = escaped; - for (int i = 0; i < copy.size(); i += stride) { + for (size_t i = 0; i < copy.size(); i += stride) { CAPTURE(i); REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, std::min(stride, copy.size() - i)) == @@ -282,11 +282,11 @@ TEST_CASE("bench3") { bench.batch(json.size()); bench.unit("byte"); auto *parser = WeaselJsonParser_create(1024, &c, nullptr); - for (int stride = 1; stride <= json.size(); stride *= 2) { + for (size_t stride = 1; stride <= json.size(); stride *= 2) { bench.run("parser3 (stride: " + std::to_string(stride) + ")", [&]() { auto copy = json; WeaselJsonParser_reset(parser); - for (int i = 0; i < copy.size(); i += stride) { + for (size_t i = 0; i < copy.size(); i += stride) { if (WeaselJsonParser_parse(parser, copy.data() + i, std::min(copy.size() - i, stride)) != WeaselJson_AGAIN) {