diff --git a/CMakeLists.txt b/CMakeLists.txt index d4127f59..e97049b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -205,8 +205,8 @@ if (CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT "${CMAKE_CXX_SIMULATE_ID}" STREQ endif() if (FLATCC_DEBUG_CLANG_SANITIZE) if (CMAKE_BUILD_TYPE MATCHES Debug) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") endif() endif() # Suppress warning relaxed in clang-6, see https://reviews.llvm.org/D28148 diff --git a/include/flatcc/flatcc_json_parser.h b/include/flatcc/flatcc_json_parser.h index f8281295..4319ece9 100644 --- a/include/flatcc/flatcc_json_parser.h +++ b/include/flatcc/flatcc_json_parser.h @@ -307,11 +307,10 @@ static inline uint64_t flatcc_json_parser_symbol_part(const char *buf, const cha { size_t n = (size_t)(end - buf); -#if FLATCC_ALLOW_UNALIGNED_ACCESS - if (n >= 8) { + /* Read directly if the word is aligned. */ + if (n >= 8 && ((uintptr_t)buf % 8) == 0) { return be64toh(*(uint64_t *)buf); } -#endif return flatcc_json_parser_symbol_part_ext(buf, end); } diff --git a/include/flatcc/portable/pprintint.h b/include/flatcc/portable/pprintint.h index d05f3761..b29c02ec 100644 --- a/include/flatcc/portable/pprintint.h +++ b/include/flatcc/portable/pprintint.h @@ -76,6 +76,7 @@ extern "C" { #endif #include "pattributes.h" /* fallthrough */ +#include "pmemaccess.h" /* mem_copy_word */ #define PDIAGNOSTIC_IGNORE_UNUSED_FUNCTION #include "pdiagnostic_push.h" @@ -102,14 +103,6 @@ static int print_int(int n, char *p); static int print_long(long n, char *p); -#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) -#define __print_unaligned_copy_16(p, q) (*(uint16_t*)(p) = *(uint16_t*)(q)) -#else -#define __print_unaligned_copy_16(p, q) \ - ((((uint8_t*)(p))[0] = ((uint8_t*)(q))[0]), \ - (((uint8_t*)(p))[1] = ((uint8_t*)(q))[1])) -#endif - static const char __print_digit_pairs[] = "0001020304050607080910111213141516171819" "2021222324252627282930313233343536373839" @@ -121,7 +114,7 @@ static const char __print_digit_pairs[] = p -= 2; \ dp = __print_digit_pairs + (n % 100) * 2; \ n /= 100; \ - __print_unaligned_copy_16(p, dp); + mem_copy_word(p, dp, 2); #define __print_long_stage() \ __print_stage() \ @@ -435,11 +428,11 @@ static int UNAME(UT n, char *buf) \ p -= 2; \ m = (unsigned int)(n % 100) * 2; \ n /= 100; \ - __print_unaligned_copy_16(p, __print_digit_pairs + m); \ + mem_copy_word(p, __print_digit_pairs + m, 2); \ } \ p -= 2; \ m = (unsigned int)n * 2; \ - __print_unaligned_copy_16(p, __print_digit_pairs + m); \ + mem_copy_word(p, __print_digit_pairs + m, 2); \ if (n < 10) { \ ++p; \ } \ diff --git a/scripts/test.sh b/scripts/test.sh index d87924b9..cb4d92d9 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -25,6 +25,11 @@ fi echo "building before tests ..." $ROOT/scripts/build.sh $DEBUG +# Configure the UBSan if used. +if [ -z "${UBSAN_OPTIONS}" ]; then + export UBSAN_OPTIONS="print_stacktrace=1" +fi + echo "running test in debug build ..." cd $DBGDIR && ctest $ROOT diff --git a/src/runtime/json_parser.c b/src/runtime/json_parser.c index 4472af2d..e6065b39 100644 --- a/src/runtime/json_parser.c +++ b/src/runtime/json_parser.c @@ -103,39 +103,39 @@ const char *flatcc_json_parser_space_ext(flatcc_json_parser_t *ctx, const char * */ //cmpistri(end, buf, "\x20\t\v\f\r\n", _SIDD_NEGATIVE_POLARITY); cmpistri(end, buf, "\x20\t\v\f", _SIDD_NEGATIVE_POLARITY); -#else -#if FLATCC_ALLOW_UNALIGNED_ACCESS - while (end - buf >= 16) { - if (*buf > 0x20) { - return buf; - } -#if FLATCC_JSON_PARSE_WIDE_SPACE - if (((uint64_t *)buf)[0] != 0x2020202020202020) { -descend: - if (((uint32_t *)buf)[0] == 0x20202020) { - buf += 4; - } -#endif - if (((uint16_t *)buf)[0] == 0x2020) { - buf += 2; - } - if (*buf == 0x20) { - ++buf; - } - if (*buf > 0x20) { - return buf; - } - break; -#if FLATCC_JSON_PARSE_WIDE_SPACE - } - if (((uint64_t *)buf)[1] != 0x2020202020202020) { - buf += 8; - goto descend; - } - buf += 16; -#endif - } -#endif +//#else +//#if FLATCC_ALLOW_UNALIGNED_ACCESS +// while (end - buf >= 16) { +// if (*buf > 0x20) { +// return buf; +// } +//#if FLATCC_JSON_PARSE_WIDE_SPACE +// if (((uint64_t *)buf)[0] != 0x2020202020202020) { +//descend: +// if (((uint32_t *)buf)[0] == 0x20202020) { +// buf += 4; +// } +//#endif +// if (((uint16_t *)buf)[0] == 0x2020) { +// buf += 2; +// } +// if (*buf == 0x20) { +// ++buf; +// } +// if (*buf > 0x20) { +// return buf; +// } +// break; +//#if FLATCC_JSON_PARSE_WIDE_SPACE +// } +// if (((uint64_t *)buf)[1] != 0x2020202020202020) { +// buf += 8; +// goto descend; +// } +// buf += 16; +//#endif +// } +//#endif #endif while (buf != end && *buf == 0x20) { ++buf; diff --git a/test/monster_test/monster_test.c b/test/monster_test/monster_test.c index f3150d8e..206e3017 100644 --- a/test/monster_test/monster_test.c +++ b/test/monster_test/monster_test.c @@ -2535,7 +2535,11 @@ int verify_include(void *buffer) int test_struct_buffer(flatcc_builder_t *B) { - uint8_t buffer[100]; + /* Allocate a buffer and make sure it's aligned on targets that don't + * use a 16 bytes stack alignment (e.g. 32-bit/x86 and s390x). + * This will avoid an undefined behaviour in this testcase: + * "member access within misaligned address". */ + alignas(16) uint8_t buffer[100]; size_t size; ns(Vec3_t) *v; @@ -2584,7 +2588,11 @@ int test_struct_buffer(flatcc_builder_t *B) int test_typed_struct_buffer(flatcc_builder_t *B) { - uint8_t buffer[100]; + /* Allocate a buffer and make sure it's aligned on targets that don't + * use a 16 bytes stack alignment (e.g. 32-bit/x86 and s390x). + * This will avoid an undefined behaviour in this testcase: + * "member access within misaligned address". */ + alignas(16) uint8_t buffer[100]; size_t size; ns(Vec3_t) *v;