Add support for UBsan builds to RocksDB

Summary:
Undefined Behavior Sanitizer (ubsan) is //a good thing// which will help us to find sneaky bugs with low cost. Please see http://developerblog.redhat.com/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/ for more details and official GCC documentation for more context: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html.

Changes itself are quite simple and pretty much imitating whatever is implemented for ASan.

Hooking the UBsan validation build to Sandcastle is a separate step and will be dealt as separate diff because code is in internal repository.

Test Plan: Make sure that that there no regressions when it comes to builds and test pass rate.

Reviewers: leveldb, sdong, IslamAbdelRahman, yhchiang

Reviewed By: yhchiang

Subscribers: andrewkr, dhruba

Differential Revision: https://reviews.facebook.net/D56049
main
Gunnar Kudrjavets 9 years ago
parent 21700a5106
commit 994b3bd693
  1. 21
      Makefile
  2. 2
      build_tools/precommit_checker.py
  3. 49
      build_tools/rocksdb-lego-determinator
  4. 5
      tools/sst_dump_tool.cc

@ -174,6 +174,15 @@ else
pg = -pg pg = -pg
endif endif
# USAN doesn't work well with jemalloc. If we're compiling with USAN, we should use regular malloc.
ifdef COMPILE_WITH_UBSAN
DISABLE_JEMALLOC=1
EXEC_LDFLAGS += -fsanitize=undefined
PLATFORM_CCFLAGS += -fsanitize=undefined
PLATFORM_CXXFLAGS += -fsanitize=undefined
endif
ifndef DISABLE_JEMALLOC ifndef DISABLE_JEMALLOC
EXEC_LDFLAGS := $(JEMALLOC_LIB) $(EXEC_LDFLAGS) EXEC_LDFLAGS := $(JEMALLOC_LIB) $(EXEC_LDFLAGS)
PLATFORM_CXXFLAGS += $(JEMALLOC_INCLUDE) PLATFORM_CXXFLAGS += $(JEMALLOC_INCLUDE)
@ -617,6 +626,16 @@ asan_crash_test:
COMPILE_WITH_ASAN=1 $(MAKE) crash_test COMPILE_WITH_ASAN=1 $(MAKE) crash_test
$(MAKE) clean $(MAKE) clean
ubsan_check:
$(MAKE) clean
COMPILE_WITH_UBSAN=1 $(MAKE) check -j32
$(MAKE) clean
ubsan_crash_test:
$(MAKE) clean
COMPILE_WITH_UBSAN=1 $(MAKE) crash_test
$(MAKE) clean
valgrind_check: $(TESTS) valgrind_check: $(TESTS)
for t in $(filter-out %skiplist_test,$(TESTS)); do \ for t in $(filter-out %skiplist_test,$(TESTS)); do \
$(VALGRIND_VER) $(VALGRIND_OPTS) ./$$t; \ $(VALGRIND_VER) $(VALGRIND_OPTS) ./$$t; \
@ -1221,7 +1240,7 @@ jdb_bench:
commit_prereq: build_tools/rocksdb-lego-determinator \ commit_prereq: build_tools/rocksdb-lego-determinator \
build_tools/precommit_checker.py build_tools/precommit_checker.py
J=$(J) build_tools/precommit_checker.py unit unit_481 clang_unit tsan asan lite J=$(J) build_tools/precommit_checker.py unit unit_481 clang_unit tsan asan ubsan lite
$(MAKE) clean && $(MAKE) jclean && $(MAKE) rocksdbjava; $(MAKE) clean && $(MAKE) jclean && $(MAKE) rocksdbjava;
xfunc: xfunc:

@ -184,7 +184,7 @@ parser = argparse.ArgumentParser(description='RocksDB pre-commit checker.')
# <test ....> # <test ....>
parser.add_argument('test', nargs='+', parser.add_argument('test', nargs='+',
help='CI test(s) to run. e.g: unit punit asan tsan') help='CI test(s) to run. e.g: unit punit asan tsan ubsan')
print("Please follow log %s" % Log.LOG_FILE) print("Please follow log %s" % Log.LOG_FILE)

@ -67,6 +67,7 @@ ASAN="COMPILE_WITH_ASAN=1"
CLANG="USE_CLANG=1" CLANG="USE_CLANG=1"
LITE="OPT=-DROCKSDB_LITE" LITE="OPT=-DROCKSDB_LITE"
TSAN="COMPILE_WITH_TSAN=1" TSAN="COMPILE_WITH_TSAN=1"
UBSAN="COMPILE_WITH_UBSAN=1"
DISABLE_JEMALLOC="DISABLE_JEMALLOC=1" DISABLE_JEMALLOC="DISABLE_JEMALLOC=1"
PARSER="'parser':'egrep \'Failure|^#|Abort|Expected|Actual|GoogleTestFailure|^==\''" PARSER="'parser':'egrep \'Failure|^#|Abort|Expected|Actual|GoogleTestFailure|^==\''"
@ -376,6 +377,48 @@ ASAN_CRASH_TEST_COMMANDS="[
} }
]" ]"
#
# RocksDB test under undefined behavior sanitizer
#
UBSAN_TEST_COMMANDS="[
{
'name':'Rocksdb Unit Test under UBSAN',
'oncall':'$ONCALL',
'steps': [
$CLEANUP_ENV,
{
'name':'Test RocksDB debug under UBSAN',
'shell':'set -o pipefail && $SHM $UBSAN $DEBUG make J=1 ubsan_check',
'user':'root',
$PARSER
}
],
$REPORT
}
]"
#
# RocksDB crash testing under udnefined behavior sanitizer
#
UBSAN_CRASH_TEST_COMMANDS="[
{
'name':'Rocksdb crash test under UBSAN',
'oncall':'$ONCALL',
'timeout': 86400,
'steps': [
$CLEANUP_ENV,
{
'name':'Build and run RocksDB debug ubsan_crash_test',
'timeout': 86400,
'shell':'$SHM $DEBUG make J=1 ubsan_crash_test',
'user':'root',
$PARSER
},
],
$REPORT
}
]"
# #
# RocksDB unit test under valgrind # RocksDB unit test under valgrind
# #
@ -632,6 +675,12 @@ case $1 in
asan_crash) asan_crash)
echo $ASAN_CRASH_TEST_COMMANDS echo $ASAN_CRASH_TEST_COMMANDS
;; ;;
ubsan)
echo $UBSAN_TEST_COMMANDS
;;
ubsan_crash)
echo $UBSAN_CRASH_TEST_COMMANDS
;;
valgrind) valgrind)
echo $VALGRIND_TEST_COMMANDS echo $VALGRIND_TEST_COMMANDS
;; ;;

@ -59,7 +59,10 @@ extern const uint64_t kLegacyPlainTableMagicNumber;
const char* testFileName = "test_file_name"; const char* testFileName = "test_file_name";
Status SstFileReader::GetTableReader(const std::string& file_path) { Status SstFileReader::GetTableReader(const std::string& file_path) {
uint64_t magic_number; // Warning about 'magic_number' being uninitialized shows up only in UBsan
// builds. Though access is guarded by 's.ok()' checks, fix the issue to
// avoid any warnings.
uint64_t magic_number = Footer::kInvalidTableMagicNumber;
// read table magic number // read table magic number
Footer footer; Footer footer;

Loading…
Cancel
Save