summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:11:54 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:11:54 +0000
commitcdf4f3055e964bb585f294cf77cb549ead82783f (patch)
tree7bceeca766b3fbe491245bc926a083f78c35d1de /test
parent625108084a3ec7c19c7745004c5af0ed7aa417a9 (diff)
Notes
Diffstat (limited to 'test')
-rw-r--r--test/CMakeLists.txt19
-rw-r--r--test/asan/CMakeLists.txt15
-rw-r--r--test/asan/TestCases/Darwin/abort_on_error.cc2
-rw-r--r--test/asan/TestCases/Darwin/dump_registers.cc14
-rw-r--r--test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc16
-rw-r--r--test/asan/TestCases/Darwin/dyld_insert_libraries_remove.cc26
-rw-r--r--test/asan/TestCases/Darwin/fclose.c13
-rw-r--r--test/asan/TestCases/Darwin/getpwnam.c15
-rw-r--r--test/asan/TestCases/Darwin/interface_symbols_darwin.cc (renamed from test/asan/TestCases/Darwin/interface_symbols_darwin.c)4
-rw-r--r--test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc2
-rw-r--r--test/asan/TestCases/Darwin/suppressions-function.cc28
-rw-r--r--test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc8
-rw-r--r--test/asan/TestCases/Helpers/underflow.cc1
-rw-r--r--test/asan/TestCases/Linux/abort_on_error.cc1
-rw-r--r--test/asan/TestCases/Linux/aligned_delete_test.cc168
-rw-r--r--test/asan/TestCases/Linux/allocator_oom_test.cc1
-rw-r--r--test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc2
-rw-r--r--test/asan/TestCases/Linux/asan_prelink_test.cc2
-rw-r--r--test/asan/TestCases/Linux/asan_preload_test-1.cc2
-rw-r--r--test/asan/TestCases/Linux/asan_preload_test-2.cc2
-rw-r--r--test/asan/TestCases/Linux/calloc-preload.c2
-rw-r--r--test/asan/TestCases/Linux/cuda_test.cc4
-rw-r--r--test/asan/TestCases/Linux/interface_symbols_linux.cc (renamed from test/asan/TestCases/Linux/interface_symbols_linux.c)4
-rw-r--r--test/asan/TestCases/Linux/kernel-area.cc3
-rw-r--r--test/asan/TestCases/Linux/nohugepage_test.cc2
-rw-r--r--test/asan/TestCases/Linux/preinstalled_signal.cc14
-rw-r--r--test/asan/TestCases/Linux/printf-fortify-1.c18
-rw-r--r--test/asan/TestCases/Linux/printf-fortify-2.c18
-rw-r--r--test/asan/TestCases/Linux/printf-fortify-3.c22
-rw-r--r--test/asan/TestCases/Linux/printf-fortify-4.c22
-rw-r--r--test/asan/TestCases/Linux/printf-fortify-5.c18
-rw-r--r--test/asan/TestCases/Linux/pvalloc-overflow.cc41
-rw-r--r--test/asan/TestCases/Linux/recoverable-lsan.cc22
-rw-r--r--test/asan/TestCases/Linux/release_to_os_test.cc18
-rw-r--r--test/asan/TestCases/Linux/swapcontext_annotation.cc1
-rw-r--r--test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc2
-rw-r--r--test/asan/TestCases/Posix/concurrent_overflow.cc33
-rw-r--r--test/asan/TestCases/Posix/coverage-reset.cc65
-rw-r--r--test/asan/TestCases/Posix/deep_call_stack.cc3
-rw-r--r--test/asan/TestCases/Posix/halt_on_error-signals.c5
-rw-r--r--test/asan/TestCases/Posix/halt_on_error-torture.cc28
-rw-r--r--test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc5
-rw-r--r--test/asan/TestCases/Posix/handle_abort_on_error.cc2
-rw-r--r--test/asan/TestCases/Posix/invalid-pointer-pairs-threads.cc57
-rw-r--r--test/asan/TestCases/Posix/new_array_cookie_test.cc3
-rw-r--r--test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc3
-rw-r--r--test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc3
-rw-r--r--test/asan/TestCases/Posix/stack-overflow.cc2
-rw-r--r--test/asan/TestCases/Posix/stack-use-after-return.cc3
-rw-r--r--test/asan/TestCases/Windows/fuse-lld.cc6
-rw-r--r--test/asan/TestCases/Windows/interface_symbols_windows.cc (renamed from test/asan/TestCases/Windows/interface_symbols_windows.c)2
-rw-r--r--test/asan/TestCases/Windows/shadow_conflict_32.cc6
-rw-r--r--test/asan/TestCases/alloca_constant_size.cc2
-rw-r--r--test/asan/TestCases/asan_and_llvm_coverage_test.cc2
-rw-r--r--test/asan/TestCases/atexit_stats.cc2
-rw-r--r--test/asan/TestCases/contiguous_container_crash.cc2
-rw-r--r--test/asan/TestCases/debug_ppc64_mapping.cc19
-rw-r--r--test/asan/TestCases/error_report_callback.cc21
-rw-r--r--test/asan/TestCases/global-address.cpp4
-rw-r--r--test/asan/TestCases/global-underflow.cc17
-rw-r--r--test/asan/TestCases/heavy_uar_test.cc5
-rw-r--r--test/asan/TestCases/intra-object-overflow.cc2
-rw-r--r--test/asan/TestCases/invalid-pointer-pairs-compare-errors.cc103
-rw-r--r--test/asan/TestCases/invalid-pointer-pairs-compare-success.cc74
-rw-r--r--test/asan/TestCases/invalid-pointer-pairs-subtract-errors.cc48
-rw-r--r--test/asan/TestCases/invalid-pointer-pairs-subtract-success.cc33
-rw-r--r--test/asan/TestCases/max_redzone.cc4
-rw-r--r--test/asan/TestCases/memcmp_test.cc4
-rw-r--r--test/asan/TestCases/memset_test.cc2
-rw-r--r--test/asan/TestCases/non-executable-pc.cpp4
-rw-r--r--test/asan/TestCases/pass-object-byval.cc40
-rw-r--r--test/asan/TestCases/pass-struct-byval-uar.cc38
-rw-r--r--test/asan/TestCases/pass-struct-byval.cc23
-rw-r--r--test/asan/TestCases/scariness_score_test.cc22
-rw-r--r--test/asan/TestCases/sleep_after_init.c10
-rw-r--r--test/asan/TestCases/small_memcpy_test.cc1
-rw-r--r--test/asan/TestCases/stack-buffer-overflow-with-position.cc1
-rw-r--r--test/asan/TestCases/strtol_strict.c1
-rw-r--r--test/asan/TestCases/strtoll_strict.c1
-rw-r--r--test/asan/TestCases/suppressions-function.cc4
-rw-r--r--test/asan/TestCases/use-after-delete.cc2
-rw-r--r--test/asan/TestCases/use-after-free.cc2
-rw-r--r--test/asan/TestCases/use-after-scope-conversion.cc50
-rw-r--r--test/asan/TestCases/verbose-log-path_test.cc2
-rw-r--r--test/asan/lit.cfg78
-rw-r--r--test/asan/lit.site.cfg.in2
-rw-r--r--test/builtins/Unit/clear_cache_test.c2
-rw-r--r--test/builtins/Unit/divxc3_test.c2
-rw-r--r--test/builtins/Unit/endianness.h4
-rw-r--r--test/builtins/Unit/fixunsxfti_test.c5
-rw-r--r--test/builtins/Unit/fixxfti_test.c5
-rw-r--r--test/builtins/Unit/floattixf_test.c5
-rw-r--r--test/builtins/Unit/floatuntixf_test.c5
-rw-r--r--test/builtins/Unit/lit.cfg1
-rw-r--r--test/builtins/Unit/mulsc3_test.c2
-rw-r--r--test/builtins/Unit/mulxc3_test.c2
-rw-r--r--test/builtins/Unit/powixf2_test.c2
-rw-r--r--test/cfi/CMakeLists.txt32
-rw-r--r--test/cfi/anon-namespace.cpp12
-rw-r--r--test/cfi/bad-cast.cpp104
-rw-r--r--test/cfi/bad-split.cpp2
-rw-r--r--test/cfi/base-derived-destructor.cpp36
-rw-r--r--test/cfi/cross-dso/icall/diag.cpp16
-rw-r--r--test/cfi/cross-dso/icall/icall-from-dso.cpp8
-rw-r--r--test/cfi/cross-dso/icall/icall.cpp8
-rw-r--r--test/cfi/cross-dso/lit.local.cfg4
-rw-r--r--test/cfi/cross-dso/shadow_is_read_only.cpp3
-rw-r--r--test/cfi/cross-dso/simple-fail.cpp68
-rw-r--r--test/cfi/cross-dso/simple-pass.cpp40
-rw-r--r--test/cfi/cross-dso/stats.cpp3
-rw-r--r--test/cfi/cross-dso/util/cfi_stubs.h30
-rw-r--r--test/cfi/icall/external-call.c3
-rw-r--r--test/cfi/lit.cfg16
-rw-r--r--test/cfi/lit.site.cfg.in3
-rw-r--r--test/cfi/multiple-inheritance.cpp24
-rw-r--r--test/cfi/nvcall.cpp12
-rw-r--r--test/cfi/overwrite.cpp12
-rw-r--r--test/cfi/sibling.cpp10
-rw-r--r--test/cfi/simple-fail.cpp38
-rw-r--r--test/cfi/simple-pass.cpp2
-rw-r--r--test/cfi/stats.cpp7
-rw-r--r--test/cfi/target_uninstrumented.cpp9
-rw-r--r--test/cfi/two-vcalls.cpp2
-rw-r--r--test/cfi/vdtor.cpp12
-rw-r--r--test/cfi/vtable-may-alias.cpp25
-rw-r--r--test/esan/TestCases/large-stack-linux.c4
-rw-r--r--test/fuzzer/AFLDriverTest.cpp28
-rw-r--r--test/fuzzer/AbsNegAndConstant64Test.cpp24
-rw-r--r--test/fuzzer/AbsNegAndConstantTest.cpp24
-rw-r--r--test/fuzzer/AccumulateAllocationsTest.cpp17
-rw-r--r--test/fuzzer/BadStrcmpTest.cpp19
-rw-r--r--test/fuzzer/BogusInitializeTest.cpp15
-rw-r--r--test/fuzzer/BufferOverflowOnInput.cpp24
-rw-r--r--test/fuzzer/CMakeLists.txt43
-rw-r--r--test/fuzzer/CallerCalleeTest.cpp59
-rw-r--r--test/fuzzer/CleanseTest.cpp16
-rw-r--r--test/fuzzer/CounterTest.cpp18
-rw-r--r--test/fuzzer/CustomCrossOverAndMutateTest.cpp34
-rw-r--r--test/fuzzer/CustomCrossOverTest.cpp59
-rw-r--r--test/fuzzer/CustomMutatorTest.cpp39
-rw-r--r--test/fuzzer/CxxStringEqTest.cpp25
-rw-r--r--test/fuzzer/DSO1.cpp14
-rw-r--r--test/fuzzer/DSO2.cpp14
-rw-r--r--test/fuzzer/DSOTestExtra.cpp11
-rw-r--r--test/fuzzer/DSOTestMain.cpp31
-rw-r--r--test/fuzzer/DeepRecursionTest.cpp25
-rw-r--r--test/fuzzer/DivTest.cpp20
-rw-r--r--test/fuzzer/EmptyTest.cpp11
-rw-r--r--test/fuzzer/EquivalenceATest.cpp17
-rw-r--r--test/fuzzer/EquivalenceBTest.cpp27
-rw-r--r--test/fuzzer/FlagsTest.cpp32
-rw-r--r--test/fuzzer/FourIndependentBranchesTest.cpp22
-rw-r--r--test/fuzzer/FullCoverageSetTest.cpp24
-rw-r--r--test/fuzzer/GcSectionsTest.cpp14
-rw-r--r--test/fuzzer/InitializeTest.cpp29
-rw-r--r--test/fuzzer/LargeTest.cpp37
-rw-r--r--test/fuzzer/LeakTest.cpp17
-rw-r--r--test/fuzzer/LeakTimeoutTest.cpp17
-rw-r--r--test/fuzzer/LoadTest.cpp22
-rw-r--r--test/fuzzer/Memcmp64BytesTest.cpp20
-rw-r--r--test/fuzzer/MemcmpTest.cpp31
-rw-r--r--test/fuzzer/NotinstrumentedTest.cpp11
-rw-r--r--test/fuzzer/NthRunCrashTest.cpp19
-rw-r--r--test/fuzzer/NullDerefOnEmptyTest.cpp19
-rw-r--r--test/fuzzer/NullDerefTest.cpp26
-rw-r--r--test/fuzzer/OneHugeAllocTest.cpp28
-rw-r--r--test/fuzzer/OutOfMemorySingleLargeMallocTest.cpp27
-rw-r--r--test/fuzzer/OutOfMemoryTest.cpp31
-rw-r--r--test/fuzzer/OverwriteInputTest.cpp13
-rw-r--r--test/fuzzer/PrintFuncTest.cpp39
-rw-r--r--test/fuzzer/RepeatedBytesTest.cpp31
-rw-r--r--test/fuzzer/RepeatedMemcmp.cpp24
-rw-r--r--test/fuzzer/ShrinkControlFlowSimpleTest.cpp19
-rw-r--r--test/fuzzer/ShrinkControlFlowTest.cpp31
-rw-r--r--test/fuzzer/ShrinkValueProfileTest.cpp22
-rw-r--r--test/fuzzer/SignedIntOverflowTest.cpp28
-rw-r--r--test/fuzzer/SimpleCmpTest.cpp47
-rw-r--r--test/fuzzer/SimpleDictionaryTest.cpp30
-rw-r--r--test/fuzzer/SimpleHashTest.cpp40
-rw-r--r--test/fuzzer/SimpleTest.cpp28
-rw-r--r--test/fuzzer/SimpleThreadedTest.cpp26
-rw-r--r--test/fuzzer/SingleByteInputTest.cpp17
-rw-r--r--test/fuzzer/SingleMemcmpTest.cpp17
-rw-r--r--test/fuzzer/SingleStrcmpTest.cpp21
-rw-r--r--test/fuzzer/SingleStrncmpTest.cpp18
-rw-r--r--test/fuzzer/SleepOneSecondTest.cpp13
-rw-r--r--test/fuzzer/SpamyTest.cpp21
-rw-r--r--test/fuzzer/StrcmpTest.cpp32
-rw-r--r--test/fuzzer/StrncmpOOBTest.cpp21
-rw-r--r--test/fuzzer/StrncmpTest.cpp28
-rw-r--r--test/fuzzer/StrstrTest.cpp28
-rw-r--r--test/fuzzer/SwapCmpTest.cpp35
-rw-r--r--test/fuzzer/Switch2Test.cpp35
-rw-r--r--test/fuzzer/SwitchTest.cpp58
-rw-r--r--test/fuzzer/TableLookupTest.cpp44
-rw-r--r--test/fuzzer/ThreadedLeakTest.cpp18
-rw-r--r--test/fuzzer/ThreadedTest.cpp26
-rw-r--r--test/fuzzer/TimeoutEmptyTest.cpp14
-rw-r--r--test/fuzzer/TimeoutTest.cpp26
-rw-r--r--test/fuzzer/TraceMallocTest.cpp27
-rw-r--r--test/fuzzer/TraceMallocThreadedTest.cpp22
-rw-r--r--test/fuzzer/TwoDifferentBugsTest.cpp22
-rw-r--r--test/fuzzer/afl-driver-extra-stats.test30
-rw-r--r--test/fuzzer/afl-driver-stderr.test12
-rw-r--r--test/fuzzer/afl-driver.test29
-rw-r--r--test/fuzzer/bad-strcmp.test2
-rw-r--r--test/fuzzer/caller-callee.test3
-rw-r--r--test/fuzzer/cleanse.test4
-rw-r--r--test/fuzzer/coverage.test21
-rw-r--r--test/fuzzer/cxxstring.test6
-rw-r--r--test/fuzzer/deep-recursion.test5
-rw-r--r--test/fuzzer/dict1.txt4
-rw-r--r--test/fuzzer/disable-leaks.test5
-rw-r--r--test/fuzzer/dump_coverage.test20
-rw-r--r--test/fuzzer/equivalence-signals.test9
-rw-r--r--test/fuzzer/equivalence.test9
-rw-r--r--test/fuzzer/exit-report.test6
-rw-r--r--test/fuzzer/exit_on_src_pos.test8
-rw-r--r--test/fuzzer/extra-counters.test7
-rw-r--r--test/fuzzer/fprofile-instr-generate.test7
-rw-r--r--test/fuzzer/fuzzer-customcrossover.test12
-rw-r--r--test/fuzzer/fuzzer-customcrossoverandmutate.test2
-rw-r--r--test/fuzzer/fuzzer-custommutator.test5
-rw-r--r--test/fuzzer/fuzzer-dict.test8
-rw-r--r--test/fuzzer/fuzzer-dirs.test21
-rw-r--r--test/fuzzer/fuzzer-fdmask.test32
-rw-r--r--test/fuzzer/fuzzer-finalstats.test12
-rw-r--r--test/fuzzer/fuzzer-flags.test19
-rw-r--r--test/fuzzer/fuzzer-leak.test41
-rw-r--r--test/fuzzer/fuzzer-oom-with-profile.test7
-rw-r--r--test/fuzzer/fuzzer-oom.test22
-rw-r--r--test/fuzzer/fuzzer-printcovpcs.test9
-rw-r--r--test/fuzzer/fuzzer-runs.test9
-rw-r--r--test/fuzzer/fuzzer-seed.test4
-rw-r--r--test/fuzzer/fuzzer-segv.test8
-rw-r--r--test/fuzzer/fuzzer-singleinputs.test19
-rw-r--r--test/fuzzer/fuzzer-threaded.test8
-rw-r--r--test/fuzzer/fuzzer-timeout.test21
-rw-r--r--test/fuzzer/fuzzer-ubsan.test5
-rw-r--r--test/fuzzer/fuzzer.test70
-rw-r--r--test/fuzzer/gc-sections.test13
-rw-r--r--test/fuzzer/hi.txt1
-rw-r--r--test/fuzzer/inline-8bit-counters.test4
-rw-r--r--test/fuzzer/lit.cfg79
-rw-r--r--test/fuzzer/lit.site.cfg.in17
-rw-r--r--test/fuzzer/max-number-of-runs.test10
-rw-r--r--test/fuzzer/memcmp.test3
-rw-r--r--test/fuzzer/memcmp64.test3
-rw-r--r--test/fuzzer/merge-control-file.test57
-rw-r--r--test/fuzzer/merge-posix.test23
-rw-r--r--test/fuzzer/merge-sigusr.test25
-rw-r--r--test/fuzzer/merge-summary.test17
-rw-r--r--test/fuzzer/merge.test70
-rw-r--r--test/fuzzer/minimize_crash.test16
-rw-r--r--test/fuzzer/minimize_two_crashes.test18
-rw-r--r--test/fuzzer/overwrite-input.test3
-rw-r--r--test/fuzzer/print-func.test10
-rw-r--r--test/fuzzer/recommended-dictionary.test6
-rw-r--r--test/fuzzer/reduce_inputs.test16
-rw-r--r--test/fuzzer/repeated-bytes.test3
-rw-r--r--test/fuzzer/shrink.test10
-rw-r--r--test/fuzzer/sigusr.test13
-rw-r--r--test/fuzzer/simple-cmp.test3
-rw-r--r--test/fuzzer/standalone.test8
-rw-r--r--test/fuzzer/strcmp.test4
-rw-r--r--test/fuzzer/strncmp.test4
-rw-r--r--test/fuzzer/strstr.test4
-rw-r--r--test/fuzzer/swap-cmp.test3
-rw-r--r--test/fuzzer/trace-malloc-2.test10
-rw-r--r--test/fuzzer/trace-malloc-threaded.test36
-rw-r--r--test/fuzzer/trace-malloc-unbalanced.test27
-rw-r--r--test/fuzzer/trace-malloc.test7
-rw-r--r--test/fuzzer/trace-pc.test3
-rw-r--r--test/fuzzer/ulimit.test3
-rw-r--r--test/fuzzer/unit/lit.site.cfg.in9
-rw-r--r--test/fuzzer/value-profile-cmp.test3
-rw-r--r--test/fuzzer/value-profile-cmp2.test3
-rw-r--r--test/fuzzer/value-profile-cmp3.test3
-rw-r--r--test/fuzzer/value-profile-cmp4.test3
-rw-r--r--test/fuzzer/value-profile-div.test4
-rw-r--r--test/fuzzer/value-profile-load.test3
-rw-r--r--test/fuzzer/value-profile-mem.test3
-rw-r--r--test/fuzzer/value-profile-set.test4
-rw-r--r--test/fuzzer/value-profile-strcmp.test3
-rw-r--r--test/fuzzer/value-profile-strncmp.test3
-rw-r--r--test/fuzzer/value-profile-switch.test5
-rw-r--r--test/hwasan/CMakeLists.txt29
-rw-r--r--test/hwasan/TestCases/halt-on-error.cc26
-rw-r--r--test/hwasan/TestCases/use-after-free.cc28
-rw-r--r--test/hwasan/lit.cfg32
-rw-r--r--test/hwasan/lit.site.cfg.in12
-rw-r--r--test/lit.common.cfg104
-rw-r--r--test/lit.common.configured.in14
-rw-r--r--test/lsan/TestCases/Linux/use_tls_dynamic.cc2
-rw-r--r--test/lsan/TestCases/default_options.cc11
-rw-r--r--test/lsan/TestCases/link_turned_off.cc2
-rw-r--r--test/lsan/TestCases/stale_stack_leak.cc2
-rw-r--r--test/lsan/TestCases/swapcontext.cc2
-rw-r--r--test/lsan/TestCases/use_registers.cc5
-rw-r--r--test/lsan/lit.common.cfg2
-rw-r--r--test/msan/CMakeLists.txt30
-rw-r--r--test/msan/Linux/mallinfo.cc2
-rw-r--r--test/msan/Linux/poll.cc42
-rw-r--r--test/msan/__strxfrm_l.cc19
-rw-r--r--test/msan/ftime.cc4
-rw-r--r--test/msan/iconv.cc4
-rw-r--r--test/msan/ifaddrs.cc2
-rw-r--r--test/msan/lit.cfg6
-rw-r--r--test/msan/lit.site.cfg.in4
-rw-r--r--test/msan/msan_print_shadow3.cc4
-rw-r--r--test/msan/pvalloc.cc43
-rw-r--r--test/msan/sigaction.cc47
-rw-r--r--test/msan/sigwait.cc7
-rw-r--r--test/msan/strxfrm.cc11
-rw-r--r--test/msan/tsearch.cc3
-rw-r--r--test/profile/Linux/counter_promo_for.c8
-rw-r--r--test/profile/Linux/coverage_ctors.cpp2
-rw-r--r--test/profile/Linux/coverage_dtor.cpp2
-rw-r--r--test/profile/Linux/coverage_test.cpp6
-rw-r--r--test/profile/Linux/instrprof-comdat.test2
-rw-r--r--test/profile/Linux/lit.local.cfg4
-rw-r--r--test/profile/infinite_loop.c30
-rw-r--r--test/profile/instrprof-darwin-dead-strip.c1
-rw-r--r--test/profile/lit.cfg16
-rw-r--r--test/profile/runtime_infinite.c36
-rw-r--r--test/safestack/lit.cfg8
-rw-r--r--test/sanitizer_common/CMakeLists.txt10
-rw-r--r--test/sanitizer_common/TestCases/Darwin/print-stack-trace.cc19
-rw-r--r--test/sanitizer_common/TestCases/Linux/abort_on_error.cc3
-rw-r--r--test/sanitizer_common/TestCases/Linux/allow_user_segv.cc (renamed from test/asan/TestCases/Posix/allow_user_segv.cc)39
-rw-r--r--test/sanitizer_common/TestCases/Linux/assert.cc15
-rw-r--r--test/sanitizer_common/TestCases/Linux/decorate_proc_maps.cc6
-rw-r--r--test/sanitizer_common/TestCases/Linux/deepbind.cc2
-rw-r--r--test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc2
-rw-r--r--test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc6
-rw-r--r--test/sanitizer_common/TestCases/Linux/iconv_test.c3
-rw-r--r--test/sanitizer_common/TestCases/Linux/ill.cc16
-rw-r--r--test/sanitizer_common/TestCases/Linux/mlock_test.cc2
-rw-r--r--test/sanitizer_common/TestCases/Linux/mprobe.cc2
-rw-r--r--test/sanitizer_common/TestCases/Linux/ptrace.cc2
-rw-r--r--test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc2
-rw-r--r--test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc15
-rw-r--r--test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc1
-rw-r--r--test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc2
-rw-r--r--test/sanitizer_common/TestCases/Linux/unexpected_format_specifier_test.cc1
-rw-r--r--test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc4
-rw-r--r--test/sanitizer_common/TestCases/Posix/dump_instruction_bytes.cc (renamed from test/asan/TestCases/Posix/dump_instruction_bytes.cc)11
-rw-r--r--test/sanitizer_common/TestCases/Posix/dump_registers.cc20
-rw-r--r--test/sanitizer_common/TestCases/Posix/fpe.cc13
-rw-r--r--test/sanitizer_common/TestCases/Posix/getpass.cc3
-rw-r--r--test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc1
-rw-r--r--test/sanitizer_common/TestCases/Posix/sanitizer_set_report_fd_test.cc5
-rw-r--r--test/sanitizer_common/TestCases/Posix/weak_hook_test.cc1
-rw-r--r--test/sanitizer_common/TestCases/corelimit.cc2
-rw-r--r--test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc4
-rw-r--r--test/sanitizer_common/TestCases/malloc_hook.cc1
-rw-r--r--test/sanitizer_common/TestCases/options-include.cc2
-rw-r--r--test/sanitizer_common/TestCases/print-stack-trace.cc8
-rw-r--r--test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc24
-rw-r--r--test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc7
-rw-r--r--test/sanitizer_common/TestCases/sanitizer_coverage_stack_depth.cc32
-rw-r--r--test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc10
-rw-r--r--test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc15
-rw-r--r--test/sanitizer_common/android_commands/android_common.py (renamed from test/asan/android_commands/android_common.py)9
-rwxr-xr-xtest/sanitizer_common/android_commands/android_compile.py (renamed from test/asan/android_commands/android_compile.py)0
-rwxr-xr-xtest/sanitizer_common/android_commands/android_run.py (renamed from test/asan/android_commands/android_run.py)5
-rw-r--r--test/sanitizer_common/lit.common.cfg14
-rw-r--r--test/scudo/CMakeLists.txt10
-rw-r--r--test/scudo/alignment.c (renamed from test/scudo/alignment.cpp)2
-rw-r--r--test/scudo/double-free.cpp2
-rw-r--r--test/scudo/interface.cpp48
-rw-r--r--test/scudo/lit.cfg43
-rw-r--r--test/scudo/malloc.cpp2
-rw-r--r--test/scudo/memalign.c (renamed from test/scudo/memalign.cpp)21
-rw-r--r--test/scudo/mismatch.cpp25
-rw-r--r--test/scudo/options.cpp10
-rw-r--r--test/scudo/overflow.c (renamed from test/scudo/overflow.cpp)6
-rw-r--r--test/scudo/preinit.c (renamed from test/scudo/preinit.cpp)6
-rw-r--r--test/scudo/preload.cpp20
-rw-r--r--test/scudo/quarantine.c124
-rw-r--r--test/scudo/quarantine.cpp57
-rw-r--r--test/scudo/random_shuffle.cpp3
-rw-r--r--test/scudo/realloc.cpp104
-rw-r--r--test/scudo/rss.c56
-rw-r--r--test/scudo/secondary.c (renamed from test/scudo/secondary.cpp)2
-rw-r--r--test/scudo/sized-delete.cpp14
-rw-r--r--test/scudo/sizes.cpp20
-rw-r--r--test/scudo/threads.c (renamed from test/scudo/threads.cpp)8
-rw-r--r--test/scudo/tsd_destruction.c42
-rw-r--r--test/scudo/valloc.c65
-rw-r--r--test/tsan/CMakeLists.txt4
-rw-r--r--test/tsan/Darwin/xpc-race.mm53
-rw-r--r--test/tsan/Linux/double_race.cc52
-rw-r--r--test/tsan/Linux/user_malloc.cc7
-rw-r--r--test/tsan/allocator_returns_null.cc12
-rw-r--r--test/tsan/atexit3.cc41
-rw-r--r--test/tsan/cond_cancel.c2
-rw-r--r--test/tsan/custom_mutex.h10
-rw-r--r--test/tsan/custom_mutex4.cc33
-rw-r--r--test/tsan/custom_mutex5.cc33
-rw-r--r--test/tsan/lit.cfg11
-rw-r--r--test/tsan/map32bit.cc5
-rw-r--r--test/tsan/signal_pause.cc35
-rw-r--r--test/tsan/strerror_r.cc3
-rw-r--r--test/tsan/thread_name.cc8
-rw-r--r--test/tsan/thread_name2.cc10
-rw-r--r--test/tsan/tls_race.cc1
-rw-r--r--test/tsan/tls_race2.cc1
-rw-r--r--test/ubsan/CMakeLists.txt42
-rw-r--r--test/ubsan/TestCases/Float/cast-overflow.cpp14
-rw-r--r--test/ubsan/TestCases/Integer/suppressions.cpp1
-rw-r--r--test/ubsan/TestCases/Misc/Inputs/no-interception-dso.c3
-rw-r--r--test/ubsan/TestCases/Misc/bounds.cpp16
-rw-r--r--test/ubsan/TestCases/Misc/builtins.cpp35
-rw-r--r--test/ubsan/TestCases/Misc/coverage-levels.cc1
-rw-r--r--test/ubsan/TestCases/Misc/no-interception.cpp20
-rw-r--r--test/ubsan/TestCases/TypeCheck/Function/function.cpp10
-rw-r--r--test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg2
-rw-r--r--test/ubsan/TestCases/TypeCheck/Linux/PR33221.cpp2
-rw-r--r--test/ubsan/TestCases/TypeCheck/PR33221.cpp3
-rw-r--r--test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp2
-rw-r--r--test/ubsan/TestCases/TypeCheck/vptr-non-unique-typeinfo.cpp5
-rw-r--r--test/ubsan/TestCases/TypeCheck/vptr-virtual-base-construction.cpp1
-rw-r--r--test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp3
-rw-r--r--test/ubsan/TestCases/TypeCheck/vptr.cpp26
-rw-r--r--test/ubsan/lit.common.cfg27
-rw-r--r--test/ubsan/lit.site.cfg.in3
-rw-r--r--test/ubsan_minimal/CMakeLists.txt26
-rw-r--r--test/ubsan_minimal/TestCases/recover-dedup-limit.cpp41
-rw-r--r--test/ubsan_minimal/TestCases/recover-dedup.cpp39
-rw-r--r--test/ubsan_minimal/TestCases/test-darwin-interface.c16
-rw-r--r--test/ubsan_minimal/TestCases/uadd-overflow.cpp10
-rw-r--r--test/ubsan_minimal/lit.common.cfg40
-rw-r--r--test/ubsan_minimal/lit.site.cfg.in11
-rw-r--r--test/xray/TestCases/Linux/arg1-logger.cc12
-rw-r--r--test/xray/TestCases/Linux/argv0-log-file-name.cc2
-rw-r--r--test/xray/TestCases/Linux/basic-filtering.cc51
-rw-r--r--test/xray/TestCases/Linux/common-trampoline-alignment.cc57
-rw-r--r--test/xray/TestCases/Linux/coverage-sample.cc17
-rw-r--r--test/xray/TestCases/Linux/custom-event-handler-alignment.cc42
-rw-r--r--test/xray/TestCases/Linux/custom-event-logging.cc2
-rw-r--r--test/xray/TestCases/Linux/fdr-mode.cc27
-rw-r--r--test/xray/TestCases/Linux/fdr-single-thread.cc38
-rw-r--r--test/xray/TestCases/Linux/fdr-thread-order.cc54
-rw-r--r--test/xray/TestCases/Linux/fixedsize-logging.cc2
-rw-r--r--test/xray/TestCases/Linux/func-id-utils.cc2
-rw-r--r--test/xray/TestCases/Linux/logging-modes.cc59
-rw-r--r--test/xray/TestCases/Linux/optional-inmemory-log.cc2
-rw-r--r--test/xray/TestCases/Linux/patching-unpatching.cc2
-rw-r--r--test/xray/TestCases/Linux/pic_test.cc11
-rw-r--r--test/xray/TestCases/Linux/quiet-start.cc26
-rw-r--r--test/xray/Unit/lit.site.cfg.in2
-rw-r--r--test/xray/lit.cfg10
-rw-r--r--test/xray/lit.site.cfg.in2
454 files changed, 6904 insertions, 919 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 9b4759dfb8d49..ab16f42d33d4f 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,7 +1,7 @@
-# Needed for lit support
+# Needed for lit support in standalone builds.
include(AddLLVM)
-configure_lit_site_cfg(
+configure_compiler_rt_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.common.configured.in
${CMAKE_CURRENT_BINARY_DIR}/lit.common.configured)
@@ -9,6 +9,11 @@ configure_lit_site_cfg(
# add_subdirectory(BlocksRuntime)
set(SANITIZER_COMMON_LIT_TEST_DEPS)
+
+if(COMPILER_RT_BUILD_PROFILE AND COMPILER_RT_HAS_PROFILE)
+ list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS profile)
+endif()
+
if(COMPILER_RT_STANDALONE_BUILD)
add_executable(FileCheck IMPORTED GLOBAL)
set_property(TARGET FileCheck PROPERTY IMPORTED_LOCATION ${LLVM_TOOLS_BINARY_DIR}/FileCheck)
@@ -23,9 +28,6 @@ if(NOT ANDROID)
list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS
clang clang-headers FileCheck count not llvm-config llvm-nm llvm-objdump
llvm-readobj llvm-symbolizer compiler-rt-headers sancov)
- if (COMPILER_RT_HAS_PROFILE)
- list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS profile)
- endif()
if (WIN32)
list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS KillTheDoctor)
endif()
@@ -59,13 +61,18 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS)
compiler_rt_test_runtime(ubsan cfi)
compiler_rt_test_runtime(sanitizer_common)
+ if(COMPILER_RT_BUILD_LIBFUZZER)
+ compiler_rt_test_runtime(fuzzer)
+ endif()
+
foreach(sanitizer ${COMPILER_RT_SANITIZERS_TO_BUILD})
# cfi testing is gated on ubsan
if(NOT ${sanitizer} STREQUAL cfi)
compiler_rt_test_runtime(${sanitizer})
endif()
endforeach()
-
+ endif()
+ if(COMPILER_RT_BUILD_PROFILE AND COMPILER_RT_HAS_PROFILE)
compiler_rt_test_runtime(profile)
endif()
if(COMPILER_RT_BUILD_XRAY)
diff --git a/test/asan/CMakeLists.txt b/test/asan/CMakeLists.txt
index 8bfc15b5c6f69..739ae56e782bc 100644
--- a/test/asan/CMakeLists.txt
+++ b/test/asan/CMakeLists.txt
@@ -18,7 +18,7 @@ if (SHADOW_MAPPING_UNRELIABLE)
endif()
macro(get_bits_for_arch arch bits)
- if (${arch} MATCHES "i386|i686|arm|mips|mipsel")
+ if (${arch} MATCHES "i386|arm|mips|mipsel")
set(${bits} 32)
elseif (${arch} MATCHES "x86_64|powerpc64|powerpc64le|aarch64|mips64|mips64el|s390x")
set(${bits} 64)
@@ -31,9 +31,7 @@ set(ASAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
if(NOT COMPILER_RT_STANDALONE_BUILD)
list(APPEND ASAN_TEST_DEPS asan)
if(NOT APPLE AND COMPILER_RT_HAS_LLD)
- list(APPEND ASAN_TEST_DEPS
- lld
- )
+ list(APPEND ASAN_TEST_DEPS lld)
endif()
endif()
set(ASAN_DYNAMIC_TEST_DEPS ${ASAN_TEST_DEPS})
@@ -164,21 +162,12 @@ add_lit_testsuite(check-asan "Running the AddressSanitizer tests"
set_target_properties(check-asan PROPERTIES FOLDER "Compiler-RT Misc")
if(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME)
- # Add check-dynamic-asan target. It is a part of check-all only on Windows,
- # where we want to always test both dynamic and static runtime.
-
- if(NOT OS_NAME MATCHES "Windows")
- set(EXCLUDE_FROM_ALL TRUE)
- endif()
add_lit_testsuite(check-asan-dynamic
"Running the AddressSanitizer tests with dynamic runtime"
${ASAN_DYNAMIC_TESTSUITES}
DEPENDS ${ASAN_DYNAMIC_TEST_DEPS})
set_target_properties(check-asan-dynamic
PROPERTIES FOLDER "Compiler-RT Misc")
- if(NOT OS_NAME MATCHES "Windows")
- set(EXCLUDE_FROM_ALL FALSE)
- endif()
endif()
# Reset EXCLUDE_FROM_ALL to its initial value.
diff --git a/test/asan/TestCases/Darwin/abort_on_error.cc b/test/asan/TestCases/Darwin/abort_on_error.cc
index 295afb8442a4a..0aa1234149df1 100644
--- a/test/asan/TestCases/Darwin/abort_on_error.cc
+++ b/test/asan/TestCases/Darwin/abort_on_error.cc
@@ -8,6 +8,8 @@
// When we use lit's default ASAN_OPTIONS, we shouldn't crash.
// RUN: not %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: ios
+
#include <stdlib.h>
int main() {
char *x = (char*)malloc(10 * sizeof(char));
diff --git a/test/asan/TestCases/Darwin/dump_registers.cc b/test/asan/TestCases/Darwin/dump_registers.cc
index 42db446ffc1c6..cc2710f062d89 100644
--- a/test/asan/TestCases/Darwin/dump_registers.cc
+++ b/test/asan/TestCases/Darwin/dump_registers.cc
@@ -5,22 +5,22 @@
#include <assert.h>
#include <stdio.h>
+#include <sys/mman.h>
int main() {
fprintf(stderr, "Hello\n");
char *ptr;
- if (sizeof(void *) == 8)
- ptr = (char *)0x6666666666666666;
- else if (sizeof(void *) == 4)
- ptr = (char *)0x55555555;
- else
- assert(0 && "Your computer is weird.");
+ ptr = (char *)mmap(NULL, 0x10000, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ assert(ptr && "failed to mmap");
+
+ fprintf(stderr, sizeof(uintptr_t) == 8 ? "p = 0x%016lx\n" : "p = 0x%08lx\n", (uintptr_t)ptr);
+ // CHECK: p = [[ADDR:0x[0-9]+]]
char c = *ptr; // BOOM
// CHECK: ERROR: AddressSanitizer: {{SEGV|BUS}}
// CHECK: Register values:
- // CHECK: {{0x55555555|0x6666666666666666}}
+ // CHECK: [[ADDR]]
fprintf(stderr, "World\n");
return c;
}
diff --git a/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc b/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc
index 5c975b8dad2bd..d195258d71f6c 100644
--- a/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc
+++ b/test/asan/TestCases/Darwin/dyld_insert_libraries_reexec.cc
@@ -3,30 +3,28 @@
// UNSUPPORTED: ios
-// RUN: mkdir -p %T/dyld_insert_libraries_reexec
-// RUN: cp `%clang_asan %s -fsanitize=address -### 2>&1 \
-// RUN: | grep "libclang_rt.asan_osx_dynamic.dylib" \
-// RUN: | sed -e 's/.*"\(.*libclang_rt.asan_osx_dynamic.dylib\)".*/\1/'` \
-// RUN: %T/dyld_insert_libraries_reexec/libclang_rt.asan_osx_dynamic.dylib
-// RUN: %clangxx_asan %s -o %T/dyld_insert_libraries_reexec/a.out
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: cp `%clang_asan -print-file-name=lib`/darwin/libclang_rt.asan_osx_dynamic.dylib \
+// RUN: %t/libclang_rt.asan_osx_dynamic.dylib
+// RUN: %clangxx_asan %s -o %t/a.out
// RUN: %env_asan_opts=verbosity=1 \
// RUN: DYLD_INSERT_LIBRARIES=@executable_path/libclang_rt.asan_osx_dynamic.dylib \
-// RUN: %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \
+// RUN: %run %t/a.out 2>&1 \
// RUN: | FileCheck %s
// RUN: IS_OSX_10_11_OR_HIGHER=$([ `sw_vers -productVersion | cut -d'.' -f2` -lt 11 ]; echo $?)
// On OS X 10.10 and lower, if the dylib is not DYLD-inserted, ASan will re-exec.
// RUN: if [ $IS_OSX_10_11_OR_HIGHER == 0 ]; then \
-// RUN: %env_asan_opts=verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \
+// RUN: %env_asan_opts=verbosity=1 %run %t/a.out 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOINSERT %s; \
// RUN: fi
// On OS X 10.11 and higher, we don't need to DYLD-insert anymore, and the interceptors
// still installed correctly. Let's just check that things work and we don't try to re-exec.
// RUN: if [ $IS_OSX_10_11_OR_HIGHER == 1 ]; then \
-// RUN: %env_asan_opts=verbosity=1 %run %T/dyld_insert_libraries_reexec/a.out 2>&1 \
+// RUN: %env_asan_opts=verbosity=1 %run %t/a.out 2>&1 \
// RUN: | FileCheck %s; \
// RUN: fi
diff --git a/test/asan/TestCases/Darwin/dyld_insert_libraries_remove.cc b/test/asan/TestCases/Darwin/dyld_insert_libraries_remove.cc
index 69d849793d7ae..0672e064a1904 100644
--- a/test/asan/TestCases/Darwin/dyld_insert_libraries_remove.cc
+++ b/test/asan/TestCases/Darwin/dyld_insert_libraries_remove.cc
@@ -4,26 +4,29 @@
// UNSUPPORTED: ios
-// RUN: mkdir -p %T/dyld_insert_libraries_remove
-// RUN: cp `%clang_asan %s -fsanitize=address -### 2>&1 \
-// RUN: | grep "libclang_rt.asan_osx_dynamic.dylib" \
-// RUN: | sed -e 's/.*"\(.*libclang_rt.asan_osx_dynamic.dylib\)".*/\1/'` \
-// RUN: %T/dyld_insert_libraries_remove/libclang_rt.asan_osx_dynamic.dylib
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: cp `%clang_asan -print-file-name=lib`/darwin/libclang_rt.asan_osx_dynamic.dylib \
+// RUN: %t/libclang_rt.asan_osx_dynamic.dylib
-// RUN: %clangxx_asan %s -o %T/dyld_insert_libraries_remove/a.out
+// RUN: %clangxx_asan %s -o %t/a.out
// RUN: %clangxx -DSHARED_LIB %s \
-// RUN: -dynamiclib -o %T/dyld_insert_libraries_remove/dummy-so.dylib
+// RUN: -dynamiclib -o %t/dummy-so.dylib
-// RUN: ( cd %T/dyld_insert_libraries_remove && \
+// RUN: ( cd %t && \
// RUN: DYLD_INSERT_LIBRARIES=@executable_path/libclang_rt.asan_osx_dynamic.dylib:dummy-so.dylib \
// RUN: %run ./a.out 2>&1 ) | FileCheck %s || exit 1
-// RUN: ( cd %T/dyld_insert_libraries_remove && \
+// RUN: ( cd %t && \
// RUN: DYLD_INSERT_LIBRARIES=libclang_rt.asan_osx_dynamic.dylib:dummy-so.dylib \
// RUN: %run ./a.out 2>&1 ) | FileCheck %s || exit 1
-// RUN: ( cd %T/dyld_insert_libraries_remove && \
-// RUN: DYLD_INSERT_LIBRARIES=%T/dyld_insert_libraries_remove/libclang_rt.asan_osx_dynamic.dylib:dummy-so.dylib \
+// RUN: ( cd %t && \
+// RUN: %env_asan_opts=strip_env=0 \
+// RUN: DYLD_INSERT_LIBRARIES=libclang_rt.asan_osx_dynamic.dylib:dummy-so.dylib \
+// RUN: %run ./a.out 2>&1 ) | FileCheck %s --check-prefix=CHECK-KEEP || exit 1
+
+// RUN: ( cd %t && \
+// RUN: DYLD_INSERT_LIBRARIES=%t/libclang_rt.asan_osx_dynamic.dylib:dummy-so.dylib \
// RUN: %run ./a.out 2>&1 ) | FileCheck %s || exit 1
#if !defined(SHARED_LIB)
@@ -34,6 +37,7 @@ int main() {
const char kEnvName[] = "DYLD_INSERT_LIBRARIES";
printf("%s=%s\n", kEnvName, getenv(kEnvName));
// CHECK: {{DYLD_INSERT_LIBRARIES=dummy-so.dylib}}
+ // CHECK-KEEP: {{DYLD_INSERT_LIBRARIES=libclang_rt.asan_osx_dynamic.dylib:dummy-so.dylib}}
return 0;
}
#else // SHARED_LIB
diff --git a/test/asan/TestCases/Darwin/fclose.c b/test/asan/TestCases/Darwin/fclose.c
new file mode 100644
index 0000000000000..7807122bdcc17
--- /dev/null
+++ b/test/asan/TestCases/Darwin/fclose.c
@@ -0,0 +1,13 @@
+// RUN: %clang_asan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, const char * argv[]) {
+ fclose(NULL);
+ fprintf(stderr, "Finished.\n");
+ return 0;
+}
+
+// CHECK: Finished.
diff --git a/test/asan/TestCases/Darwin/getpwnam.c b/test/asan/TestCases/Darwin/getpwnam.c
new file mode 100644
index 0000000000000..db3ec3f8c2a80
--- /dev/null
+++ b/test/asan/TestCases/Darwin/getpwnam.c
@@ -0,0 +1,15 @@
+// RUN: %clang_asan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+int main(int argc, const char * argv[]) {
+ getpwnam(NULL);
+ fprintf(stderr, "Finished.\n");
+ return 0;
+}
+
+// CHECK: Finished.
diff --git a/test/asan/TestCases/Darwin/interface_symbols_darwin.c b/test/asan/TestCases/Darwin/interface_symbols_darwin.cc
index 09af1ece589fc..a8e2bcb3ebc8d 100644
--- a/test/asan/TestCases/Darwin/interface_symbols_darwin.c
+++ b/test/asan/TestCases/Darwin/interface_symbols_darwin.cc
@@ -2,7 +2,7 @@
// If you're changing this file, please also change
// ../Linux/interface_symbols.c
-// RUN: %clang_asan -dead_strip -O2 %s -o %t.exe
+// RUN: %clangxx_asan -dead_strip -O2 %s -o %t.exe
//
// note: we can not use -D on Darwin.
// RUN: nm -g `%clang_asan %s -fsanitize=address -### 2>&1 | grep "libclang_rt.asan_osx_dynamic.dylib" | sed -e 's/.*"\(.*libclang_rt.asan_osx_dynamic.dylib\)".*/\1/'` \
@@ -11,7 +11,7 @@
// RUN: | grep -v "__sanitizer_syscall" \
// RUN: | grep -v "__sanitizer_weak_hook" \
// RUN: | grep -v "__sanitizer_mz" \
-// RUN: | grep -v "__ubsan_handle_dynamic_type_cache_miss" \
+// RUN: | grep -v "__sancov_lowest_stack" \
// RUN: | sed -e "s/__asan_version_mismatch_check_v[0-9]+/__asan_version_mismatch_check/" \
// RUN: > %t.exports
//
diff --git a/test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc b/test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc
index cd277a05b40b8..bee23f25c89c8 100644
--- a/test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc
+++ b/test/asan/TestCases/Darwin/reexec-insert-libraries-env.cc
@@ -10,6 +10,8 @@
// RUN: %env DYLD_INSERT_LIBRARIES=darwin-dummy-shared-lib-so.dylib \
// RUN: %run %t 2>&1 | FileCheck %s || exit 1
+// UNSUPPORTED: ios
+
#if !defined(SHARED_LIB)
#include <stdio.h>
#include <stdlib.h>
diff --git a/test/asan/TestCases/Darwin/suppressions-function.cc b/test/asan/TestCases/Darwin/suppressions-function.cc
new file mode 100644
index 0000000000000..f58796fb878d4
--- /dev/null
+++ b/test/asan/TestCases/Darwin/suppressions-function.cc
@@ -0,0 +1,28 @@
+// Check that without suppressions, we catch the issue.
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
+
+// RUN: echo "interceptor_via_fun:crash_function" > %t.supp
+// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=suppressions='"%t.supp"' %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
+
+// UNSUPPORTED: ios
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void crash_function() {
+ char *a = (char *)malloc(6);
+ free(a);
+ size_t len = strlen(a); // BOOM
+ fprintf(stderr, "strlen ignored, len = %zu\n", len);
+}
+
+int main() {
+ crash_function();
+}
+
+// CHECK-CRASH: AddressSanitizer: heap-use-after-free
+// CHECK-CRASH-NOT: strlen ignored
+// CHECK-IGNORE-NOT: AddressSanitizer: heap-use-after-free
+// CHECK-IGNORE: strlen ignored
diff --git a/test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc b/test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc
index 62cf853a54361..38fb3aa558483 100644
--- a/test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc
+++ b/test/asan/TestCases/Darwin/unset-insert-libraries-on-exec.cc
@@ -2,16 +2,18 @@
// executing other programs.
// RUN: %clangxx_asan %s -o %t
-// RUN: %clangxx %p/../Helpers/echo-env.cc -o %T/echo-env
+// RUN: %clangxx %p/../Helpers/echo-env.cc -o %t-echo-env
// RUN: %clangxx -DSHARED_LIB %s \
// RUN: -dynamiclib -o %t-darwin-dummy-shared-lib-so.dylib
// Make sure DYLD_INSERT_LIBRARIES doesn't contain the runtime library before
// execl().
-// RUN: %run %t %T/echo-env >/dev/null 2>&1
+// RUN: %run %t %t-echo-env >/dev/null 2>&1
// RUN: %env DYLD_INSERT_LIBRARIES=%t-darwin-dummy-shared-lib-so.dylib \
-// RUN: %run %t %T/echo-env 2>&1 | FileCheck %s || exit 1
+// RUN: %run %t %t-echo-env 2>&1 | FileCheck %s || exit 1
+
+// UNSUPPORTED: ios
#if !defined(SHARED_LIB)
#include <unistd.h>
diff --git a/test/asan/TestCases/Helpers/underflow.cc b/test/asan/TestCases/Helpers/underflow.cc
new file mode 100644
index 0000000000000..26979482fab18
--- /dev/null
+++ b/test/asan/TestCases/Helpers/underflow.cc
@@ -0,0 +1 @@
+int YYY[3]={1,2,3};
diff --git a/test/asan/TestCases/Linux/abort_on_error.cc b/test/asan/TestCases/Linux/abort_on_error.cc
index 3f70613e4c7c1..3fe98995f6856 100644
--- a/test/asan/TestCases/Linux/abort_on_error.cc
+++ b/test/asan/TestCases/Linux/abort_on_error.cc
@@ -9,6 +9,7 @@
// lit doesn't set ASAN_OPTIONS anyway.
// RUN: not %run %t 2>&1 | FileCheck %s
+// Android runs with abort_on_error=0
// UNSUPPORTED: android
#include <stdlib.h>
diff --git a/test/asan/TestCases/Linux/aligned_delete_test.cc b/test/asan/TestCases/Linux/aligned_delete_test.cc
new file mode 100644
index 0000000000000..5b9455e56553d
--- /dev/null
+++ b/test/asan/TestCases/Linux/aligned_delete_test.cc
@@ -0,0 +1,168 @@
+// RUN: %clangxx_asan -std=c++1z -faligned-allocation -fsanitize-recover=address -O0 %s -o %t
+// RUN: %env_asan_opts=new_delete_type_mismatch=1:halt_on_error=false:detect_leaks=false %run %t 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=new_delete_type_mismatch=0 %run %t
+
+// RUN: %clangxx_asan -std=c++1z -faligned-allocation -fsized-deallocation -fsanitize-recover=address -O0 %s -o %t
+// RUN: %env_asan_opts=new_delete_type_mismatch=1:halt_on_error=false:detect_leaks=false %run %t 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=new_delete_type_mismatch=0 %run %t
+
+// REQUIRES: asan-static-runtime
+
+#include <stdio.h>
+
+// Define all new/delete to do not depend on the version provided by the
+// plaform. The implementation is provided by ASan anyway.
+
+namespace std {
+struct nothrow_t {};
+static const nothrow_t nothrow;
+enum class align_val_t : size_t {};
+} // namespace std
+
+void *operator new(size_t);
+void *operator new[](size_t);
+void *operator new(size_t, std::nothrow_t const&);
+void *operator new[](size_t, std::nothrow_t const&);
+void *operator new(size_t, std::align_val_t);
+void *operator new[](size_t, std::align_val_t);
+void *operator new(size_t, std::align_val_t, std::nothrow_t const&);
+void *operator new[](size_t, std::align_val_t, std::nothrow_t const&);
+
+void operator delete(void*) throw();
+void operator delete[](void*) throw();
+void operator delete(void*, std::nothrow_t const&);
+void operator delete[](void*, std::nothrow_t const&);
+void operator delete(void*, size_t) throw();
+void operator delete[](void*, size_t) throw();
+void operator delete(void*, std::align_val_t) throw();
+void operator delete[](void*, std::align_val_t) throw();
+void operator delete(void*, std::align_val_t, std::nothrow_t const&);
+void operator delete[](void*, std::align_val_t, std::nothrow_t const&);
+void operator delete(void*, size_t, std::align_val_t) throw();
+void operator delete[](void*, size_t, std::align_val_t) throw();
+
+
+template<typename T>
+inline T* break_optimization(T *arg) {
+ __asm__ __volatile__("" : : "r" (arg) : "memory");
+ return arg;
+}
+
+
+struct S12 { int a, b, c; };
+struct alignas(128) S12_128 { int a, b, c; };
+struct alignas(256) S12_256 { int a, b, c; };
+struct alignas(512) S1024_512 { char a[1024]; };
+struct alignas(1024) S1024_1024 { char a[1024]; };
+
+
+int main(int argc, char **argv) {
+ fprintf(stderr, "Testing valid cases\n");
+
+ delete break_optimization(new S12);
+ operator delete(break_optimization(new S12), std::nothrow);
+ delete [] break_optimization(new S12[100]);
+ operator delete[](break_optimization(new S12[100]), std::nothrow);
+
+ delete break_optimization(new S12_128);
+ operator delete(break_optimization(new S12_128),
+ std::align_val_t(alignof(S12_128)));
+ operator delete(break_optimization(new S12_128),
+ std::align_val_t(alignof(S12_128)), std::nothrow);
+ operator delete(break_optimization(new S12_128), sizeof(S12_128),
+ std::align_val_t(alignof(S12_128)));
+
+ delete [] break_optimization(new S12_128[100]);
+ operator delete[](break_optimization(new S12_128[100]),
+ std::align_val_t(alignof(S12_128)));
+ operator delete[](break_optimization(new S12_128[100]),
+ std::align_val_t(alignof(S12_128)), std::nothrow);
+ operator delete[](break_optimization(new S12_128[100]), sizeof(S12_128[100]),
+ std::align_val_t(alignof(S12_128)));
+
+ fprintf(stderr, "Done\n");
+ // CHECK: Testing valid cases
+ // CHECK-NEXT: Done
+
+ // Explicit mismatched calls.
+
+ operator delete(break_optimization(new S12_128), std::nothrow);
+ // CHECK: AddressSanitizer: new-delete-type-mismatch
+ // CHECK: object passed to delete has wrong type:
+ // CHECK: alignment of the allocated type: 128 bytes;
+ // CHECK: alignment of the deallocated type: default-aligned.
+ // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch
+
+ operator delete(break_optimization(new S12_128), sizeof(S12_128));
+ // CHECK: AddressSanitizer: new-delete-type-mismatch
+ // CHECK: object passed to delete has wrong type:
+ // CHECK: alignment of the allocated type: 128 bytes;
+ // CHECK: alignment of the deallocated type: default-aligned.
+ // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch
+
+ operator delete[](break_optimization(new S12_128[100]), std::nothrow);
+ // CHECK: AddressSanitizer: new-delete-type-mismatch
+ // CHECK: object passed to delete has wrong type:
+ // CHECK: alignment of the allocated type: 128 bytes;
+ // CHECK: alignment of the deallocated type: default-aligned.
+ // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch
+
+ operator delete[](break_optimization(new S12_128[100]), sizeof(S12_128[100]));
+ // CHECK: AddressSanitizer: new-delete-type-mismatch
+ // CHECK: object passed to delete has wrong type:
+ // CHECK: alignment of the allocated type: 128 bytes;
+ // CHECK: alignment of the deallocated type: default-aligned.
+ // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch
+
+ // Various mismatched alignments.
+
+ delete break_optimization(reinterpret_cast<S12*>(new S12_256));
+ // CHECK: AddressSanitizer: new-delete-type-mismatch
+ // CHECK: object passed to delete has wrong type:
+ // CHECK: alignment of the allocated type: 256 bytes;
+ // CHECK: alignment of the deallocated type: default-aligned.
+ // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch
+
+ delete break_optimization(reinterpret_cast<S12_256*>(new S12));
+ // CHECK: AddressSanitizer: new-delete-type-mismatch
+ // CHECK: object passed to delete has wrong type:
+ // CHECK: alignment of the allocated type: default-aligned;
+ // CHECK: alignment of the deallocated type: 256 bytes.
+ // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch
+
+ delete break_optimization(reinterpret_cast<S12_128*>(new S12_256));
+ // CHECK: AddressSanitizer: new-delete-type-mismatch
+ // CHECK: object passed to delete has wrong type:
+ // CHECK: alignment of the allocated type: 256 bytes;
+ // CHECK: alignment of the deallocated type: 128 bytes.
+ // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch
+
+ delete [] break_optimization(reinterpret_cast<S12*>(new S12_256[100]));
+ // CHECK: AddressSanitizer: new-delete-type-mismatch
+ // CHECK: object passed to delete has wrong type:
+ // CHECK: alignment of the allocated type: 256 bytes;
+ // CHECK: alignment of the deallocated type: default-aligned.
+ // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch
+
+ delete [] break_optimization(reinterpret_cast<S12_256*>(new S12[100]));
+ // CHECK: AddressSanitizer: new-delete-type-mismatch
+ // CHECK: object passed to delete has wrong type:
+ // CHECK: alignment of the allocated type: default-aligned;
+ // CHECK: alignment of the deallocated type: 256 bytes.
+ // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch
+
+ delete [] break_optimization(reinterpret_cast<S12_128*>(new S12_256[100]));
+ // CHECK: AddressSanitizer: new-delete-type-mismatch
+ // CHECK: object passed to delete has wrong type:
+ // CHECK: alignment of the allocated type: 256 bytes;
+ // CHECK: alignment of the deallocated type: 128 bytes.
+ // CHECK: SUMMARY: AddressSanitizer: new-delete-type-mismatch
+
+ // Push ASan limits, the current limitation is that it cannot differentiate
+ // alignments above 512 bytes.
+ fprintf(stderr, "Checking alignments >= 512 bytes\n");
+ delete break_optimization(reinterpret_cast<S1024_512*>(new S1024_1024));
+ fprintf(stderr, "Done\n");
+ // CHECK: Checking alignments >= 512 bytes
+ // CHECK-NEXT: Done
+}
diff --git a/test/asan/TestCases/Linux/allocator_oom_test.cc b/test/asan/TestCases/Linux/allocator_oom_test.cc
index f94475f9b7805..6382003781ce7 100644
--- a/test/asan/TestCases/Linux/allocator_oom_test.cc
+++ b/test/asan/TestCases/Linux/allocator_oom_test.cc
@@ -31,6 +31,7 @@
// ASan shadow memory on s390 is too large for this test.
// AArch64 bots fail on this test.
// TODO(alekseys): Android lit do not run ulimit on device.
+// REQUIRES: shadow-scale-3
// UNSUPPORTED: s390,android,arm,aarch64
#include <stdlib.h>
diff --git a/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc b/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc
index cbc900decea31..acbe947267622 100644
--- a/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc
+++ b/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc
@@ -1,7 +1,7 @@
// Check that a stack unwinding algorithm works corretly even with the assembly
// instrumentation.
-// REQUIRES: x86_64-target-arch
+// REQUIRES: x86_64-target-arch, shadow-scale-3
// RUN: %clangxx_asan -g -O1 %s -fno-inline-functions -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -mllvm -asan-instrument-assembly -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -g -O1 %s -fno-inline-functions -fomit-frame-pointer -momit-leaf-frame-pointer -mllvm -asan-instrument-assembly -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -g0 -O1 %s -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-exceptions -fno-inline-functions -fomit-frame-pointer -momit-leaf-frame-pointer -mllvm -asan-instrument-assembly -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nounwind
diff --git a/test/asan/TestCases/Linux/asan_prelink_test.cc b/test/asan/TestCases/Linux/asan_prelink_test.cc
index a5808ba3a9a51..e00c215e92b11 100644
--- a/test/asan/TestCases/Linux/asan_prelink_test.cc
+++ b/test/asan/TestCases/Linux/asan_prelink_test.cc
@@ -10,7 +10,7 @@
// RUN: %env_asan_opts=verbosity=1 %run %t 2>&1 | FileCheck %s
// GNU driver doesn't handle .so files properly.
-// REQUIRES: x86_64-target-arch, Clang
+// REQUIRES: x86_64-target-arch, shadow-scale-3, Clang
#if BUILD_SO
int G;
int *getG() {
diff --git a/test/asan/TestCases/Linux/asan_preload_test-1.cc b/test/asan/TestCases/Linux/asan_preload_test-1.cc
index 4e365b5633f37..e11bd623ddb6b 100644
--- a/test/asan/TestCases/Linux/asan_preload_test-1.cc
+++ b/test/asan/TestCases/Linux/asan_preload_test-1.cc
@@ -10,7 +10,7 @@
// REQUIRES: asan-dynamic-runtime
// This way of setting LD_PRELOAD does not work with Android test runner.
-// REQUIRES: not-android
+// REQUIRES: !android
#if BUILD_SO
char dummy;
diff --git a/test/asan/TestCases/Linux/asan_preload_test-2.cc b/test/asan/TestCases/Linux/asan_preload_test-2.cc
index 488fd52e682a6..817c560d42abb 100644
--- a/test/asan/TestCases/Linux/asan_preload_test-2.cc
+++ b/test/asan/TestCases/Linux/asan_preload_test-2.cc
@@ -6,7 +6,7 @@
// REQUIRES: asan-dynamic-runtime
// This way of setting LD_PRELOAD does not work with Android test runner.
-// REQUIRES: not-android
+// REQUIRES: !android
#include <stdlib.h>
diff --git a/test/asan/TestCases/Linux/calloc-preload.c b/test/asan/TestCases/Linux/calloc-preload.c
index eb1c6738b6e92..e1f33192b57c6 100644
--- a/test/asan/TestCases/Linux/calloc-preload.c
+++ b/test/asan/TestCases/Linux/calloc-preload.c
@@ -7,7 +7,7 @@
// REQUIRES: asan-dynamic-runtime
//
// This way of setting LD_PRELOAD does not work with Android test runner.
-// REQUIRES: not-android
+// REQUIRES: !android
#include <stdio.h>
#include <stdlib.h>
diff --git a/test/asan/TestCases/Linux/cuda_test.cc b/test/asan/TestCases/Linux/cuda_test.cc
index e87f56b0c20e2..e532f2ee7bf8d 100644
--- a/test/asan/TestCases/Linux/cuda_test.cc
+++ b/test/asan/TestCases/Linux/cuda_test.cc
@@ -1,7 +1,7 @@
// Emulate the behavior of the NVIDIA CUDA driver
// that mmaps memory inside the asan's shadow gap.
//
-// REQUIRES: x86_64-target-arch
+// REQUIRES: x86_64-target-arch, shadow-scale-3
//
// RUN: %clangxx_asan %s -o %t
// RUN: not %env_asan_opts=protect_shadow_gap=1 %t 2>&1 | FileCheck %s --check-prefix=CHECK-PROTECT1
@@ -33,5 +33,3 @@ int main(void) {
*(char*)(Base + 1234) = 1;
// CHECK-PROTECT0: AddressSanitizer: use-after-poison on address 0x0002000004d2
}
-
-
diff --git a/test/asan/TestCases/Linux/interface_symbols_linux.c b/test/asan/TestCases/Linux/interface_symbols_linux.cc
index 33fdd5ca1d824..8c22976e71078 100644
--- a/test/asan/TestCases/Linux/interface_symbols_linux.c
+++ b/test/asan/TestCases/Linux/interface_symbols_linux.cc
@@ -1,11 +1,11 @@
// Check the presence of interface symbols in compiled file.
-// RUN: %clang_asan -O2 %s -o %t.exe
+// RUN: %clangxx_asan -O2 %s -o %t.exe
// RUN: nm -D %t.exe | grep " [TWw] " \
// RUN: | grep -o "\(__asan_\|__ubsan_\|__sancov_\|__sanitizer_\)[^ ]*" \
// RUN: | grep -v "__sanitizer_syscall" \
// RUN: | grep -v "__sanitizer_weak_hook" \
-// RUN: | grep -v "__ubsan_handle_dynamic_type_cache_miss" \
+// RUN: | grep -v "__sancov_lowest_stack" \
// RUN: | sed -e "s/__asan_version_mismatch_check_v[0-9]+/__asan_version_mismatch_check/" \
// RUN: > %t.exports
//
diff --git a/test/asan/TestCases/Linux/kernel-area.cc b/test/asan/TestCases/Linux/kernel-area.cc
index d7a544fecaf9b..41b507cdfe0f3 100644
--- a/test/asan/TestCases/Linux/kernel-area.cc
+++ b/test/asan/TestCases/Linux/kernel-area.cc
@@ -16,9 +16,8 @@
// CHECK-kernel-64-bits: || `[0x28{{0+}}, 0x3{{f+}}]` || HighShadow ||
// CHECK-kernel-64-bits: || `[0x24{{0+}}, 0x27{{f+}}]` || ShadowGap ||
//
-// REQUIRES: i386-target-arch
+// REQUIRES: i386-target-arch, shadow-scale-3
int main() {
return 0;
}
-
diff --git a/test/asan/TestCases/Linux/nohugepage_test.cc b/test/asan/TestCases/Linux/nohugepage_test.cc
index ce8f17e7899ec..0fd7c558d6df4 100644
--- a/test/asan/TestCases/Linux/nohugepage_test.cc
+++ b/test/asan/TestCases/Linux/nohugepage_test.cc
@@ -9,7 +9,7 @@
// Would be great to run the test with no_huge_pages_for_shadow=0, but
// the result will depend on the OS version and settings...
//
-// REQUIRES: x86_64-target-arch
+// REQUIRES: x86_64-target-arch, shadow-scale-3
//
// WARNING: this test is very subtle and may nto work on some systems.
// If this is the case we'll need to futher improve it or disable it.
diff --git a/test/asan/TestCases/Linux/preinstalled_signal.cc b/test/asan/TestCases/Linux/preinstalled_signal.cc
index 4d466c21f9440..ac4ea93a5418d 100644
--- a/test/asan/TestCases/Linux/preinstalled_signal.cc
+++ b/test/asan/TestCases/Linux/preinstalled_signal.cc
@@ -16,7 +16,7 @@
// REQUIRES: asan-dynamic-runtime
// This way of setting LD_PRELOAD does not work with Android test runner.
-// REQUIRES: not-android
+// REQUIRES: !android
// clang-format on
#include <assert.h>
@@ -32,8 +32,14 @@ void SigHandler(int signum) { handler = "TestSigHandler"; }
void SigAction(int, siginfo_t *, void *) { handler = "TestSigAction"; }
struct KernelSigaction {
+
+#if defined(__mips__)
+ unsigned long flags;
+ __sighandler_t handler;
+#else
__sighandler_t handler;
unsigned long flags;
+#endif
void (*restorer)();
char unused[1024];
};
@@ -98,10 +104,10 @@ int main(int argc, char *argv[]) {
}
// CHECK-NOT: TestSig
-// CHECK: ASAN:DEADLYSIGNAL
+// CHECK: AddressSanitizer:DEADLYSIGNAL
-// CHECK-HANDLER-NOT: ASAN:DEADLYSIGNAL
+// CHECK-HANDLER-NOT: AddressSanitizer:DEADLYSIGNAL
// CHECK-HANDLER: TestSigHandler
-// CHECK-ACTION-NOT: ASAN:DEADLYSIGNAL
+// CHECK-ACTION-NOT: AddressSanitizer:DEADLYSIGNAL
// CHECK-ACTION: TestSigAction
diff --git a/test/asan/TestCases/Linux/printf-fortify-1.c b/test/asan/TestCases/Linux/printf-fortify-1.c
new file mode 100644
index 0000000000000..2e0c70c1e6485
--- /dev/null
+++ b/test/asan/TestCases/Linux/printf-fortify-1.c
@@ -0,0 +1,18 @@
+// RUN: %clang -fPIC -shared -O2 -D_FORTIFY_SOURCE=2 -D_DSO %s -o %t.so
+// RUN: %clang_asan -o %t %t.so %s
+// RUN: not %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: android
+#ifdef _DSO
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+__attribute__((noinline)) int foo() {
+ char *write_buffer = (char *)malloc(1);
+ // CHECK: AddressSanitizer: heap-buffer-overflow
+ sprintf(write_buffer, "%s_%s", "one", "two");
+ return write_buffer[0];
+}
+#else
+extern int foo();
+int main() { return foo(); }
+#endif
diff --git a/test/asan/TestCases/Linux/printf-fortify-2.c b/test/asan/TestCases/Linux/printf-fortify-2.c
new file mode 100644
index 0000000000000..6ea1e00e4a66d
--- /dev/null
+++ b/test/asan/TestCases/Linux/printf-fortify-2.c
@@ -0,0 +1,18 @@
+// RUN: %clang -fPIC -shared -O2 -D_FORTIFY_SOURCE=2 -D_DSO %s -o %t.so
+// RUN: %clang_asan %s -o %t %t.so
+// RUN: not %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: android
+#ifdef _DSO
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+__attribute__((noinline)) int foo() {
+ char *write_buffer = (char *)malloc(1);
+ // CHECK: AddressSanitizer: heap-buffer-overflow
+ snprintf(write_buffer, 4096, "%s_%s", "one", "two");
+ return write_buffer[0];
+}
+#else
+extern int foo();
+int main() { return foo(); }
+#endif
diff --git a/test/asan/TestCases/Linux/printf-fortify-3.c b/test/asan/TestCases/Linux/printf-fortify-3.c
new file mode 100644
index 0000000000000..a4b49dc981678
--- /dev/null
+++ b/test/asan/TestCases/Linux/printf-fortify-3.c
@@ -0,0 +1,22 @@
+// RUN: %clang -shared -fPIC -D_DSO -O2 -D_FORTIFY_SOURCE=2 %s -o %t.so
+// RUN: %clang_asan %s -o %t %t.so
+// RUN: not %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: android
+#ifdef _DSO
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+__attribute__((noinline)) char foo(const char *format, ...) {
+ char *write_buffer = (char *)malloc(1);
+ va_list ap;
+ va_start(ap, format);
+ // CHECK: AddressSanitizer: heap-buffer-overflow
+ vsprintf(write_buffer, format, ap);
+ va_end(ap);
+ return write_buffer[0];
+}
+#else
+extern int foo(const char *format, ...);
+int main() { return foo("%s_%s", "one", "two"); }
+#endif
diff --git a/test/asan/TestCases/Linux/printf-fortify-4.c b/test/asan/TestCases/Linux/printf-fortify-4.c
new file mode 100644
index 0000000000000..57ec42f3823a4
--- /dev/null
+++ b/test/asan/TestCases/Linux/printf-fortify-4.c
@@ -0,0 +1,22 @@
+// RUN: %clang -fPIC -shared -O2 -D_FORTIFY_SOURCE=2 -D_DSO %s -o %t.so
+// RUN: %clang_asan %s -o %t %t.so
+// RUN: not %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: android
+#ifdef _DSO
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+__attribute__((noinline)) char foo(const char *format, ...) {
+ char *write_buffer = (char *)malloc(1);
+ va_list ap;
+ va_start(ap, format);
+ // CHECK: AddressSanitizer: heap-buffer-overflow
+ vsnprintf(write_buffer, 4096, format, ap);
+ va_end(ap);
+ return write_buffer[0];
+}
+#else
+extern int foo(const char *format, ...);
+int main() { return foo("%s_%s", "one", "two"); }
+#endif
diff --git a/test/asan/TestCases/Linux/printf-fortify-5.c b/test/asan/TestCases/Linux/printf-fortify-5.c
new file mode 100644
index 0000000000000..487457a90de1b
--- /dev/null
+++ b/test/asan/TestCases/Linux/printf-fortify-5.c
@@ -0,0 +1,18 @@
+// RUN: %clang -fPIC -shared -O2 -D_FORTIFY_SOURCE=2 -D_DSO %s -o %t.so
+// RUN: %clang_asan -o %t %t.so %s
+// RUN: not %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: android
+#ifdef _DSO
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+__attribute__((noinline)) int foo() {
+ char *read_buffer = (char *)malloc(1);
+ // CHECK: AddressSanitizer: heap-buffer-overflow
+ fprintf(stderr, read_buffer, 4096);
+ return read_buffer[0];
+}
+#else
+extern int foo();
+int main() { return foo(); }
+#endif
diff --git a/test/asan/TestCases/Linux/pvalloc-overflow.cc b/test/asan/TestCases/Linux/pvalloc-overflow.cc
new file mode 100644
index 0000000000000..b47c6266b93be
--- /dev/null
+++ b/test/asan/TestCases/Linux/pvalloc-overflow.cc
@@ -0,0 +1,41 @@
+// RUN: %clangxx_asan %s -o %t
+// RUN: ASAN_OPTIONS=allocator_may_return_null=0 not %run %t m1 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=allocator_may_return_null=1 %run %t m1 2>&1
+// RUN: ASAN_OPTIONS=allocator_may_return_null=0 not %run %t psm1 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=allocator_may_return_null=1 %run %t psm1 2>&1
+
+// UNSUPPORTED: freebsd, android
+
+// Checks that pvalloc overflows are caught. If the allocator is allowed to
+// return null, the errno should be set to ENOMEM.
+
+#include <assert.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[]) {
+ void *p;
+ size_t page_size;
+
+ assert(argc == 2);
+
+ page_size = sysconf(_SC_PAGESIZE);
+
+ if (!strcmp(argv[1], "m1")) {
+ p = pvalloc((uintptr_t)-1);
+ assert(!p);
+ assert(errno == ENOMEM);
+ }
+ if (!strcmp(argv[1], "psm1")) {
+ p = pvalloc((uintptr_t)-(page_size - 1));
+ assert(!p);
+ assert(errno == ENOMEM);
+ }
+
+ return 0;
+}
+
+// CHECK: AddressSanitizer's allocator is terminating the process
diff --git a/test/asan/TestCases/Linux/recoverable-lsan.cc b/test/asan/TestCases/Linux/recoverable-lsan.cc
new file mode 100644
index 0000000000000..935645327b00a
--- /dev/null
+++ b/test/asan/TestCases/Linux/recoverable-lsan.cc
@@ -0,0 +1,22 @@
+// Ensure that output is the same but exit code depends on halt_on_error value
+// RUN: %clangxx_asan %s -o %t
+// RUN: %env_asan_opts="halt_on_error=0" %run %t 2>&1 | FileCheck %s
+// RUN: %env_asan_opts="halt_on_error=1" not %run %t 2>&1 | FileCheck %s
+// RUN: not %run %t 2>&1 | FileCheck %s
+// REQUIRES: leak-detection
+// UNSUPPORTED: android
+
+#include <stdlib.h>
+
+int f() {
+ volatile int *a = (int *)malloc(20);
+ a[0] = 1;
+ return a[0];
+}
+
+int main() {
+ f();
+ f();
+}
+
+// CHECK: LeakSanitizer: detected memory leaks
diff --git a/test/asan/TestCases/Linux/release_to_os_test.cc b/test/asan/TestCases/Linux/release_to_os_test.cc
index c85bcbb7f15be..3e28ffde46ab6 100644
--- a/test/asan/TestCases/Linux/release_to_os_test.cc
+++ b/test/asan/TestCases/Linux/release_to_os_test.cc
@@ -1,18 +1,21 @@
// Tests ASAN_OPTIONS=allocator_release_to_os=1
-//
// RUN: %clangxx_asan -std=c++11 %s -o %t
// RUN: %env_asan_opts=allocator_release_to_os_interval_ms=0 %run %t 2>&1 | FileCheck %s --check-prefix=RELEASE
// RUN: %env_asan_opts=allocator_release_to_os_interval_ms=-1 %run %t 2>&1 | FileCheck %s --check-prefix=NO_RELEASE
-//
+// RUN: %env_asan_opts=allocator_release_to_os_interval_ms=-1 %run %t force 2>&1 | FileCheck %s --check-prefix=FORCE_RELEASE
+
// REQUIRES: x86_64-target-arch
-#include <stdlib.h>
-#include <stdio.h>
+
#include <algorithm>
-#include <stdint.h>
#include <assert.h>
#include <random>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sanitizer/allocator_interface.h>
#include <sanitizer/asan_interface.h>
void MallocReleaseStress() {
@@ -39,10 +42,13 @@ void MallocReleaseStress() {
delete[] p;
}
-int main() {
+int main(int argc, char **argv) {
MallocReleaseStress();
+ if (argc > 1 && !strcmp("force", argv[1]))
+ __sanitizer_purge_allocator();
__asan_print_accumulated_stats();
}
// RELEASE: mapped:{{.*}}releases: {{[1-9]}}
// NO_RELEASE: mapped:{{.*}}releases: 0
+// FORCE_RELEASE: mapped:{{.*}}releases: {{[1-9]}}
diff --git a/test/asan/TestCases/Linux/swapcontext_annotation.cc b/test/asan/TestCases/Linux/swapcontext_annotation.cc
index 44189c0608153..3bfda735307b8 100644
--- a/test/asan/TestCases/Linux/swapcontext_annotation.cc
+++ b/test/asan/TestCases/Linux/swapcontext_annotation.cc
@@ -16,6 +16,7 @@
#include <pthread.h>
#include <setjmp.h>
+#include <signal.h>
#include <stdio.h>
#include <sys/time.h>
#include <ucontext.h>
diff --git a/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc b/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
index 2c4c133b740cf..11d5928a80139 100644
--- a/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
+++ b/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
@@ -9,6 +9,8 @@
// RUN: %env_asan_opts=symbolize=0 not %run %t 2>&1 | %asan_symbolize | FileCheck %s
// REQUIRES: stable-runtime
+// UNSUPPORTED: ios
+
#if !defined(SHARED_LIB)
#include <dlfcn.h>
#include <stdio.h>
diff --git a/test/asan/TestCases/Posix/concurrent_overflow.cc b/test/asan/TestCases/Posix/concurrent_overflow.cc
new file mode 100644
index 0000000000000..e9b9899c31a20
--- /dev/null
+++ b/test/asan/TestCases/Posix/concurrent_overflow.cc
@@ -0,0 +1,33 @@
+// RUN: %clangxx_asan -O0 -w %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// Checks that concurrent reports will not trigger false "nested bug" reports.
+// Regression test for https://github.com/google/sanitizers/issues/858
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void *start_routine(void *arg) {
+ volatile int *counter = (volatile int *)arg;
+ char buf[8];
+ __atomic_sub_fetch(counter, 1, __ATOMIC_SEQ_CST);
+ while (*counter)
+ ;
+ buf[0] = buf[9];
+ return 0;
+}
+
+int main(void) {
+ const int n_threads = 8;
+ int i, counter = n_threads;
+ pthread_t thread;
+
+ for (i = 0; i < n_threads; ++i)
+ pthread_create(&thread, NULL, &start_routine, (void *)&counter);
+ sleep(5);
+ return 0;
+}
+
+// CHECK-NOT: nested bug
+// CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address
+// CHECK: SUMMARY: AddressSanitizer: stack-buffer-overflow
diff --git a/test/asan/TestCases/Posix/coverage-reset.cc b/test/asan/TestCases/Posix/coverage-reset.cc
new file mode 100644
index 0000000000000..201bf8e532527
--- /dev/null
+++ b/test/asan/TestCases/Posix/coverage-reset.cc
@@ -0,0 +1,65 @@
+// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard -DSHARED %s -shared -o %dynamiclib -fPIC %ld_flags_rpath_so
+// RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s %ld_flags_rpath_exe -o %t
+// RUN: rm -rf %T/coverage-reset && mkdir -p %T/coverage-reset && cd %T/coverage-reset
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s
+//
+// UNSUPPORTED: ios
+
+#include <stdio.h>
+
+#include <sanitizer/coverage_interface.h>
+
+#ifdef SHARED
+void bar1() { printf("bar1\n"); }
+void bar2() { printf("bar2\n"); }
+#else
+__attribute__((noinline)) void foo1() { printf("foo1\n"); }
+__attribute__((noinline)) void foo2() { printf("foo2\n"); }
+void bar1();
+void bar2();
+
+int main(int argc, char **argv) {
+ fprintf(stderr, "RESET\n");
+ __sanitizer_cov_reset();
+ foo1();
+ foo2();
+ bar1();
+ bar2();
+ __sanitizer_cov_dump();
+// CHECK: RESET
+// CHECK-DAG: SanitizerCoverage: ./coverage-reset.cc{{.*}}.sancov: 2 PCs written
+// CHECK-DAG: SanitizerCoverage: ./libcoverage-reset.cc{{.*}}.sancov: 2 PCs written
+
+ fprintf(stderr, "RESET\n");
+ __sanitizer_cov_reset();
+ foo1();
+ bar1();
+ __sanitizer_cov_dump();
+// CHECK: RESET
+// CHECK-DAG: SanitizerCoverage: ./coverage-reset.cc{{.*}}.sancov: 1 PCs written
+// CHECK-DAG: SanitizerCoverage: ./libcoverage-reset.cc{{.*}}.sancov: 1 PCs written
+
+ fprintf(stderr, "RESET\n");
+ __sanitizer_cov_reset();
+ foo1();
+ foo2();
+ __sanitizer_cov_dump();
+// CHECK: RESET
+// CHECK: SanitizerCoverage: ./coverage-reset.cc{{.*}}.sancov: 2 PCs written
+
+ fprintf(stderr, "RESET\n");
+ __sanitizer_cov_reset();
+ bar1();
+ bar2();
+ __sanitizer_cov_dump();
+// CHECK: RESET
+// CHECK: SanitizerCoverage: ./libcoverage-reset.cc{{.*}}.sancov: 2 PCs written
+
+ fprintf(stderr, "RESET\n");
+ __sanitizer_cov_reset();
+// CHECK: RESET
+
+ bar2();
+// CHECK: SanitizerCoverage: ./libcoverage-reset.cc{{.*}}.sancov: 1 PCs written
+}
+#endif
diff --git a/test/asan/TestCases/Posix/deep_call_stack.cc b/test/asan/TestCases/Posix/deep_call_stack.cc
index 2d2b056d638d0..e6e82a4757205 100644
--- a/test/asan/TestCases/Posix/deep_call_stack.cc
+++ b/test/asan/TestCases/Posix/deep_call_stack.cc
@@ -5,6 +5,9 @@
// Also check that use_sigaltstack+verbosity doesn't crash.
// RUN: %env_asan_opts=verbosity=1:use_sigaltstack=1:detect_stack_use_after_return=1 %run %t | FileCheck %s
+
+// UNSUPPORTED: ios
+
#include <stdio.h>
__attribute__((noinline))
diff --git a/test/asan/TestCases/Posix/halt_on_error-signals.c b/test/asan/TestCases/Posix/halt_on_error-signals.c
index 6bdf30bb4dd3e..931ab8635a159 100644
--- a/test/asan/TestCases/Posix/halt_on_error-signals.c
+++ b/test/asan/TestCases/Posix/halt_on_error-signals.c
@@ -2,10 +2,9 @@
//
// RUN: %clang_asan -fsanitize-recover=address -pthread %s -o %t
//
-// RUN: rm -f %t.log
-// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 100 >>%t.log 2>&1 || true
+// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 100 >%t.log 2>&1 || true
// Collision will almost always get triggered but we still need to check the unlikely case:
-// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < %t.log || FileCheck --check-prefix=CHECK-NO-COLLISION %s < %t.log
+// RUN: FileCheck --check-prefix=CHECK-COLLISION %s <%t.log || FileCheck --check-prefix=CHECK-NO-COLLISION %s <%t.log
#define _SVID_SOURCE 1 // SA_NODEFER
diff --git a/test/asan/TestCases/Posix/halt_on_error-torture.cc b/test/asan/TestCases/Posix/halt_on_error-torture.cc
index 829568e2682b7..559f9434e3925 100644
--- a/test/asan/TestCases/Posix/halt_on_error-torture.cc
+++ b/test/asan/TestCases/Posix/halt_on_error-torture.cc
@@ -2,21 +2,17 @@
//
// RUN: %clangxx_asan -fsanitize-recover=address -pthread %s -o %t
//
-// RUN: rm -f 1.txt
-// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 1 10 >>1.txt 2>&1
-// RUN: FileCheck %s < 1.txt
-// RUN: grep 'ERROR: AddressSanitizer: use-after-poison' 1.txt | count 10
-// RUN: FileCheck --check-prefix=CHECK-NO-COLLISION %s < 1.txt
+// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 1 10 >%t.log 2>&1
+// RUN: grep 'ERROR: AddressSanitizer: use-after-poison' %t.log | count 10
+// RUN: FileCheck %s <%t.log
//
-// Collisions are unlikely but still possible so we need the ||.
-// RUN: rm -f 10.txt
-// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false:exitcode=0 %run %t 10 20 2>&1 | cat > 10.txt
-// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 10.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 10.txt
+// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false:exitcode=0 %run %t 10 20 >%t.log 2>&1
+// RUN: grep 'ERROR: AddressSanitizer: use-after-poison' %t.log | count 200
+// RUN: FileCheck %s <%t.log
//
-// Collisions are unlikely but still possible so we need the ||.
-// RUN: rm -f 20.txt
-// RUN: %env_asan_opts=halt_on_error=false:exitcode=0 %run %t 10 20 2>&1 | cat > 20.txt
-// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 20.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 20.txt
+// RUN: %env_asan_opts=halt_on_error=false:exitcode=0 %run %t 10 20 >%t.log 2>&1
+// RUN: grep 'ERROR: AddressSanitizer: use-after-poison' %t.log | count 1
+// RUN: FileCheck %s <%t.log
#include <stdio.h>
#include <stdlib.h>
@@ -30,7 +26,7 @@ size_t niter = 10;
void random_delay(unsigned *seed) {
*seed = 1664525 * *seed + 1013904223;
- struct timespec delay = { 0, (*seed % 1000) * 1000 };
+ struct timespec delay = { 0, static_cast<long>((*seed % 1000) * 1000) };
nanosleep(&delay, 0);
}
@@ -42,7 +38,6 @@ void *run(void *arg) {
for (size_t i = 0; i < niter; ++i) {
random_delay(&seed);
- // Expect error collisions here
// CHECK: ERROR: AddressSanitizer: use-after-poison
volatile int idx = 0;
tmp[idx] = 0;
@@ -76,8 +71,7 @@ int main(int argc, char **argv) {
}
}
- // CHECK-COLLISION: AddressSanitizer: nested bug in the same thread, aborting
- // CHECK-NO-COLLISION: All threads terminated
+ // CHECK: All threads terminated
printf("All threads terminated\n");
delete [] tids;
diff --git a/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc b/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc
index b9d85ef94b230..6b926180cc2f3 100644
--- a/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc
+++ b/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc
@@ -6,8 +6,7 @@
// RUN: %env_asan_opts=halt_on_error=false %run %t 2>&1 | FileCheck %s
//
// Check that we die after reaching different reports number threshold.
-// RUN: rm -f %t1.log
-// RUN: %env_asan_opts=halt_on_error=false not %run %t 1 >> %t1.log 2>&1
+// RUN: %env_asan_opts=halt_on_error=false not %run %t 1 >%t1.log 2>&1
// RUN: grep 'ERROR: AddressSanitizer: stack-buffer-overflow' %t1.log | count 25
//
// Check suppress_equal_pcs=true behavior is equal to default one.
@@ -15,7 +14,7 @@
//
// Check suppress_equal_pcs=false behavior isn't equal to default one.
// RUN: rm -f %t2.log
-// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t >> %t2.log 2>&1
+// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t >%t2.log 2>&1
// RUN: grep 'ERROR: AddressSanitizer: stack-buffer-overflow' %t2.log | count 30
#define ACCESS_ARRAY_FIVE_ELEMENTS(array, i) \
diff --git a/test/asan/TestCases/Posix/handle_abort_on_error.cc b/test/asan/TestCases/Posix/handle_abort_on_error.cc
index fa8cdd4ce0c86..1be060e06aa85 100644
--- a/test/asan/TestCases/Posix/handle_abort_on_error.cc
+++ b/test/asan/TestCases/Posix/handle_abort_on_error.cc
@@ -1,6 +1,8 @@
// Regression test: this used to abort() in SIGABRT handler in an infinite loop.
// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=handle_abort=1,abort_on_error=1 not --crash %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: ios
+
#include <stdlib.h>
int main() {
diff --git a/test/asan/TestCases/Posix/invalid-pointer-pairs-threads.cc b/test/asan/TestCases/Posix/invalid-pointer-pairs-threads.cc
new file mode 100644
index 0000000000000..28be9b59117b8
--- /dev/null
+++ b/test/asan/TestCases/Posix/invalid-pointer-pairs-threads.cc
@@ -0,0 +1,57 @@
+// RUN: %clangxx_asan -O0 %s -pthread -o %t -mllvm -asan-detect-invalid-pointer-pair
+
+// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t a 2>&1 | FileCheck %s -check-prefix=OK -allow-empty
+// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t b 2>&1 | FileCheck %s -check-prefix=B
+
+// pthread barriers are not available on OS X
+// UNSUPPORTED: darwin
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+char *pointers[2];
+pthread_barrier_t bar;
+
+void *thread_main(void *n) {
+ char local;
+
+ unsigned long id = (unsigned long)n;
+ pointers[id] = &local;
+ pthread_barrier_wait(&bar);
+ pthread_barrier_wait(&bar);
+
+ return NULL;
+}
+
+int main(int argc, char **argv) {
+ assert(argc >= 2);
+
+ char t = argv[1][0];
+
+ pthread_t threads[2];
+ pthread_barrier_init(&bar, NULL, 3);
+ pthread_create(&threads[0], 0, thread_main, (void *)0);
+ pthread_create(&threads[1], 0, thread_main, (void *)1);
+ pthread_barrier_wait(&bar);
+
+ if (t == 'a') {
+ // OK-NOT: not handled yet
+ unsigned r = pointers[0] - pointers[1];
+ } else {
+ char local;
+ char *parent_pointer = &local;
+
+ // B: ERROR: AddressSanitizer: invalid-pointer-pair
+ // B: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-threads.cc:[[@LINE+1]]
+ unsigned r = parent_pointer - pointers[0];
+ }
+
+ pthread_barrier_wait(&bar);
+ pthread_join(threads[0], 0);
+ pthread_join(threads[1], 0);
+ pthread_barrier_destroy(&bar);
+
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/new_array_cookie_test.cc b/test/asan/TestCases/Posix/new_array_cookie_test.cc
index dd50bf7fe6a83..40a9b78749b22 100644
--- a/test/asan/TestCases/Posix/new_array_cookie_test.cc
+++ b/test/asan/TestCases/Posix/new_array_cookie_test.cc
@@ -3,6 +3,9 @@
// RUN: not %run %t 2>&1 | FileCheck %s
// RUN: %env_asan_opts=poison_array_cookie=1 not %run %t 2>&1 | FileCheck %s
// RUN: %env_asan_opts=poison_array_cookie=0 not %run %t 2>&1 | FileCheck %s --check-prefix=NO_COOKIE
+
+// UNSUPPORTED: ios
+
#include <stdio.h>
#include <stdlib.h>
struct C {
diff --git a/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc b/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc
index f36da2b5438d7..335a56757d296 100644
--- a/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc
+++ b/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc
@@ -2,6 +2,9 @@
// RUN: %clangxx_asan -O3 %s -o %t
// RUN: %env_asan_opts=poison_array_cookie=1 not %run %t 2>&1 | FileCheck %s --check-prefix=COOKIE
// RUN: %env_asan_opts=poison_array_cookie=0 not %run %t 2>&1 | FileCheck %s --check-prefix=NO_COOKIE
+
+// UNSUPPORTED: ios
+
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
diff --git a/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc b/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc
index 0683e391cf232..e7f774674e26c 100644
--- a/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc
+++ b/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc
@@ -3,6 +3,9 @@
// RUN: %clangxx_asan %s -o %t && %run %t
//
// XFAIL: arm
+
+// UNSUPPORTED: ios
+
#include <new>
#include <stdlib.h>
#include <stdint.h>
diff --git a/test/asan/TestCases/Posix/stack-overflow.cc b/test/asan/TestCases/Posix/stack-overflow.cc
index 8ef1618624992..d6b062ed3fbf9 100644
--- a/test/asan/TestCases/Posix/stack-overflow.cc
+++ b/test/asan/TestCases/Posix/stack-overflow.cc
@@ -16,6 +16,8 @@
// RUN: not %run %t 2>&1 | FileCheck %s
// REQUIRES: stable-runtime
+// UNSUPPORTED: ios
+
#include <assert.h>
#include <stdlib.h>
#include <pthread.h>
diff --git a/test/asan/TestCases/Posix/stack-use-after-return.cc b/test/asan/TestCases/Posix/stack-use-after-return.cc
index 822d5be9491e7..2da1a0590db78 100644
--- a/test/asan/TestCases/Posix/stack-use-after-return.cc
+++ b/test/asan/TestCases/Posix/stack-use-after-return.cc
@@ -17,6 +17,9 @@
// This test runs out of stack on AArch64.
// UNSUPPORTED: aarch64
+// FIXME: Fix this test for dynamic runtime on armhf-linux.
+// UNSUPPORTED: armhf-linux && asan-dynamic-runtime
+
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
diff --git a/test/asan/TestCases/Windows/fuse-lld.cc b/test/asan/TestCases/Windows/fuse-lld.cc
index c20e5ff6c786e..2aee0385d1586 100644
--- a/test/asan/TestCases/Windows/fuse-lld.cc
+++ b/test/asan/TestCases/Windows/fuse-lld.cc
@@ -2,11 +2,7 @@
//
// REQUIRES: lld-available
//
-// FIXME: Use -fuse-ld=lld after the old COFF linker is removed.
-// FIXME: Test will fail until we add flags for requesting dwarf or cv.
-// RUNX: %clangxx_asan -O2 %s -o %t.exe -fuse-ld=lld -Wl,-debug
-// RUN: %clangxx_asan -c -O2 %s -o %t.o -g -gdwarf
-// RUN: lld-link %t.o -out:%t.exe -debug -nopdb -defaultlib:libcmt %asan_lib %asan_cxx_lib
+// RUN: %clangxx_asan -O2 %s -o %t.exe -g -gcodeview -fuse-ld=lld -Wl,-debug
// RUN: not %run %t.exe 2>&1 | FileCheck %s
#include <stdlib.h>
diff --git a/test/asan/TestCases/Windows/interface_symbols_windows.c b/test/asan/TestCases/Windows/interface_symbols_windows.cc
index a08f358726d70..4a59dba25b088 100644
--- a/test/asan/TestCases/Windows/interface_symbols_windows.c
+++ b/test/asan/TestCases/Windows/interface_symbols_windows.cc
@@ -38,6 +38,8 @@
// IMPORT: __asan_set_seh_filter
// IMPORT: __asan_unhandled_exception_filter
// IMPORT: __asan_test_only_reported_buggy_pointer
+// IMPORT: __sancov_lowest_stack
+// IMPORT: __ubsan_vptr_type_cache
//
// RUN: cat %t.imports1 %t.imports2 %t.imports3 | sort | uniq > %t.imports-sorted
// RUN: cat %t.exports | sort | uniq > %t.exports-sorted
diff --git a/test/asan/TestCases/Windows/shadow_conflict_32.cc b/test/asan/TestCases/Windows/shadow_conflict_32.cc
index 7c6d94b37483c..a2b6b4688bc7c 100644
--- a/test/asan/TestCases/Windows/shadow_conflict_32.cc
+++ b/test/asan/TestCases/Windows/shadow_conflict_32.cc
@@ -20,9 +20,9 @@ int main() {
extern "C" __declspec(dllexport) int test_function() { return 0; }
#endif
-// CHECK: =={{[0-9]+}}==Shadow memory range interleaves with an existing memory mapping. ASan cannot proceed correctly. ABORTING.
-// CHECK: =={{[0-9]+}}==ASan shadow was supposed to be located in the [0x2fff0000-0x3fffffff] range.
-// CHECK: =={{[0-9]+}}==Dumping process modules
+// CHECK: =={{[0-9:]+}}==Shadow memory range interleaves with an existing memory mapping. ASan cannot proceed correctly. ABORTING.
+// CHECK: =={{[0-9:]+}}==ASan shadow was supposed to be located in the [0x2fff0000-0x3fffffff] range.
+// CHECK: =={{[0-9:]+}}==Dumping process modules
// CHECK-DAG: {{0x30000000-0x300.....}} {{.*}}\shadow_conflict_32.cc.tmp_dll.dll
// CHECK-DAG: {{0x........-0x........}} {{.*}}\shadow_conflict_32.cc.tmp.exe
diff --git a/test/asan/TestCases/alloca_constant_size.cc b/test/asan/TestCases/alloca_constant_size.cc
index a766ae75be07a..57aa315705f94 100644
--- a/test/asan/TestCases/alloca_constant_size.cc
+++ b/test/asan/TestCases/alloca_constant_size.cc
@@ -10,7 +10,7 @@
// MSVC provides _alloca instead of alloca.
#if defined(_MSC_VER) && !defined(alloca)
# define alloca _alloca
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
#include <stdlib.h>
#else
#include <alloca.h>
diff --git a/test/asan/TestCases/asan_and_llvm_coverage_test.cc b/test/asan/TestCases/asan_and_llvm_coverage_test.cc
index d53deb4475de3..1574a344399b5 100644
--- a/test/asan/TestCases/asan_and_llvm_coverage_test.cc
+++ b/test/asan/TestCases/asan_and_llvm_coverage_test.cc
@@ -1,6 +1,6 @@
// RUN: %clangxx_asan -coverage -O0 %s -o %t
// RUN: %env_asan_opts=check_initialization_order=1 %run %t 2>&1 | FileCheck %s
-// XFAIL: android
+
// We don't really support running tests using profile runtime on Windows.
// UNSUPPORTED: win32
#include <stdio.h>
diff --git a/test/asan/TestCases/atexit_stats.cc b/test/asan/TestCases/atexit_stats.cc
index f0b5830b405aa..c8d97da529212 100644
--- a/test/asan/TestCases/atexit_stats.cc
+++ b/test/asan/TestCases/atexit_stats.cc
@@ -7,7 +7,7 @@
// UNSUPPORTED: android
#include <stdlib.h>
-#if !defined(__APPLE__) && !defined(__FreeBSD__)
+#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#include <malloc.h>
#endif
int *p1 = (int*)malloc(900);
diff --git a/test/asan/TestCases/contiguous_container_crash.cc b/test/asan/TestCases/contiguous_container_crash.cc
index af2102e6a12de..2b555f9019eb0 100644
--- a/test/asan/TestCases/contiguous_container_crash.cc
+++ b/test/asan/TestCases/contiguous_container_crash.cc
@@ -37,7 +37,7 @@ void BadBounds() {
void BadAlignment() {
int t[100];
// CHECK-BAD-ALIGNMENT: ERROR: AddressSanitizer: bad parameters to __sanitizer_annotate_contiguous_container
-// CHECK-BAD-ALIGNMENT: ERROR: beg is not aligned by 8
+// CHECK-BAD-ALIGNMENT: ERROR: beg is not aligned by {{[0-9]+}}
__sanitizer_annotate_contiguous_container(&t[1], &t[0] + 100, &t[1] + 10,
&t[0] + 50);
}
diff --git a/test/asan/TestCases/debug_ppc64_mapping.cc b/test/asan/TestCases/debug_ppc64_mapping.cc
index 43e1183a2d033..0db7956693c58 100644
--- a/test/asan/TestCases/debug_ppc64_mapping.cc
+++ b/test/asan/TestCases/debug_ppc64_mapping.cc
@@ -6,11 +6,11 @@
#include <stdio.h>
int main() {
-// CHECK-PPC64: || `[{{0x0a0|0x040}}000000000, {{0x3ff|0x0ff}}fffffffff]` || HighMem ||
-// CHECK-PPC64: || `[{{0x034|0x028}}000000000, {{0x09f|0x03f}}fffffffff]` || HighShadow ||
-// CHECK-PPC64: || `[{{0x024|0x024}}000000000, {{0x033|0x027}}fffffffff]` || ShadowGap ||
-// CHECK-PPC64: || `[0x020000000000, 0x023fffffffff]` || LowShadow ||
-// CHECK-PPC64: || `[0x000000000000, 0x01ffffffffff]` || LowMem ||
+// CHECK-PPC64: || `[{{0x180|0x0a0|0x040}}000000000, {{0x3ff|0x0ff}}fffffffff]` || HighMem ||
+// CHECK-PPC64: || `[{{0x130|0x034|0x028}}000000000, {{0x17f|0x09f|0x03f}}fffffffff]` || HighShadow ||
+// CHECK-PPC64: || `[{{0x120|0x024|0x024}}000000000, {{0x12f|0x033|0x027}}fffffffff]` || ShadowGap ||
+// CHECK-PPC64: || `[{{0x100|0x020}}000000000, {{0x11f|0x023}}fffffffff]` || LowShadow ||
+// CHECK-PPC64: || `[0x000000000000, {{0x0ff|0x01f}}fffffffff]` || LowMem ||
//
printf("ppc64 eyecatcher \n");
// CHECK-PPC64-V0: ppc64 eyecatcher
@@ -19,7 +19,14 @@ int main() {
}
/*
- * Two different signatures noted at the time of writing.
+ * Three different signatures noted.
+Newer kernel: (starting with kernel version 4.?)
+|| `[0x180000000000, 0x3fffffffffff]` || HighMem ||
+|| `[0x130000000000, 0x17ffffffffff]` || HighShadow ||
+|| `[0x120000000000, 0x12ffffffffff]` || ShadowGap ||
+|| `[0x100000000000, 0x11ffffffffff]` || LowShadow ||
+|| `[0x000000000000, 0x0fffffffffff]` || LowMem ||
+
Newish kernel: (64TB address range support, starting with kernel version 3.7)
|| `[0x0a0000000000, 0x3fffffffffff]` || HighMem ||
|| `[0x034000000000, 0x09ffffffffff]` || HighShadow ||
diff --git a/test/asan/TestCases/error_report_callback.cc b/test/asan/TestCases/error_report_callback.cc
new file mode 100644
index 0000000000000..8c5bbe418fc52
--- /dev/null
+++ b/test/asan/TestCases/error_report_callback.cc
@@ -0,0 +1,21 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run %t 0 2>&1 | FileCheck %s
+
+#include <sanitizer/asan_interface.h>
+#include <stdio.h>
+
+static void ErrorReportCallbackOneToZ(const char *report) {
+ fprintf(stderr, "ABCDEF%sGHIJKL", report);
+ fflush(stderr);
+}
+
+int main(int argc, char **argv) {
+ __asan_set_error_report_callback(ErrorReportCallbackOneToZ);
+ __asan_report_error(
+ (void *)__builtin_extract_return_addr(__builtin_return_address(0)), 0, 0,
+ 0, true, 1);
+ // CHECK: ABCDEF
+ // CHECK: ERROR: AddressSanitizer
+ // CHECK: GHIJKL
+ return 0;
+}
diff --git a/test/asan/TestCases/global-address.cpp b/test/asan/TestCases/global-address.cpp
index 0e56ca10c39c2..81f0230b733f5 100644
--- a/test/asan/TestCases/global-address.cpp
+++ b/test/asan/TestCases/global-address.cpp
@@ -5,8 +5,8 @@
int g_i = 42;
int main() {
// CHECK: AddressSanitizer: attempting to call __sanitizer_get_allocated_size() for pointer which is not owned
- // CHECK-NOT: ASAN:DEADLYSIGNAL
+ // CHECK-NOT: AddressSanitizer:DEADLYSIGNAL
// CHECK: SUMMARY: AddressSanitizer: bad-__sanitizer_get_allocated_size
- // CHECK-NOT: ASAN:DEADLYSIGNAL
+ // CHECK-NOT: AddressSanitizer:DEADLYSIGNAL
return (int)__sanitizer_get_allocated_size(&g_i);
}
diff --git a/test/asan/TestCases/global-underflow.cc b/test/asan/TestCases/global-underflow.cc
new file mode 100644
index 0000000000000..4a03513567cd2
--- /dev/null
+++ b/test/asan/TestCases/global-underflow.cc
@@ -0,0 +1,17 @@
+// RUN: %clangxx_asan -O0 %s %p/Helpers/underflow.cc -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s %p/Helpers/underflow.cc -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s %p/Helpers/underflow.cc -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s %p/Helpers/underflow.cc -o %t && not %run %t 2>&1 | FileCheck %s
+
+int XXX[2] = {2, 3};
+extern int YYY[];
+#include <string.h>
+int main(int argc, char **argv) {
+ memset(XXX, 0, 2*sizeof(int));
+ // CHECK: {{READ of size 4 at 0x.* thread T0}}
+ // CHECK: {{ #0 0x.* in main .*global-underflow.cc:}}[[@LINE+3]]
+ // CHECK: {{0x.* is located 4 bytes to the left of global variable}}
+ // CHECK: {{.*YYY.* of size 12}}
+ int res = YYY[-1];
+ return res;
+}
diff --git a/test/asan/TestCases/heavy_uar_test.cc b/test/asan/TestCases/heavy_uar_test.cc
index 8338f808539e0..9ad29f079d92f 100644
--- a/test/asan/TestCases/heavy_uar_test.cc
+++ b/test/asan/TestCases/heavy_uar_test.cc
@@ -5,6 +5,11 @@
// FIXME: Fix this test under GCC.
// REQUIRES: Clang
+// FIXME: Fix this test for dynamic runtime on armhf-linux.
+// UNSUPPORTED: armhf-linux && asan-dynamic-runtime
+
+// UNSUPPORTED: ios
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
diff --git a/test/asan/TestCases/intra-object-overflow.cc b/test/asan/TestCases/intra-object-overflow.cc
index 4032cc1448582..56b5bb2b729fd 100644
--- a/test/asan/TestCases/intra-object-overflow.cc
+++ b/test/asan/TestCases/intra-object-overflow.cc
@@ -3,7 +3,7 @@
// RUN: %run %t 10
//
// FIXME: fix 32-bits.
-// REQUIRES: asan-64-bits
+// REQUIRES: asan-64-bits, shadow-scale-3
// FIXME: Implement ASan intra-object padding in Clang's MS record layout
// UNSUPPORTED: win32
#include <stdio.h>
diff --git a/test/asan/TestCases/invalid-pointer-pairs-compare-errors.cc b/test/asan/TestCases/invalid-pointer-pairs-compare-errors.cc
new file mode 100644
index 0000000000000..82f63359ead79
--- /dev/null
+++ b/test/asan/TestCases/invalid-pointer-pairs-compare-errors.cc
@@ -0,0 +1,103 @@
+// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair
+
+// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1:halt_on_error=0 %run %t 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <stdlib.h>
+
+int foo(char *p, char *q) {
+ return p > q;
+}
+
+char global1[100] = {}, global2[100] = {};
+char small_global[7] = {};
+char large_global[5000] = {};
+
+int main() {
+ // Heap allocated memory.
+ char *heap1 = (char *)malloc(42);
+ char *heap2 = (char *)malloc(42);
+
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(heap1, heap2);
+ free(heap1);
+ free(heap2);
+
+ heap1 = (char *)malloc(1024);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(heap1, heap1 + 1025);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(heap1 + 1024, heap1 + 1025);
+ free(heap1);
+
+ heap1 = (char *)malloc(4096);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(heap1, heap1 + 4097);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(heap1, 0);
+
+ // Global variables.
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(&global1[0], &global2[10]);
+
+ char *p = &small_global[0];
+ foo(p, p); // OK
+ foo(p, p + 7); // OK
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(p, p + 8);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(p - 1, p);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(p, p - 1);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(p - 1, p + 8);
+
+ p = &large_global[0];
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(p - 1, p);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(p, p - 1);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(p, &global1[0]);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(p, &small_global[0]);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(p, 0);
+
+ // Stack variables.
+ char stack1, stack2;
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(&stack1, &stack2);
+
+ // Mixtures.
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(heap1, &stack1);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ foo(heap1, &global1[0]);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ foo(&stack1, &global1[0]);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cc:[[@LINE+1]]
+ foo(&stack1, 0);
+
+ free(heap1);
+
+ return 0;
+}
diff --git a/test/asan/TestCases/invalid-pointer-pairs-compare-success.cc b/test/asan/TestCases/invalid-pointer-pairs-compare-success.cc
new file mode 100644
index 0000000000000..565d39088340c
--- /dev/null
+++ b/test/asan/TestCases/invalid-pointer-pairs-compare-success.cc
@@ -0,0 +1,74 @@
+// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair
+
+// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t
+
+#include <assert.h>
+#include <stdlib.h>
+
+int foo(char *p) {
+ char *p2 = p + 20;
+ return p > p2;
+}
+
+int bar(char *p, char *q) {
+ return p <= q;
+}
+
+int baz(char *p, char *q) {
+ return p != 0 && p < q;
+}
+
+char global[8192] = {};
+char small_global[7] = {};
+
+int main() {
+ // Heap allocated memory.
+ char *p = (char *)malloc(42);
+ int r = foo(p);
+ free(p);
+
+ p = (char *)malloc(1024);
+ bar(p, p + 1024);
+ bar(p + 1024, p + 1023);
+ bar(p + 1, p + 1023);
+ free(p);
+
+ p = (char *)malloc(4096);
+ bar(p, p + 4096);
+ bar(p + 10, p + 100);
+ bar(p + 1024, p + 4096);
+ bar(p + 4095, p + 4096);
+ bar(p + 4095, p + 4094);
+ bar(p + 100, p + 4096);
+ bar(p + 100, p + 4094);
+ free(p);
+
+ // Global variable.
+ bar(&global[0], &global[1]);
+ bar(&global[1], &global[2]);
+ bar(&global[2], &global[1]);
+ bar(&global[0], &global[100]);
+ bar(&global[1000], &global[7000]);
+ bar(&global[500], &global[10]);
+ p = &global[0];
+ bar(p, p + 8192);
+ p = &global[8000];
+ bar(p, p + 192);
+
+ p = &small_global[0];
+ bar(p, p + 1);
+ bar(p, p + 7);
+ bar(p + 7, p + 1);
+ bar(p + 6, p + 7);
+ bar(p + 7, p + 7);
+
+ // Stack variable.
+ char stack[10000];
+ bar(&stack[0], &stack[100]);
+ bar(&stack[1000], &stack[9000]);
+ bar(&stack[500], &stack[10]);
+
+ baz(0, &stack[10]);
+
+ return 0;
+}
diff --git a/test/asan/TestCases/invalid-pointer-pairs-subtract-errors.cc b/test/asan/TestCases/invalid-pointer-pairs-subtract-errors.cc
new file mode 100644
index 0000000000000..546f61f8184de
--- /dev/null
+++ b/test/asan/TestCases/invalid-pointer-pairs-subtract-errors.cc
@@ -0,0 +1,48 @@
+// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair
+
+// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1:halt_on_error=0 %run %t 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <stdlib.h>
+
+int foo(char *p, char *q) {
+ return p - q;
+}
+
+char global1[100] = {}, global2[100] = {};
+
+int main() {
+ // Heap allocated memory.
+ char *heap1 = (char *)malloc(42);
+ char *heap2 = (char *)malloc(42);
+
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-subtract-errors.cc:[[@LINE+1]]
+ foo(heap1, heap2);
+
+ // Global variables.
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-subtract-errors.cc:[[@LINE+1]]
+ foo(&global1[0], &global2[10]);
+
+ // Stack variables.
+ char stack1, stack2;
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-subtract-errors.cc:[[@LINE+1]]
+ foo(&stack1, &stack2);
+
+ // Mixtures.
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-subtract-errors.cc:[[@LINE+1]]
+ foo(heap1, &stack1);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-subtract-errors.cc:[[@LINE+1]]
+ foo(heap1, &global1[0]);
+ // CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
+ // CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-subtract-errors.cc:[[@LINE+1]]
+ foo(&stack1, &global1[0]);
+
+ free(heap1);
+ free(heap2);
+ return 0;
+}
diff --git a/test/asan/TestCases/invalid-pointer-pairs-subtract-success.cc b/test/asan/TestCases/invalid-pointer-pairs-subtract-success.cc
new file mode 100644
index 0000000000000..4ce48424899d3
--- /dev/null
+++ b/test/asan/TestCases/invalid-pointer-pairs-subtract-success.cc
@@ -0,0 +1,33 @@
+// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair
+
+// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t
+
+#include <assert.h>
+#include <stdlib.h>
+
+int bar(char *p, char *q) {
+ return p <= q;
+}
+
+char global[10000] = {};
+
+int main() {
+ // Heap allocated memory.
+ char *p = (char *)malloc(42);
+ int r = bar(p, p + 20);
+ free(p);
+
+ // Global variable.
+ bar(&global[0], &global[100]);
+ bar(&global[1000], &global[9000]);
+ bar(&global[500], &global[10]);
+ bar(&global[0], &global[10000]);
+
+ // Stack variable.
+ char stack[10000];
+ bar(&stack[0], &stack[100]);
+ bar(&stack[1000], &stack[9000]);
+ bar(&stack[500], &stack[10]);
+
+ return 0;
+}
diff --git a/test/asan/TestCases/max_redzone.cc b/test/asan/TestCases/max_redzone.cc
index e2a0a2bdec2ff..99c886d1e6837 100644
--- a/test/asan/TestCases/max_redzone.cc
+++ b/test/asan/TestCases/max_redzone.cc
@@ -1,8 +1,8 @@
// Test max_redzone runtime option.
-// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=max_redzone=16 %run %t 0 2>&1
+// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=max_redzone=32 %run %t 0 2>&1
// RUN: %clangxx_asan -O0 %s -o %t && %run %t 1 2>&1
-// RUN: %clangxx_asan -O3 %s -o %t && %env_asan_opts=max_redzone=16 %run %t 0 2>&1
+// RUN: %clangxx_asan -O3 %s -o %t && %env_asan_opts=max_redzone=32 %run %t 0 2>&1
// RUN: %clangxx_asan -O3 %s -o %t && %run %t 1 2>&1
#include <stdio.h>
diff --git a/test/asan/TestCases/memcmp_test.cc b/test/asan/TestCases/memcmp_test.cc
index 3b3b8894b73cb..0dd9820f52ab4 100644
--- a/test/asan/TestCases/memcmp_test.cc
+++ b/test/asan/TestCases/memcmp_test.cc
@@ -7,8 +7,8 @@
#include <string.h>
int main(int argc, char **argv) {
- char a1[] = {argc, 2, 3, 4};
- char a2[] = {1, 2*argc, 3, 4};
+ char a1[] = {static_cast<char>(argc), 2, 3, 4};
+ char a2[] = {1, static_cast<char>(2*argc), 3, 4};
int res = memcmp(a1, a2, 4 + argc); // BOOM
// CHECK: AddressSanitizer: stack-buffer-overflow
// CHECK: {{#0.*memcmp}}
diff --git a/test/asan/TestCases/memset_test.cc b/test/asan/TestCases/memset_test.cc
index e244d54deb3c4..0530c8483d72f 100644
--- a/test/asan/TestCases/memset_test.cc
+++ b/test/asan/TestCases/memset_test.cc
@@ -41,7 +41,7 @@ typedef void *(*memcpy_t)(void *, const void *, size_t);
int main(int argc, char **argv) {
char * volatile p = (char *)malloc(3000);
- __asan_poison_memory_region(p + 512, 16);
+ __asan_poison_memory_region(p + 512, 32);
#if defined(TEST_MEMSET)
memset(p, 0, 3000);
assert(p[1] == 0);
diff --git a/test/asan/TestCases/non-executable-pc.cpp b/test/asan/TestCases/non-executable-pc.cpp
index f8adee613b096..6ef40540b0ace 100644
--- a/test/asan/TestCases/non-executable-pc.cpp
+++ b/test/asan/TestCases/non-executable-pc.cpp
@@ -2,8 +2,8 @@
// RUN: not %run %t 0 2>&1 | FileCheck %s
// RUN: not %run %t n 2>&1 | FileCheck %s -check-prefix=CHECK -check-prefix=NON_EXEC
-// Only Linux and FreeBSD list every memory region in MemoryMappingLayout, for now.
-// REQUIRES: linux || freebsd
+// Not every OS lists every memory region in MemoryMappingLayout.
+// REQUIRES: linux || freebsd || netbsd
#include <assert.h>
diff --git a/test/asan/TestCases/pass-object-byval.cc b/test/asan/TestCases/pass-object-byval.cc
new file mode 100644
index 0000000000000..b99360fa78500
--- /dev/null
+++ b/test/asan/TestCases/pass-object-byval.cc
@@ -0,0 +1,40 @@
+// Verify that objects passed by value get red zones and that the copy
+// constructor is called.
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s --implicit-check-not \
+// RUN: Assertion{{.*}}failed
+
+// ASan instrumentation can't insert red-zones around inalloca parameters.
+// XFAIL: win32 && asan-32-bits
+
+#include <cassert>
+
+class A {
+ public:
+ A() : me(this) {}
+ A(const A &other) : me(this) {
+ for (int i = 0; i < 8; ++i) a[i] = other.a[i];
+ }
+
+ int a[8];
+ A *me;
+};
+
+int bar(A *a) {
+ int *volatile ptr = &a->a[0];
+ return *(ptr - 1);
+}
+
+void foo(A a) {
+ assert(a.me == &a);
+ bar(&a);
+}
+
+int main() {
+ A a;
+ foo(a);
+}
+
+// CHECK: ERROR: AddressSanitizer: stack-buffer-overflow
+// CHECK: READ of size 4 at
+// CHECK: is located in stack of thread
diff --git a/test/asan/TestCases/pass-struct-byval-uar.cc b/test/asan/TestCases/pass-struct-byval-uar.cc
new file mode 100644
index 0000000000000..aa6fa579e183c
--- /dev/null
+++ b/test/asan/TestCases/pass-struct-byval-uar.cc
@@ -0,0 +1,38 @@
+// Test that use-after-return works with arguments passed by value.
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: %env_asan_opts=detect_stack_use_after_return=0 %run %t 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-NO-UAR %s
+// RUN: not %env_asan_opts=detect_stack_use_after_return=1 %run %t 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-UAR %s
+//
+// On several architectures, the IR does not use byval arguments for foo() and
+// instead creates a copy in main() and gives foo() a pointer to the copy. In
+// that case, ASAN has nothing to poison on return from foo() and will not
+// detect the UAR.
+// REQUIRES: x86_64-target-arch, linux, !android
+
+#include <cstdio>
+
+struct A {
+ int a[8];
+};
+
+A *foo(A a) {
+ return &a;
+}
+
+int main() {
+ A *a = foo(A());
+ a->a[0] = 7;
+ std::fprintf(stderr, "\n"); // Ensures some output is generated for FileCheck
+ // to verify in the case where UAR is not
+ // detected.
+}
+
+// CHECK-NO-UAR-NOT: ERROR: AddressSanitizer: stack-use-after-return
+// CHECK-NO-UAR-NOT: WRITE of size 4 at
+// CHECK-NO-UAR-NOT: Memory access at offset {{[0-9]+}} is inside this variable
+//
+// CHECK-UAR: ERROR: AddressSanitizer: stack-use-after-return
+// CHECK-UAR: WRITE of size 4 at
+// CHECK-UAR: Memory access at offset {{[0-9]+}} is inside this variable
diff --git a/test/asan/TestCases/pass-struct-byval.cc b/test/asan/TestCases/pass-struct-byval.cc
new file mode 100644
index 0000000000000..ba49eccf41cab
--- /dev/null
+++ b/test/asan/TestCases/pass-struct-byval.cc
@@ -0,0 +1,23 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+struct A {
+ int a[8];
+};
+
+int bar(A *a) {
+ int *volatile ptr = &a->a[0];
+ return *(ptr - 1);
+}
+
+void foo(A a) {
+ bar(&a);
+}
+
+int main() {
+ foo(A());
+}
+
+// CHECK: ERROR: AddressSanitizer: stack-buffer-underflow
+// CHECK: READ of size 4 at
+// CHECK: is located in stack of thread
diff --git a/test/asan/TestCases/scariness_score_test.cc b/test/asan/TestCases/scariness_score_test.cc
index dee7a13b7b3be..171bea9ee1917 100644
--- a/test/asan/TestCases/scariness_score_test.cc
+++ b/test/asan/TestCases/scariness_score_test.cc
@@ -39,6 +39,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <algorithm>
#include <sanitizer/asan_interface.h>
@@ -129,6 +130,11 @@ void UseAfterPoison() {
}
int main(int argc, char **argv) {
+ size_t scale;
+ size_t offset;
+ __asan_get_shadow_mapping(&scale, &offset);
+ size_t grain = 1 << scale;
+
char arr[100];
static volatile int zero = 0;
static volatile int *zero_ptr = 0;
@@ -139,7 +145,8 @@ int main(int argc, char **argv) {
case 1: HeapBuferOverflow<char>(0, Read); break;
case 2: HeapBuferOverflow<int>(0, Read); break;
case 3: HeapBuferOverflow<short>(0, Write); break;
- case 4: HeapBuferOverflow<int64_t>(2, Write); break;
+ case 4: HeapBuferOverflow<int64_t>(
+ 2 * std::max(1, (int)(grain / sizeof(int64_t))), Write); break;
case 5: HeapBuferOverflow<S32>(4, Write); break;
case 6: HeapUseAfterFree<char>(0, Read); break;
case 7: HeapUseAfterFree<int>(0, Write); break;
@@ -147,7 +154,18 @@ int main(int argc, char **argv) {
case 9: HeapUseAfterFree<S32>(0, Write); break;
case 10: StackBufferOverflow<char>(0, Write); break;
case 11: StackBufferOverflow<int64_t>(0, Read); break;
- case 12: StackBufferOverflow<int>(4, Write); break;
+ case 12:
+ if (scale <= 3)
+ StackBufferOverflow<int>(16, Write);
+ else {
+ // At large shadow granularity, there is not enough redzone
+ // between stack elements to detect far-from-bounds. Pretend
+ // that this test passes.
+ fprintf(stderr, "SCARINESS: 61 "
+ "(4-byte-write-stack-buffer-overflow-far-from-bounds)\n");
+ return 1;
+ }
+ break;
case 13: StackUseAfterReturn<char>(0, Read); break;
case 14: StackUseAfterReturn<S32>(0, Write); break;
case 15: g1[zero + 100] = 0; break;
diff --git a/test/asan/TestCases/sleep_after_init.c b/test/asan/TestCases/sleep_after_init.c
new file mode 100644
index 0000000000000..147af67c72ea7
--- /dev/null
+++ b/test/asan/TestCases/sleep_after_init.c
@@ -0,0 +1,10 @@
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: %env_asan_opts=sleep_after_init=1 not %run %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+int main() {
+ // CHECK: Sleeping for 1 second
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+}
diff --git a/test/asan/TestCases/small_memcpy_test.cc b/test/asan/TestCases/small_memcpy_test.cc
index 2d6dea60caedd..ef0ac35b8a2b7 100644
--- a/test/asan/TestCases/small_memcpy_test.cc
+++ b/test/asan/TestCases/small_memcpy_test.cc
@@ -7,6 +7,7 @@
// RUN: not %run %t 32 48 2>&1 | FileCheck %s --check-prefix=CHECK
// RUN: not %run %t 40 56 2>&1 | FileCheck %s --check-prefix=CHECK
// RUN: not %run %t 48 64 2>&1 | FileCheck %s --check-prefix=CHECK
+// REQUIRES: shadow-scale-3
#include <assert.h>
#include <string.h>
#include <stdlib.h>
diff --git a/test/asan/TestCases/stack-buffer-overflow-with-position.cc b/test/asan/TestCases/stack-buffer-overflow-with-position.cc
index 2a575f7755ffd..0077663d6a176 100644
--- a/test/asan/TestCases/stack-buffer-overflow-with-position.cc
+++ b/test/asan/TestCases/stack-buffer-overflow-with-position.cc
@@ -42,3 +42,4 @@ int main(int argc, char **argv) {
// CHECK-63: 'CCC'{{.*}} <== {{.*}}partially underflows this variable
// CHECK-73: 'CCC'{{.*}} <== {{.*}}partially overflows this variable
// CHECK-74: 'CCC'{{.*}} <== {{.*}}overflows this variable
+// REQUIRES: shadow-scale-3
diff --git a/test/asan/TestCases/strtol_strict.c b/test/asan/TestCases/strtol_strict.c
index 999067e89e0af..bc30c87b18cb3 100644
--- a/test/asan/TestCases/strtol_strict.c
+++ b/test/asan/TestCases/strtol_strict.c
@@ -21,6 +21,7 @@
// RUN: %run %t test7 2>&1
// RUN: %env_asan_opts=strict_string_checks=false %run %t test7 2>&1
// RUN: %env_asan_opts=strict_string_checks=true not %run %t test7 2>&1 | FileCheck %s --check-prefix=CHECK7
+// REQUIRES: shadow-scale-3
#include <assert.h>
#include <stdlib.h>
diff --git a/test/asan/TestCases/strtoll_strict.c b/test/asan/TestCases/strtoll_strict.c
index f6a1716bcc82c..93cce30f8cb95 100644
--- a/test/asan/TestCases/strtoll_strict.c
+++ b/test/asan/TestCases/strtoll_strict.c
@@ -23,6 +23,7 @@
// RUN: %env_asan_opts=strict_string_checks=true not %run %t test7 2>&1 | FileCheck %s --check-prefix=CHECK7
// FIXME: Enable strtoll interceptor.
+// REQUIRES: shadow-scale-3
// XFAIL: win32
#include <assert.h>
diff --git a/test/asan/TestCases/suppressions-function.cc b/test/asan/TestCases/suppressions-function.cc
index c7f1ebe66968a..becefa2ee31c8 100644
--- a/test/asan/TestCases/suppressions-function.cc
+++ b/test/asan/TestCases/suppressions-function.cc
@@ -10,6 +10,10 @@
// XFAIL: android,win32
// UNSUPPORTED: ios
+// FIXME: atos does not work for inlined functions, yet llvm-symbolizer
+// does not always work with debug info on Darwin.
+// UNSUPPORTED: darwin
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/test/asan/TestCases/use-after-delete.cc b/test/asan/TestCases/use-after-delete.cc
index 1cc8c2f079aca..44404cd181fcd 100644
--- a/test/asan/TestCases/use-after-delete.cc
+++ b/test/asan/TestCases/use-after-delete.cc
@@ -24,7 +24,7 @@ int main() {
// CHECK-Linux: {{ #0 0x.* in operator new\[\]}}
// CHECK-Linux: {{ #1 0x.* in main .*use-after-delete.cc:}}[[@LINE-16]]
- // CHECK: Shadow byte legend (one shadow byte represents 8 application bytes):
+ // CHECK: Shadow byte legend (one shadow byte represents {{[0-9]+}} application bytes):
// CHECK: Global redzone:
// CHECK: ASan internal:
}
diff --git a/test/asan/TestCases/use-after-free.cc b/test/asan/TestCases/use-after-free.cc
index c96d7f2e24e1f..a24c7d497c1d5 100644
--- a/test/asan/TestCases/use-after-free.cc
+++ b/test/asan/TestCases/use-after-free.cc
@@ -29,7 +29,7 @@ int main() {
// CHECK-Darwin: {{ #0 0x.* in wrap_malloc.*}}
// CHECK-Darwin: {{ #1 0x.* in main .*use-after-free.cc:}}[[@LINE-22]]
- // CHECK: Shadow byte legend (one shadow byte represents 8 application bytes):
+ // CHECK: Shadow byte legend (one shadow byte represents {{[0-9]+}} application bytes):
// CHECK: Global redzone:
// CHECK: ASan internal:
}
diff --git a/test/asan/TestCases/use-after-scope-conversion.cc b/test/asan/TestCases/use-after-scope-conversion.cc
new file mode 100644
index 0000000000000..99b845d07a14e
--- /dev/null
+++ b/test/asan/TestCases/use-after-scope-conversion.cc
@@ -0,0 +1,50 @@
+// RUN: %clangxx_asan -O0 -fsanitize-address-use-after-scope %s -o %t
+
+// RUN: not %run %t 'A' 2>&1 | FileCheck %s
+// RUN: not %run %t 'B' 2>&1 | FileCheck %s
+
+// Missing lifetime markers in test_a
+// https://bugs.llvm.org/show_bug.cgi?id=34353
+// XFAIL: *
+
+struct B {
+ B() : p('B') {}
+ char p;
+};
+
+struct C {
+ const char *p;
+ explicit C(const char *c) : p(c) {}
+ C(const B &b) : p(&b.p) {} // NOLINT
+};
+
+struct A {
+ char p;
+ explicit A() : p('C') {}
+ const operator C() const { return C(&p); }
+};
+
+volatile char r;
+void test_a() {
+ C s = A();
+ r = *s.p;
+}
+
+void test_b() {
+ C s = B();
+ r = *s.p;
+}
+
+int main(int argc, char **argv) {
+ switch (argv[1][0]) {
+ case 'A':
+ test_a();
+ return 0;
+ case 'B':
+ test_b();
+ return 0;
+ }
+ return 1;
+}
+
+// CHECK: ERROR: AddressSanitizer: stack-use-after-scope
diff --git a/test/asan/TestCases/verbose-log-path_test.cc b/test/asan/TestCases/verbose-log-path_test.cc
index a63c584752428..3c3db0883f616 100644
--- a/test/asan/TestCases/verbose-log-path_test.cc
+++ b/test/asan/TestCases/verbose-log-path_test.cc
@@ -8,7 +8,7 @@
// RUN: %env_asan_opts=log_path=%T/asan.log:log_exe_name=1 not %run %T/verbose-log-path_test-binary 2> %t.out
// RUN: FileCheck %s --check-prefix=CHECK-ERROR < %T/asan.log.verbose-log-path_test-binary.*
-// FIXME: only FreeBSD and Linux have verbose log paths now.
+// FIXME: only FreeBSD, NetBSD and Linux have verbose log paths now.
// XFAIL: win32,android
// UNSUPPORTED: ios
diff --git a/test/asan/lit.cfg b/test/asan/lit.cfg
index e25dd297aa3b0..4a08a7b475a2f 100644
--- a/test/asan/lit.cfg
+++ b/test/asan/lit.cfg
@@ -31,29 +31,19 @@ def push_dynamic_library_lookup_path(config, new_path):
config.name = 'AddressSanitizer' + config.name_suffix
# Platform-specific default ASAN_OPTIONS for lit tests.
-default_asan_opts = ''
-if config.host_os == 'Darwin':
- # On Darwin, we default to `abort_on_error=1`, which would make tests run
- # much slower. Let's override this and run lit tests with 'abort_on_error=0'.
- # Also, make sure we do not overwhelm the syslog while testing.
- default_asan_opts = 'abort_on_error=0'
- default_asan_opts += ':log_to_syslog=0'
-
- # On Darwin, leak checking is not enabled by default. Enable for x86_64
- # tests to prevent regressions
- if config.target_arch == 'x86_64':
- default_asan_opts += ':detect_leaks=1'
-elif config.android:
- # The same as on Darwin, we default to "abort_on_error=1" which slows down
- # testing. Also, all existing tests are using "not" instead of "not --crash"
- # which does not work for abort()-terminated programs.
- default_asan_opts = 'abort_on_error=0'
-
-if default_asan_opts:
- config.environment['ASAN_OPTIONS'] = default_asan_opts
- default_asan_opts += ':'
+default_asan_opts = list(config.default_sanitizer_opts)
+
+# On Darwin, leak checking is not enabled by default. Enable for x86_64
+# tests to prevent regressions
+if config.host_os == 'Darwin' and config.target_arch == 'x86_64':
+ default_asan_opts += ['detect_leaks=1']
+
+default_asan_opts_str = ':'.join(default_asan_opts)
+if default_asan_opts_str:
+ config.environment['ASAN_OPTIONS'] = default_asan_opts_str
+ default_asan_opts_str += ':'
config.substitutions.append(('%env_asan_opts=',
- 'env ASAN_OPTIONS=' + default_asan_opts))
+ 'env ASAN_OPTIONS=' + default_asan_opts_str))
# Setup source root.
config.test_source_root = os.path.dirname(__file__)
@@ -71,11 +61,6 @@ if config.compiler_id == 'GNU':
else:
extra_link_flags = []
-# BFD linker in 64-bit android toolchains fails to find libm.so, which is a
-# transitive shared library dependency (via asan runtime).
-if config.android:
- extra_link_flags += ["-lm"]
-
# Setup default compiler flags used with -fsanitize=address option.
# FIXME: Review the set of required flags and check if it can be reduced.
target_cflags = [get_required_attr(config, "target_cflags")] + extra_link_flags
@@ -110,27 +95,14 @@ if platform.system() == 'Windows':
win_runtime_feature = "win32-static-asan"
config.available_features.add(win_runtime_feature)
-asan_lit_source_dir = get_required_attr(config, "asan_lit_source_dir")
-if config.android == "1":
- config.available_features.add('android')
- compile_wrapper = os.path.join(asan_lit_source_dir, "android_commands", "android_compile.py") + " "
- config.compile_wrapper = compile_wrapper
-else:
- config.available_features.add('not-android')
-
def build_invocation(compile_flags):
- return " " + " ".join([config.compile_wrapper, config.clang] + compile_flags) + " "
-
-# Clang driver link 'x86' (i686) architecture to 'i386'.
-target_arch = config.target_arch
-if (target_arch == "i686"):
- target_arch = "i386"
+ return " " + " ".join([config.clang] + compile_flags) + " "
config.substitutions.append( ("%clang ", build_invocation(target_cflags)) )
config.substitutions.append( ("%clangxx ", build_invocation(target_cxxflags)) )
config.substitutions.append( ("%clang_asan ", build_invocation(clang_asan_cflags)) )
config.substitutions.append( ("%clangxx_asan ", build_invocation(clang_asan_cxxflags)) )
-config.substitutions.append( ("%shared_libasan", "libclang_rt.asan-%s.so" % target_arch))
+config.substitutions.append( ("%shared_libasan", "libclang_rt.asan-%s.so" % config.target_arch))
if config.asan_dynamic:
config.substitutions.append( ("%clang_asan_static ", build_invocation(clang_asan_static_cflags)) )
config.substitutions.append( ("%clangxx_asan_static ", build_invocation(clang_asan_static_cxxflags)) )
@@ -185,7 +157,7 @@ python_exec = get_required_attr(config, "python_executable")
config.substitutions.append( ("%sancov ", python_exec + " " + sancov + " ") )
# Determine kernel bitness
-if config.host_arch.find('64') != -1 and config.android != "1":
+if config.host_arch.find('64') != -1 and not config.android:
kernel_bits = '64'
else:
kernel_bits = '32'
@@ -196,26 +168,6 @@ config.substitutions.append( ("%libdl", libdl_flag) )
config.available_features.add("asan-" + config.bits + "-bits")
-if config.host_os == 'Darwin':
- config.substitutions.append( ("%ld_flags_rpath_exe", '-Wl,-rpath,@executable_path/ %dynamiclib') )
- config.substitutions.append( ("%ld_flags_rpath_so", '-install_name @rpath/`basename %dynamiclib`') )
-elif config.host_os == 'FreeBSD':
- config.substitutions.append( ("%ld_flags_rpath_exe", "-Wl,-z,origin -Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec") )
- config.substitutions.append( ("%ld_flags_rpath_so", '') )
-elif config.host_os == 'Linux':
- config.substitutions.append( ("%ld_flags_rpath_exe", "-Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec") )
- config.substitutions.append( ("%ld_flags_rpath_so", '') )
-
-# Must be defined after the substitutions that use %dynamiclib.
-config.substitutions.append( ("%dynamiclib", '%T/%xdynamiclib_filename') )
-config.substitutions.append( ("%xdynamiclib_filename", 'lib%xdynamiclib_namespec.so') )
-config.substitutions.append( ("%xdynamiclib_namespec", '%basename_t.dynamic') )
-
-# Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL
-# because the test hangs. Adding armhf as we now have two modes.
-if config.target_arch != 'arm' and config.target_arch != 'armhf' and config.target_arch != 'aarch64':
- config.available_features.add('stable-runtime')
-
# Fast unwinder doesn't work with Thumb
if re.search('mthumb', config.target_cflags) is not None:
config.available_features.add('fast-unwinder-works')
diff --git a/test/asan/lit.site.cfg.in b/test/asan/lit.site.cfg.in
index 100592db267dd..6c8f882bcc2c7 100644
--- a/test/asan/lit.site.cfg.in
+++ b/test/asan/lit.site.cfg.in
@@ -2,11 +2,9 @@
# Tool-specific config options.
config.name_suffix = "@ASAN_TEST_CONFIG_SUFFIX@"
-config.asan_lit_source_dir = "@ASAN_LIT_SOURCE_DIR@"
config.target_cflags = "@ASAN_TEST_TARGET_CFLAGS@"
config.clang = "@ASAN_TEST_TARGET_CC@"
config.bits = "@ASAN_TEST_BITS@"
-config.android = "@ANDROID@"
config.ios = @ASAN_TEST_IOS_PYBOOL@
config.iossim = @ASAN_TEST_IOSSIM_PYBOOL@
config.asan_dynamic = @ASAN_TEST_DYNAMIC@
diff --git a/test/builtins/Unit/clear_cache_test.c b/test/builtins/Unit/clear_cache_test.c
index 58960ce3ca38c..e50e66f5efadc 100644
--- a/test/builtins/Unit/clear_cache_test.c
+++ b/test/builtins/Unit/clear_cache_test.c
@@ -52,7 +52,7 @@ memcpy_f(void *dst, const void *src, size_t n) {
#endif
}
-unsigned char execution_buffer[128];
+unsigned char execution_buffer[128] __attribute__((aligned(8)));
int main()
{
diff --git a/test/builtins/Unit/divxc3_test.c b/test/builtins/Unit/divxc3_test.c
index 6517ef124891c..876cdde57dfaa 100644
--- a/test/builtins/Unit/divxc3_test.c
+++ b/test/builtins/Unit/divxc3_test.c
@@ -1,4 +1,6 @@
// RUN: %clang_builtins %s %librt -lm -o %t && %run %t
+// REQUIRES: x86-target-arch
+// UNSUPPORTED: powerpc64
//===-- divxc3_test.c - Test __divxc3 -------------------------------------===//
//
// The LLVM Compiler Infrastructure
diff --git a/test/builtins/Unit/endianness.h b/test/builtins/Unit/endianness.h
index 06c53de0bfa9a..9cecd21659bf4 100644
--- a/test/builtins/Unit/endianness.h
+++ b/test/builtins/Unit/endianness.h
@@ -51,7 +51,7 @@
/* .. */
-#if defined(__OpenBSD__) || defined(__Bitrig__)
+#if defined(__OpenBSD__)
#include <machine/endian.h>
#if _BYTE_ORDER == _BIG_ENDIAN
@@ -62,7 +62,7 @@
#define _YUGA_BIG_ENDIAN 0
#endif /* _BYTE_ORDER */
-#endif /* OpenBSD and Bitrig. */
+#endif /* OpenBSD */
/* .. */
diff --git a/test/builtins/Unit/fixunsxfti_test.c b/test/builtins/Unit/fixunsxfti_test.c
index 0a48a73327036..256ba0cf452e7 100644
--- a/test/builtins/Unit/fixunsxfti_test.c
+++ b/test/builtins/Unit/fixunsxfti_test.c
@@ -1,8 +1,5 @@
// RUN: %clang_builtins %s %librt -o %t && %run %t
-// XFAIL: aarch64
-// test fails for aarch64 (see pr32260)
-
-// UNSUPPORTED: mips
+// REQUIRES: x86-target-arch
//===-- fixunsxfti_test.c - Test __fixunsxfti -----------------------------===//
//
diff --git a/test/builtins/Unit/fixxfti_test.c b/test/builtins/Unit/fixxfti_test.c
index e5e15ab780d42..518ef44fbdb95 100644
--- a/test/builtins/Unit/fixxfti_test.c
+++ b/test/builtins/Unit/fixxfti_test.c
@@ -1,8 +1,5 @@
// RUN: %clang_builtins %s %librt -o %t && %run %t
-// XFAIL: aarch64
-// test fails for aarch64 (see pr32260)
-
-// UNSUPPORTED: mips
+// REQUIRES: x86-target-arch
//===-- fixxfti_test.c - Test __fixxfti -----------------------------------===//
//
diff --git a/test/builtins/Unit/floattixf_test.c b/test/builtins/Unit/floattixf_test.c
index 3de4729342d24..77a6f7dbf0ce0 100644
--- a/test/builtins/Unit/floattixf_test.c
+++ b/test/builtins/Unit/floattixf_test.c
@@ -1,8 +1,5 @@
// RUN: %clang_builtins %s %librt -o %t && %run %t
-// XFAIL: aarch64
-// test fails for aarch64 (see pr32260)
-
-// UNSUPPORTED: mips
+// REQUIRES: x86-target-arch
//===-- floattixf.c - Test __floattixf ------------------------------------===//
//
diff --git a/test/builtins/Unit/floatuntixf_test.c b/test/builtins/Unit/floatuntixf_test.c
index 2d71f0f886045..0f7ad463450dd 100644
--- a/test/builtins/Unit/floatuntixf_test.c
+++ b/test/builtins/Unit/floatuntixf_test.c
@@ -1,8 +1,5 @@
// RUN: %clang_builtins %s %librt -o %t && %run %t
-// XFAIL: aarch64
-// test fails for aarch64 (see pr32260)
-
-// UNSUPPORTED: mips
+// REQUIRES: x86-target-arch
//===-- floatuntixf.c - Test __floatuntixf --------------------------------===//
//
diff --git a/test/builtins/Unit/lit.cfg b/test/builtins/Unit/lit.cfg
index 9e3a0d6f7eb54..0e17e479e6b62 100644
--- a/test/builtins/Unit/lit.cfg
+++ b/test/builtins/Unit/lit.cfg
@@ -55,7 +55,6 @@ clang_builtins_cxxflags = clang_builtins_static_cxxflags
if not is_msvc:
config.available_features.add('c99-complex')
-config.available_features.add('not-android')
clang_wrapper = ""
def build_invocation(compile_flags):
diff --git a/test/builtins/Unit/mulsc3_test.c b/test/builtins/Unit/mulsc3_test.c
index 46309c3e4c4d3..4125a307b9832 100644
--- a/test/builtins/Unit/mulsc3_test.c
+++ b/test/builtins/Unit/mulsc3_test.c
@@ -1,6 +1,4 @@
// RUN: %clang_builtins %s %librt -lm -o %t && %run %t
-// UNSUPPORTED: armhf-target-arch
-// see pr 32475.
//===-- mulsc3_test.c - Test __mulsc3 -------------------------------------===//
//
// The LLVM Compiler Infrastructure
diff --git a/test/builtins/Unit/mulxc3_test.c b/test/builtins/Unit/mulxc3_test.c
index c48b0da506923..9f0b418296e82 100644
--- a/test/builtins/Unit/mulxc3_test.c
+++ b/test/builtins/Unit/mulxc3_test.c
@@ -1,4 +1,6 @@
// RUN: %clang_builtins %s %librt -lm -o %t && %run %t
+// UNSUPPORTED: powerpc64
+// REQUIRES: x86-target-arch
//===-- mulxc3_test.c - Test __mulxc3 -------------------------------------===//
//
// The LLVM Compiler Infrastructure
diff --git a/test/builtins/Unit/powixf2_test.c b/test/builtins/Unit/powixf2_test.c
index bf5a812fa1c55..1df76f2b809a2 100644
--- a/test/builtins/Unit/powixf2_test.c
+++ b/test/builtins/Unit/powixf2_test.c
@@ -1,4 +1,6 @@
// RUN: %clang_builtins %s %librt -o %t && %run %t
+// UNSUPPORTED: powerpc64
+// REQUIRES: x86-target-arch
//===-- powixf2_test.cpp - Test __powixf2 ---------------------------------===//
//
// The LLVM Compiler Infrastructure
diff --git a/test/cfi/CMakeLists.txt b/test/cfi/CMakeLists.txt
index fb45f2f400ce1..c7fadde530954 100644
--- a/test/cfi/CMakeLists.txt
+++ b/test/cfi/CMakeLists.txt
@@ -8,6 +8,7 @@ macro (add_cfi_test_suites lld thinlto)
if (${thinlto})
set(suffix ${suffix}-thinlto)
endif()
+ set(suffix ${suffix}-${CFI_TEST_TARGET_ARCH})
set(CFI_TEST_USE_LLD ${lld})
set(CFI_TEST_USE_THINLTO ${thinlto})
@@ -29,20 +30,29 @@ macro (add_cfi_test_suites lld thinlto)
list(APPEND CFI_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Devirt${suffix})
endmacro()
-if (APPLE)
- # FIXME: enable ThinLTO tests after fixing http://llvm.org/pr32741
- add_cfi_test_suites(False False)
-elseif(WIN32)
- # FIXME: enable ThinLTO tests after fixing http://llvm.org/pr32770
- add_cfi_test_suites(True False)
-else()
- add_cfi_test_suites(False False)
- add_cfi_test_suites(False True)
- if (COMPILER_RT_HAS_LLD)
+set(CFI_TEST_ARCH ${CFI_SUPPORTED_ARCH})
+if(APPLE)
+ darwin_filter_host_archs(CFI_SUPPORTED_ARCH CFI_TEST_ARCH)
+endif()
+
+foreach(arch ${CFI_TEST_ARCH})
+ set(CFI_TEST_TARGET_ARCH ${arch})
+ get_test_cc_for_arch(${arch} CFI_TEST_TARGET_CC CFI_TEST_TARGET_CFLAGS)
+ if (APPLE)
+ # FIXME: enable ThinLTO tests after fixing http://llvm.org/pr32741
+ add_cfi_test_suites(False False)
+ elseif(WIN32)
add_cfi_test_suites(True False)
add_cfi_test_suites(True True)
+ else()
+ add_cfi_test_suites(False False)
+ add_cfi_test_suites(False True)
+ if (COMPILER_RT_HAS_LLD AND NOT arch STREQUAL "i386")
+ add_cfi_test_suites(True False)
+ add_cfi_test_suites(True True)
+ endif()
endif()
-endif()
+endforeach()
set(CFI_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
list(APPEND CFI_TEST_DEPS
diff --git a/test/cfi/anon-namespace.cpp b/test/cfi/anon-namespace.cpp
index 8e6c1c1157d58..2a7ed9c0ac5e7 100644
--- a/test/cfi/anon-namespace.cpp
+++ b/test/cfi/anon-namespace.cpp
@@ -1,32 +1,32 @@
// RUN: %clangxx_cfi -c -DTU1 -o %t1.o %s
// RUN: %clangxx_cfi -c -DTU2 -o %t2.o %S/../cfi/anon-namespace.cpp
// RUN: %clangxx_cfi -o %t1 %t1.o %t2.o
-// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -c -DTU1 -DB32 -o %t1.o %s
// RUN: %clangxx_cfi -c -DTU2 -DB32 -o %t2.o %S/../cfi/anon-namespace.cpp
// RUN: %clangxx_cfi -o %t2 %t1.o %t2.o
-// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -c -DTU1 -DB64 -o %t1.o %s
// RUN: %clangxx_cfi -c -DTU2 -DB64 -o %t2.o %S/../cfi/anon-namespace.cpp
// RUN: %clangxx_cfi -o %t3 %t1.o %t2.o
-// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -c -DTU1 -DBM -o %t1.o %s
// RUN: %clangxx_cfi -c -DTU2 -DBM -o %t2.o %S/../cfi/anon-namespace.cpp
// RUN: %clangxx_cfi -o %t4 %t1.o %t2.o
-// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx -c -DTU1 -o %t1.o %s
// RUN: %clangxx -c -DTU2 -o %t2.o %S/../cfi/anon-namespace.cpp
// RUN: %clangxx -o %t5 %t1.o %t2.o
-// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s
// RUN: %clangxx_cfi_diag -c -DTU1 -o %t1.o %s
// RUN: %clangxx_cfi_diag -c -DTU2 -o %t2.o %S/../cfi/anon-namespace.cpp
// RUN: %clangxx_cfi_diag -o %t6 %t1.o %t2.o
-// RUN: %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
+// RUN: %run %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
// Tests that the CFI mechanism treats classes in the anonymous namespace in
// different translation units as having distinct identities. This is done by
diff --git a/test/cfi/bad-cast.cpp b/test/cfi/bad-cast.cpp
index e2f4f25a4a287..1c4f19e9e6420 100644
--- a/test/cfi/bad-cast.cpp
+++ b/test/cfi/bad-cast.cpp
@@ -1,68 +1,68 @@
// RUN: %clangxx_cfi -o %t1 %s
-// RUN: %expect_crash %t1 a 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t1 b 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t1 c 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %t1 d 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t1 e 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t1 f 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %expect_crash %t1 g 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %t1 h 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %expect_crash %run %t1 a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t1 b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t1 c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %run %t1 d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t1 e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t1 f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %expect_crash %run %t1 g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %run %t1 h 2>&1 | FileCheck --check-prefix=PASS %s
// RUN: %clangxx_cfi -DB32 -o %t2 %s
-// RUN: %expect_crash %t2 a 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t2 b 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t2 c 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %t2 d 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t2 e 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t2 f 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %expect_crash %t2 g 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %t2 h 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %expect_crash %run %t2 a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t2 b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t2 c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %run %t2 d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t2 e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t2 f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %expect_crash %run %t2 g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %run %t2 h 2>&1 | FileCheck --check-prefix=PASS %s
// RUN: %clangxx_cfi -DB64 -o %t3 %s
-// RUN: %expect_crash %t3 a 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t3 b 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t3 c 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %t3 d 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t3 e 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t3 f 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %expect_crash %t3 g 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %t3 h 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %expect_crash %run %t3 a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t3 b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t3 c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %run %t3 d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t3 e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t3 f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %expect_crash %run %t3 g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %run %t3 h 2>&1 | FileCheck --check-prefix=PASS %s
// RUN: %clangxx_cfi -DBM -o %t4 %s
-// RUN: %expect_crash %t4 a 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t4 b 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t4 c 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %t4 d 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t4 e 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t4 f 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %expect_crash %t4 g 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %t4 h 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %expect_crash %run %t4 a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t4 b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t4 c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %run %t4 d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t4 e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t4 f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %expect_crash %run %t4 g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %run %t4 h 2>&1 | FileCheck --check-prefix=PASS %s
// RUN: %clangxx_cfi -fsanitize=cfi-cast-strict -o %t5 %s
-// RUN: %expect_crash %t5 a 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t5 b 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t5 c 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t5 d 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t5 e 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t5 f 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t5 g 2>&1 | FileCheck --check-prefix=FAIL %s
-// RUN: %expect_crash %t5 h 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t5 a 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t5 b 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t5 c 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t5 d 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t5 e 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t5 f 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t5 g 2>&1 | FileCheck --check-prefix=FAIL %s
+// RUN: %expect_crash %run %t5 h 2>&1 | FileCheck --check-prefix=FAIL %s
// RUN: %clangxx -o %t6 %s
-// RUN: %t6 a 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t6 b 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t6 c 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t6 d 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t6 e 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t6 f 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t6 g 2>&1 | FileCheck --check-prefix=PASS %s
-// RUN: %t6 h 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t6 a 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t6 b 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t6 c 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t6 d 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t6 e 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t6 f 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t6 g 2>&1 | FileCheck --check-prefix=PASS %s
+// RUN: %run %t6 h 2>&1 | FileCheck --check-prefix=PASS %s
// RUN: %clangxx_cfi_diag -o %t7 %s
-// RUN: %t7 a 2>&1 | FileCheck --check-prefix=CFI-DIAG-D %s
-// RUN: %t7 b 2>&1 | FileCheck --check-prefix=CFI-DIAG-D %s
-// RUN: %t7 c 2>&1 | FileCheck --check-prefix=CFI-DIAG-D %s
-// RUN: %t7 g 2>&1 | FileCheck --check-prefix=CFI-DIAG-U %s
+// RUN: %run %t7 a 2>&1 | FileCheck --check-prefix=CFI-DIAG-D %s
+// RUN: %run %t7 b 2>&1 | FileCheck --check-prefix=CFI-DIAG-D %s
+// RUN: %run %t7 c 2>&1 | FileCheck --check-prefix=CFI-DIAG-D %s
+// RUN: %run %t7 g 2>&1 | FileCheck --check-prefix=CFI-DIAG-U %s
// Tests that the CFI enforcement detects bad casts.
diff --git a/test/cfi/bad-split.cpp b/test/cfi/bad-split.cpp
index 53504bd2710b7..37e635aef55b8 100644
--- a/test/cfi/bad-split.cpp
+++ b/test/cfi/bad-split.cpp
@@ -1,5 +1,5 @@
// GlobalSplit used to lose type metadata for classes with virtual bases but no virtual methods.
-// RUN: %clangxx_cfi -o %t1 %s && %t1
+// RUN: %clangxx_cfi -o %t1 %s && %run %t1
// UNSUPPORTED: win32
diff --git a/test/cfi/base-derived-destructor.cpp b/test/cfi/base-derived-destructor.cpp
index c5e9db1092a6f..33c7445d55ea9 100644
--- a/test/cfi/base-derived-destructor.cpp
+++ b/test/cfi/base-derived-destructor.cpp
@@ -1,56 +1,56 @@
// RUN: %clangxx_cfi -o %t1 %s
-// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB32 -o %t2 %s
-// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB64 -o %t3 %s
-// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DBM -o %t4 %s
-// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O1 -o %t5 %s
-// RUN: %expect_crash %t5 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t5 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O1 -DB32 -o %t6 %s
-// RUN: %expect_crash %t6 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t6 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O1 -DB64 -o %t7 %s
-// RUN: %expect_crash %t7 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t7 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O1 -DBM -o %t8 %s
-// RUN: %expect_crash %t8 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t8 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O2 -o %t9 %s
-// RUN: %expect_crash %t9 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t9 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O2 -DB32 -o %t10 %s
-// RUN: %expect_crash %t10 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t10 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O2 -DB64 -o %t11 %s
-// RUN: %expect_crash %t11 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t11 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O2 -DBM -o %t12 %s
-// RUN: %expect_crash %t12 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t12 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O3 -o %t13 %s
-// RUN: %expect_crash %t13 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t13 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O3 -DB32 -o %t14 %s
-// RUN: %expect_crash %t14 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t14 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O3 -DB64 -o %t15 %s
-// RUN: %expect_crash %t15 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t15 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O3 -DBM -o %t16 %s
-// RUN: %expect_crash %t16 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t16 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi_diag -o %t17 %s
-// RUN: %t17 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
+// RUN: %run %t17 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
// RUN: %clangxx -o %t18 %s
-// RUN: %t18 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %run %t18 2>&1 | FileCheck --check-prefix=NCFI %s
// Tests that the CFI mechanism crashes the program when making a
// base-to-derived cast from a destructor of the base class,
diff --git a/test/cfi/cross-dso/icall/diag.cpp b/test/cfi/cross-dso/icall/diag.cpp
index c9ca28cbf2cd8..579ee835604a8 100644
--- a/test/cfi/cross-dso/icall/diag.cpp
+++ b/test/cfi/cross-dso/icall/diag.cpp
@@ -6,8 +6,8 @@
// * otherwise, the callee decides between trap/recover/norecover.
// Full-recover.
-// RUN: %clangxx_cfi_dso_diag -g -DSHARED_LIB %s -fPIC -shared -o %t-so.so
-// RUN: %clangxx_cfi_dso_diag -g %s -o %t %t-so.so
+// RUN: %clangxx_cfi_dso_diag -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso_diag -g %s -o %t %ld_flags_rpath_exe
// RUN: %t icv 2>&1 | FileCheck %s --check-prefix=ICALL-DIAG --check-prefix=CAST-DIAG \
// RUN: --check-prefix=VCALL-DIAG --check-prefix=ALL-RECOVER
@@ -23,9 +23,9 @@
// Trap on icall, no-recover on cast.
// RUN: %clangxx_cfi_dso_diag -fsanitize-trap=cfi-icall -fno-sanitize-recover=cfi-unrelated-cast \
-// RUN: -g -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
// RUN: %clangxx_cfi_dso_diag -fsanitize-trap=cfi-icall -fno-sanitize-recover=cfi-unrelated-cast \
-// RUN: -g %s -o %t %t-so.so
+// RUN: -g %s -o %t %ld_flags_rpath_exe
// RUN: %expect_crash %t icv 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-NODIAG \
// RUN: --check-prefix=VCALL-NODIAG --check-prefix=ICALL-FATAL
@@ -40,9 +40,9 @@
// Caller: recover on everything.
// The same as in the previous case, behaviour is decided by the callee.
// RUN: %clangxx_cfi_dso_diag -fsanitize-trap=cfi-icall -fno-sanitize-recover=cfi-unrelated-cast \
-// RUN: -g -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
// RUN: %clangxx_cfi_dso_diag \
-// RUN: -g %s -o %t %t-so.so
+// RUN: -g %s -o %t %ld_flags_rpath_exe
// RUN: %expect_crash %t icv 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-NODIAG \
// RUN: --check-prefix=VCALL-NODIAG --check-prefix=ICALL-FATAL
@@ -57,9 +57,9 @@
// Caller wins.
// cfi-nvcall is non-trapping in the main executable to link the diagnostic runtime library.
// RUN: %clangxx_cfi_dso_diag \
-// RUN: -g -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
// RUN: %clangxx_cfi_dso -fno-sanitize-trap=cfi-nvcall \
-// RUN: -g %s -o %t %t-so.so
+// RUN: -g %s -o %t %ld_flags_rpath_exe
// RUN: %expect_crash %t icv 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-NODIAG \
// RUN: --check-prefix=VCALL-NODIAG --check-prefix=ICALL-FATAL
diff --git a/test/cfi/cross-dso/icall/icall-from-dso.cpp b/test/cfi/cross-dso/icall/icall-from-dso.cpp
index 93cf4f676f7b0..125e030b5063c 100644
--- a/test/cfi/cross-dso/icall/icall-from-dso.cpp
+++ b/test/cfi/cross-dso/icall/icall-from-dso.cpp
@@ -1,8 +1,8 @@
-// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t-so.so
-// RUN: %clangxx_cfi_dso %s -o %t %t-so.so && %expect_crash %t 2>&1 | FileCheck %s
+// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso %s -o %t %ld_flags_rpath_exe && %expect_crash %t 2>&1 | FileCheck %s
-// RUN: %clangxx_cfi_dso_diag -g -DSHARED_LIB %s -fPIC -shared -o %t2-so.so
-// RUN: %clangxx_cfi_dso_diag -g %s -o %t2 %t2-so.so && %t2 2>&1 | FileCheck %s --check-prefix=CFI-DIAG
+// RUN: %clangxx_cfi_dso_diag -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso_diag -g %s -o %t %ld_flags_rpath_exe && %t 2>&1 | FileCheck %s --check-prefix=CFI-DIAG
#include <stdio.h>
diff --git a/test/cfi/cross-dso/icall/icall.cpp b/test/cfi/cross-dso/icall/icall.cpp
index 6017b801436e4..9e9bfd07ed59f 100644
--- a/test/cfi/cross-dso/icall/icall.cpp
+++ b/test/cfi/cross-dso/icall/icall.cpp
@@ -1,8 +1,8 @@
-// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t-so.so
-// RUN: %clangxx_cfi_dso %s -o %t %t-so.so && %expect_crash %t 2>&1 | FileCheck %s
+// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso %s -o %t %ld_flags_rpath_exe && %expect_crash %t 2>&1 | FileCheck %s
-// RUN: %clangxx_cfi_dso_diag -g -DSHARED_LIB %s -fPIC -shared -o %t2-so.so
-// RUN: %clangxx_cfi_dso_diag -g %s -o %t2 %t2-so.so && %t2 2>&1 | FileCheck %s --check-prefix=CFI-DIAG
+// RUN: %clangxx_cfi_dso_diag -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso_diag -g %s -o %t %ld_flags_rpath_exe && %t 2>&1 | FileCheck %s --check-prefix=CFI-DIAG
#include <stdio.h>
diff --git a/test/cfi/cross-dso/lit.local.cfg b/test/cfi/cross-dso/lit.local.cfg
index 57271b8078a49..afdac4246223b 100644
--- a/test/cfi/cross-dso/lit.local.cfg
+++ b/test/cfi/cross-dso/lit.local.cfg
@@ -7,3 +7,7 @@ root = getRoot(config)
if root.host_os not in ['Linux']:
config.unsupported = True
+
+# Android O (API level 26) has support for cross-dso cfi in libdl.so.
+if config.android and 'android-26' not in config.available_features:
+ config.unsupported = True
diff --git a/test/cfi/cross-dso/shadow_is_read_only.cpp b/test/cfi/cross-dso/shadow_is_read_only.cpp
index 65aec826c0015..8811506afe854 100644
--- a/test/cfi/cross-dso/shadow_is_read_only.cpp
+++ b/test/cfi/cross-dso/shadow_is_read_only.cpp
@@ -12,6 +12,9 @@
// Tests that shadow is read-only most of the time.
// REQUIRES: cxxabi
+// Uses private API that is not available on Android.
+// UNSUPPORTED: android
+
#include <assert.h>
#include <dlfcn.h>
#include <stdio.h>
diff --git a/test/cfi/cross-dso/simple-fail.cpp b/test/cfi/cross-dso/simple-fail.cpp
index 276b67d4b7f2a..93503ebe5b363 100644
--- a/test/cfi/cross-dso/simple-fail.cpp
+++ b/test/cfi/cross-dso/simple-fail.cpp
@@ -1,37 +1,37 @@
-// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t1-so.so
-// RUN: %clangxx_cfi_dso %s -o %t1 %t1-so.so
-// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s
-// RUN: %expect_crash %t1 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s
-
-// RUN: %clangxx_cfi_dso -DB32 -DSHARED_LIB %s -fPIC -shared -o %t2-so.so
-// RUN: %clangxx_cfi_dso -DB32 %s -o %t2 %t2-so.so
-// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s
-// RUN: %expect_crash %t2 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s
-
-// RUN: %clangxx_cfi_dso -DB64 -DSHARED_LIB %s -fPIC -shared -o %t3-so.so
-// RUN: %clangxx_cfi_dso -DB64 %s -o %t3 %t3-so.so
-// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s
-// RUN: %expect_crash %t3 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s
-
-// RUN: %clangxx_cfi_dso -DBM -DSHARED_LIB %s -fPIC -shared -o %t4-so.so
-// RUN: %clangxx_cfi_dso -DBM %s -o %t4 %t4-so.so
-// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s
-// RUN: %expect_crash %t4 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s
-
-// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %t5-so.so
-// RUN: %clangxx -DBM %s -o %t5 %t5-so.so
-// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s
-// RUN: %t5 x 2>&1 | FileCheck --check-prefix=NCFI %s
-
-// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %t6-so.so
-// RUN: %clangxx_cfi_dso -DBM %s -o %t6 %t6-so.so
-// RUN: %t6 2>&1 | FileCheck --check-prefix=NCFI %s
-// RUN: %t6 x 2>&1 | FileCheck --check-prefix=NCFI %s
-
-// RUN: %clangxx_cfi_dso_diag -DSHARED_LIB %s -fPIC -shared -o %t7-so.so
-// RUN: %clangxx_cfi_dso_diag %s -o %t7 %t7-so.so
-// RUN: %t7 2>&1 | FileCheck --check-prefix=CFI-DIAG-CALL %s
-// RUN: %t7 x 2>&1 | FileCheck --check-prefix=CFI-DIAG-CALL --check-prefix=CFI-DIAG-CAST %s
+// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso %s -o %t %ld_flags_rpath_exe
+// RUN: %expect_crash %t 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %t x 2>&1 | FileCheck --check-prefix=CFI-CAST %s
+
+// RUN: %clangxx_cfi_dso -DB32 -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso -DB32 %s -o %t %ld_flags_rpath_exe
+// RUN: %expect_crash %t 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %t x 2>&1 | FileCheck --check-prefix=CFI-CAST %s
+
+// RUN: %clangxx_cfi_dso -DB64 -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso -DB64 %s -o %t %ld_flags_rpath_exe
+// RUN: %expect_crash %t 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %t x 2>&1 | FileCheck --check-prefix=CFI-CAST %s
+
+// RUN: %clangxx_cfi_dso -DBM -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso -DBM %s -o %t %ld_flags_rpath_exe
+// RUN: %expect_crash %t 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %t x 2>&1 | FileCheck --check-prefix=CFI-CAST %s
+
+// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx -DBM %s -o %t %ld_flags_rpath_exe
+// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %t x 2>&1 | FileCheck --check-prefix=NCFI %s
+
+// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso -DBM %s -o %t %ld_flags_rpath_exe
+// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %t x 2>&1 | FileCheck --check-prefix=NCFI %s
+
+// RUN: %clangxx_cfi_dso_diag -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso_diag %s -o %t %ld_flags_rpath_exe
+// RUN: %t 2>&1 | FileCheck --check-prefix=CFI-DIAG-CALL %s
+// RUN: %t x 2>&1 | FileCheck --check-prefix=CFI-DIAG-CALL --check-prefix=CFI-DIAG-CAST %s
// Tests that the CFI mechanism crashes the program when making a virtual call
// to an object of the wrong class but with a compatible vtable, by casting a
diff --git a/test/cfi/cross-dso/simple-pass.cpp b/test/cfi/cross-dso/simple-pass.cpp
index 42f7a273453e8..6ce64713a6e2c 100644
--- a/test/cfi/cross-dso/simple-pass.cpp
+++ b/test/cfi/cross-dso/simple-pass.cpp
@@ -1,23 +1,23 @@
-// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t1-so.so
-// RUN: %clangxx_cfi_dso %s -o %t1 %t1-so.so
-// RUN: %t1 2>&1 | FileCheck --check-prefix=CFI %s
-
-// RUN: %clangxx_cfi_dso -DB32 -DSHARED_LIB %s -fPIC -shared -o %t2-so.so
-// RUN: %clangxx_cfi_dso -DB32 %s -o %t2 %t2-so.so
-// RUN: %t2 2>&1 | FileCheck --check-prefix=CFI %s
-
-// RUN: %clangxx_cfi_dso -DB64 -DSHARED_LIB %s -fPIC -shared -o %t3-so.so
-// RUN: %clangxx_cfi_dso -DB64 %s -o %t3 %t3-so.so
-// RUN: %t3 2>&1 | FileCheck --check-prefix=CFI %s
-
-// RUN: %clangxx_cfi_dso -DBM -DSHARED_LIB %s -fPIC -shared -o %t4-so.so
-// RUN: %clangxx_cfi_dso -DBM %s -o %t4 %t4-so.so
-// RUN: %t4 2>&1 | FileCheck --check-prefix=CFI %s
-
-// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %t5-so.so
-// RUN: %clangxx -DBM %s -o %t5 %t5-so.so
-// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s
-// RUN: %t5 x 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso -g %s -o %t %ld_flags_rpath_exe
+// RUN: %t 2>&1 | FileCheck --check-prefix=CFI %s
+
+// RUN: %clangxx_cfi_dso -DB32 -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso -DB32 %s -o %t %ld_flags_rpath_exe
+// RUN: %t 2>&1 | FileCheck --check-prefix=CFI %s
+
+// RUN: %clangxx_cfi_dso -DB64 -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso -DB64 %s -o %t %ld_flags_rpath_exe
+// RUN: %t 2>&1 | FileCheck --check-prefix=CFI %s
+
+// RUN: %clangxx_cfi_dso -DBM -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_dso -DBM %s -o %t %ld_flags_rpath_exe
+// RUN: %t 2>&1 | FileCheck --check-prefix=CFI %s
+
+// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx -DBM %s -o %t %ld_flags_rpath_exe
+// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %t x 2>&1 | FileCheck --check-prefix=NCFI %s
// Tests that the CFI mechanism crashes the program when making a virtual call
// to an object of the wrong class but with a compatible vtable, by casting a
diff --git a/test/cfi/cross-dso/stats.cpp b/test/cfi/cross-dso/stats.cpp
index 975a1ff9fa27a..09a7217bf066a 100644
--- a/test/cfi/cross-dso/stats.cpp
+++ b/test/cfi/cross-dso/stats.cpp
@@ -6,6 +6,9 @@
// CFI-icall is not implemented in thinlto mode => ".cfi" suffixes are missing
// in sanstats output.
+// FIXME: %t.stats must be transferred from device to host for this to work on Android.
+// XFAIL: android
+
struct ABase {};
struct A : ABase {
diff --git a/test/cfi/cross-dso/util/cfi_stubs.h b/test/cfi/cross-dso/util/cfi_stubs.h
new file mode 100644
index 0000000000000..b742074f037e1
--- /dev/null
+++ b/test/cfi/cross-dso/util/cfi_stubs.h
@@ -0,0 +1,30 @@
+// This is a hack to access CFI interface that Android has in libdl.so on
+// device, but not in the NDK.
+#include <dlfcn.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+typedef void (*cfi_slowpath_ty)(uint64_t, void *);
+typedef void (*cfi_slowpath_diag_ty)(uint64_t, void *, void *);
+
+static cfi_slowpath_ty cfi_slowpath;
+static cfi_slowpath_diag_ty cfi_slowpath_diag;
+
+__attribute__((constructor(0), no_sanitize("cfi"))) static void init() {
+ cfi_slowpath = (cfi_slowpath_ty)dlsym(RTLD_NEXT, "__cfi_slowpath");
+ cfi_slowpath_diag =
+ (cfi_slowpath_diag_ty)dlsym(RTLD_NEXT, "__cfi_slowpath_diag");
+ if (!cfi_slowpath || !cfi_slowpath_diag) abort();
+}
+
+extern "C" {
+__attribute__((visibility("hidden"), no_sanitize("cfi"))) void __cfi_slowpath(
+ uint64_t Type, void *Addr) {
+ cfi_slowpath(Type, Addr);
+}
+
+__attribute__((visibility("hidden"), no_sanitize("cfi"))) void
+__cfi_slowpath_diag(uint64_t Type, void *Addr, void *Diag) {
+ cfi_slowpath_diag(Type, Addr, Diag);
+}
+}
diff --git a/test/cfi/icall/external-call.c b/test/cfi/icall/external-call.c
index e90c7e042c274..27c4478781645 100644
--- a/test/cfi/icall/external-call.c
+++ b/test/cfi/icall/external-call.c
@@ -4,7 +4,8 @@
// This test uses jump tables containing PC-relative references to external
// symbols, which the Mach-O object writer does not currently support.
-// XFAIL: darwin
+// The test passes on i386 Darwin and fails on x86_64, hence unsupported instead of xfail.
+// UNSUPPORTED: darwin
#include <stdlib.h>
#include <stdio.h>
diff --git a/test/cfi/lit.cfg b/test/cfi/lit.cfg
index 314ba5ce9e069..cbffe6ea8a65a 100644
--- a/test/cfi/lit.cfg
+++ b/test/cfi/lit.cfg
@@ -5,12 +5,16 @@ config.name = 'cfi' + config.name_suffix
config.suffixes = ['.c', '.cpp', '.test']
config.test_source_root = os.path.dirname(__file__)
-clangxx = ' '.join([config.clang] + config.cxx_mode_flags)
+def build_invocation(compile_flags):
+ return " " + " ".join([config.clang] + compile_flags) + " "
-config.substitutions.append((r"%clang ", ' '.join([config.clang]) + ' '))
+clang = build_invocation([config.target_cflags])
+clangxx = build_invocation([config.target_cflags] + config.cxx_mode_flags)
+
+config.substitutions.append((r"%clang ", clang + ' '))
config.substitutions.append((r"%clangxx ", clangxx + ' '))
if config.lto_supported:
- clang_cfi = ' '.join(config.lto_launch + [config.clang] + config.lto_flags + ['-fsanitize=cfi '])
+ clang_cfi = clang + '-fsanitize=cfi '
if config.cfi_lit_test_mode == "Devirt":
config.available_features.add('devirt')
@@ -23,14 +27,20 @@ if config.lto_supported:
diag = '-fno-sanitize-trap=cfi -fsanitize-recover=cfi '
non_dso = '-fvisibility=hidden '
dso = '-fsanitize-cfi-cross-dso -fvisibility=default '
+ if config.android:
+ dso += '-include ' + config.test_source_root + '/cross-dso/util/cfi_stubs.h '
config.substitutions.append((r"%clang_cfi ", clang_cfi + non_dso))
config.substitutions.append((r"%clangxx_cfi ", clang_cfi + cxx + non_dso))
config.substitutions.append((r"%clang_cfi_diag ", clang_cfi + non_dso + diag))
config.substitutions.append((r"%clangxx_cfi_diag ", clang_cfi + cxx + non_dso + diag))
config.substitutions.append((r"%clangxx_cfi_dso ", clang_cfi + cxx + dso))
config.substitutions.append((r"%clangxx_cfi_dso_diag ", clang_cfi + cxx + dso + diag))
+ config.substitutions.append((r"%debug_info_flags", ' '.join(config.debug_info_flags)))
else:
config.unsupported = True
+if config.default_sanitizer_opts:
+ config.environment['UBSAN_OPTIONS'] = ':'.join(config.default_sanitizer_opts)
+
if lit_config.params.get('check_supported', None) and config.unsupported:
raise BaseException("Tests unsupported")
diff --git a/test/cfi/lit.site.cfg.in b/test/cfi/lit.site.cfg.in
index 63611f659f16c..eb9b44137fdf2 100644
--- a/test/cfi/lit.site.cfg.in
+++ b/test/cfi/lit.site.cfg.in
@@ -2,7 +2,10 @@
config.name_suffix = "@CFI_TEST_CONFIG_SUFFIX@"
config.cfi_lit_test_mode = "@CFI_LIT_TEST_MODE@"
+config.target_arch = "@CFI_TEST_TARGET_ARCH@"
+config.target_cflags = "@CFI_TEST_TARGET_CFLAGS@"
config.use_lld = @CFI_TEST_USE_LLD@
+config.use_lto = True # CFI *requires* LTO.
config.use_thinlto = @CFI_TEST_USE_THINLTO@
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
diff --git a/test/cfi/multiple-inheritance.cpp b/test/cfi/multiple-inheritance.cpp
index a3b2ac56f6338..b8520d8b08b10 100644
--- a/test/cfi/multiple-inheritance.cpp
+++ b/test/cfi/multiple-inheritance.cpp
@@ -1,26 +1,26 @@
// RUN: %clangxx_cfi -o %t1 %s
-// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s
-// RUN: %expect_crash %t1 x 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t1 x 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB32 -o %t2 %s
-// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s
-// RUN: %expect_crash %t2 x 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t2 x 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB64 -o %t3 %s
-// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s
-// RUN: %expect_crash %t3 x 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t3 x 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DBM -o %t4 %s
-// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s
-// RUN: %expect_crash %t4 x 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t4 x 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx -o %t5 %s
-// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s
-// RUN: %t5 x 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %run %t5 x 2>&1 | FileCheck --check-prefix=NCFI %s
// RUN: %clangxx_cfi_diag -o %t6 %s
-// RUN: %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG2 %s
-// RUN: %t6 x 2>&1 | FileCheck --check-prefix=CFI-DIAG1 %s
+// RUN: %run %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG2 %s
+// RUN: %run %t6 x 2>&1 | FileCheck --check-prefix=CFI-DIAG1 %s
// Tests that the CFI mechanism is sensitive to multiple inheritance and only
// permits calls via virtual tables for the correct base class.
diff --git a/test/cfi/nvcall.cpp b/test/cfi/nvcall.cpp
index 9d8f5f49f38da..b61adb1fed064 100644
--- a/test/cfi/nvcall.cpp
+++ b/test/cfi/nvcall.cpp
@@ -1,20 +1,20 @@
// RUN: %clangxx_cfi -o %t1 %s
-// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB32 -o %t2 %s
-// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB64 -o %t3 %s
-// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DBM -o %t4 %s
-// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx -o %t5 %s
-// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s
// RUN: %clangxx_cfi_diag -o %t6 %s
-// RUN: %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
+// RUN: %run %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
// Tests that the CFI mechanism crashes the program when making a non-virtual
// call to an object of the wrong class, by casting a pointer to such an object
diff --git a/test/cfi/overwrite.cpp b/test/cfi/overwrite.cpp
index 48c0a89c8f662..7d7ad1c77f0cb 100644
--- a/test/cfi/overwrite.cpp
+++ b/test/cfi/overwrite.cpp
@@ -1,20 +1,20 @@
// RUN: %clangxx_cfi -o %t1 %s
-// RUN: %expect_crash_unless_devirt %t1 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash_unless_devirt %run %t1 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB32 -o %t2 %s
-// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB64 -o %t3 %s
-// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DBM -o %t4 %s
-// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx -o %t5 %s
-// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s
// RUN: %clangxx_cfi_diag -o %t6 %s
-// RUN: %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
+// RUN: %run %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
// Tests that the CFI mechanism crashes the program when a virtual table is
// replaced with a compatible table of function pointers that does not belong to
diff --git a/test/cfi/sibling.cpp b/test/cfi/sibling.cpp
index 601359888df06..fb6e2f295ff32 100644
--- a/test/cfi/sibling.cpp
+++ b/test/cfi/sibling.cpp
@@ -1,19 +1,19 @@
// XFAIL: *
// RUN: %clangxx_cfi -o %t1 %s
-// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB32 -o %t2 %s
-// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB64 -o %t3 %s
-// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DBM -o %t4 %s
-// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx -o %t5 %s
-// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s
// Tests that the CFI enforcement distinguishes between non-overriding siblings.
// XFAILed as not implemented yet.
diff --git a/test/cfi/simple-fail.cpp b/test/cfi/simple-fail.cpp
index 595ca1617a02a..ef36fb08ab4e0 100644
--- a/test/cfi/simple-fail.cpp
+++ b/test/cfi/simple-fail.cpp
@@ -1,59 +1,59 @@
// RUN: %clangxx_cfi -o %t1 %s
-// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB32 -o %t2 %s
-// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB64 -o %t3 %s
-// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DBM -o %t4 %s
-// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O1 -o %t5 %s
-// RUN: %expect_crash %t5 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t5 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O1 -DB32 -o %t6 %s
-// RUN: %expect_crash %t6 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t6 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O1 -DB64 -o %t7 %s
-// RUN: %expect_crash %t7 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t7 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O1 -DBM -o %t8 %s
-// RUN: %expect_crash %t8 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t8 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O2 -o %t9 %s
-// RUN: %expect_crash %t9 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t9 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O2 -DB32 -o %t10 %s
-// RUN: %expect_crash %t10 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t10 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O2 -DB64 -o %t11 %s
-// RUN: %expect_crash %t11 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t11 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O2 -DBM -o %t12 %s
-// RUN: %expect_crash %t12 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t12 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O3 -o %t13 %s
-// RUN: %expect_crash %t13 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t13 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O3 -DB32 -o %t14 %s
-// RUN: %expect_crash %t14 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t14 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O3 -DB64 -o %t15 %s
-// RUN: %expect_crash %t15 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t15 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -O3 -DBM -o %t16 %s
-// RUN: %expect_crash %t16 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t16 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi_diag -o %t17 %s
-// RUN: %t17 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
+// RUN: %run %t17 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
// RUN: %clangxx -o %t18 %s
-// RUN: %t18 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %run %t18 2>&1 | FileCheck --check-prefix=NCFI %s
// RUN: %clangxx_cfi -DCHECK_NO_SANITIZE_CFI -o %t19 %s
-// RUN: %t19 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %run %t19 2>&1 | FileCheck --check-prefix=NCFI %s
// Tests that the CFI mechanism crashes the program when making a virtual call
// to an object of the wrong class but with a compatible vtable, by casting a
diff --git a/test/cfi/simple-pass.cpp b/test/cfi/simple-pass.cpp
index 4d856eb48ce7a..aba09be2d8169 100644
--- a/test/cfi/simple-pass.cpp
+++ b/test/cfi/simple-pass.cpp
@@ -1,5 +1,5 @@
// RUN: %clangxx_cfi -o %t %s
-// RUN: %t
+// RUN: %run %t
// Tests that the CFI mechanism does not crash the program when making various
// kinds of valid calls involving classes with various different linkages and
diff --git a/test/cfi/stats.cpp b/test/cfi/stats.cpp
index 566fcfbc2581d..ca6b3bf0df481 100644
--- a/test/cfi/stats.cpp
+++ b/test/cfi/stats.cpp
@@ -1,10 +1,13 @@
-// RUN: %clangxx_cfi -g -fsanitize-stats -o %t %s
-// RUN: env SANITIZER_STATS_PATH=%t.stats %t
+// RUN: %clangxx_cfi %debug_info_flags -fsanitize-stats -o %t %s
+// RUN: env SANITIZER_STATS_PATH=%t.stats %run %t
// RUN: sanstats %t.stats | FileCheck %s
// FIXME: We currently emit the wrong debug info under devirtualization.
// UNSUPPORTED: devirt
+// FIXME: %t.stats must be transferred from device to host for this to work on Android.
+// XFAIL: android
+
struct ABase {};
struct A : ABase {
diff --git a/test/cfi/target_uninstrumented.cpp b/test/cfi/target_uninstrumented.cpp
index 2ec2b5bbc9788..5df0738c078b6 100644
--- a/test/cfi/target_uninstrumented.cpp
+++ b/test/cfi/target_uninstrumented.cpp
@@ -1,8 +1,9 @@
-// RUN: %clangxx -g -DSHARED_LIB %s -fPIC -shared -o %T/target_uninstrumented-so.so
-// RUN: %clangxx_cfi_diag -g %s -o %t %T/target_uninstrumented-so.so
-// RUN: %t 2>&1 | FileCheck %s
+// RUN: %clangxx -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+// RUN: %clangxx_cfi_diag -g %s -o %t %ld_flags_rpath_exe
+// RUN: %run %t 2>&1 | FileCheck %s
// REQUIRES: cxxabi
+// UNSUPPORTED: win32
#include <stdio.h>
#include <string.h>
@@ -31,7 +32,7 @@ void A::f() {}
int main(int argc, char *argv[]) {
void *p = create_B();
// CHECK: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type
- // CHECK: invalid vtable in module {{.*}}target_uninstrumented-so.so
+ // CHECK: invalid vtable in module {{.*}}libtarget_uninstrumented.cpp.dynamic.so
A *a = (A *)p;
memset(p, 0, sizeof(A));
// CHECK: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type
diff --git a/test/cfi/two-vcalls.cpp b/test/cfi/two-vcalls.cpp
index 854b3e0059c12..fbe4d971ace88 100644
--- a/test/cfi/two-vcalls.cpp
+++ b/test/cfi/two-vcalls.cpp
@@ -1,5 +1,5 @@
// RUN: %clangxx_cfi_diag -o %t %s
-// RUN: %t 2>&1 | FileCheck %s
+// RUN: %run %t 2>&1 | FileCheck %s
// This test checks that we don't generate two type checks,
// if two virtual calls are in the same function.
diff --git a/test/cfi/vdtor.cpp b/test/cfi/vdtor.cpp
index 522d24c2a4708..defa4ce15f50e 100644
--- a/test/cfi/vdtor.cpp
+++ b/test/cfi/vdtor.cpp
@@ -1,20 +1,20 @@
// RUN: %clangxx_cfi -o %t1 %s
-// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB32 -o %t2 %s
-// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DB64 -o %t3 %s
-// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx_cfi -DBM -o %t4 %s
-// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s
+// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s
// RUN: %clangxx -o %t5 %s
-// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s
+// RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s
// RUN: %clangxx_cfi_diag -o %t6 %s
-// RUN: %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
+// RUN: %run %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
// Tests that the CFI enforcement also applies to virtual destructor calls made
// via 'delete'.
diff --git a/test/cfi/vtable-may-alias.cpp b/test/cfi/vtable-may-alias.cpp
new file mode 100644
index 0000000000000..f63b53b8c9e64
--- /dev/null
+++ b/test/cfi/vtable-may-alias.cpp
@@ -0,0 +1,25 @@
+// RUN: %clangxx_cfi -o %t %s
+// RUN: %run %t
+
+// In this example, both __typeid_A_global_addr and __typeid_B_global_addr will
+// refer to the same address. Make sure that the compiler does not assume that
+// they do not alias.
+
+struct A {
+ virtual void f() = 0;
+};
+
+struct B : A {
+ virtual void f() {}
+};
+
+__attribute__((weak)) void foo(void *p) {
+ B *b = (B *)p;
+ A *a = (A *)b;
+ a->f();
+}
+
+int main() {
+ B b;
+ foo(&b);
+}
diff --git a/test/esan/TestCases/large-stack-linux.c b/test/esan/TestCases/large-stack-linux.c
index 3e024fc4e900b..1af32f8ba25ee 100644
--- a/test/esan/TestCases/large-stack-linux.c
+++ b/test/esan/TestCases/large-stack-linux.c
@@ -56,14 +56,14 @@ int main(int argc, char *argv[]) {
// CHECK: in esan::initializeLibrary
// CHECK: Testing child with infinite stack
// CHECK-NEXT: in esan::initializeLibrary
- // CHECK-NEXT: =={{[0-9]+}}==The stack size limit is beyond the maximum supported.
+ // CHECK-NEXT: =={{[0-9:]+}}==The stack size limit is beyond the maximum supported.
// CHECK-NEXT: Re-execing with a stack size below 1TB.
// CHECK-NEXT: in esan::initializeLibrary
// CHECK: done
// CHECK: in esan::finalizeLibrary
// CHECK: Testing child with 1TB stack
// CHECK-NEXT: in esan::initializeLibrary
- // CHECK-NEXT: =={{[0-9]+}}==The stack size limit is beyond the maximum supported.
+ // CHECK-NEXT: =={{[0-9:]+}}==The stack size limit is beyond the maximum supported.
// CHECK-NEXT: Re-execing with a stack size below 1TB.
// CHECK-NEXT: in esan::initializeLibrary
// CHECK: done
diff --git a/test/fuzzer/AFLDriverTest.cpp b/test/fuzzer/AFLDriverTest.cpp
new file mode 100644
index 0000000000000..b949adc7de159
--- /dev/null
+++ b/test/fuzzer/AFLDriverTest.cpp
@@ -0,0 +1,28 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Contains dummy functions used to avoid dependency on AFL.
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern "C" void __afl_manual_init() {}
+
+extern "C" int __afl_persistent_loop(unsigned int N) {
+ static int Count = N;
+ fprintf(stderr, "__afl_persistent_loop calle, Count = %d\n", Count);
+ if (Count--) return 1;
+ return 0;
+}
+
+// This declaration exists to prevent the Darwin linker
+// from complaining about this being a missing weak symbol.
+extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ fprintf(stderr, "LLVMFuzzerInitialize called\n");
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ fprintf(stderr, "LLVMFuzzerTestOneInput called; Size = %zd\n", Size);
+ return 0;
+}
diff --git a/test/fuzzer/AbsNegAndConstant64Test.cpp b/test/fuzzer/AbsNegAndConstant64Test.cpp
new file mode 100644
index 0000000000000..abeb784e9a116
--- /dev/null
+++ b/test/fuzzer/AbsNegAndConstant64Test.cpp
@@ -0,0 +1,24 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// abs(x) < 0 and y == Const puzzle, 64-bit variant.
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 16) return 0;
+ int64_t x;
+ uint64_t y;
+ memcpy(&x, Data, sizeof(x));
+ memcpy(&y, Data + sizeof(x), sizeof(y));
+ if (llabs(x) < 0 && y == 0xbaddcafedeadbeefULL) {
+ printf("BINGO; Found the target, exiting; x = 0x%lx y 0x%lx\n", x, y);
+ fflush(stdout);
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/AbsNegAndConstantTest.cpp b/test/fuzzer/AbsNegAndConstantTest.cpp
new file mode 100644
index 0000000000000..049db0a60c3d5
--- /dev/null
+++ b/test/fuzzer/AbsNegAndConstantTest.cpp
@@ -0,0 +1,24 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// abs(x) < 0 and y == Const puzzle.
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 8) return 0;
+ int x;
+ unsigned y;
+ memcpy(&x, Data, sizeof(x));
+ memcpy(&y, Data + sizeof(x), sizeof(y));
+ if (abs(x) < 0 && y == 0xbaddcafe) {
+ printf("BINGO; Found the target, exiting; x = 0x%x y 0x%x\n", x, y);
+ fflush(stdout);
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/AccumulateAllocationsTest.cpp b/test/fuzzer/AccumulateAllocationsTest.cpp
new file mode 100644
index 0000000000000..e9acd7ccbd30f
--- /dev/null
+++ b/test/fuzzer/AccumulateAllocationsTest.cpp
@@ -0,0 +1,17 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test with a more mallocs than frees, but no leak.
+#include <cstddef>
+#include <cstdint>
+
+const int kAllocatedPointersSize = 10000;
+int NumAllocatedPointers = 0;
+int *AllocatedPointers[kAllocatedPointersSize];
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (NumAllocatedPointers < kAllocatedPointersSize)
+ AllocatedPointers[NumAllocatedPointers++] = new int;
+ return 0;
+}
+
diff --git a/test/fuzzer/BadStrcmpTest.cpp b/test/fuzzer/BadStrcmpTest.cpp
new file mode 100644
index 0000000000000..ba2b068f741d4
--- /dev/null
+++ b/test/fuzzer/BadStrcmpTest.cpp
@@ -0,0 +1,19 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test that we don't creash in case of bad strcmp params.
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 10) return 0;
+ // Data is not zero-terminated, so this call is bad.
+ // Still, there are cases when such calles appear, see e.g.
+ // https://bugs.llvm.org/show_bug.cgi?id=32357
+ Sink = strcmp(reinterpret_cast<const char*>(Data), "123456789");
+ return 0;
+}
+
diff --git a/test/fuzzer/BogusInitializeTest.cpp b/test/fuzzer/BogusInitializeTest.cpp
new file mode 100644
index 0000000000000..c7e81a5478b25
--- /dev/null
+++ b/test/fuzzer/BogusInitializeTest.cpp
@@ -0,0 +1,15 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Make sure LLVMFuzzerInitialize does not change argv[0].
+#include <stddef.h>
+#include <stdint.h>
+
+extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ ***argv = 'X';
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ return 0;
+}
diff --git a/test/fuzzer/BufferOverflowOnInput.cpp b/test/fuzzer/BufferOverflowOnInput.cpp
new file mode 100644
index 0000000000000..159da92d4e991
--- /dev/null
+++ b/test/fuzzer/BufferOverflowOnInput.cpp
@@ -0,0 +1,24 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+#include <ostream>
+
+static volatile bool SeedLargeBuffer;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ if (Size >= 4)
+ SeedLargeBuffer = true;
+ if (Size == 3 && SeedLargeBuffer && Data[3]) {
+ std::cout << "Woops, reading Data[3] w/o crashing\n" << std::flush;
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/CMakeLists.txt b/test/fuzzer/CMakeLists.txt
new file mode 100644
index 0000000000000..bd511123255b2
--- /dev/null
+++ b/test/fuzzer/CMakeLists.txt
@@ -0,0 +1,43 @@
+set(LIBFUZZER_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+list(REMOVE_ITEM LIBFUZZER_TEST_DEPS SanitizerLintCheck)
+if (NOT COMPILER_RT_STANDALONE_BUILD)
+ list(APPEND LIBFUZZER_TEST_DEPS fuzzer asan ubsan)
+endif()
+
+if(COMPILER_RT_INCLUDE_TESTS)
+ list(APPEND LIBFUZZER_TEST_DEPS FuzzerUnitTests)
+endif()
+
+set(LIBFUZZER_TESTSUITES)
+
+
+if(COMPILER_RT_INCLUDE_TESTS)
+ # libFuzzer unit tests.
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg)
+ list(APPEND LIBFUZZER_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/unit)
+endif()
+
+foreach(arch ${FUZZER_SUPPORTED_ARCH})
+ set(LIBFUZZER_TEST_COMPILER ${COMPILER_RT_TEST_COMPILER})
+ get_test_cc_for_arch(${arch} LIBFUZZER_TEST_COMPILER LIBFUZZER_TEST_FLAGS)
+
+ string(TOUPPER ${arch} ARCH_UPPER_CASE)
+ set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
+
+ # LIT-based libFuzzer tests.
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg
+ )
+ list(APPEND LIBFUZZER_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+
+endforeach()
+
+set(EXCLUDE_FROM_ALL ON)
+
+add_lit_testsuite(check-fuzzer "Running Fuzzer tests"
+ ${LIBFUZZER_TESTSUITES}
+ DEPENDS ${LIBFUZZER_TEST_DEPS})
+set_target_properties(check-fuzzer PROPERTIES FOLDER "Compiler-RT Tests")
diff --git a/test/fuzzer/CallerCalleeTest.cpp b/test/fuzzer/CallerCalleeTest.cpp
new file mode 100644
index 0000000000000..ed9f37cc15218
--- /dev/null
+++ b/test/fuzzer/CallerCalleeTest.cpp
@@ -0,0 +1,59 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer.
+// Try to find the target using the indirect caller-callee pairs.
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+typedef void (*F)();
+static F t[256];
+
+void f34() {
+ std::cerr << "BINGO\n";
+ exit(1);
+}
+void f23() { t[(unsigned)'d'] = f34;}
+void f12() { t[(unsigned)'c'] = f23;}
+void f01() { t[(unsigned)'b'] = f12;}
+void f00() {}
+
+static F t0[256] = {
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 4) return 0;
+ // Spoof the counters.
+ for (int i = 0; i < 200; i++) {
+ f23();
+ f12();
+ f01();
+ }
+ memcpy(t, t0, sizeof(t));
+ t[(unsigned)'a'] = f01;
+ t[Data[0]]();
+ t[Data[1]]();
+ t[Data[2]]();
+ t[Data[3]]();
+ return 0;
+}
+
diff --git a/test/fuzzer/CleanseTest.cpp b/test/fuzzer/CleanseTest.cpp
new file mode 100644
index 0000000000000..ee18457012693
--- /dev/null
+++ b/test/fuzzer/CleanseTest.cpp
@@ -0,0 +1,16 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test the the fuzzer is able to 'cleanse' the reproducer
+// by replacing all irrelevant bytes with garbage.
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size >= 20 && Data[1] == '1' && Data[5] == '5' && Data[10] == 'A' &&
+ Data[19] == 'Z')
+ abort();
+ return 0;
+}
+
diff --git a/test/fuzzer/CounterTest.cpp b/test/fuzzer/CounterTest.cpp
new file mode 100644
index 0000000000000..4917934c62e53
--- /dev/null
+++ b/test/fuzzer/CounterTest.cpp
@@ -0,0 +1,18 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test for a fuzzer: must find the case where a particular basic block is
+// executed many times.
+#include <iostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ int Num = 0;
+ for (size_t i = 0; i < Size; i++)
+ if (Data[i] == 'A' + i)
+ Num++;
+ if (Num >= 4) {
+ std::cerr << "BINGO!\n";
+ exit(1);
+ }
+ return 0;
+}
diff --git a/test/fuzzer/CustomCrossOverAndMutateTest.cpp b/test/fuzzer/CustomCrossOverAndMutateTest.cpp
new file mode 100644
index 0000000000000..74fc939534ca4
--- /dev/null
+++ b/test/fuzzer/CustomCrossOverAndMutateTest.cpp
@@ -0,0 +1,34 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test that libFuzzer does not crash when LLVMFuzzerMutate called from
+// LLVMFuzzerCustomCrossOver.
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <string.h>
+#include <string>
+#include <vector>
+
+#include "FuzzerInterface.h"
+
+static volatile int sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ std::string Str(reinterpret_cast<const char *>(Data), Size);
+ if (Size && Data[0] == '0')
+ sink++;
+ return 0;
+}
+
+extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1,
+ const uint8_t *Data2, size_t Size2,
+ uint8_t *Out, size_t MaxOutSize,
+ unsigned int Seed) {
+ std::vector<uint8_t> Buffer(MaxOutSize * 10);
+ LLVMFuzzerMutate(Buffer.data(), Buffer.size(), Buffer.size());
+ size_t Size = std::min(Size1, MaxOutSize);
+ memcpy(Out, Data1, Size);
+ return Size;
+}
diff --git a/test/fuzzer/CustomCrossOverTest.cpp b/test/fuzzer/CustomCrossOverTest.cpp
new file mode 100644
index 0000000000000..bd9afe774d33c
--- /dev/null
+++ b/test/fuzzer/CustomCrossOverTest.cpp
@@ -0,0 +1,59 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a cutom crossover.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+#include <ostream>
+#include <random>
+#include <string.h>
+#include <functional>
+
+static const char *Separator = "-########-";
+static const char *Target = "A-########-B";
+
+static volatile int sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ std::string Str(reinterpret_cast<const char *>(Data), Size);
+ static const size_t TargetHash = std::hash<std::string>{}(std::string(Target));
+ size_t StrHash = std::hash<std::string>{}(Str);
+
+ // Ensure we have 'A' and 'B' in the corpus.
+ if (Size == 1 && *Data == 'A')
+ sink++;
+ if (Size == 1 && *Data == 'B')
+ sink--;
+
+ if (TargetHash == StrHash) {
+ std::cout << "BINGO; Found the target, exiting\n" << std::flush;
+ exit(1);
+ }
+ return 0;
+}
+
+extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1,
+ const uint8_t *Data2, size_t Size2,
+ uint8_t *Out, size_t MaxOutSize,
+ unsigned int Seed) {
+ static size_t Printed;
+ static size_t SeparatorLen = strlen(Separator);
+
+ if (Printed++ < 32)
+ std::cerr << "In LLVMFuzzerCustomCrossover " << Size1 << " " << Size2 << "\n";
+
+ size_t Size = Size1 + Size2 + SeparatorLen;
+
+ if (Size > MaxOutSize)
+ return 0;
+
+ memcpy(Out, Data1, Size1);
+ memcpy(Out + Size1, Separator, SeparatorLen);
+ memcpy(Out + Size1 + SeparatorLen, Data2, Size2);
+
+ return Size;
+}
diff --git a/test/fuzzer/CustomMutatorTest.cpp b/test/fuzzer/CustomMutatorTest.cpp
new file mode 100644
index 0000000000000..b2adb94082dae
--- /dev/null
+++ b/test/fuzzer/CustomMutatorTest.cpp
@@ -0,0 +1,39 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a cutom mutator.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+#include <ostream>
+
+#include "FuzzerInterface.h"
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ if (Size > 0 && Data[0] == 'H') {
+ Sink = 1;
+ if (Size > 1 && Data[1] == 'i') {
+ Sink = 2;
+ if (Size > 2 && Data[2] == '!') {
+ std::cout << "BINGO; Found the target, exiting\n" << std::flush;
+ exit(1);
+ }
+ }
+ }
+ return 0;
+}
+
+extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
+ size_t MaxSize, unsigned int Seed) {
+ static bool Printed;
+ if (!Printed) {
+ std::cerr << "In LLVMFuzzerCustomMutator\n";
+ Printed = true;
+ }
+ return LLVMFuzzerMutate(Data, Size, MaxSize);
+}
diff --git a/test/fuzzer/CxxStringEqTest.cpp b/test/fuzzer/CxxStringEqTest.cpp
new file mode 100644
index 0000000000000..924851c5ad536
--- /dev/null
+++ b/test/fuzzer/CxxStringEqTest.cpp
@@ -0,0 +1,25 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. Must find a specific string
+// used in std::string operator ==.
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ std::string Str((const char*)Data, Size);
+ bool Eq = Str == "FooBar";
+ Sink = Str == "123456"; // Try to confuse the fuzzer
+ if (Eq) {
+ std::cout << "BINGO; Found the target, exiting\n";
+ std::cout.flush();
+ abort();
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/DSO1.cpp b/test/fuzzer/DSO1.cpp
new file mode 100644
index 0000000000000..72a5ec4a0cdef
--- /dev/null
+++ b/test/fuzzer/DSO1.cpp
@@ -0,0 +1,14 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Source code for a simple DSO.
+#ifdef _WIN32
+__declspec( dllexport )
+#endif
+int DSO1(int a) {
+ if (a < 123456)
+ return 0;
+ return 1;
+}
+
+void Uncovered1() { }
diff --git a/test/fuzzer/DSO2.cpp b/test/fuzzer/DSO2.cpp
new file mode 100644
index 0000000000000..2967055dc2279
--- /dev/null
+++ b/test/fuzzer/DSO2.cpp
@@ -0,0 +1,14 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Source code for a simple DSO.
+#ifdef _WIN32
+__declspec( dllexport )
+#endif
+int DSO2(int a) {
+ if (a < 3598235)
+ return 0;
+ return 1;
+}
+
+void Uncovered2() {}
diff --git a/test/fuzzer/DSOTestExtra.cpp b/test/fuzzer/DSOTestExtra.cpp
new file mode 100644
index 0000000000000..a2274d070ebbf
--- /dev/null
+++ b/test/fuzzer/DSOTestExtra.cpp
@@ -0,0 +1,11 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Source code for a simple DSO.
+
+int DSOTestExtra(int a) {
+ if (a < 452345)
+ return 0;
+ return 1;
+}
+
diff --git a/test/fuzzer/DSOTestMain.cpp b/test/fuzzer/DSOTestMain.cpp
new file mode 100644
index 0000000000000..e0c857d4fdec3
--- /dev/null
+++ b/test/fuzzer/DSOTestMain.cpp
@@ -0,0 +1,31 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Source code for a simple DSO.
+
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+extern int DSO1(int a);
+extern int DSO2(int a);
+extern int DSOTestExtra(int a);
+
+static volatile int *nil = 0;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ int x, y, z;
+ if (Size < sizeof(int) * 3) {
+ x = y = z = 0;
+ } else {
+ memcpy(&x, Data + 0 * sizeof(int), sizeof(int));
+ memcpy(&y, Data + 1 * sizeof(int), sizeof(int));
+ memcpy(&z, Data + 2 * sizeof(int), sizeof(int));
+ }
+ int sum = DSO1(x) + DSO2(y) + (z ? DSOTestExtra(z) : 0);
+ if (sum == 3) {
+ fprintf(stderr, "BINGO %d %d %d\n", x, y, z);
+ *nil = 0;
+ }
+ return 0;
+}
diff --git a/test/fuzzer/DeepRecursionTest.cpp b/test/fuzzer/DeepRecursionTest.cpp
new file mode 100644
index 0000000000000..bf4621d04923e
--- /dev/null
+++ b/test/fuzzer/DeepRecursionTest.cpp
@@ -0,0 +1,25 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the deep recursion.
+// To generate a crashy input:
+// for((i=0;i<110;i++)); do echo -n ABCDEFGHIJ >> INPUT; done
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+
+static volatile int Sink;
+
+void Recursive(const uint8_t *Data, size_t Size, int Depth) {
+ if (Depth > 1000) abort();
+ if (!Size) return;
+ if (*Data == ('A' + Depth % 10))
+ Recursive(Data + 1, Size - 1, Depth + 1);
+ Sink++;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ Recursive(Data, Size, 0);
+ return 0;
+}
+
diff --git a/test/fuzzer/DivTest.cpp b/test/fuzzer/DivTest.cpp
new file mode 100644
index 0000000000000..bce13feb790f0
--- /dev/null
+++ b/test/fuzzer/DivTest.cpp
@@ -0,0 +1,20 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer: find the interesting argument for div.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <iostream>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 4) return 0;
+ int a;
+ memcpy(&a, Data, 4);
+ Sink = 12345678 / (987654 - a);
+ return 0;
+}
+
diff --git a/test/fuzzer/EmptyTest.cpp b/test/fuzzer/EmptyTest.cpp
new file mode 100644
index 0000000000000..5e843308fa570
--- /dev/null
+++ b/test/fuzzer/EmptyTest.cpp
@@ -0,0 +1,11 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// A fuzzer with empty target function.
+
+#include <cstdint>
+#include <cstdlib>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ return 0;
+}
diff --git a/test/fuzzer/EquivalenceATest.cpp b/test/fuzzer/EquivalenceATest.cpp
new file mode 100644
index 0000000000000..7d1ebb0f6a4ab
--- /dev/null
+++ b/test/fuzzer/EquivalenceATest.cpp
@@ -0,0 +1,17 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+// Test for libFuzzer's "equivalence" fuzzing, part A.
+extern "C" void LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size);
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ // fprintf(stderr, "A %zd\n", Size);
+ uint8_t Result[50];
+ if (Size > 50) Size = 50;
+ for (size_t i = 0; i < Size; i++)
+ Result[Size - i - 1] = Data[i];
+ LLVMFuzzerAnnounceOutput(Result, Size);
+ return 0;
+}
diff --git a/test/fuzzer/EquivalenceBTest.cpp b/test/fuzzer/EquivalenceBTest.cpp
new file mode 100644
index 0000000000000..b1de208b57f65
--- /dev/null
+++ b/test/fuzzer/EquivalenceBTest.cpp
@@ -0,0 +1,27 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+// Test for libFuzzer's "equivalence" fuzzing, part B.
+extern "C" void LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size);
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ // fprintf(stderr, "B %zd\n", Size);
+ uint8_t Result[50];
+ if (Size > 50) Size = 50;
+ for (size_t i = 0; i < Size; i++)
+ Result[Size - i - 1] = Data[i];
+
+ // Be a bit different from EquivalenceATest
+ if (Size > 10 && Data[5] == 'B' && Data[6] == 'C' && Data[7] == 'D') {
+ static int c;
+ if (!c)
+ fprintf(stderr, "ZZZZZZZ\n");
+ c = 1;
+ Result[2]++;
+ }
+
+ LLVMFuzzerAnnounceOutput(Result, Size);
+ return 0;
+}
diff --git a/test/fuzzer/FlagsTest.cpp b/test/fuzzer/FlagsTest.cpp
new file mode 100644
index 0000000000000..6eeac177bd97e
--- /dev/null
+++ b/test/fuzzer/FlagsTest.cpp
@@ -0,0 +1,32 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Parse some flags
+#include <string>
+#include <vector>
+
+static std::vector<std::string> Flags;
+
+extern "C" int LLVMFuzzerInitialize(int *Argc, char ***Argv) {
+ // Parse --flags and anything after -ignore_remaining_args=1 is passed.
+ int I = 1;
+ while (I < *Argc) {
+ std::string S((*Argv)[I++]);
+ if (S == "-ignore_remaining_args=1")
+ break;
+ if (S.substr(0, 2) == "--")
+ Flags.push_back(S);
+ }
+ while (I < *Argc)
+ Flags.push_back(std::string((*Argv)[I++]));
+
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ fprintf(stderr, "BINGO ");
+ for (auto Flag : Flags)
+ fprintf(stderr, "%s ", Flag.c_str());
+ fprintf(stderr, "\n");
+ return 0;
+}
diff --git a/test/fuzzer/FourIndependentBranchesTest.cpp b/test/fuzzer/FourIndependentBranchesTest.cpp
new file mode 100644
index 0000000000000..bbf5ea235c7af
--- /dev/null
+++ b/test/fuzzer/FourIndependentBranchesTest.cpp
@@ -0,0 +1,22 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "FUZZ".
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ int bits = 0;
+ if (Size > 0 && Data[0] == 'F') bits |= 1;
+ if (Size > 1 && Data[1] == 'U') bits |= 2;
+ if (Size > 2 && Data[2] == 'Z') bits |= 4;
+ if (Size > 3 && Data[3] == 'Z') bits |= 8;
+ if (bits == 15) {
+ std::cerr << "BINGO!\n";
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/FullCoverageSetTest.cpp b/test/fuzzer/FullCoverageSetTest.cpp
new file mode 100644
index 0000000000000..6d7e48fe51f8b
--- /dev/null
+++ b/test/fuzzer/FullCoverageSetTest.cpp
@@ -0,0 +1,24 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "FUZZER".
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ int bits = 0;
+ if (Size > 0 && Data[0] == 'F') bits |= 1;
+ if (Size > 1 && Data[1] == 'U') bits |= 2;
+ if (Size > 2 && Data[2] == 'Z') bits |= 4;
+ if (Size > 3 && Data[3] == 'Z') bits |= 8;
+ if (Size > 4 && Data[4] == 'E') bits |= 16;
+ if (Size > 5 && Data[5] == 'R') bits |= 32;
+ if (bits == 63) {
+ std::cerr << "BINGO!\n";
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/GcSectionsTest.cpp b/test/fuzzer/GcSectionsTest.cpp
new file mode 100644
index 0000000000000..fd9da7735cdef
--- /dev/null
+++ b/test/fuzzer/GcSectionsTest.cpp
@@ -0,0 +1,14 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer.
+// The unused function should not be present in the binary.
+#include <cstddef>
+#include <cstdint>
+
+extern "C" void UnusedFunctionShouldBeRemovedByLinker() { }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ return 0;
+}
+
diff --git a/test/fuzzer/InitializeTest.cpp b/test/fuzzer/InitializeTest.cpp
new file mode 100644
index 0000000000000..a93c2a525088b
--- /dev/null
+++ b/test/fuzzer/InitializeTest.cpp
@@ -0,0 +1,29 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Make sure LLVMFuzzerInitialize is called.
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char *argv0;
+
+extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ assert(*argc > 0);
+ argv0 = **argv;
+ fprintf(stderr, "LLVMFuzzerInitialize: %s\n", argv0);
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(argv0);
+ if (Size == strlen(argv0) &&
+ !memmem(Data, Size, argv0, Size)) {
+ fprintf(stderr, "BINGO %s\n", argv0);
+ exit(1);
+ }
+ return 0;
+}
diff --git a/test/fuzzer/LargeTest.cpp b/test/fuzzer/LargeTest.cpp
new file mode 100644
index 0000000000000..83ed619718019
--- /dev/null
+++ b/test/fuzzer/LargeTest.cpp
@@ -0,0 +1,37 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// A fuzz target with lots of edges.
+#include <cstdint>
+#include <cstdlib>
+
+static inline void break_optimization(const void *arg) {
+ __asm__ __volatile__("" : : "r" (arg) : "memory");
+}
+
+#define A \
+ do { \
+ i++; \
+ c++; \
+ if (Data[(i + __LINE__) % Size] == (c % 256)) \
+ break_optimization(Data); \
+ else \
+ break_optimization(0); \
+ } while (0)
+
+// for (int i = 0, n = Data[(__LINE__ - 1) % Size] % 16; i < n; i++)
+
+#define B do{A; A; A; A; A; A; A; A; A; A; A; A; A; A; A; A; A; A; }while(0)
+#define C do{B; B; B; B; B; B; B; B; B; B; B; B; B; B; B; B; B; B; }while(0)
+#define D do{C; C; C; C; C; C; C; C; C; C; C; C; C; C; C; C; C; C; }while(0)
+#define E do{D; D; D; D; D; D; D; D; D; D; D; D; D; D; D; D; D; D; }while(0)
+
+volatile int sink;
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (!Size) return 0;
+ int c = 0;
+ int i = 0;
+ D;
+ return 0;
+}
+
diff --git a/test/fuzzer/LeakTest.cpp b/test/fuzzer/LeakTest.cpp
new file mode 100644
index 0000000000000..ea89e39010573
--- /dev/null
+++ b/test/fuzzer/LeakTest.cpp
@@ -0,0 +1,17 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test with a leak.
+#include <cstddef>
+#include <cstdint>
+
+static volatile void *Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && *Data == 'H') {
+ Sink = new int;
+ Sink = nullptr;
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/LeakTimeoutTest.cpp b/test/fuzzer/LeakTimeoutTest.cpp
new file mode 100644
index 0000000000000..92526194a508a
--- /dev/null
+++ b/test/fuzzer/LeakTimeoutTest.cpp
@@ -0,0 +1,17 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test with a leak.
+#include <cstddef>
+#include <cstdint>
+
+static volatile int *Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (!Size) return 0;
+ Sink = new int;
+ Sink = new int;
+ while (Sink) *Sink = 0; // Infinite loop.
+ return 0;
+}
+
diff --git a/test/fuzzer/LoadTest.cpp b/test/fuzzer/LoadTest.cpp
new file mode 100644
index 0000000000000..67a28c7cb22ff
--- /dev/null
+++ b/test/fuzzer/LoadTest.cpp
@@ -0,0 +1,22 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer: find interesting value of array index.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <iostream>
+
+static volatile int Sink;
+const int kArraySize = 1234567;
+int array[kArraySize];
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 8) return 0;
+ uint64_t a = 0;
+ memcpy(&a, Data, 8);
+ Sink = array[a % (kArraySize + 1)];
+ return 0;
+}
+
diff --git a/test/fuzzer/Memcmp64BytesTest.cpp b/test/fuzzer/Memcmp64BytesTest.cpp
new file mode 100644
index 0000000000000..5b6cb707173f2
--- /dev/null
+++ b/test/fuzzer/Memcmp64BytesTest.cpp
@@ -0,0 +1,20 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find a particular string.
+#include <cassert>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ const char kString64Bytes[] =
+ "123456789 123456789 123456789 123456789 123456789 123456789 1234";
+ assert(sizeof(kString64Bytes) == 65);
+ if (Size >= 64 && memcmp(Data, kString64Bytes, 64) == 0) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/test/fuzzer/MemcmpTest.cpp b/test/fuzzer/MemcmpTest.cpp
new file mode 100644
index 0000000000000..8dbb7d84fbbaf
--- /dev/null
+++ b/test/fuzzer/MemcmpTest.cpp
@@ -0,0 +1,31 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find a particular string.
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ // TODO: check other sizes.
+ if (Size >= 8 && memcmp(Data, "01234567", 8) == 0) {
+ if (Size >= 12 && memcmp(Data + 8, "ABCD", 4) == 0) {
+ if (Size >= 14 && memcmp(Data + 12, "XY", 2) == 0) {
+ if (Size >= 17 && memcmp(Data + 14, "KLM", 3) == 0) {
+ if (Size >= 27 && memcmp(Data + 17, "ABCDE-GHIJ", 10) == 0){
+ fprintf(stderr, "BINGO %zd\n", Size);
+ for (size_t i = 0; i < Size; i++) {
+ uint8_t C = Data[i];
+ if (C >= 32 && C < 127)
+ fprintf(stderr, "%c", C);
+ }
+ fprintf(stderr, "\n");
+ exit(1);
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
diff --git a/test/fuzzer/NotinstrumentedTest.cpp b/test/fuzzer/NotinstrumentedTest.cpp
new file mode 100644
index 0000000000000..91418990b1922
--- /dev/null
+++ b/test/fuzzer/NotinstrumentedTest.cpp
@@ -0,0 +1,11 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// This test should not be instrumented.
+#include <cstddef>
+#include <cstdint>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ return 0;
+}
+
diff --git a/test/fuzzer/NthRunCrashTest.cpp b/test/fuzzer/NthRunCrashTest.cpp
new file mode 100644
index 0000000000000..26cdc8f17adf3
--- /dev/null
+++ b/test/fuzzer/NthRunCrashTest.cpp
@@ -0,0 +1,19 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Crash on the N-th execution.
+#include <cstddef>
+#include <cstdint>
+#include <iostream>
+#include <ostream>
+
+static int Counter;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Counter++ == 1000) {
+ std::cout << "BINGO; Found the target, exiting\n" << std::flush;
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/NullDerefOnEmptyTest.cpp b/test/fuzzer/NullDerefOnEmptyTest.cpp
new file mode 100644
index 0000000000000..459db51f8a3b8
--- /dev/null
+++ b/test/fuzzer/NullDerefOnEmptyTest.cpp
@@ -0,0 +1,19 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the empty string.
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+
+static volatile int *Null = 0;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size == 0) {
+ std::cout << "Found the target, dereferencing NULL\n";
+ *Null = 1;
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/NullDerefTest.cpp b/test/fuzzer/NullDerefTest.cpp
new file mode 100644
index 0000000000000..1b44b682ace68
--- /dev/null
+++ b/test/fuzzer/NullDerefTest.cpp
@@ -0,0 +1,26 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+
+static volatile int Sink;
+static volatile int *Null = 0;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && Data[0] == 'H') {
+ Sink = 1;
+ if (Size > 1 && Data[1] == 'i') {
+ Sink = 2;
+ if (Size > 2 && Data[2] == '!') {
+ std::cout << "Found the target, dereferencing NULL\n";
+ *Null = 1;
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/OneHugeAllocTest.cpp b/test/fuzzer/OneHugeAllocTest.cpp
new file mode 100644
index 0000000000000..32a5578710008
--- /dev/null
+++ b/test/fuzzer/OneHugeAllocTest.cpp
@@ -0,0 +1,28 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Tests OOM handling when there is a single large allocation.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+static volatile char *SinkPtr;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && Data[0] == 'H') {
+ if (Size > 1 && Data[1] == 'i') {
+ if (Size > 2 && Data[2] == '!') {
+ size_t kSize = (size_t)1 << 31;
+ char *p = new char[kSize];
+ memset(p, 0, kSize);
+ SinkPtr = p;
+ delete [] p;
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/OutOfMemorySingleLargeMallocTest.cpp b/test/fuzzer/OutOfMemorySingleLargeMallocTest.cpp
new file mode 100644
index 0000000000000..a07795a08dffa
--- /dev/null
+++ b/test/fuzzer/OutOfMemorySingleLargeMallocTest.cpp
@@ -0,0 +1,27 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Tests OOM handling.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+static volatile char *SinkPtr;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && Data[0] == 'H') {
+ if (Size > 1 && Data[1] == 'i') {
+ if (Size > 2 && Data[2] == '!') {
+ size_t kSize = 0x20000000U;
+ char *p = new char[kSize];
+ SinkPtr = p;
+ delete [] p;
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/OutOfMemoryTest.cpp b/test/fuzzer/OutOfMemoryTest.cpp
new file mode 100644
index 0000000000000..5e59bde09853f
--- /dev/null
+++ b/test/fuzzer/OutOfMemoryTest.cpp
@@ -0,0 +1,31 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Tests OOM handling.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <thread>
+
+static volatile char *SinkPtr;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && Data[0] == 'H') {
+ if (Size > 1 && Data[1] == 'i') {
+ if (Size > 2 && Data[2] == '!') {
+ while (true) {
+ size_t kSize = 1 << 28;
+ char *p = new char[kSize];
+ memset(p, 0, kSize);
+ SinkPtr = p;
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/OverwriteInputTest.cpp b/test/fuzzer/OverwriteInputTest.cpp
new file mode 100644
index 0000000000000..e688682346a61
--- /dev/null
+++ b/test/fuzzer/OverwriteInputTest.cpp
@@ -0,0 +1,13 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. Make sure we abort if Data is overwritten.
+#include <cstdint>
+#include <iostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size)
+ *const_cast<uint8_t*>(Data) = 1;
+ return 0;
+}
+
diff --git a/test/fuzzer/PrintFuncTest.cpp b/test/fuzzer/PrintFuncTest.cpp
new file mode 100644
index 0000000000000..d41b462392451
--- /dev/null
+++ b/test/fuzzer/PrintFuncTest.cpp
@@ -0,0 +1,39 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+
+extern "C" {
+__attribute__((noinline))
+void FunctionC(const uint8_t *Data, size_t Size) {
+ if (Size > 3 && Data[3] == 'Z') {
+ static bool PrintedOnce = false;
+ if (!PrintedOnce) {
+ std::cout << "BINGO\n";
+ PrintedOnce = true;
+ }
+ }
+}
+
+__attribute__((noinline))
+void FunctionB(const uint8_t *Data, size_t Size) {
+ if (Size > 2 && Data[2] == 'Z')
+ FunctionC(Data, Size);
+}
+__attribute__((noinline))
+void FunctionA(const uint8_t *Data, size_t Size) {
+ if (Size > 1 && Data[1] == 'U')
+ FunctionB(Data, Size);
+}
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && Data[0] == 'F')
+ FunctionA(Data, Size);
+ return 0;
+}
+
diff --git a/test/fuzzer/RepeatedBytesTest.cpp b/test/fuzzer/RepeatedBytesTest.cpp
new file mode 100644
index 0000000000000..31868cf8c540a
--- /dev/null
+++ b/test/fuzzer/RepeatedBytesTest.cpp
@@ -0,0 +1,31 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find repeated bytes.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+#include <ostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ // Looking for AAAAAAAAAAAAAAAAAAAAAA or some such.
+ size_t CurA = 0, MaxA = 0;
+ for (size_t i = 0; i < Size; i++) {
+ // Make sure there are no conditionals in the loop so that
+ // coverage can't help the fuzzer.
+ int EQ = Data[i] == 'A';
+ CurA = EQ * (CurA + 1);
+ int GT = CurA > MaxA;
+ MaxA = GT * CurA + (!GT) * MaxA;
+ }
+ if (MaxA >= 20) {
+ std::cout << "BINGO; Found the target (Max: " << MaxA << "), exiting\n"
+ << std::flush;
+ exit(0);
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/RepeatedMemcmp.cpp b/test/fuzzer/RepeatedMemcmp.cpp
new file mode 100644
index 0000000000000..18369deac3b00
--- /dev/null
+++ b/test/fuzzer/RepeatedMemcmp.cpp
@@ -0,0 +1,24 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ int Matches1 = 0;
+ for (size_t i = 0; i + 2 < Size; i += 3)
+ if (!memcmp(Data + i, "foo", 3))
+ Matches1++;
+ int Matches2 = 0;
+ for (size_t i = 0; i + 2 < Size; i += 3)
+ if (!memcmp(Data + i, "bar", 3))
+ Matches2++;
+
+ if (Matches1 > 10 && Matches2 > 10) {
+ fprintf(stderr, "BINGO!\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/test/fuzzer/ShrinkControlFlowSimpleTest.cpp b/test/fuzzer/ShrinkControlFlowSimpleTest.cpp
new file mode 100644
index 0000000000000..0afd26df23a0f
--- /dev/null
+++ b/test/fuzzer/ShrinkControlFlowSimpleTest.cpp
@@ -0,0 +1,19 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test that we can find the minimal item in the corpus (3 bytes: "FUZ").
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 2) return 0;
+ if (Data[0] == 'F' && Data[Size / 2] == 'U' && Data[Size - 1] == 'Z')
+ Sink++;
+ return 0;
+}
+
diff --git a/test/fuzzer/ShrinkControlFlowTest.cpp b/test/fuzzer/ShrinkControlFlowTest.cpp
new file mode 100644
index 0000000000000..1957c1f90fc31
--- /dev/null
+++ b/test/fuzzer/ShrinkControlFlowTest.cpp
@@ -0,0 +1,31 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test that we can find the minimal item in the corpus (3 bytes: "FUZ").
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+static volatile int Sink;
+
+void Foo() {
+ Sink++;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ int8_t Ids[256];
+ memset(Ids, -1, sizeof(Ids));
+ for (size_t i = 0; i < Size; i++)
+ if (Ids[Data[i]] == -1)
+ Ids[Data[i]] = i;
+ int F = Ids[(unsigned char)'F'];
+ int U = Ids[(unsigned char)'U'];
+ int Z = Ids[(unsigned char)'Z'];
+ if (F >= 0 && U > F && Z > U) {
+ Foo();
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/ShrinkValueProfileTest.cpp b/test/fuzzer/ShrinkValueProfileTest.cpp
new file mode 100644
index 0000000000000..86e4e3cb0d9ae
--- /dev/null
+++ b/test/fuzzer/ShrinkValueProfileTest.cpp
@@ -0,0 +1,22 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test that we can find the minimal item in the corpus (3 bytes: "FUZ").
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+static volatile uint32_t Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < sizeof(uint32_t)) return 0;
+ uint32_t X, Y;
+ size_t Offset = Size < 8 ? 0 : Size / 2;
+ memcpy(&X, Data + Offset, sizeof(uint32_t));
+ memcpy(&Y, "FUZZ", sizeof(uint32_t));
+ Sink = X == Y;
+ return 0;
+}
+
diff --git a/test/fuzzer/SignedIntOverflowTest.cpp b/test/fuzzer/SignedIntOverflowTest.cpp
new file mode 100644
index 0000000000000..d80060207dee1
--- /dev/null
+++ b/test/fuzzer/SignedIntOverflowTest.cpp
@@ -0,0 +1,28 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test for signed-integer-overflow.
+#include <assert.h>
+#include <climits>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+
+static volatile int Sink;
+static int Large = INT_MAX;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ if (Size > 0 && Data[0] == 'H') {
+ Sink = 1;
+ if (Size > 1 && Data[1] == 'i') {
+ Sink = 2;
+ if (Size > 2 && Data[2] == '!') {
+ Large++; // int overflow.
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/SimpleCmpTest.cpp b/test/fuzzer/SimpleCmpTest.cpp
new file mode 100644
index 0000000000000..8acad4ac77e8f
--- /dev/null
+++ b/test/fuzzer/SimpleCmpTest.cpp
@@ -0,0 +1,47 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find several narrow ranges.
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+extern int AllLines[];
+
+bool PrintOnce(int Line) {
+ if (!AllLines[Line])
+ fprintf(stderr, "Seen line %d\n", Line);
+ AllLines[Line] = 1;
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 22) return 0;
+ uint64_t x = 0;
+ int64_t y = 0;
+ int32_t z = 0;
+ uint16_t a = 0;
+ memcpy(&x, Data, 8); // 8
+ memcpy(&y, Data + 8, 8); // 16
+ memcpy(&z, Data + 16, sizeof(z)); // 20
+ memcpy(&a, Data + 20, sizeof(a)); // 22
+ const bool k32bit = sizeof(void*) == 4;
+
+ if ((k32bit || x > 1234567890) && PrintOnce(__LINE__) &&
+ (k32bit || x < 1234567895) && PrintOnce(__LINE__) &&
+ a == 0x4242 && PrintOnce(__LINE__) &&
+ (k32bit || y >= 987654321) && PrintOnce(__LINE__) &&
+ (k32bit || y <= 987654325) && PrintOnce(__LINE__) &&
+ z < -10000 && PrintOnce(__LINE__) &&
+ z >= -10005 && PrintOnce(__LINE__) &&
+ z != -10003 && PrintOnce(__LINE__) &&
+ true) {
+ fprintf(stderr, "BINGO; Found the target: size %zd (%zd, %zd, %d, %d), exiting.\n",
+ Size, x, y, z, a);
+ exit(1);
+ }
+ return 0;
+}
+
+int AllLines[__LINE__ + 1]; // Must be the last line.
diff --git a/test/fuzzer/SimpleDictionaryTest.cpp b/test/fuzzer/SimpleDictionaryTest.cpp
new file mode 100644
index 0000000000000..ffa2e4137bdea
--- /dev/null
+++ b/test/fuzzer/SimpleDictionaryTest.cpp
@@ -0,0 +1,30 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer.
+// The fuzzer must find a string based on dictionary words:
+// "Elvis"
+// "Presley"
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <ostream>
+
+static volatile int Zero = 0;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ const char *Expected = "ElvisPresley";
+ if (Size < strlen(Expected)) return 0;
+ size_t Match = 0;
+ for (size_t i = 0; Expected[i]; i++)
+ if (Expected[i] + Zero == Data[i])
+ Match++;
+ if (Match == strlen(Expected)) {
+ std::cout << "BINGO; Found the target, exiting\n" << std::flush;
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/SimpleHashTest.cpp b/test/fuzzer/SimpleHashTest.cpp
new file mode 100644
index 0000000000000..99e96cb25dcd5
--- /dev/null
+++ b/test/fuzzer/SimpleHashTest.cpp
@@ -0,0 +1,40 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// This test computes a checksum of the data (all but the last 4 bytes),
+// and then compares the last 4 bytes with the computed value.
+// A fuzzer with cmp traces is expected to defeat this check.
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+// A modified jenkins_one_at_a_time_hash initialized by non-zero,
+// so that simple_hash(0) != 0. See also
+// https://en.wikipedia.org/wiki/Jenkins_hash_function
+static uint32_t simple_hash(const uint8_t *Data, size_t Size) {
+ uint32_t Hash = 0x12039854;
+ for (uint32_t i = 0; i < Size; i++) {
+ Hash += Data[i];
+ Hash += (Hash << 10);
+ Hash ^= (Hash >> 6);
+ }
+ Hash += (Hash << 3);
+ Hash ^= (Hash >> 11);
+ Hash += (Hash << 15);
+ return Hash;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 14)
+ return 0;
+
+ uint32_t Hash = simple_hash(&Data[0], Size - 4);
+ uint32_t Want = reinterpret_cast<const uint32_t *>(&Data[Size - 4])[0];
+ if (Hash != Want)
+ return 0;
+ fprintf(stderr, "BINGO; simple_hash defeated: %x == %x\n", (unsigned int)Hash,
+ (unsigned int)Want);
+ exit(1);
+ return 0;
+}
diff --git a/test/fuzzer/SimpleTest.cpp b/test/fuzzer/SimpleTest.cpp
new file mode 100644
index 0000000000000..3882a842b88cc
--- /dev/null
+++ b/test/fuzzer/SimpleTest.cpp
@@ -0,0 +1,28 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+#include <ostream>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ if (Size > 0 && Data[0] == 'H') {
+ Sink = 1;
+ if (Size > 1 && Data[1] == 'i') {
+ Sink = 2;
+ if (Size > 2 && Data[2] == '!') {
+ std::cout << "BINGO; Found the target, exiting\n" << std::flush;
+ exit(0);
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/SimpleThreadedTest.cpp b/test/fuzzer/SimpleThreadedTest.cpp
new file mode 100644
index 0000000000000..deeae756a8268
--- /dev/null
+++ b/test/fuzzer/SimpleThreadedTest.cpp
@@ -0,0 +1,26 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Threaded test for a fuzzer. The fuzzer should find "H"
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <iostream>
+#include <ostream>
+#include <thread>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ auto C = [&] {
+ if (Size >= 2 && Data[0] == 'H') {
+ std::cout << "BINGO; Found the target, exiting\n" << std::flush;
+ abort();
+ }
+ };
+ std::thread T[] = {std::thread(C), std::thread(C), std::thread(C),
+ std::thread(C), std::thread(C), std::thread(C)};
+ for (auto &X : T)
+ X.join();
+ return 0;
+}
+
diff --git a/test/fuzzer/SingleByteInputTest.cpp b/test/fuzzer/SingleByteInputTest.cpp
new file mode 100644
index 0000000000000..72b58ba912eb3
--- /dev/null
+++ b/test/fuzzer/SingleByteInputTest.cpp
@@ -0,0 +1,17 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer, need just one byte to crash.
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && Data[Size/2] == 42) {
+ fprintf(stderr, "BINGO\n");
+ abort();
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/SingleMemcmpTest.cpp b/test/fuzzer/SingleMemcmpTest.cpp
new file mode 100644
index 0000000000000..19781ba4cd783
--- /dev/null
+++ b/test/fuzzer/SingleMemcmpTest.cpp
@@ -0,0 +1,17 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find a particular string.
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ const char *S = (const char*)Data;
+ if (Size >= 6 && !memcmp(S, "qwerty", 6)) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/test/fuzzer/SingleStrcmpTest.cpp b/test/fuzzer/SingleStrcmpTest.cpp
new file mode 100644
index 0000000000000..149073444c9cb
--- /dev/null
+++ b/test/fuzzer/SingleStrcmpTest.cpp
@@ -0,0 +1,21 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find a particular string.
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size >= 7) {
+ char Copy[7];
+ memcpy(Copy, Data, 6);
+ Copy[6] = 0;
+ if (!strcmp(Copy, "qwerty")) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ }
+ return 0;
+}
diff --git a/test/fuzzer/SingleStrncmpTest.cpp b/test/fuzzer/SingleStrncmpTest.cpp
new file mode 100644
index 0000000000000..47298763f28fa
--- /dev/null
+++ b/test/fuzzer/SingleStrncmpTest.cpp
@@ -0,0 +1,18 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find a particular string.
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ const char *S = (const char*)Data;
+ volatile auto Strncmp = &(strncmp); // Make sure strncmp is not inlined.
+ if (Size >= 6 && !Strncmp(S, "qwerty", 6)) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/test/fuzzer/SleepOneSecondTest.cpp b/test/fuzzer/SleepOneSecondTest.cpp
new file mode 100644
index 0000000000000..27de2f4f70024
--- /dev/null
+++ b/test/fuzzer/SleepOneSecondTest.cpp
@@ -0,0 +1,13 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer: it simply sleeps for 1 second.
+#include <cstddef>
+#include <cstdint>
+#include <thread>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ return 0;
+}
+
diff --git a/test/fuzzer/SpamyTest.cpp b/test/fuzzer/SpamyTest.cpp
new file mode 100644
index 0000000000000..721134e1841c3
--- /dev/null
+++ b/test/fuzzer/SpamyTest.cpp
@@ -0,0 +1,21 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// The test spams to stderr and stdout.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <iostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ printf("PRINTF_STDOUT\n");
+ fflush(stdout);
+ fprintf(stderr, "PRINTF_STDERR\n");
+ std::cout << "STREAM_COUT\n";
+ std::cout.flush();
+ std::cerr << "STREAM_CERR\n";
+ return 0;
+}
+
diff --git a/test/fuzzer/StrcmpTest.cpp b/test/fuzzer/StrcmpTest.cpp
new file mode 100644
index 0000000000000..81f041d913e76
--- /dev/null
+++ b/test/fuzzer/StrcmpTest.cpp
@@ -0,0 +1,32 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Break through a series of strcmp.
+#include <cassert>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+bool Eq(const uint8_t *Data, size_t Size, const char *Str) {
+ char Buff[1024];
+ size_t Len = strlen(Str);
+ if (Size < Len) return false;
+ if (Len >= sizeof(Buff)) return false;
+ memcpy(Buff, (const char*)Data, Len);
+ Buff[Len] = 0;
+ int res = strcmp(Buff, Str);
+ return res == 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Eq(Data, Size, "ABC") &&
+ Size >= 3 && Eq(Data + 3, Size - 3, "QWER") &&
+ Size >= 7 && Eq(Data + 7, Size - 7, "ZXCVN") &&
+ Size >= 14 && Data[13] == 42
+ ) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/test/fuzzer/StrncmpOOBTest.cpp b/test/fuzzer/StrncmpOOBTest.cpp
new file mode 100644
index 0000000000000..4ed71d9d021dd
--- /dev/null
+++ b/test/fuzzer/StrncmpOOBTest.cpp
@@ -0,0 +1,21 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test that libFuzzer itself does not read out of bounds.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 5) return 0;
+ const char *Ch = reinterpret_cast<const char *>(Data);
+ if (Ch[Size - 3] == 'a')
+ Sink = strncmp(Ch + Size - 3, "abcdefg", 6);
+ return 0;
+}
+
diff --git a/test/fuzzer/StrncmpTest.cpp b/test/fuzzer/StrncmpTest.cpp
new file mode 100644
index 0000000000000..a40e05690a0d5
--- /dev/null
+++ b/test/fuzzer/StrncmpTest.cpp
@@ -0,0 +1,28 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find a particular string.
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+static volatile int sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ // TODO: check other sizes.
+ const char *S = (const char*)Data;
+ if (Size >= 8 && strncmp(S, "123", 8))
+ sink = 1;
+ if (Size >= 8 && strncmp(S, "01234567", 8) == 0) {
+ if (Size >= 12 && strncmp(S + 8, "ABCD", 4) == 0) {
+ if (Size >= 14 && strncmp(S + 12, "XY", 2) == 0) {
+ if (Size >= 17 && strncmp(S + 14, "KLM", 3) == 0) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ }
+ }
+ }
+ return 0;
+}
diff --git a/test/fuzzer/StrstrTest.cpp b/test/fuzzer/StrstrTest.cpp
new file mode 100644
index 0000000000000..a3ea4e03b3d27
--- /dev/null
+++ b/test/fuzzer/StrstrTest.cpp
@@ -0,0 +1,28 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test strstr and strcasestr hooks.
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <string.h>
+#include <string>
+
+// Windows does not have strcasestr and memmem, so we are not testing them.
+#ifdef _WIN32
+#define strcasestr strstr
+#define memmem(a, b, c, d) true
+#endif
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 4) return 0;
+ std::string s(reinterpret_cast<const char*>(Data), Size);
+ if (strstr(s.c_str(), "FUZZ") &&
+ strcasestr(s.c_str(), "aBcD") &&
+ memmem(s.data(), s.size(), "kuku", 4)
+ ) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/test/fuzzer/SwapCmpTest.cpp b/test/fuzzer/SwapCmpTest.cpp
new file mode 100644
index 0000000000000..bbfbefe6ab710
--- /dev/null
+++ b/test/fuzzer/SwapCmpTest.cpp
@@ -0,0 +1,35 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// The fuzzer must find several constants with swapped bytes.
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 14) return 0;
+ uint64_t x = 0;
+ uint32_t y = 0;
+ uint16_t z = 0;
+ memcpy(&x, Data, sizeof(x));
+ memcpy(&y, Data + Size / 2, sizeof(y));
+ memcpy(&z, Data + Size - sizeof(z), sizeof(z));
+
+ x = __builtin_bswap64(x);
+ y = __builtin_bswap32(y);
+ z = __builtin_bswap16(z);
+ const bool k32bit = sizeof(void*) == 4;
+
+ if ((k32bit || x == 0x46555A5A5A5A5546ULL) &&
+ z == 0x4F4B &&
+ y == 0x66757A7A &&
+ true
+ ) {
+ if (Data[Size - 3] == 'z') {
+ fprintf(stderr, "BINGO; Found the target\n");
+ exit(1);
+ }
+ }
+ return 0;
+}
diff --git a/test/fuzzer/Switch2Test.cpp b/test/fuzzer/Switch2Test.cpp
new file mode 100644
index 0000000000000..5f66ac8b499e6
--- /dev/null
+++ b/test/fuzzer/Switch2Test.cpp
@@ -0,0 +1,35 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the interesting switch value.
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+int Switch(int a) {
+ switch(a) {
+ case 100001: return 1;
+ case 100002: return 2;
+ case 100003: return 4;
+ }
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ const int N = 3;
+ if (Size < N * sizeof(int)) return 0;
+ int Res = 0;
+ for (int i = 0; i < N; i++) {
+ int X;
+ memcpy(&X, Data + i * sizeof(int), sizeof(int));
+ Res += Switch(X);
+ }
+ if (Res == 5 || Res == 3 || Res == 6 || Res == 7) {
+ fprintf(stderr, "BINGO; Found the target, exiting; Res=%d\n", Res);
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/SwitchTest.cpp b/test/fuzzer/SwitchTest.cpp
new file mode 100644
index 0000000000000..86944cad21c5f
--- /dev/null
+++ b/test/fuzzer/SwitchTest.cpp
@@ -0,0 +1,58 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the interesting switch value.
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+static volatile int Sink;
+
+template<class T>
+bool Switch(const uint8_t *Data, size_t Size) {
+ T X;
+ if (Size < sizeof(X)) return false;
+ memcpy(&X, Data, sizeof(X));
+ switch (X) {
+ case 1: Sink = __LINE__; break;
+ case 101: Sink = __LINE__; break;
+ case 1001: Sink = __LINE__; break;
+ case 10001: Sink = __LINE__; break;
+ case 100001: Sink = __LINE__; break;
+ case 1000001: Sink = __LINE__; break;
+ case 10000001: Sink = __LINE__; break;
+ case 100000001: return true;
+ }
+ return false;
+}
+
+bool ShortSwitch(const uint8_t *Data, size_t Size) {
+ short X;
+ if (Size < sizeof(short)) return false;
+ memcpy(&X, Data, sizeof(short));
+ switch(X) {
+ case 42: Sink = __LINE__; break;
+ case 402: Sink = __LINE__; break;
+ case 4002: Sink = __LINE__; break;
+ case 5002: Sink = __LINE__; break;
+ case 7002: Sink = __LINE__; break;
+ case 9002: Sink = __LINE__; break;
+ case 14002: Sink = __LINE__; break;
+ case 21402: return true;
+ }
+ return false;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size >= 4 && Switch<int>(Data, Size) &&
+ Size >= 12 && Switch<uint64_t>(Data + 4, Size - 4) &&
+ Size >= 14 && ShortSwitch(Data + 12, 2)
+ ) {
+ fprintf(stderr, "BINGO; Found the target, exiting\n");
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/TableLookupTest.cpp b/test/fuzzer/TableLookupTest.cpp
new file mode 100644
index 0000000000000..4d8ab0611cde8
--- /dev/null
+++ b/test/fuzzer/TableLookupTest.cpp
@@ -0,0 +1,44 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Make sure the fuzzer eventually finds all possible values of a variable
+// within a range.
+#include <cassert>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <set>
+
+const size_t N = 1 << 12;
+
+// Define an array of counters that will be understood by libFuzzer
+// as extra coverage signal. The array must be:
+// * uint8_t
+// * in the section named __libfuzzer_extra_counters.
+// The target code may declare more than one such array.
+//
+// Use either `Counters[Idx] = 1` or `Counters[Idx]++;`
+// depending on whether multiple occurrences of the event 'Idx'
+// is important to distinguish from one occurrence.
+#ifdef __linux__
+__attribute__((section("__libfuzzer_extra_counters")))
+#endif
+static uint8_t Counters[N];
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ static std::set<uint16_t> SeenIdx;
+ if (Size != 4) return 0;
+ uint32_t Idx;
+ memcpy(&Idx, Data, 4);
+ Idx %= N;
+ assert(Counters[Idx] == 0); // libFuzzer should reset these between the runs.
+ // Or Counters[Idx]=1 if we don't care how many times this happened.
+ Counters[Idx]++;
+ SeenIdx.insert(Idx);
+ if (SeenIdx.size() == N) {
+ fprintf(stderr, "BINGO: found all values\n");
+ abort();
+ }
+ return 0;
+}
diff --git a/test/fuzzer/ThreadedLeakTest.cpp b/test/fuzzer/ThreadedLeakTest.cpp
new file mode 100644
index 0000000000000..538d3b434808e
--- /dev/null
+++ b/test/fuzzer/ThreadedLeakTest.cpp
@@ -0,0 +1,18 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// The fuzzer should find a leak in a non-main thread.
+#include <cstddef>
+#include <cstdint>
+#include <thread>
+
+static volatile int *Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size == 0) return 0;
+ if (Data[0] != 'F') return 0;
+ std::thread T([&] { Sink = new int; });
+ T.join();
+ return 0;
+}
+
diff --git a/test/fuzzer/ThreadedTest.cpp b/test/fuzzer/ThreadedTest.cpp
new file mode 100644
index 0000000000000..bb51ba764ebaf
--- /dev/null
+++ b/test/fuzzer/ThreadedTest.cpp
@@ -0,0 +1,26 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Threaded test for a fuzzer. The fuzzer should not crash.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <thread>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 8) return 0;
+ assert(Data);
+ auto C = [&] {
+ size_t Res = 0;
+ for (size_t i = 0; i < Size / 2; i++)
+ Res += memcmp(Data, Data + Size / 2, 4);
+ return Res;
+ };
+ std::thread T[] = {std::thread(C), std::thread(C), std::thread(C),
+ std::thread(C), std::thread(C), std::thread(C)};
+ for (auto &X : T)
+ X.join();
+ return 0;
+}
+
diff --git a/test/fuzzer/TimeoutEmptyTest.cpp b/test/fuzzer/TimeoutEmptyTest.cpp
new file mode 100644
index 0000000000000..1ddf1fa34589a
--- /dev/null
+++ b/test/fuzzer/TimeoutEmptyTest.cpp
@@ -0,0 +1,14 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the empty string.
+#include <cstddef>
+#include <cstdint>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ static volatile int Zero = 0;
+ if (!Size)
+ while(!Zero)
+ ;
+ return 0;
+}
diff --git a/test/fuzzer/TimeoutTest.cpp b/test/fuzzer/TimeoutTest.cpp
new file mode 100644
index 0000000000000..e3cdba3eec382
--- /dev/null
+++ b/test/fuzzer/TimeoutTest.cpp
@@ -0,0 +1,26 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && Data[0] == 'H') {
+ Sink = 1;
+ if (Size > 1 && Data[1] == 'i') {
+ Sink = 2;
+ if (Size > 2 && Data[2] == '!') {
+ Sink = 2;
+ while (Sink)
+ ;
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/TraceMallocTest.cpp b/test/fuzzer/TraceMallocTest.cpp
new file mode 100644
index 0000000000000..af9975603aa18
--- /dev/null
+++ b/test/fuzzer/TraceMallocTest.cpp
@@ -0,0 +1,27 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Tests -trace_malloc
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+
+int *Ptr;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (!Size) return 0;
+ if (*Data == 1) {
+ delete Ptr;
+ Ptr = nullptr;
+ } else if (*Data == 2) {
+ delete Ptr;
+ Ptr = new int;
+ } else if (*Data == 3) {
+ if (!Ptr)
+ Ptr = new int;
+ }
+ return 0;
+}
+
diff --git a/test/fuzzer/TraceMallocThreadedTest.cpp b/test/fuzzer/TraceMallocThreadedTest.cpp
new file mode 100644
index 0000000000000..5603af344cb7b
--- /dev/null
+++ b/test/fuzzer/TraceMallocThreadedTest.cpp
@@ -0,0 +1,22 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Check that allocation tracing from different threads does not cause
+// interleaving of stack traces.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <thread>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ auto C = [&] {
+ volatile void *a = malloc(5639);
+ free((void *)a);
+ };
+ std::thread T[] = {std::thread(C), std::thread(C), std::thread(C),
+ std::thread(C), std::thread(C), std::thread(C)};
+ for (auto &X : T)
+ X.join();
+ return 0;
+}
diff --git a/test/fuzzer/TwoDifferentBugsTest.cpp b/test/fuzzer/TwoDifferentBugsTest.cpp
new file mode 100644
index 0000000000000..77d2cb1a25f9f
--- /dev/null
+++ b/test/fuzzer/TwoDifferentBugsTest.cpp
@@ -0,0 +1,22 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. This test may trigger two different bugs.
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+
+static volatile int *Null = 0;
+
+void Foo() { Null[1] = 0; }
+void Bar() { Null[2] = 0; }
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 10 && Data[0] == 'H')
+ Foo();
+ if (Size >= 10 && Data[0] == 'H')
+ Bar();
+ return 0;
+}
+
diff --git a/test/fuzzer/afl-driver-extra-stats.test b/test/fuzzer/afl-driver-extra-stats.test
new file mode 100644
index 0000000000000..a6de53302002f
--- /dev/null
+++ b/test/fuzzer/afl-driver-extra-stats.test
@@ -0,0 +1,30 @@
+RUN: %no_fuzzer_cpp_compiler -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest
+
+; Test that not specifying an extra stats file isn't broken.
+RUN: unset AFL_DRIVER_EXTRA_STATS_FILENAME
+RUN: %t-AFLDriverTest
+
+; Test that specifying an invalid extra stats file causes a crash.
+RUN: ASAN_OPTIONS= AFL_DRIVER_EXTRA_STATS_FILENAME=%T not --crash %t-AFLDriverTest
+
+; Test that specifying a corrupted stats file causes a crash.
+echo "peak_rss_mb :0" > %t
+ASAN_OPTIONS= AFL_DRIVER_EXTRA_STATS_FILENAME=%t not --crash %t-AFLDriverTest
+
+; Test that specifying a valid nonexistent stats file works.
+RUN: rm -f %t
+RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%t %t-AFLDriverTest
+RUN: [[ $(grep "peak_rss_mb\|slowest_unit_time_sec" %t | wc -l) -eq 2 ]]
+
+; Test that specifying a valid preexisting stats file works.
+RUN: printf "peak_rss_mb : 0\nslowest_unit_time_sec: 0\n" > %t
+RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%t %t-AFLDriverTest
+; Check that both lines were printed.
+RUN: [[ $(grep "peak_rss_mb\|slowest_unit_time_sec" %t | wc -l) -eq 2 ]]
+
+; Test that peak_rss_mb and slowest_unit_time_in_secs are only updated when necessary.
+; Check that both lines have 9999 since there's no way we have exceeded that
+; amount of time or virtual memory.
+RUN: printf "peak_rss_mb : 9999\nslowest_unit_time_sec: 9999\n" > %t
+RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%t %t-AFLDriverTest
+RUN: [[ $(grep "9999" %t | wc -l) -eq 2 ]]
diff --git a/test/fuzzer/afl-driver-stderr.test b/test/fuzzer/afl-driver-stderr.test
new file mode 100644
index 0000000000000..be0efaa8f03ea
--- /dev/null
+++ b/test/fuzzer/afl-driver-stderr.test
@@ -0,0 +1,12 @@
+RUN: %no_fuzzer_cpp_compiler -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest
+
+; Test that not specifying a stderr file isn't broken.
+RUN: unset AFL_DRIVER_STDERR_DUPLICATE_FILENAME
+RUN: %t-AFLDriverTest
+
+; Test that specifying an invalid file causes a crash.
+RUN: ASAN_OPTIONS= AFL_DRIVER_STDERR_DUPLICATE_FILENAME="%T" not --crash %t-AFLDriverTest
+
+; Test that a file is created when specified as the duplicate stderr.
+RUN: AFL_DRIVER_STDERR_DUPLICATE_FILENAME=%t %t-AFLDriverTest
+RUN: stat %t
diff --git a/test/fuzzer/afl-driver.test b/test/fuzzer/afl-driver.test
new file mode 100644
index 0000000000000..32e7d03b43c0c
--- /dev/null
+++ b/test/fuzzer/afl-driver.test
@@ -0,0 +1,29 @@
+REQUIRES: linux
+
+RUN: %no_fuzzer_cpp_compiler -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest
+
+RUN: echo -n "abc" > %t.file3
+RUN: echo -n "abcd" > %t.file4
+
+RUN: %t-AFLDriverTest < %t.file3 2>&1 | FileCheck %s --check-prefix=CHECK1
+CHECK1: __afl_persistent_loop calle, Count = 1000
+CHECK1: LLVMFuzzerTestOneInput called; Size = 3
+
+
+RUN: %t-AFLDriverTest < %t.file3 -42 2>&1 | FileCheck %s --check-prefix=CHECK2
+CHECK2: __afl_persistent_loop calle, Count = 42
+CHECK2: LLVMFuzzerTestOneInput called; Size = 3
+
+
+RUN: %t-AFLDriverTest < %t.file3 666 2>&1 | FileCheck %s --check-prefix=CHECK3
+CHECK3: WARNING: using the deprecated call style
+CHECK3: __afl_persistent_loop calle, Count = 666
+CHECK3: LLVMFuzzerTestOneInput called; Size = 3
+
+
+RUN: %t-AFLDriverTest %t.file3 2>&1 | FileCheck %s --check-prefix=CHECK4
+CHECK4: LLVMFuzzerTestOneInput called; Size = 3
+
+RUN: %t-AFLDriverTest %t.file3 %t.file4 2>&1 | FileCheck %s --check-prefix=CHECK5
+CHECK5: LLVMFuzzerTestOneInput called; Size = 3
+CHECK5: LLVMFuzzerTestOneInput called; Size = 4
diff --git a/test/fuzzer/bad-strcmp.test b/test/fuzzer/bad-strcmp.test
new file mode 100644
index 0000000000000..fd1621a4e1eb2
--- /dev/null
+++ b/test/fuzzer/bad-strcmp.test
@@ -0,0 +1,2 @@
+RUN: %cpp_compiler %S/BadStrcmpTest.cpp -o %t-BadStrcmpTest
+RUN: %t-BadStrcmpTest -runs=100000
diff --git a/test/fuzzer/caller-callee.test b/test/fuzzer/caller-callee.test
new file mode 100644
index 0000000000000..e4eccdc307adc
--- /dev/null
+++ b/test/fuzzer/caller-callee.test
@@ -0,0 +1,3 @@
+RUN: %cpp_compiler %S/CallerCalleeTest.cpp -o %t-CallerCalleeTest
+CHECK: BINGO
+RUN: not %t-CallerCalleeTest -use_value_profile=1 -cross_over=0 -seed=1 -runs=10000000 2>&1 | FileCheck %s
diff --git a/test/fuzzer/cleanse.test b/test/fuzzer/cleanse.test
new file mode 100644
index 0000000000000..8e45dc77d9ea4
--- /dev/null
+++ b/test/fuzzer/cleanse.test
@@ -0,0 +1,4 @@
+RUN: %cpp_compiler %S/CleanseTest.cpp -o %t-CleanseTest
+RUN: echo -n 0123456789ABCDEFGHIZ > %t-in
+RUN: %t-CleanseTest -cleanse_crash=1 %t-in -exact_artifact_path=%t-out
+RUN: echo -n ' 1 5 A Z' | diff - %t-out
diff --git a/test/fuzzer/coverage.test b/test/fuzzer/coverage.test
new file mode 100644
index 0000000000000..9a2179d91add6
--- /dev/null
+++ b/test/fuzzer/coverage.test
@@ -0,0 +1,21 @@
+RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/NullDerefTest.cpp -o %t-NullDerefTest
+RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO1.cpp -fPIC -shared -o %t-DSO1.so
+RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO2.cpp -fPIC -shared -o %t-DSO2.so
+RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSOTestMain.cpp %S/DSOTestExtra.cpp -L. %t-DSO1.so %t-DSO2.so -o %t-DSOTest
+
+CHECK: COVERAGE:
+CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:13
+CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:14
+CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:16
+RUN: not %t-NullDerefTest -print_coverage=1 2>&1 | FileCheck %s
+
+RUN: %t-DSOTest -print_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO
+DSO: COVERAGE:
+DSO-DAG: COVERED:{{.*}}DSO1{{.*}}DSO1.cpp
+DSO-DAG: COVERED:{{.*}}DSO2{{.*}}DSO2.cpp
+DSO-DAG: COVERED:{{.*}}LLVMFuzzerTestOneInput{{.*}}DSOTestMain
+DSO-DAG: UNCOVERED_LINE:{{.*}}DSO1{{.*}}DSO1.cpp
+DSO-DAG: UNCOVERED_LINE:{{.*}}DSO2{{.*}}DSO2.cpp
+DSO-DAG: UNCOVERED_FUNC: in Uncovered1
+DSO-DAG: UNCOVERED_FUNC: in Uncovered2
+DSO-DAG: UNCOVERED_LINE: in LLVMFuzzerTestOneInput
diff --git a/test/fuzzer/cxxstring.test b/test/fuzzer/cxxstring.test
new file mode 100644
index 0000000000000..7bb341ba22b48
--- /dev/null
+++ b/test/fuzzer/cxxstring.test
@@ -0,0 +1,6 @@
+UNSUPPORTED: windows
+
+RUN: %cpp_compiler %S/CxxStringEqTest.cpp -o %t-CxxStringEqTest
+
+RUN: not %t-CxxStringEqTest -seed=1 -runs=1000000 2>&1 | FileCheck %s
+CHECK: BINGO
diff --git a/test/fuzzer/deep-recursion.test b/test/fuzzer/deep-recursion.test
new file mode 100644
index 0000000000000..22475f91263a5
--- /dev/null
+++ b/test/fuzzer/deep-recursion.test
@@ -0,0 +1,5 @@
+# Test that we can find a stack overflow
+REQUIRES: linux
+RUN: %cpp_compiler %S/DeepRecursionTest.cpp -o %t
+RUN: not %t -seed=1 -runs=100000000 2>&1 | FileCheck %s
+CHECK: ERROR: libFuzzer: deadly signal
diff --git a/test/fuzzer/dict1.txt b/test/fuzzer/dict1.txt
new file mode 100644
index 0000000000000..520d0cc7b7d86
--- /dev/null
+++ b/test/fuzzer/dict1.txt
@@ -0,0 +1,4 @@
+# Dictionary for SimpleDictionaryTest
+
+a="Elvis"
+b="Presley"
diff --git a/test/fuzzer/disable-leaks.test b/test/fuzzer/disable-leaks.test
new file mode 100644
index 0000000000000..bc120d98b38a9
--- /dev/null
+++ b/test/fuzzer/disable-leaks.test
@@ -0,0 +1,5 @@
+REQUIRES: lsan
+RUN: %cpp_compiler %S/AccumulateAllocationsTest.cpp -o %t-AccumulateAllocationsTest
+RUN: %t-AccumulateAllocationsTest -detect_leaks=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=ACCUMULATE_ALLOCS
+ACCUMULATE_ALLOCS: INFO: libFuzzer disabled leak detection after every mutation
+
diff --git a/test/fuzzer/dump_coverage.test b/test/fuzzer/dump_coverage.test
new file mode 100644
index 0000000000000..b240089ce2395
--- /dev/null
+++ b/test/fuzzer/dump_coverage.test
@@ -0,0 +1,20 @@
+RUN: %cpp_compiler -fsanitize-coverage=0 -fsanitize-coverage=trace-pc-guard %S/DSO1.cpp -fPIC -shared -o %t-DSO1.so
+RUN: %cpp_compiler -fsanitize-coverage=0 -fsanitize-coverage=trace-pc-guard %S/DSO2.cpp -fPIC -shared -o %t-DSO2.so
+RUN: %cpp_compiler -fsanitize-coverage=0 -fsanitize-coverage=trace-pc-guard %S/DSOTestMain.cpp %S/DSOTestExtra.cpp -L. %t-DSO1.so %t-DSO2.so -o %t-DSOTest
+
+RUN: %cpp_compiler -fsanitize-coverage=0 -fsanitize-coverage=trace-pc-guard %S/NullDerefTest.cpp -o %t-NullDerefTest
+
+RUN: rm -rf %t_workdir && mkdir -p %t_workdir
+RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' not %t-NullDerefTest -dump_coverage=1 2>&1 | FileCheck %s
+RUN: sancov -covered-functions %t-NullDerefTest* %t_workdir/*.sancov | FileCheck %s --check-prefix=SANCOV
+RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' %t-DSOTest -dump_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO
+RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' not %t-NullDerefTest -dump_coverage=0 2>&1 | FileCheck %s --check-prefix=NOCOV
+
+CHECK: SanitizerCoverage: {{.*}}NullDerefTest.{{.*}}.sancov: {{.*}} PCs written
+SANCOV: LLVMFuzzerTestOneInput
+
+DSO: SanitizerCoverage: {{.*}}DSOTest.{{.*}}.sancov: {{.*}} PCs written
+DSO-DAG: SanitizerCoverage: {{.*}}DSO1.{{.*}}.sancov: {{.*}} PCs written
+DSO-DAG: SanitizerCoverage: {{.*}}DSO2.{{.*}}.sancov: {{.*}} PCs written
+
+NOCOV-NOT: SanitizerCoverage: {{.*}} PCs written
diff --git a/test/fuzzer/equivalence-signals.test b/test/fuzzer/equivalence-signals.test
new file mode 100644
index 0000000000000..7951636e85f86
--- /dev/null
+++ b/test/fuzzer/equivalence-signals.test
@@ -0,0 +1,9 @@
+# Run EquivalenceATest against itself with a small timeout
+# to stress the signal handling and ensure that shmem doesn't mind
+# the signals.
+
+RUN: %cpp_compiler %S/EquivalenceATest.cpp -o %t-EquivalenceATest
+RUN: %t-EquivalenceATest -timeout=1 -run_equivalence_server=EQUIV_SIG_TEST & export APID=$!
+RUN: sleep 3
+RUN: %t-EquivalenceATest -timeout=1 -use_equivalence_server=EQUIV_SIG_TEST -runs=500000 2>&1
+RUN: kill -9 $APID
diff --git a/test/fuzzer/equivalence.test b/test/fuzzer/equivalence.test
new file mode 100644
index 0000000000000..12964f478a455
--- /dev/null
+++ b/test/fuzzer/equivalence.test
@@ -0,0 +1,9 @@
+RUN: %cpp_compiler %S/EquivalenceATest.cpp -o %t-EquivalenceATest
+RUN: %cpp_compiler %S/EquivalenceBTest.cpp -o %t-EquivalenceBTest
+
+RUN: %t-EquivalenceATest -run_equivalence_server=EQUIV_TEST & export APID=$!
+RUN: sleep 3
+RUN: not %t-EquivalenceBTest -use_equivalence_server=EQUIV_TEST -max_len=4096 2>&1 | FileCheck %s
+CHECK: ERROR: libFuzzer: equivalence-mismatch. Sizes: {{.*}}; offset 2
+CHECK: SUMMARY: libFuzzer: equivalence-mismatch
+RUN: kill -9 $APID
diff --git a/test/fuzzer/exit-report.test b/test/fuzzer/exit-report.test
new file mode 100644
index 0000000000000..f754c1376c437
--- /dev/null
+++ b/test/fuzzer/exit-report.test
@@ -0,0 +1,6 @@
+RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest
+RUN: not %t-SimpleTest 2>&1 | FileCheck %s
+
+CHECK: ERROR: libFuzzer: fuzz target exited
+CHECK: SUMMARY: libFuzzer: fuzz target exited
+CHECK: Test unit written to
diff --git a/test/fuzzer/exit_on_src_pos.test b/test/fuzzer/exit_on_src_pos.test
new file mode 100644
index 0000000000000..6a42c7ae95392
--- /dev/null
+++ b/test/fuzzer/exit_on_src_pos.test
@@ -0,0 +1,8 @@
+# Temporary use -mllvm -use-unknown-locations=Disable so that
+# all instructions have debug info (file line numbers) attached.
+RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest -mllvm -use-unknown-locations=Disable
+RUN: %cpp_compiler %S/ShrinkControlFlowTest.cpp -o %t-ShrinkControlFlowTest
+
+RUN: %t-SimpleTest -exit_on_src_pos=SimpleTest.cpp:18 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS
+RUN: %t-ShrinkControlFlowTest -exit_on_src_pos=Foo 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS
+EXIT_ON_SRC_POS: INFO: found line matching '{{.*}}', exiting.
diff --git a/test/fuzzer/extra-counters.test b/test/fuzzer/extra-counters.test
new file mode 100644
index 0000000000000..230f74a1b0bb5
--- /dev/null
+++ b/test/fuzzer/extra-counters.test
@@ -0,0 +1,7 @@
+REQUIRES: linux
+
+RUN: %cpp_compiler %S/TableLookupTest.cpp -o %t-TableLookupTest
+RUN: not %t-TableLookupTest -print_final_stats=1 2>&1 | FileCheck %s
+CHECK: BINGO
+// Expecting >= 4096 new_units_added
+CHECK: stat::new_units_added:{{.*[4][0-9][0-9][0-9]}}
diff --git a/test/fuzzer/fprofile-instr-generate.test b/test/fuzzer/fprofile-instr-generate.test
new file mode 100644
index 0000000000000..2a3ec96f10f77
--- /dev/null
+++ b/test/fuzzer/fprofile-instr-generate.test
@@ -0,0 +1,7 @@
+# Test libFuzzer + -fprofile-instr-generate
+REQUIRES: linux
+RUN: %cpp_compiler %S/SimpleTest.cpp -fsanitize-coverage=0 -fprofile-instr-generate -o %t-SimpleTest-fprofile-instr-generate
+CHECK-NOT: INFO: Loaded 1 modules
+CHECK: INFO: {{.*}} Clang Coverage Counters
+CHECK: BINGO
+RUN: not %t-SimpleTest-fprofile-instr-generate -runs=1000000 -seed=1 -use_clang_coverage=1 2>&1 | FileCheck %s
diff --git a/test/fuzzer/fuzzer-customcrossover.test b/test/fuzzer/fuzzer-customcrossover.test
new file mode 100644
index 0000000000000..5a78307c7a3bf
--- /dev/null
+++ b/test/fuzzer/fuzzer-customcrossover.test
@@ -0,0 +1,12 @@
+RUN: %cpp_compiler %S/CustomCrossOverTest.cpp -o %t-CustomCrossOverTest
+
+RUN: not %t-CustomCrossOverTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=CHECK_CO
+Disable cross_over, verify that we can't find the target w/o it.
+RUN: %t-CustomCrossOverTest -seed=1 -runs=1000000 -cross_over=0 2>&1 | FileCheck %s --check-prefix=CHECK_NO_CO
+
+CHECK_CO: In LLVMFuzzerCustomCrossover
+CHECK_CO: BINGO
+
+CHECK_NO_CO-NO: LLVMFuzzerCustomCrossover
+CHECK_NO_CO: DONE
+
diff --git a/test/fuzzer/fuzzer-customcrossoverandmutate.test b/test/fuzzer/fuzzer-customcrossoverandmutate.test
new file mode 100644
index 0000000000000..4a7dfba2ab8be
--- /dev/null
+++ b/test/fuzzer/fuzzer-customcrossoverandmutate.test
@@ -0,0 +1,2 @@
+RUN: %cpp_compiler %S/CustomCrossOverAndMutateTest.cpp -o %t-CustomCrossOverAndMutateTest
+RUN: %t-CustomCrossOverAndMutateTest -seed=1 -runs=100000
diff --git a/test/fuzzer/fuzzer-custommutator.test b/test/fuzzer/fuzzer-custommutator.test
new file mode 100644
index 0000000000000..7a693cd473249
--- /dev/null
+++ b/test/fuzzer/fuzzer-custommutator.test
@@ -0,0 +1,5 @@
+RUN: %cpp_compiler %S/CustomMutatorTest.cpp -o %t-CustomMutatorTest
+RUN: not %t-CustomMutatorTest 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomMutator
+LLVMFuzzerCustomMutator: In LLVMFuzzerCustomMutator
+LLVMFuzzerCustomMutator: BINGO
+
diff --git a/test/fuzzer/fuzzer-dict.test b/test/fuzzer/fuzzer-dict.test
new file mode 100644
index 0000000000000..48c91dc1d6fe8
--- /dev/null
+++ b/test/fuzzer/fuzzer-dict.test
@@ -0,0 +1,8 @@
+RUN: %cpp_compiler %S/SimpleDictionaryTest.cpp -o %t-SimpleDictionaryTest
+
+CHECK: BINGO
+Done1000000: Done 1000000 runs in
+
+RUN: not %t-SimpleDictionaryTest -dict=%S/dict1.txt -seed=1 -runs=1000003 2>&1 | FileCheck %s
+RUN: %t-SimpleDictionaryTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
+
diff --git a/test/fuzzer/fuzzer-dirs.test b/test/fuzzer/fuzzer-dirs.test
new file mode 100644
index 0000000000000..9b6e4d1eedda6
--- /dev/null
+++ b/test/fuzzer/fuzzer-dirs.test
@@ -0,0 +1,21 @@
+RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest
+
+RUN: rm -rf %t/SUB1
+RUN: mkdir -p %t/SUB1/SUB2/SUB3
+RUN: echo a > %t/SUB1/a
+RUN: echo b > %t/SUB1/SUB2/b
+RUN: echo c > %t/SUB1/SUB2/SUB3/c
+RUN: %t-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=SUBDIRS
+SUBDIRS: INFO: seed corpus: files: 3 min: 2b max: 2b total: 6b
+RUN: echo -n zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz > %t/SUB1/f64
+RUN: cat %t/SUB1/f64 %t/SUB1/f64 %t/SUB1/f64 %t/SUB1/f64 > %t/SUB1/f256
+RUN: cat %t/SUB1/f256 %t/SUB1/f256 %t/SUB1/f256 %t/SUB1/f256 > %t/SUB1/f1024
+RUN: cat %t/SUB1/f1024 %t/SUB1/f1024 %t/SUB1/f1024 %t/SUB1/f1024 > %t/SUB1/f4096
+RUN: cat %t/SUB1/f4096 %t/SUB1/f4096 > %t/SUB1/f8192
+RUN: %t-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=LONG
+LONG: INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 8192 bytes
+RUN: rm -rf %t/SUB1
+
+RUN: not %t-SimpleTest NONEXISTENT_DIR 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR
+NONEXISTENT_DIR: No such directory: NONEXISTENT_DIR; exiting
+
diff --git a/test/fuzzer/fuzzer-fdmask.test b/test/fuzzer/fuzzer-fdmask.test
new file mode 100644
index 0000000000000..3f04993b5d7ed
--- /dev/null
+++ b/test/fuzzer/fuzzer-fdmask.test
@@ -0,0 +1,32 @@
+RUN: %cpp_compiler %S/SpamyTest.cpp -o %t-SpamyTest
+
+RUN: %t-SpamyTest -runs=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_0
+RUN: %t-SpamyTest -runs=1 -close_fd_mask=0 2>&1 | FileCheck %s --check-prefix=FD_MASK_0
+RUN: %t-SpamyTest -runs=1 -close_fd_mask=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_1
+RUN: %t-SpamyTest -runs=1 -close_fd_mask=2 2>&1 | FileCheck %s --check-prefix=FD_MASK_2
+RUN: %t-SpamyTest -runs=1 -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=FD_MASK_3
+
+FD_MASK_0: PRINTF_STDOUT
+FD_MASK_0: PRINTF_STDERR
+FD_MASK_0: STREAM_COUT
+FD_MASK_0: STREAM_CERR
+FD_MASK_0: INITED
+
+FD_MASK_1-NOT: PRINTF_STDOUT
+FD_MASK_1: PRINTF_STDERR
+FD_MASK_1-NOT: STREAM_COUT
+FD_MASK_1: STREAM_CERR
+FD_MASK_1: INITED
+
+FD_MASK_2: PRINTF_STDOUT
+FD_MASK_2-NOT: PRINTF_STDERR
+FD_MASK_2: STREAM_COUT
+FD_MASK_2-NOTE: STREAM_CERR
+FD_MASK_2: INITED
+
+FD_MASK_3-NOT: PRINTF_STDOUT
+FD_MASK_3-NOT: PRINTF_STDERR
+FD_MASK_3-NOT: STREAM_COUT
+FD_MASK_3-NOT: STREAM_CERR
+FD_MASK_3: INITED
+
diff --git a/test/fuzzer/fuzzer-finalstats.test b/test/fuzzer/fuzzer-finalstats.test
new file mode 100644
index 0000000000000..4f983bea825e9
--- /dev/null
+++ b/test/fuzzer/fuzzer-finalstats.test
@@ -0,0 +1,12 @@
+RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest
+RUN: %t-SimpleTest -seed=1 -runs=77 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS
+FINAL_STATS: stat::number_of_executed_units: 77
+FINAL_STATS: stat::average_exec_per_sec: 0
+FINAL_STATS: stat::new_units_added:
+FINAL_STATS: stat::slowest_unit_time_sec: 0
+FINAL_STATS: stat::peak_rss_mb:
+
+RUN: %t-SimpleTest %S/dict1.txt -runs=33 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS1
+FINAL_STATS1: stat::number_of_executed_units: 33
+FINAL_STATS1: stat::peak_rss_mb:
+
diff --git a/test/fuzzer/fuzzer-flags.test b/test/fuzzer/fuzzer-flags.test
new file mode 100644
index 0000000000000..b812b01695d89
--- /dev/null
+++ b/test/fuzzer/fuzzer-flags.test
@@ -0,0 +1,19 @@
+RUN: %cpp_compiler %S/FlagsTest.cpp -o %t-FlagsTest
+RUN: %t-FlagsTest -runs=10 -foo_bar=1 2>&1 | FileCheck %s --check-prefix=FOO_BAR
+FOO_BAR: WARNING: unrecognized flag '-foo_bar=1'; use -help=1 to list all flags
+FOO_BAR: BINGO
+
+RUN: %t-FlagsTest -runs=10 --max_len=100 2>&1 | FileCheck %s --check-prefix=DASH_DASH
+DASH_DASH: WARNING: did you mean '-max_len=100' (single dash)?
+DASH_DASH: INFO: A corpus is not provided, starting from an empty corpus
+
+RUN: %t-FlagsTest -help=1 2>&1 | FileCheck %s --check-prefix=NO_INTERNAL
+NO_INTERNAL-NOT: internal flag
+
+RUN: %t-FlagsTest --foo-bar -runs=10 -ignore_remaining_args=1 --baz -help=1 test 2>&1 | FileCheck %s --check-prefix=PASSTHRU
+PASSTHRU: BINGO --foo-bar --baz -help=1 test
+
+RUN: mkdir -p %t/T0 %t/T1
+RUN: echo z > %t/T1/z
+RUN: %t-FlagsTest -runs=10 --foo-bar -merge=1 %t/T0 %t/T1 -ignore_remaining_args=1 --baz -help=1 test 2>&1 | FileCheck %s --check-prefix=PASSTHRU-MERGE
+PASSTHRU-MERGE: BINGO --foo-bar --baz -help=1 test
diff --git a/test/fuzzer/fuzzer-leak.test b/test/fuzzer/fuzzer-leak.test
new file mode 100644
index 0000000000000..0652a88f9d5d1
--- /dev/null
+++ b/test/fuzzer/fuzzer-leak.test
@@ -0,0 +1,41 @@
+REQUIRES: lsan
+RUN: %cpp_compiler %S/LeakTest.cpp -o %t-LeakTest
+RUN: %cpp_compiler %S/ThreadedLeakTest.cpp -o %t-ThreadedLeakTest
+RUN: %cpp_compiler %S/LeakTimeoutTest.cpp -o %t-LeakTimeoutTest
+
+RUN: rm -rf %t-corpus && mkdir -p %t-corpus
+RUN: not %t-LeakTest -runs=100000 -detect_leaks=1 %t-corpus 2>&1 | FileCheck %s --check-prefix=LEAK_DURING
+LEAK_DURING: ERROR: LeakSanitizer: detected memory leaks
+LEAK_DURING: Direct leak of 4 byte(s) in 1 object(s) allocated from:
+LEAK_DURING: INFO: to ignore leaks on libFuzzer side use -detect_leaks=0
+LEAK_DURING: Test unit written to ./leak-
+LEAK_DURING-NOT: DONE
+LEAK_DURING-NOT: Done
+
+// Verify leaking input was not added to corpus
+RUN: %t-LeakTest -runs=0 %t-corpus
+
+RUN: not %t-LeakTest -runs=0 -detect_leaks=1 %S 2>&1 | FileCheck %s --check-prefix=LEAK_IN_CORPUS
+LEAK_IN_CORPUS: ERROR: LeakSanitizer: detected memory leaks
+LEAK_IN_CORPUS: INFO: a leak has been found in the initial corpus.
+
+RUN: not %t-LeakTest -runs=100000000 %S/hi.txt 2>&1 | FileCheck %s --check-prefix=MULTI_RUN_LEAK
+MULTI_RUN_LEAK-NOT: pulse
+MULTI_RUN_LEAK: LeakSanitizer: detected memory leaks
+
+RUN: not %t-LeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER
+RUN: not %t-LeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING
+RUN: not %t-ThreadedLeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER
+RUN: not %t-ThreadedLeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING
+LEAK_AFTER: Done 100000 runs in
+LEAK_AFTER: ERROR: LeakSanitizer: detected memory leaks
+
+RUN: not %t-LeakTest -runs=100000 -max_len=1 2>&1 | FileCheck %s --check-prefix=MAX_LEN_1
+MAX_LEN_1: Test unit written to ./leak-7cf184f4c67ad58283ecb19349720b0cae756829
+
+RUN: not %t-LeakTimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=LEAK_TIMEOUT
+LEAK_TIMEOUT: ERROR: libFuzzer: timeout after
+LEAK_TIMEOUT-NOT: LeakSanitizer
+
+
+RUN: %t-LeakTest -error_exitcode=0
diff --git a/test/fuzzer/fuzzer-oom-with-profile.test b/test/fuzzer/fuzzer-oom-with-profile.test
new file mode 100644
index 0000000000000..75cf48430a467
--- /dev/null
+++ b/test/fuzzer/fuzzer-oom-with-profile.test
@@ -0,0 +1,7 @@
+REQUIRES: linux
+RUN: %cpp_compiler %S/OutOfMemoryTest.cpp -o %t-OutOfMemoryTest
+RUN: not %t-OutOfMemoryTest -rss_limit_mb=300 2>&1 | FileCheck %s
+CHECK: ERROR: libFuzzer: out-of-memory (used: {{.*}}; limit: 300Mb)
+CHECK: Live Heap Allocations
+CHECK: Test unit written to ./oom-
+SUMMARY: libFuzzer: out-of-memory
diff --git a/test/fuzzer/fuzzer-oom.test b/test/fuzzer/fuzzer-oom.test
new file mode 100644
index 0000000000000..308c4c5cd3946
--- /dev/null
+++ b/test/fuzzer/fuzzer-oom.test
@@ -0,0 +1,22 @@
+RUN: %cpp_compiler %S/OutOfMemoryTest.cpp -o %t-OutOfMemoryTest
+RUN: %cpp_compiler %S/OutOfMemorySingleLargeMallocTest.cpp -o %t-OutOfMemorySingleLargeMallocTest
+RUN: %cpp_compiler %S/AccumulateAllocationsTest.cpp -o %t-AccumulateAllocationsTest
+
+RUN: not %t-OutOfMemoryTest -rss_limit_mb=300 2>&1 | FileCheck %s
+
+CHECK: ERROR: libFuzzer: out-of-memory (used: {{.*}}; limit: 300Mb)
+CHECK: Test unit written to ./oom-
+SUMMARY: libFuzzer: out-of-memory
+
+RUN: not %t-OutOfMemorySingleLargeMallocTest -rss_limit_mb=300 2>&1 | FileCheck %s --check-prefix=SINGLE_LARGE_MALLOC
+RUN: not %t-OutOfMemorySingleLargeMallocTest -malloc_limit_mb=300 2>&1 | FileCheck %s --check-prefix=SINGLE_LARGE_MALLOC
+RUN: not %t-OutOfMemorySingleLargeMallocTest -rss_limit_mb=1000 -malloc_limit_mb=300 2>&1 | FileCheck %s --check-prefix=SINGLE_LARGE_MALLOC
+
+We used to check for "out-of-memory (malloc(53{{.*}}))", but that would fail
+sometimes, so now we accept any OOM message.
+
+SINGLE_LARGE_MALLOC: libFuzzer: out-of-memory
+SINGLE_LARGE_MALLOC: in LLVMFuzzerTestOneInput
+
+# Check that -rss_limit_mb=0 means no limit.
+RUN: %t-AccumulateAllocationsTest -runs=1000 -rss_limit_mb=0
diff --git a/test/fuzzer/fuzzer-printcovpcs.test b/test/fuzzer/fuzzer-printcovpcs.test
new file mode 100644
index 0000000000000..e55ce14aa72fe
--- /dev/null
+++ b/test/fuzzer/fuzzer-printcovpcs.test
@@ -0,0 +1,9 @@
+RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest
+RUN: not %t-SimpleTest -print_pcs=1 -seed=1 2>&1 | FileCheck %s --check-prefix=PCS
+PCS-NOT: NEW_PC
+PCS:INITED
+PCS:NEW_PC: {{0x[a-f0-9]+}}
+PCS:NEW_PC: {{0x[a-f0-9]+}}
+PCS:NEW
+PCS:BINGO
+
diff --git a/test/fuzzer/fuzzer-runs.test b/test/fuzzer/fuzzer-runs.test
new file mode 100644
index 0000000000000..04987eee50291
--- /dev/null
+++ b/test/fuzzer/fuzzer-runs.test
@@ -0,0 +1,9 @@
+RUN: mkdir -p %t
+RUN: %cpp_compiler %S/NthRunCrashTest.cpp -o %t-NthRunCrashTest
+RUN: echo abcd > %t/NthRunCrashTest.in
+RUN: %t-NthRunCrashTest %t/NthRunCrashTest.in
+RUN: %t-NthRunCrashTest %t/NthRunCrashTest.in -runs=10
+RUN: not %t-NthRunCrashTest %t/NthRunCrashTest.in -runs=10000 2>&1 | FileCheck %s
+RUN: rm %t/NthRunCrashTest.in
+CHECK: BINGO
+
diff --git a/test/fuzzer/fuzzer-seed.test b/test/fuzzer/fuzzer-seed.test
new file mode 100644
index 0000000000000..a69ea5432849a
--- /dev/null
+++ b/test/fuzzer/fuzzer-seed.test
@@ -0,0 +1,4 @@
+RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-SimpleCmpTest
+RUN: %t-SimpleCmpTest -seed=-1 -runs=0 2>&1 | FileCheck %s --check-prefix=CHECK_SEED_MINUS_ONE
+CHECK_SEED_MINUS_ONE: Seed: 4294967295
+
diff --git a/test/fuzzer/fuzzer-segv.test b/test/fuzzer/fuzzer-segv.test
new file mode 100644
index 0000000000000..4d3c7575f7a8b
--- /dev/null
+++ b/test/fuzzer/fuzzer-segv.test
@@ -0,0 +1,8 @@
+RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest
+RUN: env ASAN_OPTIONS=handle_segv=0 not %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_OWN_SEGV_HANDLER
+LIBFUZZER_OWN_SEGV_HANDLER: == ERROR: libFuzzer: deadly signal
+LIBFUZZER_OWN_SEGV_HANDLER: SUMMARY: libFuzzer: deadly signal
+LIBFUZZER_OWN_SEGV_HANDLER: Test unit written to ./crash-
+
+RUN: env ASAN_OPTIONS=handle_segv=1 not %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_ASAN_SEGV_HANDLER
+LIBFUZZER_ASAN_SEGV_HANDLER: ERROR: AddressSanitizer: {{SEGV|access-violation}} on unknown address
diff --git a/test/fuzzer/fuzzer-singleinputs.test b/test/fuzzer/fuzzer-singleinputs.test
new file mode 100644
index 0000000000000..468da5622af93
--- /dev/null
+++ b/test/fuzzer/fuzzer-singleinputs.test
@@ -0,0 +1,19 @@
+RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest
+RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest
+
+RUN: not %t-NullDerefTest %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInput
+SingleInput-NOT: Test unit written to ./crash-
+
+RUN: rm -rf %tmp/SINGLE_INPUTS
+RUN: mkdir -p %tmp/SINGLE_INPUTS
+RUN: echo aaa > %tmp/SINGLE_INPUTS/aaa
+RUN: echo bbb > %tmp/SINGLE_INPUTS/bbb
+RUN: %t-SimpleTest %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS
+RUN: %t-SimpleTest -max_len=2 %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS
+RUN: rm -rf %tmp/SINGLE_INPUTS
+SINGLE_INPUTS: SimpleTest{{.*}}: Running 2 inputs 1 time(s) each.
+SINGLE_INPUTS: aaa in
+SINGLE_INPUTS: bbb in
+SINGLE_INPUTS: NOTE: fuzzing was not performed, you have only
+SINGLE_INPUTS: executed the target code on a fixed set of inputs.
+
diff --git a/test/fuzzer/fuzzer-threaded.test b/test/fuzzer/fuzzer-threaded.test
new file mode 100644
index 0000000000000..572ed5a355186
--- /dev/null
+++ b/test/fuzzer/fuzzer-threaded.test
@@ -0,0 +1,8 @@
+CHECK: Done 1000 runs in
+RUN: %cpp_compiler %S/ThreadedTest.cpp -o %t-ThreadedTest
+
+RUN: %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s
+RUN: %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s
+RUN: %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s
+RUN: %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s
+
diff --git a/test/fuzzer/fuzzer-timeout.test b/test/fuzzer/fuzzer-timeout.test
new file mode 100644
index 0000000000000..41f4ba3643983
--- /dev/null
+++ b/test/fuzzer/fuzzer-timeout.test
@@ -0,0 +1,21 @@
+RUN: %cpp_compiler %S/TimeoutTest.cpp -o %t-TimeoutTest
+RUN: %cpp_compiler %S/TimeoutEmptyTest.cpp -o %t-TimeoutEmptyTest
+RUN: not %t-TimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutTest
+TimeoutTest: ALARM: working on the last Unit for
+TimeoutTest: Test unit written to ./timeout-
+TimeoutTest: == ERROR: libFuzzer: timeout after
+TimeoutTest: #0
+TimeoutTest: #1
+TimeoutTest: #2
+TimeoutTest: SUMMARY: libFuzzer: timeout
+
+RUN: not %t-TimeoutTest -timeout=1 %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInputTimeoutTest
+SingleInputTimeoutTest: ALARM: working on the last Unit for {{[1-3]}} seconds
+SingleInputTimeoutTest-NOT: Test unit written to ./timeout-
+
+RUN: %t-TimeoutTest -timeout=1 -timeout_exitcode=0
+
+RUN: not %t-TimeoutEmptyTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutEmptyTest
+TimeoutEmptyTest: ALARM: working on the last Unit for
+TimeoutEmptyTest: == ERROR: libFuzzer: timeout after
+TimeoutEmptyTest: SUMMARY: libFuzzer: timeout
diff --git a/test/fuzzer/fuzzer-ubsan.test b/test/fuzzer/fuzzer-ubsan.test
new file mode 100644
index 0000000000000..49c190cd034b5
--- /dev/null
+++ b/test/fuzzer/fuzzer-ubsan.test
@@ -0,0 +1,5 @@
+RUN: %cpp_compiler -fsanitize=undefined -fno-sanitize-recover=all %S/SignedIntOverflowTest.cpp -o %t-SignedIntOverflowTest-Ubsan
+RUN: not %t-SignedIntOverflowTest-Ubsan 2>&1 | FileCheck %s
+CHECK: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
+CHECK: Test unit written to ./crash-
+
diff --git a/test/fuzzer/fuzzer.test b/test/fuzzer/fuzzer.test
new file mode 100644
index 0000000000000..29bc8f0ce795f
--- /dev/null
+++ b/test/fuzzer/fuzzer.test
@@ -0,0 +1,70 @@
+CHECK: BINGO
+Done1000000: Done 1000000 runs in
+RUN: %cpp_compiler %S/BogusInitializeTest.cpp -o %t-BogusInitializeTest
+RUN: %cpp_compiler %S/BufferOverflowOnInput.cpp -o %t-BufferOverflowOnInput
+RUN: %cpp_compiler %S/CounterTest.cpp -o %t-CounterTest
+RUN: %cpp_compiler %S/DSO1.cpp -fPIC -shared -o %t-DSO1.so
+RUN: %cpp_compiler %S/DSO2.cpp -fPIC -shared -o %t-DSO2.so
+RUN: %cpp_compiler %S/DSOTestMain.cpp %S/DSOTestExtra.cpp -L. %t-DSO1.so %t-DSO2.so -o %t-DSOTest
+RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t-FullCoverageSetTest
+RUN: %cpp_compiler %S/InitializeTest.cpp -o %t-InitializeTest
+RUN: %cpp_compiler %S/NotinstrumentedTest.cpp -fsanitize-coverage=0 -o %t-NotinstrumentedTest-NoCoverage
+RUN: %cpp_compiler %S/NullDerefOnEmptyTest.cpp -o %t-NullDerefOnEmptyTest
+RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest
+RUN: %cpp_compiler %S/SimpleCmpTest.cpp -o %t-SimpleCmpTest
+RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest
+RUN: %cpp_compiler %S/StrncmpOOBTest.cpp -o %t-StrncmpOOBTest
+
+RUN: not %t-SimpleTest 2>&1 | FileCheck %s
+
+# only_ascii mode. Will perform some minimal self-validation.
+RUN: not %t-SimpleTest -only_ascii=1 2>&1
+
+RUN: %t-SimpleCmpTest -max_total_time=1 -use_cmp=0 2>&1 | FileCheck %s --check-prefix=MaxTotalTime
+MaxTotalTime: Done {{.*}} runs in {{.}} second(s)
+
+RUN: not %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=NullDerefTest
+RUN: not %t-NullDerefTest -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=NullDerefTest
+NullDerefTest: ERROR: AddressSanitizer: {{SEGV|access-violation}} on unknown address
+NullDerefTest: Test unit written to ./crash-
+RUN: not %t-NullDerefTest -artifact_prefix=ZZZ 2>&1 | FileCheck %s --check-prefix=NullDerefTestPrefix
+NullDerefTestPrefix: Test unit written to ZZZcrash-
+RUN: not %t-NullDerefTest -artifact_prefix=ZZZ -exact_artifact_path=FOOBAR 2>&1 | FileCheck %s --check-prefix=NullDerefTestExactPath
+NullDerefTestExactPath: Test unit written to FOOBAR
+
+RUN: not %t-NullDerefOnEmptyTest -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=NULL_DEREF_ON_EMPTY
+NULL_DEREF_ON_EMPTY: stat::number_of_executed_units:
+
+#not %t-FullCoverageSetTest -timeout=15 -seed=1 -mutate_depth=2 -use_full_coverage_set=1 2>&1 | FileCheck %s
+
+RUN: not %t-CounterTest -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s --check-prefix=COUNTERS
+
+COUNTERS: INITED {{.*}} {{bits:|ft:}}
+COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}}
+COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}}
+COUNTERS: BINGO
+
+# Don't run UninstrumentedTest for now since we build libFuzzer itself with asan.
+DISABLED: not %t-UninstrumentedTest-Uninstrumented 2>&1 | FileCheck %s --check-prefix=UNINSTRUMENTED
+UNINSTRUMENTED: ERROR: __sanitizer_set_death_callback is not defined. Exiting.
+
+RUN: not %t-NotinstrumentedTest-NoCoverage 2>&1 | FileCheck %s --check-prefix=NO_COVERAGE
+NO_COVERAGE: ERROR: no interesting inputs were found. Is the code instrumented for coverage? Exiting
+
+RUN: not %t-BufferOverflowOnInput 2>&1 | FileCheck %s --check-prefix=OOB
+OOB: AddressSanitizer: heap-buffer-overflow
+OOB: is located 0 bytes to the right of 3-byte region
+
+RUN: not %t-InitializeTest -use_value_profile=1 2>&1 | FileCheck %s
+
+RUN: not %t-DSOTest 2>&1 | FileCheck %s --check-prefix=DSO
+DSO: INFO: Loaded 3 modules
+DSO: BINGO
+
+RUN: env ASAN_OPTIONS=strict_string_checks=1 not %t-StrncmpOOBTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=STRNCMP
+STRNCMP: AddressSanitizer: heap-buffer-overflow
+STRNCMP-NOT: __sanitizer_weak_hook_strncmp
+STRNCMP: in LLVMFuzzerTestOneInput
+
+RUN: not %t-BogusInitializeTest 2>&1 | FileCheck %s --check-prefix=BOGUS_INITIALIZE
+BOGUS_INITIALIZE: argv[0] has been modified in LLVMFuzzerInitialize
diff --git a/test/fuzzer/gc-sections.test b/test/fuzzer/gc-sections.test
new file mode 100644
index 0000000000000..8785bb00ec1ba
--- /dev/null
+++ b/test/fuzzer/gc-sections.test
@@ -0,0 +1,13 @@
+REQUIRES: linux
+
+No gc-sections:
+RUN: %cpp_compiler %S/GcSectionsTest.cpp -o %t
+RUN: nm %t | grep UnusedFunctionShouldBeRemovedByLinker | count 1
+
+With gc-sections. Currently, we can't remove unused code.
+DISABLED: %cpp_compiler %S/GcSectionsTest.cpp -o %t -ffunction-sections -Wl,-gc-sections
+DISABLED: nm %t | grep UnusedFunctionShouldBeRemovedByLinker | count 1
+
+With gc sections, with trace-pc. Unused code is removed.
+RUN: %cpp_compiler %S/GcSectionsTest.cpp -o %t -fsanitize-coverage=0 -fsanitize-coverage=trace-pc -ffunction-sections -Wl,-gc-sections
+RUN: nm %t | not grep UnusedFunctionShouldBeRemovedByLinker
diff --git a/test/fuzzer/hi.txt b/test/fuzzer/hi.txt
new file mode 100644
index 0000000000000..2f9031f0ec7bb
--- /dev/null
+++ b/test/fuzzer/hi.txt
@@ -0,0 +1 @@
+Hi! \ No newline at end of file
diff --git a/test/fuzzer/inline-8bit-counters.test b/test/fuzzer/inline-8bit-counters.test
new file mode 100644
index 0000000000000..76ae1f537f723
--- /dev/null
+++ b/test/fuzzer/inline-8bit-counters.test
@@ -0,0 +1,4 @@
+RUN: %cpp_compiler %S/SimpleTest.cpp -fno-sanitize-coverage=trace-pc-guard -fsanitize-coverage=inline-8bit-counters -o %t-SimpleTest-Inline8bitCounters
+CHECK: INFO: Loaded 1 modules ({{.*}} inline 8-bit counters)
+CHECK: BINGO
+RUN: not %t-SimpleTest-Inline8bitCounters -runs=1000000 -seed=1 2>&1 | FileCheck %s
diff --git a/test/fuzzer/lit.cfg b/test/fuzzer/lit.cfg
new file mode 100644
index 0000000000000..0350a1ad77978
--- /dev/null
+++ b/test/fuzzer/lit.cfg
@@ -0,0 +1,79 @@
+import lit.formats
+import sys
+import os
+
+config.name = "LLVMFuzzer"
+config.test_format = lit.formats.ShTest(True)
+config.suffixes = ['.test']
+config.test_source_root = os.path.dirname(__file__)
+
+# Choose between lit's internal shell pipeline runner and a real shell. If
+# LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override.
+use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
+if use_lit_shell:
+ # 0 is external, "" is default, and everything else is internal.
+ execute_external = (use_lit_shell == "0")
+else:
+ # Otherwise we default to internal on Windows and external elsewhere, as
+ # bash on Windows is usually very slow.
+ execute_external = (not sys.platform in ['win32'])
+
+# testFormat: The test format to use to interpret tests.
+#
+# For now we require '&&' between commands, until they get globally killed and
+# the test runner updated.
+config.test_format = lit.formats.ShTest(execute_external)
+
+# LeakSanitizer is not supported on OSX right now.
+if sys.platform.startswith('darwin'):
+ lit_config.note('lsan feature unavailable')
+else:
+ lit_config.note('lsan feature available')
+ config.available_features.add('lsan')
+
+if sys.platform.startswith('win') or sys.platform.startswith('cygwin'):
+ config.available_features.add('windows')
+
+if sys.platform.startswith('darwin'):
+ config.available_features.add('darwin')
+
+if sys.platform.startswith('linux'):
+ # Note the value of ``sys.platform`` is not consistent
+ # between python 2 and 3, hence the use of ``.startswith()``.
+ lit_config.note('linux feature available')
+ config.available_features.add('linux')
+else:
+ lit_config.note('linux feature unavailable')
+
+config.substitutions.append(('%build_dir', config.cmake_binary_dir))
+libfuzzer_src_root = os.path.join(config.compiler_rt_src_root, "lib", "fuzzer")
+config.substitutions.append(('%libfuzzer_src', libfuzzer_src_root))
+
+def generate_compiler_cmd(is_cpp=True, fuzzer_enabled=True):
+ compiler_cmd = config.c_compiler
+ link_cmd = '-lc++' if 'darwin' in config.target_triple else '-lstdc++'
+ std_cmd = '-std=c++11' if is_cpp else ''
+ sanitizers = ['address']
+ if fuzzer_enabled:
+ sanitizers.append('fuzzer')
+ sanitizers_cmd = ('-fsanitize=%s' % ','.join(sanitizers))
+ isysroot_cmd = config.osx_sysroot_flag if config.osx_sysroot_flag else ''
+ include_cmd = '-I%s' % libfuzzer_src_root
+ return '%s %s %s -gline-tables-only %s %s %s' % (
+ compiler_cmd, std_cmd, link_cmd, isysroot_cmd, sanitizers_cmd, include_cmd)
+
+config.substitutions.append(('%cpp_compiler',
+ generate_compiler_cmd(is_cpp=True, fuzzer_enabled=True)
+ ))
+
+config.substitutions.append(('%c_compiler',
+ generate_compiler_cmd(is_cpp=False, fuzzer_enabled=True)
+ ))
+
+config.substitutions.append(('%no_fuzzer_cpp_compiler',
+ generate_compiler_cmd(is_cpp=True, fuzzer_enabled=False)
+ ))
+
+config.substitutions.append(('%no_fuzzer_c_compiler',
+ generate_compiler_cmd(is_cpp=False, fuzzer_enabled=False)
+ ))
diff --git a/test/fuzzer/lit.site.cfg.in b/test/fuzzer/lit.site.cfg.in
new file mode 100644
index 0000000000000..7f70c8f67d69d
--- /dev/null
+++ b/test/fuzzer/lit.site.cfg.in
@@ -0,0 +1,17 @@
+@LIT_SITE_CFG_IN_HEADER@
+
+config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@"
+
+config.cpp_compiler = "@LIBFUZZER_TEST_COMPILER@"
+config.target_flags = "@LIBFUZZER_TEST_FLAGS@"
+config.c_compiler = "@LIBFUZZER_TEST_COMPILER@"
+
+config.osx_sysroot_flag = "@OSX_SYSROOT_FLAG@"
+config.cmake_binary_dir = "@CMAKE_BINARY_DIR@"
+config.target_triple = "@TARGET_TRIPLE@"
+
+# Load common config for all compiler-rt lit tests.
+lit_config.load_config(config,
+ "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
+
+lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg")
diff --git a/test/fuzzer/max-number-of-runs.test b/test/fuzzer/max-number-of-runs.test
new file mode 100644
index 0000000000000..efe7a9c0f629f
--- /dev/null
+++ b/test/fuzzer/max-number-of-runs.test
@@ -0,0 +1,10 @@
+RUN: %cpp_compiler %S/AccumulateAllocationsTest.cpp -o %t-AccumulateAllocationsTest
+
+RUN: %t-AccumulateAllocationsTest -seed=1 -runs=2 2>&1 | FileCheck %s --check-prefix=CHECK1
+CHECK1: Done 2 runs
+
+RUN: %t-AccumulateAllocationsTest -seed=1 -runs=3 2>&1 | FileCheck %s --check-prefix=CHECK2
+CHECK2: Done 3 runs
+
+RUN: %t-AccumulateAllocationsTest -seed=1 -runs=4 2>&1 | FileCheck %s --check-prefix=CHECK3
+CHECK3: Done 4 runs
diff --git a/test/fuzzer/memcmp.test b/test/fuzzer/memcmp.test
new file mode 100644
index 0000000000000..3431a524ced5d
--- /dev/null
+++ b/test/fuzzer/memcmp.test
@@ -0,0 +1,3 @@
+RUN: %cpp_compiler %S/MemcmpTest.cpp -o %t-MemcmpTest
+RUN: not %t-MemcmpTest -seed=1 -runs=10000000 2>&1 | FileCheck %s
+CHECK: BINGO
diff --git a/test/fuzzer/memcmp64.test b/test/fuzzer/memcmp64.test
new file mode 100644
index 0000000000000..223c3bd42a7df
--- /dev/null
+++ b/test/fuzzer/memcmp64.test
@@ -0,0 +1,3 @@
+RUN: %cpp_compiler %S/Memcmp64BytesTest.cpp -o %t-Memcmp64BytesTest
+RUN: not %t-Memcmp64BytesTest -seed=1 -runs=1000000 2>&1 | FileCheck %s
+CHECK: BINGO
diff --git a/test/fuzzer/merge-control-file.test b/test/fuzzer/merge-control-file.test
new file mode 100644
index 0000000000000..2da5c4ccfb2bc
--- /dev/null
+++ b/test/fuzzer/merge-control-file.test
@@ -0,0 +1,57 @@
+RUN: mkdir -p %t
+RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t/T
+
+RUN: rm -rf %t/T0 %t/T1 %t/T2
+RUN: mkdir -p %t/T0 %t/T1 %t/T2
+RUN: echo F..... > %t/T0/1
+RUN: echo .U.... > %t/T0/2
+RUN: echo ..Z... > %t/T0/3
+
+# Test what happens if the control file is junk.
+
+RUN: echo JUNK > %t/MCF
+RUN: not %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=JUNK
+RUN: echo 3 > %t/MCF; echo 0 >> %t/MCF; echo %t/T1/1 >> %t/MCF
+RUN: not %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=JUNK
+JUNK: MERGE-OUTER: non-empty control file provided: {{.*}}MCF
+JUNK: MERGE-OUTER: bad control file, will overwrite it
+
+
+# Check valid control files
+
+RUN: rm -f %t/T1/*; cp %t/T0/* %t/T1
+RUN: echo 3 > %t/MCF; echo 0 >> %t/MCF; echo %t/T1/1 >> %t/MCF; echo %t/T1/2 >> %t/MCF; echo %t/T1/3 >> %t/MCF
+RUN: %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=OK_0
+OK_0: MERGE-OUTER: control file ok, 3 files total, first not processed file 0
+OK_0: MERGE-OUTER: 3 new files with {{.*}} new features added
+
+RUN: rm -f %t/T1/*; cp %t/T0/* %t/T1
+RUN: echo 3 > %t/MCF; echo 0 >> %t/MCF; echo %t/T1/1 >> %t/MCF; echo %t/T1/2 >> %t/MCF; echo %t/T1/3 >> %t/MCF
+RUN: %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF -save_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=SAVE_SUMMARY
+SAVE_SUMMARY: MERGE-OUTER: writing coverage summary for 3 files to {{.*}}/SUMMARY
+
+RUN: rm -f %t/T1/*; cp %t/T0/* %t/T1
+RUN: echo 3 > %t/MCF; echo 0 >> %t/MCF; echo %t/T1/1 >> %t/MCF; echo %t/T1/2 >> %t/MCF; echo %t/T1/3 >> %t/MCF
+RUN: %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF -load_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=LOAD_SUMMARY
+LOAD_SUMMARY: MERGE-OUTER: coverage summary loaded from
+
+RUN: rm -f %t/T1/*; cp %t/T0/* %t/T1
+RUN: echo 3 > %t/MCF; echo 0 >> %t/MCF; echo %t/T1/1 >> %t/MCF; echo %t/T1/2 >> %t/MCF; echo %t/T1/3 >> %t/MCF
+RUN: echo STARTED 0 1 >> %t/MCF
+RUN: echo DONE 0 11 >> %t/MCF
+RUN: echo STARTED 1 2 >> %t/MCF
+RUN: echo DONE 1 12 >> %t/MCF
+RUN: %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=OK_2
+OK_2: MERGE-OUTER: control file ok, 3 files total, first not processed file 2
+OK_2: MERGE-OUTER: 3 new files with {{.*}} new features added
+
+RUN: rm -f %t/T1/*; cp %t/T0/* %t/T1
+RUN: echo 3 > %t/MCF; echo 0 >> %t/MCF; echo %t/T1/1 >> %t/MCF; echo %t/T1/2 >> %t/MCF; echo %t/T1/3 >> %t/MCF
+RUN: echo STARTED 0 1 >> %t/MCF
+RUN: echo DONE 0 11 >> %t/MCF
+RUN: echo STARTED 1 2 >> %t/MCF
+RUN: echo DONE 1 12 >> %t/MCF
+RUN: echo STARTED 2 2 >> %t/MCF
+RUN: echo DONE 2 13 >> %t/MCF
+RUN: %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=OK_3
+OK_3: MERGE-OUTER: nothing to do, merge has been completed before
diff --git a/test/fuzzer/merge-posix.test b/test/fuzzer/merge-posix.test
new file mode 100644
index 0000000000000..e34e3a325b741
--- /dev/null
+++ b/test/fuzzer/merge-posix.test
@@ -0,0 +1,23 @@
+RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t-FullCoverageSetTest
+
+RUN: rm -rf %tmp/T1 %tmp/T2
+RUN: mkdir -p %tmp/T1 %tmp/T2
+
+RUN: echo F..... > %tmp/T1/1
+RUN: echo .U.... > %tmp/T1/2
+RUN: echo ..Z... > %tmp/T1/3
+
+RUN: echo .....F > %tmp/T2/1
+RUN: echo ....U. > %tmp/T2/2
+RUN: echo ...Z.. > %tmp/T2/3
+RUN: echo ...Z.. > %tmp/T2/4
+RUN: echo ....E. > %tmp/T2/5
+RUN: echo .....R > %tmp/T2/6
+
+# Check that we can report an error if file size exceeded
+RUN: (ulimit -f 1; not %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=SIGXFSZ)
+SIGXFSZ: ERROR: libFuzzer: file size exceeded
+
+# Check that we honor TMPDIR
+RUN: TMPDIR=DIR_DOES_NOT_EXIST not %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=TMPDIR
+TMPDIR: MERGE-OUTER: failed to write to the control file: DIR_DOES_NOT_EXIST/libFuzzerTemp
diff --git a/test/fuzzer/merge-sigusr.test b/test/fuzzer/merge-sigusr.test
new file mode 100644
index 0000000000000..efb00daa4643a
--- /dev/null
+++ b/test/fuzzer/merge-sigusr.test
@@ -0,0 +1,25 @@
+# Check that libFuzzer honors SIGUSR1/SIGUSR2
+RUN: rm -rf %t
+RUN: mkdir -p %t
+RUN: %cpp_compiler %S/SleepOneSecondTest.cpp -o %t/LFSIGUSR
+
+RUN: mkdir -p %t/C1 %t/C2
+RUN: echo a > %t/C2/a
+RUN: echo b > %t/C2/b
+RUN: echo c > %t/C2/c
+RUN: echo d > %t/C2/d
+RUN: echo e > %t/C2/e
+RUN: echo f > %t/C2/f
+RUN: echo g > %t/C2/g
+
+RUN: %t/LFSIGUSR -merge=1 -merge_control_file=%t/MCF %t/C1 %t/C2 2> %t/log & export PID=$!
+RUN: sleep 3
+RUN: pkill -SIGUSR2 -f %t/LFSIGUSR
+RUN: sleep 3
+RUN: cat %t/log | FileCheck %s
+RUN: grep C2/g %t/MCF
+RUN: grep STARTED %t/MCF
+RUN: tail -n 1 %t/MCF | grep DONE
+
+CHECK: INFO: signal received, trying to exit gracefully
+CHECK: INFO: libFuzzer: exiting as requested
diff --git a/test/fuzzer/merge-summary.test b/test/fuzzer/merge-summary.test
new file mode 100644
index 0000000000000..3e21c23ef38d7
--- /dev/null
+++ b/test/fuzzer/merge-summary.test
@@ -0,0 +1,17 @@
+RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t-FullCoverageSetTest
+
+RUN: rm -rf %t/T1 %t/T2
+RUN: mkdir -p %t/T0 %t/T1 %t/T2
+RUN: echo ...Z.. > %t/T2/1
+RUN: echo ....E. > %t/T2/2
+RUN: echo .....R > %t/T2/3
+RUN: echo F..... > %t/T2/a
+RUN: echo .U.... > %t/T2/b
+RUN: echo ..Z... > %t/T2/c
+
+RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -save_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=SAVE_SUMMARY
+SAVE_SUMMARY: MERGE-OUTER: writing coverage summary for 6 files to {{.*}}SUMMARY
+RUN: rm %t/T1/*
+RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -load_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=LOAD_SUMMARY
+LOAD_SUMMARY: MERGE-OUTER: coverage summary loaded from {{.*}}SUMMAR
+LOAD_SUMMARY: MERGE-OUTER: 0 new files with 0 new features added
diff --git a/test/fuzzer/merge.test b/test/fuzzer/merge.test
new file mode 100644
index 0000000000000..d17405595eb72
--- /dev/null
+++ b/test/fuzzer/merge.test
@@ -0,0 +1,70 @@
+CHECK: BINGO
+
+RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t-FullCoverageSetTest
+
+RUN: rm -rf %t/T0 %t/T1 %t/T2
+RUN: mkdir -p %t/T0 %t/T1 %t/T2
+RUN: echo F..... > %t/T0/1
+RUN: echo .U.... > %t/T0/2
+RUN: echo ..Z... > %t/T0/3
+
+# T1 has 3 elements, T2 is empty.
+RUN: cp %t/T0/* %t/T1/
+RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=CHECK1
+CHECK1: MERGE-OUTER: 3 files, 3 in the initial corpus
+CHECK1: MERGE-OUTER: 0 new files with 0 new features added
+
+RUN: echo ...Z.. > %t/T2/1
+RUN: echo ....E. > %t/T2/2
+RUN: echo .....R > %t/T2/3
+RUN: echo F..... > %t/T2/a
+RUN: echo .U.... > %t/T2/b
+RUN: echo ..Z... > %t/T2/c
+
+# T1 has 3 elements, T2 has 6 elements, only 3 are new.
+RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=CHECK2
+CHECK2: MERGE-OUTER: 9 files, 3 in the initial corpus
+CHECK2: MERGE-OUTER: 3 new files with 3 new features added
+
+# Now, T1 has 6 units and T2 has no new interesting units.
+RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=CHECK3
+CHECK3: MERGE-OUTER: 12 files, 6 in the initial corpus
+CHECK3: MERGE-OUTER: 0 new files with 0 new features added
+
+# Check that we respect max_len during the merge and don't crash.
+RUN: rm %t/T1/*
+RUN: cp %t/T0/* %t/T1/
+RUN: echo looooooooong > %t/T2/looooooooong
+RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -max_len=6 2>&1 | FileCheck %s --check-prefix=MAX_LEN
+MAX_LEN: MERGE-OUTER: 3 new files
+
+# Check that we respect -merge_control_file=FILE
+RUN: rm %t/T1/*
+RUN: cp %t/T0/* %t/T1/
+RUN: rm -f %t/MCF
+RUN: %t-FullCoverageSetTest -merge=1 -merge_control_file=%t/MCF %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=MCF
+RUN: grep STARTED %t/MCF
+RUN: grep DONE %t/MCF
+MCF: MERGE-INNER: using the control file {{.*}}MCF
+MCF: MERGE-OUTER: 3 new files
+
+
+# Check that merge tolerates failures.
+RUN: rm %t/T1/*
+RUN: cp %t/T0/* %t/T1/
+RUN: echo 'FUZZER' > %t/T2/FUZZER
+RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=MERGE_WITH_CRASH
+MERGE_WITH_CRASH: MERGE-OUTER: succesfull in 2 attempt(s)
+MERGE_WITH_CRASH: MERGE-OUTER: 3 new files
+
+# Check that we actually limit the size with max_len
+RUN: rm %t/T1/* %t/T2/*
+RUN: echo 'FUZZER' > %t/T2/FUZZER
+RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -max_len=5 2>&1 | FileCheck %s --check-prefix=MERGE_LEN5
+RUN: not grep FUZZER %t/T1/*
+RUN: grep FUZZE %t/T1/*
+MERGE_LEN5: MERGE-OUTER: succesfull in 1 attempt(s)
+
+RUN: rm -rf %t/T1/* %t/T2/*
+RUN: not %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=EMPTY
+EMPTY: MERGE-OUTER: zero succesfull attempts, exiting
diff --git a/test/fuzzer/minimize_crash.test b/test/fuzzer/minimize_crash.test
new file mode 100644
index 0000000000000..77ab370fa8992
--- /dev/null
+++ b/test/fuzzer/minimize_crash.test
@@ -0,0 +1,16 @@
+RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest
+RUN: %cpp_compiler %S/SingleByteInputTest.cpp -o %t-SingleByteInputTest
+
+RUN: echo 'Hi!rv349f34t3gg' > not_minimal_crash
+RUN: %t-NullDerefTest -minimize_crash=1 not_minimal_crash -max_total_time=2 2>&1 | FileCheck %s
+CHECK: CRASH_MIN: failed to minimize beyond ./minimized-from-{{.*}} (3 bytes), exiting
+RUN: %t-NullDerefTest -minimize_crash=1 not_minimal_crash -max_total_time=2 -exact_artifact_path=exact_minimized_path 2>&1 | FileCheck %s --check-prefix=CHECK_EXACT
+CHECK_EXACT: CRASH_MIN: failed to minimize beyond exact_minimized_path (3 bytes), exiting
+RUN: rm not_minimal_crash minimized-from-* exact_minimized_path
+
+RUN: echo -n 'abcd*xyz' > not_minimal_crash
+RUN: %t-SingleByteInputTest -minimize_crash=1 not_minimal_crash -exact_artifact_path=exact_minimized_path 2>&1 | FileCheck %s --check-prefix=MIN1
+MIN1: Test unit written to exact_minimized_path
+MIN1: Test unit written to exact_minimized_path
+MIN1: INFO: The input is small enough, exiting
+MIN1: CRASH_MIN: failed to minimize beyond exact_minimized_path (1 bytes), exiting
diff --git a/test/fuzzer/minimize_two_crashes.test b/test/fuzzer/minimize_two_crashes.test
new file mode 100644
index 0000000000000..e6ff9990ffd82
--- /dev/null
+++ b/test/fuzzer/minimize_two_crashes.test
@@ -0,0 +1,18 @@
+# Test that the minimizer stops when it sees a differe bug.
+
+RUN: %cpp_compiler %S/TwoDifferentBugsTest.cpp -o %t-TwoDifferentBugsTest
+
+RUN: rm -rf %t && mkdir %t
+RUN: echo H12345678901234667888090 > %t/long_crash
+RUN: env ASAN_OPTIONS=dedup_token_length=3 %t-TwoDifferentBugsTest -seed=1 -minimize_crash=1 %t/long_crash -exact_artifact_path=%t/result 2>&1 | FileCheck %s
+
+CHECK: DedupToken1: DEDUP_TOKEN: Bar
+CHECK: DedupToken2: DEDUP_TOKEN: Bar
+CHECK: DedupToken1: DEDUP_TOKEN: Bar
+CHECK: DedupToken2: DEDUP_TOKEN: Foo
+CHECK: CRASH_MIN: mismatch in dedup tokens
+
+RUN: not %t-TwoDifferentBugsTest %t/result 2>&1 | FileCheck %s --check-prefix=VERIFY
+
+VERIFY: ERROR: AddressSanitizer:
+VERIFY: in Bar
diff --git a/test/fuzzer/overwrite-input.test b/test/fuzzer/overwrite-input.test
new file mode 100644
index 0000000000000..3695622d03526
--- /dev/null
+++ b/test/fuzzer/overwrite-input.test
@@ -0,0 +1,3 @@
+RUN: %cpp_compiler %S/OverwriteInputTest.cpp -o %t-OverwriteInputTest
+RUN: not %t-OverwriteInputTest 2>&1 | FileCheck %s
+CHECK: ERROR: libFuzzer: fuzz target overwrites it's const input
diff --git a/test/fuzzer/print-func.test b/test/fuzzer/print-func.test
new file mode 100644
index 0000000000000..930e9992a2f9c
--- /dev/null
+++ b/test/fuzzer/print-func.test
@@ -0,0 +1,10 @@
+RUN: %cpp_compiler %S/PrintFuncTest.cpp -o %t
+RUN: %t -seed=1 -runs=100000 2>&1 | FileCheck %s
+RUN: %t -seed=1 -runs=100000 -print_funcs=0 2>&1 | FileCheck %s --check-prefix=NO
+CHECK: NEW_FUNC{{.*}} FunctionA
+CHECK: NEW_FUNC{{.*}} FunctionB
+CHECK: NEW_FUNC{{.*}} FunctionC
+CHECK: BINGO
+
+NO-NOT: NEW_FUNC
+NO: BINGO
diff --git a/test/fuzzer/recommended-dictionary.test b/test/fuzzer/recommended-dictionary.test
new file mode 100644
index 0000000000000..41b62c924ceb0
--- /dev/null
+++ b/test/fuzzer/recommended-dictionary.test
@@ -0,0 +1,6 @@
+RUN: %cpp_compiler %S/RepeatedMemcmp.cpp -o %t-RepeatedMemcmp
+RUN: %t-RepeatedMemcmp -seed=11 -runs=100000 -max_len=20 2>&1 | FileCheck %s --check-prefix=RECOMMENDED_DICT
+RECOMMENDED_DICT:###### Recommended dictionary. ######
+RECOMMENDED_DICT-DAG: "foo"
+RECOMMENDED_DICT-DAG: "bar"
+RECOMMENDED_DICT:###### End of recommended dictionary. ######
diff --git a/test/fuzzer/reduce_inputs.test b/test/fuzzer/reduce_inputs.test
new file mode 100644
index 0000000000000..94f8cc4f37a8f
--- /dev/null
+++ b/test/fuzzer/reduce_inputs.test
@@ -0,0 +1,16 @@
+# Test -reduce_inputs=1
+
+RUN: rm -rf %t/C
+RUN: mkdir -p %t/C
+RUN: %cpp_compiler %S/ShrinkControlFlowSimpleTest.cpp -o %t-ShrinkControlFlowSimpleTest
+RUN: %cpp_compiler %S/ShrinkControlFlowTest.cpp -o %t-ShrinkControlFlowTest
+RUN: %t-ShrinkControlFlowSimpleTest -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 %t/C 2>&1 | FileCheck %s
+CHECK: INFO: found item with checksum '0eb8e4ed029b774d80f2b66408203801cb982a60'
+
+# Test that reduce_inputs deletes redundant files in the corpus.
+RUN: %t-ShrinkControlFlowSimpleTest -runs=0 %t/C 2>&1 | FileCheck %s --check-prefix=COUNT
+COUNT: seed corpus: files: 4
+
+# a bit longer test
+RUN: %t-ShrinkControlFlowTest -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -seed=1 -runs=1000000 2>&1 | FileCheck %s
+
diff --git a/test/fuzzer/repeated-bytes.test b/test/fuzzer/repeated-bytes.test
new file mode 100644
index 0000000000000..0bba2a91688ff
--- /dev/null
+++ b/test/fuzzer/repeated-bytes.test
@@ -0,0 +1,3 @@
+RUN: %cpp_compiler %S/RepeatedBytesTest.cpp -o %t-RepeatedBytesTest
+CHECK: BINGO
+RUN: not %t-RepeatedBytesTest -seed=1 -runs=1000000 2>&1 | FileCheck %s
diff --git a/test/fuzzer/shrink.test b/test/fuzzer/shrink.test
new file mode 100644
index 0000000000000..2988d4bbb043d
--- /dev/null
+++ b/test/fuzzer/shrink.test
@@ -0,0 +1,10 @@
+RUN: %cpp_compiler %S/ShrinkControlFlowTest.cpp -o %t-ShrinkControlFlowTest
+RUN: %cpp_compiler %S/ShrinkValueProfileTest.cpp -o %t-ShrinkValueProfileTest
+RUN: %t-ShrinkControlFlowTest -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=1 -reduce_inputs=0 2>&1 | FileCheck %s --check-prefix=SHRINK1
+# Limit max_len to run this negative test faster.
+RUN: %t-ShrinkControlFlowTest -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=0 -reduce_inputs=0 -max_len=64 2>&1 | FileCheck %s --check-prefix=SHRINK0
+RUN: %t-ShrinkValueProfileTest -seed=1 -exit_on_item=aea2e3923af219a8956f626558ef32f30a914ebc -runs=100000 -shrink=1 -reduce_inputs=0 -use_value_profile=1 2>&1 | FileCheck %s --check-prefix=SHRINK1_VP
+
+SHRINK0: Done 1000000 runs in
+SHRINK1: INFO: found item with checksum '0eb8e4ed029b774d80f2b66408203801cb982a60', exiting.
+SHRINK1_VP: INFO: found item with checksum 'aea2e3923af219a8956f626558ef32f30a914ebc', exiting
diff --git a/test/fuzzer/sigusr.test b/test/fuzzer/sigusr.test
new file mode 100644
index 0000000000000..12e3ac996c6ce
--- /dev/null
+++ b/test/fuzzer/sigusr.test
@@ -0,0 +1,13 @@
+# Check that libFuzzer honors SIGUSR1/SIGUSR2
+RUN: rm -rf %t
+RUN: mkdir -p %t
+RUN: %cpp_compiler %S/SleepOneSecondTest.cpp -o %t/LFSIGUSR
+
+RUN: %t/LFSIGUSR 2> %t/log & export PID=$!
+RUN: sleep 2
+RUN: kill -SIGUSR1 $PID
+RUN: sleep 3
+RUN: cat %t/log | FileCheck %s
+
+CHECK: INFO: signal received, trying to exit gracefully
+CHECK: INFO: libFuzzer: exiting as requested
diff --git a/test/fuzzer/simple-cmp.test b/test/fuzzer/simple-cmp.test
new file mode 100644
index 0000000000000..08123ed3ac474
--- /dev/null
+++ b/test/fuzzer/simple-cmp.test
@@ -0,0 +1,3 @@
+RUN: %cpp_compiler %S/SimpleCmpTest.cpp -o %t-SimpleCmpTest
+CHECK: BINGO
+RUN: not %t-SimpleCmpTest -seed=1 -runs=100000000 2>&1 | FileCheck %s
diff --git a/test/fuzzer/standalone.test b/test/fuzzer/standalone.test
new file mode 100644
index 0000000000000..e6483703f9661
--- /dev/null
+++ b/test/fuzzer/standalone.test
@@ -0,0 +1,8 @@
+RUN: %no_fuzzer_c_compiler %libfuzzer_src/standalone/StandaloneFuzzTargetMain.c -c -o %t_1.o
+RUN: %no_fuzzer_cpp_compiler %S/InitializeTest.cpp -c -o %t_2.o
+
+RUN: %no_fuzzer_cpp_compiler %t_1.o %t_2.o -o %t-StandaloneInitializeTest
+RUN: %t-StandaloneInitializeTest %S/hi.txt %S/dict1.txt 2>&1 | FileCheck %s
+CHECK: StandaloneFuzzTargetMain: running 2 inputs
+CHECK: Done: {{.*}}hi.txt: (3 bytes)
+CHECK: Done: {{.*}}dict1.txt: (61 bytes)
diff --git a/test/fuzzer/strcmp.test b/test/fuzzer/strcmp.test
new file mode 100644
index 0000000000000..47ad8f9ba0f5b
--- /dev/null
+++ b/test/fuzzer/strcmp.test
@@ -0,0 +1,4 @@
+RUN: %cpp_compiler %S/StrcmpTest.cpp -o %t-StrcmpTest
+RUN: not %t-StrcmpTest -seed=1 -runs=2000000 2>&1 | FileCheck %s
+CHECK: BINGO
+
diff --git a/test/fuzzer/strncmp.test b/test/fuzzer/strncmp.test
new file mode 100644
index 0000000000000..49693c8de8f01
--- /dev/null
+++ b/test/fuzzer/strncmp.test
@@ -0,0 +1,4 @@
+RUN: %cpp_compiler %S/StrncmpTest.cpp -o %t-StrncmpTest
+RUN: not %t-StrncmpTest -seed=2 -runs=10000000 2>&1 | FileCheck %s
+CHECK: BINGO
+
diff --git a/test/fuzzer/strstr.test b/test/fuzzer/strstr.test
new file mode 100644
index 0000000000000..c39d5801acdba
--- /dev/null
+++ b/test/fuzzer/strstr.test
@@ -0,0 +1,4 @@
+RUN: %cpp_compiler %S/StrstrTest.cpp -o %t-StrstrTest
+RUN: not %t-StrstrTest -seed=1 -runs=2000000 2>&1 | FileCheck %s
+CHECK: BINGO
+
diff --git a/test/fuzzer/swap-cmp.test b/test/fuzzer/swap-cmp.test
new file mode 100644
index 0000000000000..5c2379cde4f6a
--- /dev/null
+++ b/test/fuzzer/swap-cmp.test
@@ -0,0 +1,3 @@
+RUN: %cpp_compiler %S/SwapCmpTest.cpp -o %t-SwapCmpTest
+CHECK: BINGO
+RUN: not %t-SwapCmpTest -seed=1 -runs=10000000 2>&1 | FileCheck %s
diff --git a/test/fuzzer/trace-malloc-2.test b/test/fuzzer/trace-malloc-2.test
new file mode 100644
index 0000000000000..56f16d7860129
--- /dev/null
+++ b/test/fuzzer/trace-malloc-2.test
@@ -0,0 +1,10 @@
+// FIXME: This test infinite loops on darwin because it crashes
+// printing a stack trace repeatedly
+UNSUPPORTED: darwin
+
+RUN: %cpp_compiler %S/TraceMallocTest.cpp -o %t-TraceMallocTest
+
+RUN: %t-TraceMallocTest -seed=1 -trace_malloc=2 -runs=1000 2>&1 | FileCheck %s --check-prefix=TRACE2
+TRACE2-DAG: FREE[0]
+TRACE2-DAG: MALLOC[0]
+TRACE2-DAG: in LLVMFuzzerTestOneInput
diff --git a/test/fuzzer/trace-malloc-threaded.test b/test/fuzzer/trace-malloc-threaded.test
new file mode 100644
index 0000000000000..11f3f049155fe
--- /dev/null
+++ b/test/fuzzer/trace-malloc-threaded.test
@@ -0,0 +1,36 @@
+// FIXME: This test infinite loops on darwin because it crashes
+// printing a stack trace repeatedly
+UNSUPPORTED: darwin
+
+RUN: %cpp_compiler %S/TraceMallocThreadedTest.cpp -o %t-TraceMallocThreadedTest
+
+RUN: %t-TraceMallocThreadedTest -trace_malloc=2 -runs=1 2>&1 | FileCheck %s
+CHECK: {{MALLOC\[[0-9]+] +0x[0-9]+ 5639}}
+CHECK-NEXT: {{ +\#0 +}}
+CHECK-NEXT: {{ +\#1 +}}
+CHECK-NEXT: {{ +\#2 +}}
+
+CHECK: {{MALLOC\[[0-9]+] +0x[0-9]+ 5639}}
+CHECK-NEXT: {{ +\#0 +}}
+CHECK-NEXT: {{ +\#1 +}}
+CHECK-NEXT: {{ +\#2 +}}
+
+CHECK: {{MALLOC\[[0-9]+] +0x[0-9]+ 5639}}
+CHECK-NEXT: {{ +\#0 +}}
+CHECK-NEXT: {{ +\#1 +}}
+CHECK-NEXT: {{ +\#2 +}}
+
+CHECK: {{MALLOC\[[0-9]+] +0x[0-9]+ 5639}}
+CHECK-NEXT: {{ +\#0 +}}
+CHECK-NEXT: {{ +\#1 +}}
+CHECK-NEXT: {{ +\#2 +}}
+
+CHECK: {{MALLOC\[[0-9]+] +0x[0-9]+ 5639}}
+CHECK-NEXT: {{ +\#0 +}}
+CHECK-NEXT: {{ +\#1 +}}
+CHECK-NEXT: {{ +\#2 +}}
+
+CHECK: {{MALLOC\[[0-9]+] +0x[0-9]+ 5639}}
+CHECK-NEXT: {{ +\#0 +}}
+CHECK-NEXT: {{ +\#1 +}}
+CHECK-NEXT: {{ +\#2 +}}
diff --git a/test/fuzzer/trace-malloc-unbalanced.test b/test/fuzzer/trace-malloc-unbalanced.test
new file mode 100644
index 0000000000000..8be5fab0ca43f
--- /dev/null
+++ b/test/fuzzer/trace-malloc-unbalanced.test
@@ -0,0 +1,27 @@
+// FIXME: This test infinite loops on darwin because it crashes
+// printing a stack trace repeatedly
+UNSUPPORTED: darwin
+
+// Verifies lib/fuzzer/scripts/unbalanced_allocs.py script
+
+RUN: %cpp_compiler %S/TraceMallocTest.cpp -o %t-TraceMallocTest
+
+RUN: %t-TraceMallocTest -seed=1 -trace_malloc=1 -runs=200 2>&1 | \
+RUN: %libfuzzer_src/scripts/unbalanced_allocs.py --skip=5 | FileCheck %s
+
+RUN: %t-TraceMallocTest -seed=1 -trace_malloc=2 -runs=200 2>&1 | \
+RUN: %libfuzzer_src/scripts/unbalanced_allocs.py --skip=5 | FileCheck %s --check-prefixes=CHECK,CHECK2
+
+CHECK: MallocFreeTracer: START
+CHECK: Unbalanced MALLOC[{{[0-9]+}}] [[PTR:0x[0-9a-f]+]] 4
+CHECK2-NEXT: {{ #0 0x[0-9a-f]+ in }}
+CHECK2-NEXT: {{ #1 0x[0-9a-f]+ in }}
+CHECK2-NEXT: {{ #2 0x[0-9a-f]+ in }}
+CHECK: MallocFreeTracer: STOP
+
+CHECK: MallocFreeTracer: START
+CHECK: Unbalanced FREE[{{[0-9]+}}] [[PTR]]
+CHECK2-NEXT: {{ #0 0x[0-9a-f]+ in }}
+CHECK2-NEXT: {{ #1 0x[0-9a-f]+ in }}
+CHECK2-NEXT: {{ #2 0x[0-9a-f]+ in }}
+CHECK: MallocFreeTracer: STOP
diff --git a/test/fuzzer/trace-malloc.test b/test/fuzzer/trace-malloc.test
new file mode 100644
index 0000000000000..979be99b7ac27
--- /dev/null
+++ b/test/fuzzer/trace-malloc.test
@@ -0,0 +1,7 @@
+RUN: %cpp_compiler %S/TraceMallocTest.cpp -o %t-TraceMallocTest
+
+RUN: %t-TraceMallocTest -seed=1 -trace_malloc=1 -runs=10000 2>&1 | FileCheck %s
+CHECK-DAG: MallocFreeTracer: STOP 0 0 (same)
+CHECK-DAG: MallocFreeTracer: STOP 0 1 (DIFFERENT)
+CHECK-DAG: MallocFreeTracer: STOP 1 0 (DIFFERENT)
+CHECK-DAG: MallocFreeTracer: STOP 1 1 (same)
diff --git a/test/fuzzer/trace-pc.test b/test/fuzzer/trace-pc.test
new file mode 100644
index 0000000000000..eaa0cb08afbed
--- /dev/null
+++ b/test/fuzzer/trace-pc.test
@@ -0,0 +1,3 @@
+RUN: %cpp_compiler %S/SimpleTest.cpp -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard -fsanitize-coverage=trace-pc -o %t-SimpleTest-TracePC
+CHECK: BINGO
+RUN: not %t-SimpleTest-TracePC -runs=1000000 -seed=1 2>&1 | FileCheck %s
diff --git a/test/fuzzer/ulimit.test b/test/fuzzer/ulimit.test
new file mode 100644
index 0000000000000..8772caa2d4c35
--- /dev/null
+++ b/test/fuzzer/ulimit.test
@@ -0,0 +1,3 @@
+RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest
+RUN: ulimit -s 1000
+RUN: not %t-SimpleTest
diff --git a/test/fuzzer/unit/lit.site.cfg.in b/test/fuzzer/unit/lit.site.cfg.in
new file mode 100644
index 0000000000000..bab2824e442b6
--- /dev/null
+++ b/test/fuzzer/unit/lit.site.cfg.in
@@ -0,0 +1,9 @@
+@LIT_SITE_CFG_IN_HEADER@
+
+config.name = "LLVMFuzzer-Unittest"
+# Load common config for all compiler-rt unit tests.
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/unittests/lit.common.unit.configured")
+
+config.test_exec_root = os.path.join("@COMPILER_RT_BINARY_DIR@",
+ "lib", "fuzzer", "tests")
+config.test_source_root = config.test_exec_root
diff --git a/test/fuzzer/value-profile-cmp.test b/test/fuzzer/value-profile-cmp.test
new file mode 100644
index 0000000000000..64244297c64a0
--- /dev/null
+++ b/test/fuzzer/value-profile-cmp.test
@@ -0,0 +1,3 @@
+CHECK: BINGO
+RUN: %cpp_compiler %S/SimpleCmpTest.cpp -o %t-SimpleCmpTest
+RUN: not %t-SimpleCmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s
diff --git a/test/fuzzer/value-profile-cmp2.test b/test/fuzzer/value-profile-cmp2.test
new file mode 100644
index 0000000000000..a585c9317fab3
--- /dev/null
+++ b/test/fuzzer/value-profile-cmp2.test
@@ -0,0 +1,3 @@
+CHECK: BINGO
+RUN: %cpp_compiler -fno-sanitize=address %S/SimpleHashTest.cpp -o %t-SimpleHashTest
+RUN: not %t-SimpleHashTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 -max_len=64 2>&1 | FileCheck %s
diff --git a/test/fuzzer/value-profile-cmp3.test b/test/fuzzer/value-profile-cmp3.test
new file mode 100644
index 0000000000000..d2284750b51ed
--- /dev/null
+++ b/test/fuzzer/value-profile-cmp3.test
@@ -0,0 +1,3 @@
+CHECK: BINGO
+RUN: %cpp_compiler %S/AbsNegAndConstantTest.cpp -o %t-AbsNegAndConstantTest
+RUN: not %t-AbsNegAndConstantTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s
diff --git a/test/fuzzer/value-profile-cmp4.test b/test/fuzzer/value-profile-cmp4.test
new file mode 100644
index 0000000000000..bcbc67b1801fa
--- /dev/null
+++ b/test/fuzzer/value-profile-cmp4.test
@@ -0,0 +1,3 @@
+CHECK: BINGO
+RUN: %cpp_compiler %S/AbsNegAndConstant64Test.cpp -o %t-AbsNegAndConstant64Test
+RUN: not %t-AbsNegAndConstant64Test -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s
diff --git a/test/fuzzer/value-profile-div.test b/test/fuzzer/value-profile-div.test
new file mode 100644
index 0000000000000..8711a25466e57
--- /dev/null
+++ b/test/fuzzer/value-profile-div.test
@@ -0,0 +1,4 @@
+CHECK: AddressSanitizer: {{FPE|int-divide-by-zero}}
+RUN: %cpp_compiler %S/DivTest.cpp -fsanitize-coverage=trace-div -o %t-DivTest
+RUN: not %t-DivTest -seed=1 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s
+
diff --git a/test/fuzzer/value-profile-load.test b/test/fuzzer/value-profile-load.test
new file mode 100644
index 0000000000000..3bf2a658a5b29
--- /dev/null
+++ b/test/fuzzer/value-profile-load.test
@@ -0,0 +1,3 @@
+CHECK: AddressSanitizer: global-buffer-overflow
+RUN: %cpp_compiler %S/LoadTest.cpp -fsanitize-coverage=trace-pc-guard,indirect-calls,trace-gep,trace-div,trace-cmp -o %t-LoadTest
+RUN: not %t-LoadTest -seed=2 -use_cmp=0 -use_value_profile=1 -runs=20000000 2>&1 | FileCheck %s
diff --git a/test/fuzzer/value-profile-mem.test b/test/fuzzer/value-profile-mem.test
new file mode 100644
index 0000000000000..0b0c21d689ce0
--- /dev/null
+++ b/test/fuzzer/value-profile-mem.test
@@ -0,0 +1,3 @@
+CHECK: BINGO
+RUN: %cpp_compiler %S/SingleMemcmpTest.cpp -o %t-SingleMemcmpTest
+RUN: not %t-SingleMemcmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s
diff --git a/test/fuzzer/value-profile-set.test b/test/fuzzer/value-profile-set.test
new file mode 100644
index 0000000000000..e2e3fb47f3ad0
--- /dev/null
+++ b/test/fuzzer/value-profile-set.test
@@ -0,0 +1,4 @@
+CHECK: BINGO
+RUN: %cpp_compiler %S/FourIndependentBranchesTest.cpp -o %t-FourIndependentBranchesTest
+RUN: not %t-FourIndependentBranchesTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s
+
diff --git a/test/fuzzer/value-profile-strcmp.test b/test/fuzzer/value-profile-strcmp.test
new file mode 100644
index 0000000000000..f5c766a658f45
--- /dev/null
+++ b/test/fuzzer/value-profile-strcmp.test
@@ -0,0 +1,3 @@
+CHECK: BINGO
+RUN: %cpp_compiler %S/SingleStrcmpTest.cpp -o %t-SingleStrcmpTest
+RUN: not %t-SingleStrcmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s
diff --git a/test/fuzzer/value-profile-strncmp.test b/test/fuzzer/value-profile-strncmp.test
new file mode 100644
index 0000000000000..2dfe43c4abc5e
--- /dev/null
+++ b/test/fuzzer/value-profile-strncmp.test
@@ -0,0 +1,3 @@
+CHECK: BINGO
+RUN: %cpp_compiler %S/SingleStrncmpTest.cpp -o %t-SingleStrncmpTest
+RUN: not %t-SingleStrncmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s
diff --git a/test/fuzzer/value-profile-switch.test b/test/fuzzer/value-profile-switch.test
new file mode 100644
index 0000000000000..7edb312a07b07
--- /dev/null
+++ b/test/fuzzer/value-profile-switch.test
@@ -0,0 +1,5 @@
+CHECK: BINGO
+RUN: %cpp_compiler %S/SwitchTest.cpp -o %t-SwitchTest
+RUN: %cpp_compiler %S/Switch2Test.cpp -o %t-Switch2Test
+RUN: not %t-SwitchTest -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s
+RUN: not %t-Switch2Test -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s
diff --git a/test/hwasan/CMakeLists.txt b/test/hwasan/CMakeLists.txt
new file mode 100644
index 0000000000000..972c73250cf3a
--- /dev/null
+++ b/test/hwasan/CMakeLists.txt
@@ -0,0 +1,29 @@
+set(HWASAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+
+set(HWASAN_TESTSUITES)
+
+set(HWASAN_TEST_ARCH ${HWASAN_SUPPORTED_ARCH})
+
+foreach(arch ${HWASAN_TEST_ARCH})
+ set(HWASAN_TEST_TARGET_ARCH ${arch})
+ string(TOLOWER "-${arch}" HWASAN_TEST_CONFIG_SUFFIX)
+ get_test_cc_for_arch(${arch} HWASAN_TEST_TARGET_CC HWASAN_TEST_TARGET_CFLAGS)
+ string(TOUPPER ${arch} ARCH_UPPER_CASE)
+ set(CONFIG_NAME ${ARCH_UPPER_CASE})
+
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
+ list(APPEND HWASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+endforeach()
+
+set(HWASAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+if(NOT COMPILER_RT_STANDALONE_BUILD)
+ list(APPEND HWASAN_TEST_DEPS hwasan)
+endif()
+
+add_lit_testsuite(check-hwasan "Running the HWAddressSanitizer tests"
+ ${HWASAN_TESTSUITES}
+ DEPENDS ${HWASAN_TEST_DEPS}
+ )
+set_target_properties(check-hwasan PROPERTIES FOLDER "Compiler-RT Misc")
diff --git a/test/hwasan/TestCases/halt-on-error.cc b/test/hwasan/TestCases/halt-on-error.cc
new file mode 100644
index 0000000000000..97693d5bceba8
--- /dev/null
+++ b/test/hwasan/TestCases/halt-on-error.cc
@@ -0,0 +1,26 @@
+// RUN: %clangxx_hwasan -O0 %s -o %t && not %env_hwasan_opts=halt_on_error=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// REQUIRES: stable-runtime
+
+#include <stdlib.h>
+#include <sanitizer/hwasan_interface.h>
+
+int main() {
+ __hwasan_enable_allocator_tagging();
+ int* volatile x = (int*)malloc(16);
+ free(x);
+ __hwasan_disable_allocator_tagging();
+ return x[2] + ((char *)x)[6] + ((char *)x)[9];
+ // CHECK: READ of size 4 at
+ // CHECK: #0 {{.*}} in main {{.*}}halt-on-error.cc:12
+ // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main
+
+ // CHECK: READ of size 1 at
+ // CHECK: #0 {{.*}} in main {{.*}}halt-on-error.cc:12
+ // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main
+
+ // CHECK: READ of size 1 at
+ // CHECK: #0 {{.*}} in main {{.*}}halt-on-error.cc:12
+ // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main
+
+ // CHECK-NOT: tag-mismatch
+}
diff --git a/test/hwasan/TestCases/use-after-free.cc b/test/hwasan/TestCases/use-after-free.cc
new file mode 100644
index 0000000000000..a4d3ee89509fd
--- /dev/null
+++ b/test/hwasan/TestCases/use-after-free.cc
@@ -0,0 +1,28 @@
+// RUN: %clangxx_hwasan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_hwasan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_hwasan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_hwasan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// REQUIRES: stable-runtime
+
+#include <stdlib.h>
+#include <sanitizer/hwasan_interface.h>
+
+int main() {
+ __hwasan_enable_allocator_tagging();
+ char *x = (char*)malloc(10);
+ free(x);
+ __hwasan_disable_allocator_tagging();
+ return x[5];
+ // CHECK: READ of size 1 at
+ // CHECK: #0 {{.*}} in main {{.*}}use-after-free.cc:15
+
+ // CHECK: freed here:
+ // CHECK: #0 {{.*}} in free {{.*}}hwasan_interceptors.cc
+ // CHECK: #1 {{.*}} in main {{.*}}use-after-free.cc:13
+
+ // CHECK: previously allocated here:
+ // CHECK: #0 {{.*}} in __interceptor_malloc {{.*}}hwasan_interceptors.cc
+ // CHECK: #1 {{.*}} in main {{.*}}use-after-free.cc:12
+
+ // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main
+}
diff --git a/test/hwasan/lit.cfg b/test/hwasan/lit.cfg
new file mode 100644
index 0000000000000..4f099af5b7fce
--- /dev/null
+++ b/test/hwasan/lit.cfg
@@ -0,0 +1,32 @@
+# -*- Python -*-
+
+import os
+
+# Setup config name.
+config.name = 'HWAddressSanitizer' + getattr(config, 'name_suffix', 'default')
+
+# Setup source root.
+config.test_source_root = os.path.dirname(__file__)
+
+# Setup default compiler flags used with -fsanitize=memory option.
+clang_hwasan_cflags = ["-fsanitize=hwaddress", config.target_cflags] + config.debug_info_flags
+clang_hwasan_cxxflags = config.cxx_mode_flags + clang_hwasan_cflags
+
+def build_invocation(compile_flags):
+ return " " + " ".join([config.clang] + compile_flags) + " "
+
+config.substitutions.append( ("%clang_hwasan ", build_invocation(clang_hwasan_cflags)) )
+config.substitutions.append( ("%clangxx_hwasan ", build_invocation(clang_hwasan_cxxflags)) )
+
+default_hwasan_opts_str = ':'.join(['disable_allocator_tagging=1'] + config.default_sanitizer_opts)
+if default_hwasan_opts_str:
+ config.environment['HWASAN_OPTIONS'] = default_hwasan_opts_str
+ default_hwasan_opts_str += ':'
+config.substitutions.append(('%env_hwasan_opts=',
+ 'env HWASAN_OPTIONS=' + default_hwasan_opts_str))
+
+# Default test suffixes.
+config.suffixes = ['.c', '.cc', '.cpp']
+
+if config.host_os not in ['Linux', 'Android']:
+ config.unsupported = True
diff --git a/test/hwasan/lit.site.cfg.in b/test/hwasan/lit.site.cfg.in
new file mode 100644
index 0000000000000..7453d1b74dc03
--- /dev/null
+++ b/test/hwasan/lit.site.cfg.in
@@ -0,0 +1,12 @@
+@LIT_SITE_CFG_IN_HEADER@
+
+# Tool-specific config options.
+config.name_suffix = "@HWASAN_TEST_CONFIG_SUFFIX@"
+config.target_cflags = "@HWASAN_TEST_TARGET_CFLAGS@"
+config.target_arch = "@HWASAN_TEST_TARGET_ARCH@"
+
+# Load common config for all compiler-rt lit tests.
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
+
+# Load tool-specific config that would do the real work.
+lit_config.load_config(config, "@HWASAN_LIT_SOURCE_DIR@/lit.cfg")
diff --git a/test/lit.common.cfg b/test/lit.common.cfg
index 6080edca4fbf9..0840f65a71615 100644
--- a/test/lit.common.cfg
+++ b/test/lit.common.cfg
@@ -11,7 +11,6 @@ import subprocess
import lit.formats
import lit.util
-
# Choose between lit's internal shell pipeline runner and a real shell. If
# LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override.
use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
@@ -28,11 +27,6 @@ config.test_format = lit.formats.ShTest(execute_external)
if execute_external:
config.available_features.add('shell')
-# Setup clang binary.
-compiler_path = getattr(config, 'clang', None)
-if (not compiler_path) or (not os.path.exists(compiler_path)):
- lit_config.fatal("Can't find compiler on path %r" % compiler_path)
-
compiler_id = getattr(config, 'compiler_id', None)
if compiler_id == "Clang":
if platform.system() != 'Windows':
@@ -52,6 +46,15 @@ else:
# Add compiler ID to the list of available features.
config.available_features.add(compiler_id)
+# If needed, add cflag for shadow scale.
+if config.asan_shadow_scale != '':
+ config.target_cflags += " -mllvm -asan-mapping-scale=" + config.asan_shadow_scale
+
+# BFD linker in 64-bit android toolchains fails to find libm.so, which is a
+# transitive shared library dependency (via asan runtime).
+if config.android:
+ config.target_cflags += " -pie -fuse-ld=gold -Wl,--enable-new-dtags"
+
# Clear some environment variables that might affect Clang.
possibly_dangerous_env_vars = ['ASAN_OPTIONS', 'DFSAN_OPTIONS', 'LSAN_OPTIONS',
'MSAN_OPTIONS', 'UBSAN_OPTIONS',
@@ -73,10 +76,9 @@ for name in possibly_dangerous_env_vars:
del config.environment[name]
# Tweak PATH to include llvm tools dir.
-llvm_tools_dir = getattr(config, 'llvm_tools_dir', None)
-if (not llvm_tools_dir) or (not os.path.exists(llvm_tools_dir)):
- lit_config.fatal("Invalid llvm_tools_dir config attribute: %r" % llvm_tools_dir)
-path = os.path.pathsep.join((llvm_tools_dir, config.environment['PATH']))
+if (not config.llvm_tools_dir) or (not os.path.exists(config.llvm_tools_dir)):
+ lit_config.fatal("Invalid llvm_tools_dir config attribute: %r" % config.llvm_tools_dir)
+path = os.path.pathsep.join((config.llvm_tools_dir, config.environment['PATH']))
config.environment['PATH'] = path
# Help MSVS link.exe find the standard libraries.
@@ -100,7 +102,6 @@ if config.emulator:
config.compile_wrapper = ""
elif config.ios:
config.available_features.add('ios')
-
device_id_env = "SANITIZER_IOSSIM_TEST_DEVICE_IDENTIFIER" if config.iossim else "SANITIZER_IOS_TEST_DEVICE_IDENTIFIER"
if device_id_env in os.environ: config.environment[device_id_env] = os.environ[device_id_env]
ios_commands_dir = os.path.join(config.compiler_rt_src_root, "test", "sanitizer_common", "ios_commands")
@@ -110,6 +111,12 @@ elif config.ios:
config.substitutions.append(('%env ', env_wrapper + " "))
compile_wrapper = os.path.join(ios_commands_dir, "iossim_compile.py" if config.iossim else "ios_compile.py")
config.compile_wrapper = compile_wrapper
+elif config.android:
+ config.available_features.add('android')
+ compile_wrapper = os.path.join(config.compiler_rt_src_root, "test", "sanitizer_common", "android_commands", "android_compile.py") + " "
+ config.compile_wrapper = compile_wrapper
+ config.substitutions.append( ('%run', "") )
+ config.substitutions.append( ('%env ', "env ") )
else:
config.substitutions.append( ('%run', "") )
config.substitutions.append( ('%env ', "env ") )
@@ -135,7 +142,7 @@ config.substitutions.append( ("%expect_crash ", config.expect_crash) )
target_arch = getattr(config, 'target_arch', None)
if target_arch:
config.available_features.add(target_arch + '-target-arch')
- if target_arch in ['x86_64', 'i386', 'i686']:
+ if target_arch in ['x86_64', 'i386']:
config.available_features.add('x86-target-arch')
config.available_features.add(target_arch + '-' + config.host_os.lower())
@@ -193,7 +200,20 @@ if config.host_os == 'Darwin':
else:
config.substitutions.append( ("%macos_min_target_10_11", "") )
-sancovcc_path = os.path.join(llvm_tools_dir, "sancov")
+if config.android:
+ adb = os.environ.get('ADB', 'adb')
+ try:
+ android_api_level_str = subprocess.check_output([adb, "shell", "getprop", "ro.build.version.sdk"]).rstrip()
+ except (subprocess.CalledProcessError, OSError):
+ lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb)" % adb)
+ try:
+ android_api_level = int(android_api_level_str)
+ except ValueError:
+ lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb): got '%s'" % (adb, android_api_level_str))
+ if android_api_level >= 26:
+ config.available_features.add('android-26')
+
+sancovcc_path = os.path.join(config.llvm_tools_dir, "sancov")
if os.path.exists(sancovcc_path):
config.available_features.add("has_sancovcc")
config.substitutions.append( ("%sancovcc ", sancovcc_path) )
@@ -234,8 +254,7 @@ elif config.host_os == 'Linux' and is_linux_lto_supported():
elif config.host_os == 'Windows' and is_windows_lto_supported():
config.lto_supported = True
config.lto_launch = []
- # FIXME: Remove -nopdb when PDB writing is ready.
- config.lto_flags = ["-fuse-ld=lld -Wl,-nopdb"]
+ config.lto_flags = ["-fuse-ld=lld"]
else:
config.lto_supported = False
@@ -254,7 +273,7 @@ try:
stdout = subprocess.PIPE,
env=config.environment)
except OSError:
- print("Could not find llvm-config in " + llvm_tools_dir)
+ print("Could not find llvm-config in " + config.llvm_tools_dir)
exit(42)
if re.search(r'ON', llvm_config_cmd.stdout.read().decode('ascii')):
@@ -271,3 +290,56 @@ if platform.system() == 'Windows':
# of large mmap'd regions (terabytes) by the kernel.
if platform.system() == 'Darwin':
lit_config.parallelism_groups["darwin-64bit-sanitizer"] = 3
+
+if config.host_os == 'Darwin':
+ config.substitutions.append( ("%ld_flags_rpath_exe", '-Wl,-rpath,@executable_path/ %dynamiclib') )
+ config.substitutions.append( ("%ld_flags_rpath_so", '-install_name @rpath/`basename %dynamiclib`') )
+elif config.host_os == 'FreeBSD':
+ config.substitutions.append( ("%ld_flags_rpath_exe", "-Wl,-z,origin -Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec") )
+ config.substitutions.append( ("%ld_flags_rpath_so", '') )
+elif config.host_os == 'Linux':
+ config.substitutions.append( ("%ld_flags_rpath_exe", "-Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec") )
+ config.substitutions.append( ("%ld_flags_rpath_so", '') )
+
+# Must be defined after the substitutions that use %dynamiclib.
+config.substitutions.append( ("%dynamiclib", '%T/%xdynamiclib_filename') )
+config.substitutions.append( ("%xdynamiclib_filename", 'lib%xdynamiclib_namespec.so') )
+config.substitutions.append( ("%xdynamiclib_namespec", '%basename_t.dynamic') )
+
+config.default_sanitizer_opts = []
+if config.host_os == 'Darwin':
+ # On Darwin, we default to `abort_on_error=1`, which would make tests run
+ # much slower. Let's override this and run lit tests with 'abort_on_error=0'.
+ config.default_sanitizer_opts += ['abort_on_error=0']
+ config.default_sanitizer_opts += ['log_to_syslog=0']
+elif config.android:
+ config.default_sanitizer_opts += ['abort_on_error=0']
+
+# Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL
+# because the test hangs or fails on one configuration and not the other.
+if config.android or (config.target_arch not in ['arm', 'armhf', 'aarch64']):
+ config.available_features.add('stable-runtime')
+
+if config.asan_shadow_scale:
+ config.available_features.add("shadow-scale-%s" % config.asan_shadow_scale)
+else:
+ config.available_features.add("shadow-scale-3")
+
+# Propagate the LLD/LTO into the clang config option, so nothing else is needed.
+run_wrapper = []
+target_cflags = [getattr(config, 'target_cflags', None)]
+extra_cflags = []
+
+if config.use_lto and config.lto_supported:
+ run_wrapper += config.lto_launch
+ extra_cflags += config.lto_flags
+elif config.use_lto and (not config.lto_supported):
+ config.unsupported = True
+
+if config.use_lld and config.has_lld and not config.use_lto:
+ extra_cflags += ["-fuse-ld=lld"]
+elif config.use_lld and (not config.has_lld):
+ config.unsupported = True
+
+config.clang = " " + " ".join(run_wrapper + [config.compile_wrapper, config.clang]) + " "
+config.target_cflags = " " + " ".join(target_cflags + extra_cflags) + " "
diff --git a/test/lit.common.configured.in b/test/lit.common.configured.in
index dc3081d6a53b5..32a88200bf2db 100644
--- a/test/lit.common.configured.in
+++ b/test/lit.common.configured.in
@@ -16,15 +16,16 @@ set_default("llvm_src_root", "@LLVM_MAIN_SRC_DIR@")
set_default("llvm_obj_root", "@LLVM_BINARY_DIR@")
set_default("compiler_rt_src_root", "@COMPILER_RT_SOURCE_DIR@")
set_default("compiler_rt_obj_root", "@COMPILER_RT_BINARY_DIR@")
-set_default("llvm_tools_dir", "@LLVM_TOOLS_BINARY_DIR@")
+set_default("llvm_tools_dir", "@LLVM_TOOLS_DIR@")
set_default("llvm_shlib_dir", "@LLVM_LIBRARY_OUTPUT_INTDIR@")
set_default("gold_executable", "@GOLD_EXECUTABLE@")
-set_default("clang", "@COMPILER_RT_TEST_COMPILER@")
+set_default("clang", "@COMPILER_RT_RESOLVED_TEST_COMPILER@")
set_default("compiler_id", "@COMPILER_RT_TEST_COMPILER_ID@")
set_default("python_executable", "@PYTHON_EXECUTABLE@")
set_default("compiler_rt_debug", @COMPILER_RT_DEBUG_PYBOOL@)
-set_default("compiler_rt_libdir", "@COMPILER_RT_LIBRARY_OUTPUT_DIR@")
+set_default("compiler_rt_libdir", "@COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR@")
set_default("emulator", "@COMPILER_RT_EMULATOR@")
+set_default("asan_shadow_scale", "@COMPILER_RT_ASAN_SHADOW_SCALE@")
set_default("ios", False)
set_default("iossim", False)
set_default("sanitizer_can_use_cxxabi", @SANITIZER_CAN_USE_CXXABI_PYBOOL@)
@@ -32,15 +33,22 @@ set_default("has_lld", @COMPILER_RT_HAS_LLD_PYBOOL@)
set_default("can_symbolize", @CAN_SYMBOLIZE@)
set_default("use_lld", False)
set_default("use_thinlto", False)
+set_default("use_lto", config.use_thinlto)
+set_default("android", @ANDROID_PYBOOL@)
config.available_features.add('target-is-%s' % config.target_arch)
# LLVM tools dir can be passed in lit parameters, so try to
# apply substitution.
try:
config.llvm_tools_dir = config.llvm_tools_dir % lit_config.params
+ config.clang = config.clang % lit_config.params
+ config.compiler_rt_libdir = config.compiler_rt_libdir % lit_config.params
except KeyError as e:
key, = e.args
lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key, key))
+if not os.path.exists(config.clang):
+ lit_config.fatal("Can't find compiler on path %r" % config.clang)
+
# Setup attributes common for all compiler-rt projects.
lit_config.load_config(config, "@COMPILER_RT_SOURCE_DIR@/test/lit.common.cfg")
diff --git a/test/lsan/TestCases/Linux/use_tls_dynamic.cc b/test/lsan/TestCases/Linux/use_tls_dynamic.cc
index d60dec08fb2f7..f5df231ba9a6b 100644
--- a/test/lsan/TestCases/Linux/use_tls_dynamic.cc
+++ b/test/lsan/TestCases/Linux/use_tls_dynamic.cc
@@ -5,7 +5,7 @@
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s
// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t 2>&1
// RUN: %env_lsan_opts="" %run %t 2>&1
-// UNSUPPORTED: i386-linux,i686-linux,arm
+// UNSUPPORTED: i386-linux,arm
#ifndef BUILD_DSO
#include <assert.h>
diff --git a/test/lsan/TestCases/default_options.cc b/test/lsan/TestCases/default_options.cc
new file mode 100644
index 0000000000000..b5361c0cf7a1a
--- /dev/null
+++ b/test/lsan/TestCases/default_options.cc
@@ -0,0 +1,11 @@
+// RUN: %clangxx_lsan -O2 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+extern "C"
+const char *__lsan_default_options() {
+ // CHECK: Available flags for {{Leak|Address}}Sanitizer:
+ return "verbosity=1 help=1";
+}
+
+int main() {
+ return 0;
+}
diff --git a/test/lsan/TestCases/link_turned_off.cc b/test/lsan/TestCases/link_turned_off.cc
index fd11272ceae33..7e1b33e7a1c48 100644
--- a/test/lsan/TestCases/link_turned_off.cc
+++ b/test/lsan/TestCases/link_turned_off.cc
@@ -11,7 +11,7 @@
int argc_copy;
extern "C" {
-int __lsan_is_turned_off() {
+int __attribute__((used)) __lsan_is_turned_off() {
return (argc_copy == 1);
}
}
diff --git a/test/lsan/TestCases/stale_stack_leak.cc b/test/lsan/TestCases/stale_stack_leak.cc
index 635d73814272b..8c34958545e6e 100644
--- a/test/lsan/TestCases/stale_stack_leak.cc
+++ b/test/lsan/TestCases/stale_stack_leak.cc
@@ -5,7 +5,7 @@
// RUN: %env_lsan_opts=$LSAN_BASE":exitcode=0" %run %t 2>&1 | FileCheck --check-prefix=CHECK-sanity %s
//
// x86 passes parameters through stack that may lead to false negatives
-// UNSUPPORTED: x86
+// UNSUPPORTED: x86,powerpc64
#include <stdio.h>
#include <stdlib.h>
diff --git a/test/lsan/TestCases/swapcontext.cc b/test/lsan/TestCases/swapcontext.cc
index f46897a97c27f..9774f6ce4bc97 100644
--- a/test/lsan/TestCases/swapcontext.cc
+++ b/test/lsan/TestCases/swapcontext.cc
@@ -4,7 +4,7 @@
// RUN: %clangxx_lsan %s -o %t
// RUN: %env_lsan_opts= %run %t 2>&1
// RUN: %env_lsan_opts= not %run %t foo 2>&1 | FileCheck %s
-// UNSUPPORTED: arm
+// UNSUPPORTED: arm,powerpc64
#include <stdio.h>
#if defined(__APPLE__)
diff --git a/test/lsan/TestCases/use_registers.cc b/test/lsan/TestCases/use_registers.cc
index 5d5ede5cec898..edcf1ae1631e8 100644
--- a/test/lsan/TestCases/use_registers.cc
+++ b/test/lsan/TestCases/use_registers.cc
@@ -38,6 +38,11 @@ void *registers_thread_func(void *arg) {
:
: "r" (p)
);
+#elif defined(__powerpc__)
+ asm ( "mr 30, %0"
+ :
+ : "r" (p)
+ );
#else
#error "Test is not supported on this architecture."
#endif
diff --git a/test/lsan/lit.common.cfg b/test/lsan/lit.common.cfg
index 610b1b1ad958f..a5df951e2e04b 100644
--- a/test/lsan/lit.common.cfg
+++ b/test/lsan/lit.common.cfg
@@ -68,7 +68,7 @@ config.substitutions.append( ("%clang_lsan ", build_invocation(clang_lsan_cflags
config.substitutions.append( ("%clangxx_lsan ", build_invocation(clang_lsan_cxxflags)) )
# LeakSanitizer tests are currently supported on x86-64 Linux, PowerPC64 Linux, arm Linux, mips64 Linux, and x86_64 Darwin.
-supported_linux = config.host_os is 'Linux' and config.host_arch in ['x86_64', 'ppc64', 'mips64', 'arm', 'armhf', 'armv7l']
+supported_linux = config.host_os is 'Linux' and config.host_arch in ['x86_64', 'ppc64', 'ppc64le', 'mips64', 'arm', 'armhf', 'armv7l']
supported_darwin = config.host_os is 'Darwin' and config.target_arch is 'x86_64'
if not (supported_linux or supported_darwin):
config.unsupported = True
diff --git a/test/msan/CMakeLists.txt b/test/msan/CMakeLists.txt
index 171bcb9618ffe..7919a6cd2ea03 100644
--- a/test/msan/CMakeLists.txt
+++ b/test/msan/CMakeLists.txt
@@ -1,31 +1,49 @@
set(MSAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(MSAN_TESTSUITES)
+set(MSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
set(MSAN_TEST_ARCH ${MSAN_SUPPORTED_ARCH})
if(APPLE)
darwin_filter_host_archs(MSAN_SUPPORTED_ARCH MSAN_TEST_ARCH)
endif()
-foreach(arch ${MSAN_TEST_ARCH})
+macro(add_msan_testsuite arch lld thinlto)
set(MSAN_TEST_TARGET_ARCH ${arch})
- string(TOLOWER "-${arch}" MSAN_TEST_CONFIG_SUFFIX)
get_test_cc_for_arch(${arch} MSAN_TEST_TARGET_CC MSAN_TEST_TARGET_CFLAGS)
- string(TOUPPER ${arch} ARCH_UPPER_CASE)
- set(CONFIG_NAME ${ARCH_UPPER_CASE}Config)
+
+ string(TOUPPER ${arch} CONFIG_NAME)
+
+ if (${thinlto})
+ set(CONFIG_NAME "thinlto-${CONFIG_NAME}")
+ list(APPEND MSAN_TEST_DEPS LTO)
+ endif()
+ if (${lld})
+ set(CONFIG_NAME "lld-${CONFIG_NAME}")
+ list(APPEND MSAN_TEST_DEPS lld)
+ endif()
+ set(MSAN_TEST_USE_THINLTO ${thinlto})
+ set(MSAN_TEST_USE_LLD ${lld})
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
list(APPEND MSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+endmacro()
+
+foreach(arch ${MSAN_TEST_ARCH})
+ add_msan_testsuite(${arch} False False)
+
+ if(COMPILER_RT_HAS_LLD AND arch STREQUAL "x86_64" AND NOT (APPLE OR WIN32))
+ add_msan_testsuite(${arch} True False)
+ endif()
endforeach()
-set(MSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
if(NOT COMPILER_RT_STANDALONE_BUILD)
list(APPEND MSAN_TEST_DEPS msan)
endif()
-if(COMPILER_RT_INCLUDE_TESTS AND COMPILER_RT_HAS_LIBCXX_SOURCES)
+if(COMPILER_RT_INCLUDE_TESTS AND COMPILER_RT_LIBCXX_PATH)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg)
diff --git a/test/msan/Linux/mallinfo.cc b/test/msan/Linux/mallinfo.cc
index 545ae934a6111..b2021c5df3cec 100644
--- a/test/msan/Linux/mallinfo.cc
+++ b/test/msan/Linux/mallinfo.cc
@@ -1,5 +1,5 @@
// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
-// REQUIRES: stable-runtime
+// UNSUPPORTED: aarch64-target-arch
#include <assert.h>
#include <malloc.h>
diff --git a/test/msan/Linux/poll.cc b/test/msan/Linux/poll.cc
new file mode 100644
index 0000000000000..7870d18e0387b
--- /dev/null
+++ b/test/msan/Linux/poll.cc
@@ -0,0 +1,42 @@
+// RUN: %clangxx_msan -O0 -std=c++11 -g %s -o %t
+// RUN: %run %t _ 2>&1 | FileCheck %s --check-prefix=CLEAN
+// RUN: not %run %t A 2>&1 | FileCheck %s --check-prefix=A
+// RUN: not %run %t B 2>&1 | FileCheck %s --check-prefix=B
+
+#include <assert.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include <sanitizer/msan_interface.h>
+
+int main(int argc, char **argv) {
+ char T = argv[1][0];
+
+ struct timespec ts;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000;
+ int res = ppoll(nullptr, 0, &ts, nullptr);
+ assert(res == 0);
+
+ if (T == 'A') {
+ __msan_poison(&ts.tv_sec, sizeof(ts.tv_sec));
+ ppoll(nullptr, 0, &ts, nullptr);
+ // A: use-of-uninitialized-value
+ }
+
+ // A-NOT: ==1
+ // B: ==1
+ fprintf(stderr, "==1\n");
+
+ sigset_t sig;
+ if (T != 'B')
+ sigemptyset(&sig);
+ ppoll(nullptr, 0, &ts, &sig);
+ // B: use-of-uninitialized-value
+
+ // B-NOT: ==2
+ // CLEAN: ==2
+ fprintf(stderr, "==2\n");
+ return 0;
+}
diff --git a/test/msan/__strxfrm_l.cc b/test/msan/__strxfrm_l.cc
new file mode 100644
index 0000000000000..c4eb10efb3e0b
--- /dev/null
+++ b/test/msan/__strxfrm_l.cc
@@ -0,0 +1,19 @@
+// RUN: %clangxx_msan -std=c++11 -O0 -g %s -o %t && %run %t
+// REQUIRES: x86_64-linux
+
+#include <assert.h>
+#include <locale.h>
+#include <sanitizer/msan_interface.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern "C" decltype(strxfrm_l) __strxfrm_l;
+
+int main(void) {
+ char q[10];
+ locale_t loc = newlocale(LC_ALL_MASK, "", (locale_t)0);
+ size_t n = __strxfrm_l(q, "qwerty", sizeof(q), loc);
+ assert(n < sizeof(q));
+ __msan_check_mem_is_initialized(q, n + 1);
+ return 0;
+}
diff --git a/test/msan/ftime.cc b/test/msan/ftime.cc
index 7a5a2fbf7dce0..2bc8a6f2fe103 100644
--- a/test/msan/ftime.cc
+++ b/test/msan/ftime.cc
@@ -1,7 +1,7 @@
// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
-// ftime() is deprecated on FreeBSD.
-// XFAIL: freebsd
+// ftime() is deprecated on FreeBSD and NetBSD.
+// UNSUPPORTED: freebsd, netbsd
#include <assert.h>
#include <sys/timeb.h>
diff --git a/test/msan/iconv.cc b/test/msan/iconv.cc
index e5fbbf9241e78..7beb6a01877c7 100644
--- a/test/msan/iconv.cc
+++ b/test/msan/iconv.cc
@@ -15,8 +15,8 @@ int main(void) {
char inbuf_[100];
strcpy(inbuf_, "sample text");
char outbuf_[100];
-#if defined(__FreeBSD__)
- // FreeBSD's iconv() expects the 2nd argument be of type 'const char**'.
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+ // Some OSes expect the 2nd argument of iconv(3) to be of type const char **
const char *inbuf = inbuf_;
#else
char *inbuf = inbuf_;
diff --git a/test/msan/ifaddrs.cc b/test/msan/ifaddrs.cc
index 6f5eb935ab52d..91730a01f2d8a 100644
--- a/test/msan/ifaddrs.cc
+++ b/test/msan/ifaddrs.cc
@@ -10,7 +10,7 @@
#include <vector>
-#if defined(__FreeBSD__)
+#if defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/socket.h> // To define 'struct sockaddr'.
#endif
diff --git a/test/msan/lit.cfg b/test/msan/lit.cfg
index eb0ed43897caf..cac2609998774 100644
--- a/test/msan/lit.cfg
+++ b/test/msan/lit.cfg
@@ -29,13 +29,9 @@ config.substitutions.append( ("%clangxx_msan ", build_invocation(clang_msan_cxxf
# Default test suffixes.
config.suffixes = ['.c', '.cc', '.cpp']
-# MemorySanitizer tests are currently supported on Linux only.
-if config.host_os not in ['Linux']:
+if config.host_os not in ['Linux', 'NetBSD']:
config.unsupported = True
-if config.target_arch != 'aarch64':
- config.available_features.add('stable-runtime')
-
# For mips64, mips64el we have forced store_context_size to 1 because these
# archs use slow unwinder which is not async signal safe. Therefore we only
# check the first frame since store_context size is 1.
diff --git a/test/msan/lit.site.cfg.in b/test/msan/lit.site.cfg.in
index a9656f24d6037..f744d71fd66c9 100644
--- a/test/msan/lit.site.cfg.in
+++ b/test/msan/lit.site.cfg.in
@@ -1,9 +1,11 @@
@LIT_SITE_CFG_IN_HEADER@
# Tool-specific config options.
-config.name_suffix = "@MSAN_TEST_CONFIG_SUFFIX@"
+config.name_suffix = "-@CONFIG_NAME@"
config.target_cflags = "@MSAN_TEST_TARGET_CFLAGS@"
config.target_arch = "@MSAN_TEST_TARGET_ARCH@"
+config.use_lld = @MSAN_TEST_USE_LLD@
+config.use_thinlto = @MSAN_TEST_USE_THINLTO@
# Load common config for all compiler-rt lit tests.
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
diff --git a/test/msan/msan_print_shadow3.cc b/test/msan/msan_print_shadow3.cc
index 4783152797eb0..410755e5dbaaa 100644
--- a/test/msan/msan_print_shadow3.cc
+++ b/test/msan/msan_print_shadow3.cc
@@ -6,11 +6,11 @@
int main(void) {
unsigned long long x = 0; // For 8-byte alignment.
- char x_s[4] = {0x87, 0x65, 0x43, 0x21};
+ char x_s[4] = {0x77, 0x65, 0x43, 0x21};
__msan_partial_poison(&x, &x_s, sizeof(x_s));
__msan_print_shadow(&x, sizeof(x_s));
return 0;
}
// CHECK: Shadow map of [{{.*}}), 4 bytes:
-// CHECK: 0x{{.*}}: 87654321 ........ ........ ........
+// CHECK: 0x{{.*}}: 77654321 ........ ........ ........
diff --git a/test/msan/pvalloc.cc b/test/msan/pvalloc.cc
new file mode 100644
index 0000000000000..7c406df79bb1a
--- /dev/null
+++ b/test/msan/pvalloc.cc
@@ -0,0 +1,43 @@
+// RUN: %clangxx_msan -O0 %s -o %t
+// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t m1 2>&1 | FileCheck %s
+// RUN: MSAN_OPTIONS=allocator_may_return_null=1 %run %t m1 2>&1
+// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t psm1 2>&1 | FileCheck %s
+// RUN: MSAN_OPTIONS=allocator_may_return_null=1 %run %t psm1 2>&1
+
+// UNSUPPORTED: win32, freebsd, netbsd
+
+// Checks that pvalloc overflows are caught. If the allocator is allowed to
+// return null, the errno should be set to ENOMEM.
+
+#include <assert.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[]) {
+ void *p;
+ size_t page_size;
+
+ assert(argc == 2);
+
+ page_size = sysconf(_SC_PAGESIZE);
+ // Check that the page size is a power of two.
+ assert((page_size & (page_size - 1)) == 0);
+
+ if (!strcmp(argv[1], "m1")) {
+ p = pvalloc((uintptr_t)-1);
+ assert(!p);
+ assert(errno == ENOMEM);
+ }
+ if (!strcmp(argv[1], "psm1")) {
+ p = pvalloc((uintptr_t)-(page_size - 1));
+ assert(!p);
+ assert(errno == ENOMEM);
+ }
+
+ return 0;
+}
+
+// CHECK: MemorySanitizer's allocator is terminating the process
diff --git a/test/msan/sigaction.cc b/test/msan/sigaction.cc
new file mode 100644
index 0000000000000..0c69f115fdb24
--- /dev/null
+++ b/test/msan/sigaction.cc
@@ -0,0 +1,47 @@
+// RUN: %clangxx_msan -std=c++11 -O0 -g %s -o %t
+// RUN: %run %t __
+// RUN: not %run %t A_ 2>&1 | FileCheck %s
+// RUN: not %run %t AH 2>&1 | FileCheck %s
+// RUN: not %run %t B_ 2>&1 | FileCheck %s
+// RUN: not %run %t BH 2>&1 | FileCheck %s
+// RUN: not %run %t C_ 2>&1 | FileCheck %s
+// RUN: not %run %t CH 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <sanitizer/msan_interface.h>
+
+void handler(int) {}
+void action(int, siginfo_t *, void *) {}
+
+int main(int argc, char **argv) {
+ char T = argv[1][0];
+ char H = argv[1][1];
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ if (H == 'H') {
+ sa.sa_handler = handler;
+ } else {
+ sa.sa_sigaction = action;
+ sa.sa_flags = SA_SIGINFO;
+ }
+
+ if (T == 'A') {
+ if (H == 'H')
+ __msan_poison(&sa.sa_handler, sizeof(sa.sa_handler));
+ else
+ __msan_poison(&sa.sa_sigaction, sizeof(sa.sa_sigaction));
+ }
+ if (T == 'B')
+ __msan_poison(&sa.sa_flags, sizeof(sa.sa_flags));
+ if (T == 'C')
+ __msan_poison(&sa.sa_mask, sizeof(sa.sa_mask));
+ // CHECK: use-of-uninitialized-value
+ int res = sigaction(SIGUSR1, &sa, nullptr);
+ assert(res == 0);
+ return 0;
+}
diff --git a/test/msan/sigwait.cc b/test/msan/sigwait.cc
index f2e77cfd64071..222fc34a16982 100644
--- a/test/msan/sigwait.cc
+++ b/test/msan/sigwait.cc
@@ -1,16 +1,21 @@
// RUN: %clangxx_msan -std=c++11 -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_msan -DPOSITIVE -std=c++11 -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
#include <assert.h>
-#include <sanitizer/msan_interface.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>
+#include <sanitizer/msan_interface.h>
+
void test_sigwait() {
sigset_t s;
+#ifndef POSITIVE
sigemptyset(&s);
sigaddset(&s, SIGUSR1);
+#endif
sigprocmask(SIG_BLOCK, &s, 0);
+ // CHECK: MemorySanitizer: use-of-uninitialized-value
if (pid_t pid = fork()) {
kill(pid, SIGUSR1);
diff --git a/test/msan/strxfrm.cc b/test/msan/strxfrm.cc
index 9a30d03c33ae6..94b8c70240907 100644
--- a/test/msan/strxfrm.cc
+++ b/test/msan/strxfrm.cc
@@ -1,14 +1,21 @@
// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
#include <assert.h>
+#include <locale.h>
#include <sanitizer/msan_interface.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
- const char *p = "abcdef";
char q[10];
- size_t n = strxfrm(q, p, sizeof(q));
+ size_t n = strxfrm(q, "abcdef", sizeof(q));
+ assert(n < sizeof(q));
+ __msan_check_mem_is_initialized(q, n + 1);
+
+ locale_t loc = newlocale(LC_ALL_MASK, "", (locale_t)0);
+
+ __msan_poison(&q, sizeof(q));
+ n = strxfrm_l(q, "qwerty", sizeof(q), loc);
assert(n < sizeof(q));
__msan_check_mem_is_initialized(q, n + 1);
return 0;
diff --git a/test/msan/tsearch.cc b/test/msan/tsearch.cc
index 653dc60371cd5..0d8ee8f35b257 100644
--- a/test/msan/tsearch.cc
+++ b/test/msan/tsearch.cc
@@ -1,5 +1,8 @@
// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
+// tdestroy is a GNU extension
+// UNSUPPORTED: netbsd
+
#include <assert.h>
#include <search.h>
#include <stdlib.h>
diff --git a/test/profile/Linux/counter_promo_for.c b/test/profile/Linux/counter_promo_for.c
index 3139646699d51..a331f00ad0bb3 100644
--- a/test/profile/Linux/counter_promo_for.c
+++ b/test/profile/Linux/counter_promo_for.c
@@ -19,18 +19,18 @@ __attribute__((noinline)) void bar(int i) { g += i; }
__attribute__((noinline)) void foo(int n, int N) {
// PROMO-LABEL: @foo
+// PROMO: load{{.*}}@__profc_foo{{.*}} 3){{.*}}
+// PROMO-NEXT: add
+// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 3){{.*}}
// PROMO: load{{.*}}@__profc_foo{{.*}} 0){{.*}}
// PROMO-NEXT: add
// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 0){{.*}}
// PROMO-NEXT: load{{.*}}@__profc_foo{{.*}} 1){{.*}}
// PROMO-NEXT: add
// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 1){{.*}}
-// PROMO-NEXT: load{{.*}}@__profc_foo{{.*}} 2){{.*}}
+// PROMO: load{{.*}}@__profc_foo{{.*}} 2){{.*}}
// PROMO-NEXT: add
// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 2){{.*}}
-// PROMO: load{{.*}}@__profc_foo{{.*}} 3){{.*}}
-// PROMO-NEXT: add
-// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 3){{.*}}
//
// NOPROMO-LABEL: @foo
// NOPROMO: load{{.*}}@__profc_foo{{.*}} 0){{.*}}
diff --git a/test/profile/Linux/coverage_ctors.cpp b/test/profile/Linux/coverage_ctors.cpp
index 021d9df5e7347..adf078e563053 100644
--- a/test/profile/Linux/coverage_ctors.cpp
+++ b/test/profile/Linux/coverage_ctors.cpp
@@ -1,7 +1,7 @@
// RUN: %clangxx_profgen -std=c++11 -fuse-ld=gold -fcoverage-mapping -o %t %s
// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
// RUN: llvm-profdata merge -o %t.profdata %t.profraw
-// RUN: llvm-cov show %t -instr-profile %t.profdata -filename-equivalence 2>&1 | FileCheck %s
+// RUN: llvm-cov show %t -instr-profile %t.profdata -path-equivalence=/tmp,%S 2>&1 | FileCheck %s
struct Base {
int B;
diff --git a/test/profile/Linux/coverage_dtor.cpp b/test/profile/Linux/coverage_dtor.cpp
index 16415122040c9..c91dd42d21d3c 100644
--- a/test/profile/Linux/coverage_dtor.cpp
+++ b/test/profile/Linux/coverage_dtor.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_profgen -x c++ -fno-exceptions -std=c++11 -fuse-ld=gold -fcoverage-mapping -o %t %s
// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
// RUN: llvm-profdata merge -o %t.profdata %t.profraw
-// RUN: llvm-cov show %t -instr-profile %t.profdata -filename-equivalence 2>&1 | FileCheck %s
+// RUN: llvm-cov show %t -instr-profile %t.profdata -path-equivalence=/tmp,%S 2>&1 | FileCheck %s
int g = 100;
struct Base {
diff --git a/test/profile/Linux/coverage_test.cpp b/test/profile/Linux/coverage_test.cpp
index db9a14e26e3c8..67adeb7243495 100644
--- a/test/profile/Linux/coverage_test.cpp
+++ b/test/profile/Linux/coverage_test.cpp
@@ -1,12 +1,12 @@
// RUN: %clang_profgen -fuse-ld=gold -O2 -fdata-sections -ffunction-sections -fcoverage-mapping -Wl,--gc-sections -o %t %s
// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
// RUN: llvm-profdata merge -o %t.profdata %t.profraw
-// RUN: llvm-cov show %t -instr-profile %t.profdata -filename-equivalence 2>&1 | FileCheck %s
+// RUN: llvm-cov show %t -instr-profile %t.profdata -path-equivalence=/tmp,%S 2>&1 | FileCheck %s
// BFD linker older than 2.26 has a bug that per-func profile data will be wrongly garbage collected when GC is turned on. We only do end-to-end test here without GC:
// RUN: %clang_profgen -O2 -fcoverage-mapping -o %t.2 %s
// RUN: env LLVM_PROFILE_FILE=%t.2.profraw %run %t.2
// RUN: llvm-profdata merge -o %t.2.profdata %t.2.profraw
-// RUN: llvm-cov show %t.2 -instr-profile %t.2.profdata -filename-equivalence 2>&1 | FileCheck %s
+// RUN: llvm-cov show %t.2 -instr-profile %t.2.profdata -path-equivalence=/tmp,%S 2>&1 | FileCheck %s
// Check covmap is not garbage collected when GC is turned on with BFD linker. Due to the bug mentioned above, we can only
// do the check with objdump:
// RUN: %clang_profgen -O2 -fcoverage-mapping -Wl,--gc-sections -o %t.3 %s
@@ -15,7 +15,7 @@
// RUN: %clang_profgen -fuse-ld=gold -O2 -fdata-sections -ffunction-sections -fPIE -pie -fcoverage-mapping -Wl,--gc-sections -o %t.pie %s
// RUN: env LLVM_PROFILE_FILE=%t.pie.profraw %run %t.pie
// RUN: llvm-profdata merge -o %t.pie.profdata %t.pie.profraw
-// RUN: llvm-cov show %t.pie -instr-profile %t.pie.profdata -filename-equivalence 2>&1 | FileCheck %s
+// RUN: llvm-cov show %t.pie -instr-profile %t.pie.profdata -path-equivalence=/tmp,%S 2>&1 | FileCheck %s
void foo(bool cond) { // CHECK: [[@LINE]]| 1|void foo(
if (cond) { // CHECK: [[@LINE]]| 1| if (cond) {
diff --git a/test/profile/Linux/instrprof-comdat.test b/test/profile/Linux/instrprof-comdat.test
index 5a11a241ae6f8..1490ea7f06031 100644
--- a/test/profile/Linux/instrprof-comdat.test
+++ b/test/profile/Linux/instrprof-comdat.test
@@ -2,5 +2,5 @@ RUN: mkdir -p %t.d
RUN: %clangxx_profgen -o %t.d/comdat -fcoverage-mapping -fuse-ld=gold %S/../Inputs/instrprof-comdat-1.cpp %S/../Inputs/instrprof-comdat-2.cpp
RUN: LLVM_PROFILE_FILE=%t-comdat.profraw %run %t.d/comdat
RUN: llvm-profdata merge -o %t.d/comdat.prof %t-comdat.profraw
-RUN: llvm-cov show --filename-equivalence --instr-profile=%t.d/comdat.prof %t.d/comdat | FileCheck --check-prefix=HEADER %S/../Inputs/instrprof-comdat.h
+RUN: llvm-cov show --path-equivalence=/tmp,%S --instr-profile=%t.d/comdat.prof %t.d/comdat | FileCheck --check-prefix=HEADER %S/../Inputs/instrprof-comdat.h
diff --git a/test/profile/Linux/lit.local.cfg b/test/profile/Linux/lit.local.cfg
index 410ffd8c5b056..98d79518b92aa 100644
--- a/test/profile/Linux/lit.local.cfg
+++ b/test/profile/Linux/lit.local.cfg
@@ -20,7 +20,9 @@ def is_gold_linker_available():
if not '-plugin' in ld_out:
return False
- clang_cmd = subprocess.Popen([config.clang, '-fuse-ld=gold', '-xc', '-'],
+ # config.clang is not guaranteed to be just the executable!
+ clang_cmd = subprocess.Popen(" ".join([config.clang, '-fuse-ld=gold', '-xc', '-']),
+ shell=True,
universal_newlines = True,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
diff --git a/test/profile/infinite_loop.c b/test/profile/infinite_loop.c
new file mode 100644
index 0000000000000..0e3981c712f6b
--- /dev/null
+++ b/test/profile/infinite_loop.c
@@ -0,0 +1,30 @@
+// RUN: %clang_pgogen -O2 -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata show -function main -counts %t.profraw| FileCheck %s
+
+void exit(int);
+int g;
+__attribute__((noinline)) void foo()
+{
+ g++;
+ if (g==1000)
+ exit(0);
+}
+
+
+int main()
+{
+ while (1) {
+ foo();
+ }
+
+}
+
+// CHECK: Counters:
+// CHECK-NEXT: main:
+// CHECK-NEXT: Hash: {{.*}}
+// CHECK-NEXT: Counters: 2
+// CHECK-NEXT: Block counts: [1000, 1]
+
+
+
diff --git a/test/profile/instrprof-darwin-dead-strip.c b/test/profile/instrprof-darwin-dead-strip.c
index 64a4895a9ef92..03049335efda0 100644
--- a/test/profile/instrprof-darwin-dead-strip.c
+++ b/test/profile/instrprof-darwin-dead-strip.c
@@ -35,6 +35,7 @@ int main() { return 0; }
// PROF-NEXT: Hash:
// PROF-NEXT: Counters: 1
// PROF-NEXT: Function count: 1
+// PROF-NEXT: Instrumentation level: Front-end
// PROF-NEXT: Functions shown: 1
// PROF-NEXT: Total functions: 1
// PROF-NEXT: Maximum function count: 1
diff --git a/test/profile/lit.cfg b/test/profile/lit.cfg
index 9ca394212e9f4..1cd2509672fd4 100644
--- a/test/profile/lit.cfg
+++ b/test/profile/lit.cfg
@@ -22,17 +22,6 @@ if hasattr(config, 'profile_lit_binary_dir') and \
config.profile_lit_binary_dir is not None:
config.test_exec_root = os.path.join(config.profile_lit_binary_dir, config.name)
-# If the above check didn't work, we're probably in the source tree. Use some
-# magic to re-execute from the build tree.
-if config.test_exec_root is None:
- # The magic relies on knowing compilerrt_site_basedir.
- compilerrt_basedir = lit_config.params.get('compilerrt_site_basedir', None)
- if compilerrt_basedir:
- site_cfg = os.path.join(compilerrt_basedir, 'profile', 'lit.site.cfg')
- if os.path.exists(site_cfg):
- lit_config.load_config(config, site_cfg)
- raise SystemExit
-
if config.host_os in ['Linux']:
extra_link_flags = ["-ldl"]
else:
@@ -78,8 +67,11 @@ config.substitutions.append( ("%clangxx_profuse=", build_invocation(clang_cxxfla
config.substitutions.append( ("%clang_lto_profgen=", build_invocation(clang_cflags, True) + " -fprofile-instr-generate=") )
-if config.host_os not in ['Darwin', 'FreeBSD', 'Linux']:
+if config.host_os not in ['Darwin', 'FreeBSD', 'Linux', 'SunOS']:
config.unsupported = True
if config.target_arch in ['armv7l']:
config.unsupported = True
+
+if config.android:
+ config.unsupported = True
diff --git a/test/profile/runtime_infinite.c b/test/profile/runtime_infinite.c
new file mode 100644
index 0000000000000..b55f5e2750dd9
--- /dev/null
+++ b/test/profile/runtime_infinite.c
@@ -0,0 +1,36 @@
+// The waiting loop never exits via the normal
+// path before the profile is dumped and the
+// program is terminated. This tests checks
+// that the entry of main is properly instrumented
+// and has non-zero count.
+
+// RUN: %clang_pgogen -mllvm -do-counter-promotion=false -O2 -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata show -function main -counts %t.profraw| FileCheck %s
+void exit(int);
+
+int __llvm_profile_dump(void);
+void __llvm_profile_reset_counters(void);
+
+int g = 0;
+__attribute__((noinline)) void doSth() {
+ g++;
+
+ if (g > 10000) {
+ // dump profile and exit;
+ __llvm_profile_dump();
+ exit(0);
+ }
+}
+int errorcode = 0;
+int noerror() { return (errorcode == 0); }
+
+int main(int argc, const char *argv[]) {
+ // waiting_loop
+ while (noerror()) {
+ doSth();
+ }
+}
+
+// CHECK-LABEL: main
+// CHECK: [10001, 1]
diff --git a/test/safestack/lit.cfg b/test/safestack/lit.cfg
index fb5672936f284..10cd8a5a5135d 100644
--- a/test/safestack/lit.cfg
+++ b/test/safestack/lit.cfg
@@ -18,11 +18,5 @@ config.substitutions.append( ("%clang_safestack ", config.clang + " -O0 -fsaniti
if config.lto_supported:
config.substitutions.append((r"%clang_lto_safestack ", ' '.join(config.lto_launch + [config.clang] + config.lto_flags + ['-fsanitize=safe-stack '])))
-# SafeStack tests are currently supported on Linux, FreeBSD and Darwin only.
-if config.host_os not in ['Linux', 'FreeBSD', 'Darwin']:
+if config.host_os not in ['Linux', 'FreeBSD', 'Darwin', 'NetBSD']:
config.unsupported = True
-
-# Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL
-# because the test fail due some runtime issue.
-if config.target_arch != 'aarch64':
- config.available_features.add('stable-runtime')
diff --git a/test/sanitizer_common/CMakeLists.txt b/test/sanitizer_common/CMakeLists.txt
index 9b4070b0f6eb5..8b210a08aa570 100644
--- a/test/sanitizer_common/CMakeLists.txt
+++ b/test/sanitizer_common/CMakeLists.txt
@@ -4,13 +4,14 @@ set(SANITIZER_COMMON_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
set(SANITIZER_COMMON_TESTSUITES)
set(SUPPORTED_TOOLS)
-if(CMAKE_SYSTEM_NAME MATCHES "Darwin|Linux|FreeBSD" AND NOT ANDROID)
+if(CMAKE_SYSTEM_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD")
list(APPEND SUPPORTED_TOOLS asan)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT ANDROID)
list(APPEND SUPPORTED_TOOLS tsan)
list(APPEND SUPPORTED_TOOLS msan)
list(APPEND SUPPORTED_TOOLS lsan)
+ list(APPEND SUPPORTED_TOOLS ubsan)
endif()
# Create a separate config for each tool we support.
@@ -42,8 +43,11 @@ if(COMPILER_RT_INCLUDE_TESTS)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg)
- list(APPEND SANITIZER_COMMON_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
- list(APPEND SANITIZER_COMMON_TEST_DEPS SanitizerUnitTests)
+ # FIXME: support unit test in the android test runner
+ if (NOT ANDROID)
+ list(APPEND SANITIZER_COMMON_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit)
+ list(APPEND SANITIZER_COMMON_TEST_DEPS SanitizerUnitTests)
+ endif()
endif()
if(SANITIZER_COMMON_TESTSUITES)
diff --git a/test/sanitizer_common/TestCases/Darwin/print-stack-trace.cc b/test/sanitizer_common/TestCases/Darwin/print-stack-trace.cc
new file mode 100644
index 0000000000000..715282fd76674
--- /dev/null
+++ b/test/sanitizer_common/TestCases/Darwin/print-stack-trace.cc
@@ -0,0 +1,19 @@
+// RUN: %clangxx -O0 %s -o %t && %env_tool_opts=stack_trace_format=DEFAULT %run %t 2>&1 | FileCheck %s
+// RUN: %env_tool_opts=stack_trace_format='"frame:%n lineno:%l"' %run %t 2>&1 | FileCheck %s --check-prefix=CUSTOM
+
+#include <sanitizer/common_interface_defs.h>
+
+static inline void FooBarBaz() {
+ __sanitizer_print_stack_trace();
+}
+
+int main() {
+ FooBarBaz();
+ return 0;
+}
+// CHECK: {{ #0 0x.* in __sanitizer_print_stack_trace}}
+// CHECK: {{ #1 0x.* in FooBarBaz(\(\))? .*}}print-stack-trace.cc:[[@LINE-8]]
+// CHECK: {{ #2 0x.* in main.*}}print-stack-trace.cc:[[@LINE-5]]
+
+// CUSTOM: frame:1 lineno:[[@LINE-11]]
+// CUSTOM: frame:2 lineno:[[@LINE-8]]
diff --git a/test/sanitizer_common/TestCases/Linux/abort_on_error.cc b/test/sanitizer_common/TestCases/Linux/abort_on_error.cc
index a5ef665364788..e4b246e35f6a3 100644
--- a/test/sanitizer_common/TestCases/Linux/abort_on_error.cc
+++ b/test/sanitizer_common/TestCases/Linux/abort_on_error.cc
@@ -10,6 +10,9 @@
// lit doesn't set options anyway.
// RUN: not %run %t 2>&1
+// Android needs abort_on_error=0
+// UNSUPPORTED: android
+
namespace __sanitizer {
void Die();
}
diff --git a/test/asan/TestCases/Posix/allow_user_segv.cc b/test/sanitizer_common/TestCases/Linux/allow_user_segv.cc
index 4bec6ad89609f..e17de1853eb36 100644
--- a/test/asan/TestCases/Posix/allow_user_segv.cc
+++ b/test/sanitizer_common/TestCases/Linux/allow_user_segv.cc
@@ -2,21 +2,24 @@
// https://code.google.com/p/address-sanitizer/issues/detail?id=180
// clang-format off
-// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: %clangxx -O0 %s -o %t
-// RUN: %env_asan_opts=handle_segv=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
-// RUN: %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
-// RUN: %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
+// RUN: %env_tool_opts=handle_segv=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
+// RUN: %env_tool_opts=handle_segv=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
+// RUN: %env_tool_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
-// RUN: %env_asan_opts=handle_segv=0:allow_user_segv_handler=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
-// RUN: %env_asan_opts=handle_segv=1:allow_user_segv_handler=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
-// RUN: %env_asan_opts=handle_segv=2:allow_user_segv_handler=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
+// RUN: %env_tool_opts=handle_segv=0:allow_user_segv_handler=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
+// RUN: %env_tool_opts=handle_segv=1:allow_user_segv_handler=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
+// RUN: %env_tool_opts=handle_segv=2:allow_user_segv_handler=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
-// RUN: %env_asan_opts=handle_segv=0:allow_user_segv_handler=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
-// RUN: %env_asan_opts=handle_segv=1:allow_user_segv_handler=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
-// RUN: %env_asan_opts=handle_segv=2:allow_user_segv_handler=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
+// RUN: %env_tool_opts=handle_segv=0:allow_user_segv_handler=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
+// RUN: %env_tool_opts=handle_segv=1:allow_user_segv_handler=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
+// RUN: %env_tool_opts=handle_segv=2:allow_user_segv_handler=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2
// clang-format on
+// Flaky errors in debuggerd with "waitpid returned unexpected pid (0)" in logcat.
+// UNSUPPORTED: android && i386-target-arch
+
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -26,7 +29,7 @@ struct sigaction original_sigaction_sigsegv;
void User_OnSIGSEGV(int signum, siginfo_t *siginfo, void *context) {
fprintf(stderr, "User sigaction called\n");
- struct sigaction original_sigaction;
+ struct sigaction original_sigaction = {};
if (signum == SIGBUS)
original_sigaction = original_sigaction_sigbus;
else if (signum == SIGSEGV)
@@ -51,7 +54,7 @@ int DoSEGV() {
}
bool InstallHandler(int signum, struct sigaction *original_sigaction) {
- struct sigaction user_sigaction;
+ struct sigaction user_sigaction = {};
user_sigaction.sa_sigaction = User_OnSIGSEGV;
user_sigaction.sa_flags = SA_SIGINFO;
if (sigaction(signum, &user_sigaction, original_sigaction)) {
@@ -71,17 +74,17 @@ int main() {
return DoSEGV();
}
-// CHECK0-NOT: ASAN:DEADLYSIGNAL
-// CHECK0-NOT: AddressSanitizer: SEGV on unknown address
+// CHECK0-NOT: Sanitizer:DEADLYSIGNAL
+// CHECK0-NOT: Sanitizer: SEGV on unknown address
// CHECK0: User sigaction installed
// CHECK0-NEXT: User sigaction called
// CHECK1: User sigaction installed
// CHECK1-NEXT: User sigaction called
-// CHECK1-NEXT: ASAN:DEADLYSIGNAL
-// CHECK1: AddressSanitizer: SEGV on unknown address
+// CHECK1-NEXT: Sanitizer:DEADLYSIGNAL
+// CHECK1: Sanitizer: SEGV on unknown address
// CHECK2-NOT: User sigaction called
// CHECK2: User sigaction installed
-// CHECK2-NEXT: ASAN:DEADLYSIGNAL
-// CHECK2: AddressSanitizer: SEGV on unknown address
+// CHECK2-NEXT: Sanitizer:DEADLYSIGNAL
+// CHECK2: Sanitizer: SEGV on unknown address
diff --git a/test/sanitizer_common/TestCases/Linux/assert.cc b/test/sanitizer_common/TestCases/Linux/assert.cc
index 5d58ea4f7e818..9c5263f8e776a 100644
--- a/test/sanitizer_common/TestCases/Linux/assert.cc
+++ b/test/sanitizer_common/TestCases/Linux/assert.cc
@@ -1,12 +1,12 @@
// Test the handle_abort option.
-// RUN: %clang %s -o %t
+
+// clang-format off
+// RUN: %clangxx %s -o %t
// RUN: not --crash %run %t 2>&1 | FileCheck --check-prefix=CHECK0 %s
// RUN: %env_tool_opts=handle_abort=0 not --crash %run %t 2>&1 | FileCheck --check-prefix=CHECK0 %s
// RUN: %env_tool_opts=handle_abort=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK1 %s
-// FIXME: implement in other sanitizers, not just asan.
-// XFAIL: msan
-// XFAIL: lsan
-// XFAIL: tsan
+// clang-format on
+
#include <assert.h>
#include <stdio.h>
#include <sanitizer/asan_interface.h>
@@ -19,6 +19,9 @@ int main(int argc, char **argv) {
__sanitizer_set_death_callback(death);
assert(argc == 100);
}
-// CHECK1: ERROR: {{.*}}Sanitizer:
+
+// CHECK0-NOT: Sanitizer:DEADLYSIGNAL
+// CHECK1: ERROR: {{.*}}Sanitizer: ABRT
+// CHECK1: {{ #0 }}
// CHECK1: DEATH CALLBACK
// CHECK0-NOT: Sanitizer
diff --git a/test/sanitizer_common/TestCases/Linux/decorate_proc_maps.cc b/test/sanitizer_common/TestCases/Linux/decorate_proc_maps.cc
index 36d4df567ee7c..8a05f4b66868e 100644
--- a/test/sanitizer_common/TestCases/Linux/decorate_proc_maps.cc
+++ b/test/sanitizer_common/TestCases/Linux/decorate_proc_maps.cc
@@ -1,6 +1,9 @@
// RUN: %clangxx -g %s -o %t
// RUN: %env_tool_opts=decorate_proc_maps=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%tool_name
+
// REQUIRES: stable-runtime
+// XFAIL: android && asan
+
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
@@ -57,5 +60,6 @@ int main(void) {
// CHECK-tsan: rw-p {{.*}} [trace 1]
// CHECK-tsan: rw-p {{.*}} [trace header 1]
-// Nothing interesting with standalone LSan.
+// Nothing interesting with standalone LSan and UBSan.
// CHECK-lsan: decorate_proc_maps
+// CHECK-ubsan: decorate_proc_maps
diff --git a/test/sanitizer_common/TestCases/Linux/deepbind.cc b/test/sanitizer_common/TestCases/Linux/deepbind.cc
index fc810ad039f47..81150fae977e0 100644
--- a/test/sanitizer_common/TestCases/Linux/deepbind.cc
+++ b/test/sanitizer_common/TestCases/Linux/deepbind.cc
@@ -1,5 +1,5 @@
// RUN: %clangxx %s -o %t && %run not %t 1 2>&1 | FileCheck %s
-// UNSUPPORTED: lsan, android
+// UNSUPPORTED: lsan,ubsan,android
#include <dlfcn.h>
#include <stdio.h>
diff --git a/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc b/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc
index 5bee1fb4bc93e..c0d6cfea1fbef 100644
--- a/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc
+++ b/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc
@@ -1,8 +1,6 @@
// Regression test for a crash in getpwnam_r and similar interceptors.
// RUN: %clangxx -O0 -g %s -o %t && %run %t
-// XFAIL: mips
-
#include <assert.h>
#include <errno.h>
#include <pwd.h>
diff --git a/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc b/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc
index d4a60a0d37315..3c875c1793dff 100644
--- a/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc
+++ b/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc
@@ -14,6 +14,7 @@
// XFAIL: lsan
// XFAIL: tsan
// XFAIL: msan
+// XFAIL: ubsan
#include <string.h>
#include <stdio.h>
@@ -26,7 +27,10 @@ volatile char *sink[kNumAllocs];
int main(int argc, char **argv) {
for (int i = 0; i < kNumAllocs; i++) {
if ((i % 1000) == 0) {
- fprintf(stderr, "[%d]\n", i);
+ // Don't write to stderr! Doing that triggers a kernel race condition
+ // between this thread and the rss-limit thread, and may lose part of the
+ // output. See https://lkml.org/lkml/2014/2/17/324.
+ printf("[%d]\n", i);
}
char *x = new char[kAllocSize];
memset(x, 0, kAllocSize);
diff --git a/test/sanitizer_common/TestCases/Linux/iconv_test.c b/test/sanitizer_common/TestCases/Linux/iconv_test.c
index 08da34d89a3c4..eb995d21c3434 100644
--- a/test/sanitizer_common/TestCases/Linux/iconv_test.c
+++ b/test/sanitizer_common/TestCases/Linux/iconv_test.c
@@ -1,6 +1,9 @@
// RUN: %clang %s -o %t && %run %t
// Verify that even if iconv returned -1
// we still treat the initialized part of outbuf as properly initialized.
+
+// UNSUPPORTED: android
+
#include <iconv.h>
#include <assert.h>
#include <stdio.h>
diff --git a/test/sanitizer_common/TestCases/Linux/ill.cc b/test/sanitizer_common/TestCases/Linux/ill.cc
index 2c69618ad7cbd..43f7a7830495f 100644
--- a/test/sanitizer_common/TestCases/Linux/ill.cc
+++ b/test/sanitizer_common/TestCases/Linux/ill.cc
@@ -1,13 +1,12 @@
// Test the handle_sigill option.
-// RUN: %clang %s -o %t -O1
+
+// clang-format off
+// RUN: %clangxx %s -o %t -O1
// RUN: not --crash %run %t 2>&1 | FileCheck --check-prefix=CHECK0 %s
// RUN: %env_tool_opts=handle_sigill=0 not --crash %run %t 2>&1 | FileCheck --check-prefix=CHECK0 %s
// RUN: %env_tool_opts=handle_sigill=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK1 %s
-// FIXME: implement in other sanitizers, not just asan.
-// XFAIL: msan
-// XFAIL: lsan
-// XFAIL: tsan
-//
+// clang-format on
+
// FIXME: seems to fail on ARM
// REQUIRES: x86_64-target-arch
#include <assert.h>
@@ -22,6 +21,9 @@ int main(int argc, char **argv) {
__sanitizer_set_death_callback(death);
__builtin_trap();
}
-// CHECK1: ERROR: {{.*}}Sanitizer:
+
+// CHECK0-NOT: Sanitizer:DEADLYSIGNAL
+// CHECK1: ERROR: {{.*}}Sanitizer: ILL
+// CHECK1: {{#[0-9]+.* main .*ill\.cc:[0-9]+}}
// CHECK1: DEATH CALLBACK
// CHECK0-NOT: Sanitizer
diff --git a/test/sanitizer_common/TestCases/Linux/mlock_test.cc b/test/sanitizer_common/TestCases/Linux/mlock_test.cc
index 69ea7cb91c4fc..a952922aaabc8 100644
--- a/test/sanitizer_common/TestCases/Linux/mlock_test.cc
+++ b/test/sanitizer_common/TestCases/Linux/mlock_test.cc
@@ -1,5 +1,5 @@
// RUN: %clang %s -o %t && %run %t
-// XFAIL: lsan
+// XFAIL: ubsan,lsan
#include <assert.h>
#include <sys/mman.h>
diff --git a/test/sanitizer_common/TestCases/Linux/mprobe.cc b/test/sanitizer_common/TestCases/Linux/mprobe.cc
index 57e5ba5a6c747..82c0faf0e2add 100644
--- a/test/sanitizer_common/TestCases/Linux/mprobe.cc
+++ b/test/sanitizer_common/TestCases/Linux/mprobe.cc
@@ -1,5 +1,5 @@
// RUN: %clangxx %s -o %t && %run %t 2>&1 | FileCheck %s
-// UNSUPPORTED: android
+// UNSUPPORTED: android, ubsan
#include <stdio.h>
#include <stdlib.h>
diff --git a/test/sanitizer_common/TestCases/Linux/ptrace.cc b/test/sanitizer_common/TestCases/Linux/ptrace.cc
index b10aecd3579d6..82532c35fab5e 100644
--- a/test/sanitizer_common/TestCases/Linux/ptrace.cc
+++ b/test/sanitizer_common/TestCases/Linux/ptrace.cc
@@ -1,5 +1,7 @@
// RUN: %clangxx -O0 %s -o %t && %run %t
+// UNSUPPORTED: android
+
#include <assert.h>
#include <signal.h>
#include <stdio.h>
diff --git a/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc b/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc
index b7e8721a1b9e3..d623ccabb5b55 100644
--- a/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc
+++ b/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cc
@@ -1,7 +1,7 @@
// RUN: %clangxx -O0 -g %s -lutil -o %t && %run %t
// This test depends on the glibc layout of struct sem_t and checks that we
// don't leave sem_t::private uninitialized.
-// UNSUPPORTED: android, lsan-x86
+// UNSUPPORTED: android, lsan-x86, ubsan, target-is-mips64, target-is-mips64el
#include <features.h>
#include <assert.h>
#include <semaphore.h>
diff --git a/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc b/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc
index 51e8bdb6e95db..d6c3ecbff4756 100644
--- a/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc
+++ b/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc
@@ -1,4 +1,6 @@
-// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" ASAN_OPTIONS="handle_segv=0" %run %t 2>&1 | FileCheck %s
+// clang-format off
+// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" %run %t 2>&1 | FileCheck %s
+// clang-format on
// JVM uses SEGV to preempt threads. All threads do a load from a known address
// periodically. When runtime needs to preempt threads, it unmaps the page.
@@ -13,11 +15,12 @@
// "benign" SEGVs that are handled by signal handler, and ensures that
// the process survive.
+#include <assert.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
-#include <signal.h>
-#include <sys/mman.h>
#include <string.h>
+#include <sys/mman.h>
#include <unistd.h>
unsigned long page_size;
@@ -35,6 +38,12 @@ int main() {
a.sa_sigaction = handler;
a.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &a, &old);
+
+ memset(&a, 0, sizeof(a));
+ sigaction(SIGSEGV, 0, &a);
+ assert(a.sa_sigaction == handler);
+ assert(a.sa_flags & SA_SIGINFO);
+
guard = mmap(0, 3 * page_size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
guard = (char*)guard + page_size; // work around a kernel bug
for (int i = 0; i < 1000000; i++) {
diff --git a/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc b/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc
index 83570a9f13a44..2ee809547530f 100644
--- a/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc
+++ b/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc
@@ -14,6 +14,7 @@
// XFAIL: lsan
// XFAIL: tsan
// XFAIL: msan
+// XFAIL: ubsan
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
diff --git a/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc b/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc
index eb4deace060ce..c3a6560228972 100644
--- a/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc
+++ b/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc
@@ -1,5 +1,7 @@
// RUN: %clangxx -O2 %s -o %t && %run %t 2>&1 | FileCheck %s
+// XFAIL: android
+
#include <stdio.h>
// getauxval() used instead of sysconf() in GetPageSize() is defined starting
diff --git a/test/sanitizer_common/TestCases/Linux/unexpected_format_specifier_test.cc b/test/sanitizer_common/TestCases/Linux/unexpected_format_specifier_test.cc
index f48cce8ea22b0..641495508ba10 100644
--- a/test/sanitizer_common/TestCases/Linux/unexpected_format_specifier_test.cc
+++ b/test/sanitizer_common/TestCases/Linux/unexpected_format_specifier_test.cc
@@ -1,6 +1,7 @@
// RUN: %clang -w -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
// UNSUPPORTED: lsan
// UNSUPPORTED: msan
+// UNSUPPORTED: ubsan
#include <stdio.h>
int main() {
int a;
diff --git a/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc b/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc
index 261295790836f..d9a1bc66082c3 100644
--- a/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc
+++ b/test/sanitizer_common/TestCases/Posix/dedup_token_length_test.cc
@@ -7,10 +7,6 @@
// RUN: env %tool_options='abort_on_error=0, dedup_token_length=3' not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --match-full-lines
// REQUIRES: stable-runtime
-// FIXME: implement SEGV handler in other sanitizers, not just asan.
-// XFAIL: msan
-// XFAIL: lsan
-// XFAIL: tsan
volatile int *null = 0;
diff --git a/test/asan/TestCases/Posix/dump_instruction_bytes.cc b/test/sanitizer_common/TestCases/Posix/dump_instruction_bytes.cc
index b5b38ff08191b..87e797a00ae13 100644
--- a/test/asan/TestCases/Posix/dump_instruction_bytes.cc
+++ b/test/sanitizer_common/TestCases/Posix/dump_instruction_bytes.cc
@@ -1,9 +1,12 @@
-// Check that ASan prints the faulting instruction bytes on
+// Check that sanitizer prints the faulting instruction bytes on
// dump_instruction_bytes=1
-// RUN: %clangxx_asan %s -o %t
-// RUN: %env_asan_opts=dump_instruction_bytes=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-DUMP
+
+// clang-format off
+// RUN: %clangxx %s -o %t
+// RUN: %env_tool_opts=dump_instruction_bytes=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-DUMP
// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NODUMP
-//
+// clang-format on
+
// REQUIRES: x86-target-arch
int main() {
diff --git a/test/sanitizer_common/TestCases/Posix/dump_registers.cc b/test/sanitizer_common/TestCases/Posix/dump_registers.cc
new file mode 100644
index 0000000000000..07e87bedc131c
--- /dev/null
+++ b/test/sanitizer_common/TestCases/Posix/dump_registers.cc
@@ -0,0 +1,20 @@
+// Check that sanitizer prints registers dump_registers on dump_registers=1
+// RUN: %clangxx %s -o %t
+// RUN: %env_tool_opts=dump_registers=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NODUMP
+// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-DUMP
+//
+// FIXME: Implement.
+// UNSUPPORTED: asan
+// UNSUPPORTED: lsan
+// UNSUPPORTED: msan
+// UNSUPPORTED: tsan
+// UNSUPPORTED: ubsan
+
+#include <signal.h>
+
+int main() {
+ raise(SIGSEGV);
+ // CHECK-DUMP: Register values
+ // CHECK-NODUMP-NOT: Register values
+ return 0;
+}
diff --git a/test/sanitizer_common/TestCases/Posix/fpe.cc b/test/sanitizer_common/TestCases/Posix/fpe.cc
index 9a6f808a5cd79..c1e785a7ae828 100644
--- a/test/sanitizer_common/TestCases/Posix/fpe.cc
+++ b/test/sanitizer_common/TestCases/Posix/fpe.cc
@@ -1,13 +1,9 @@
// Test the handle_sigfpe option.
-// RUN: %clang %s -o %t
+// RUN: %clangxx %s -o %t
// RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK1 %s
// RUN: %env_tool_opts=handle_sigfpe=0 not --crash %run %t 2>&1 | FileCheck --check-prefix=CHECK0 %s
// RUN: %env_tool_opts=handle_sigfpe=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK1 %s
-// FIXME: implement in other sanitizers, not just asan.
-// XFAIL: msan
-// XFAIL: lsan
-// XFAIL: tsan
-//
+
// FIXME: seems to fail on ARM
// REQUIRES: x86_64-target-arch
#include <assert.h>
@@ -25,6 +21,9 @@ int main(int argc, char **argv) {
volatile int sink;
sink = one / zero;
}
-// CHECK1: ERROR: {{.*}}Sanitizer:
+
+// CHECK0-NOT: Sanitizer:DEADLYSIGNAL
+// CHECK1: ERROR: {{.*}}Sanitizer: FPE
+// CHECK1: {{#[0-9]+.* main .*fpe\.cc}}:[[@LINE-5]]
// CHECK1: DEATH CALLBACK
// CHECK0-NOT: Sanitizer
diff --git a/test/sanitizer_common/TestCases/Posix/getpass.cc b/test/sanitizer_common/TestCases/Posix/getpass.cc
index 251f9119d6828..b91a3d7d5264f 100644
--- a/test/sanitizer_common/TestCases/Posix/getpass.cc
+++ b/test/sanitizer_common/TestCases/Posix/getpass.cc
@@ -1,5 +1,8 @@
// RUN: %clangxx -O0 -g %s -lutil -o %t && %run %t | FileCheck %s
+
// REQUIRES: stable-runtime
+// XFAIL: android && asan
+
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
diff --git a/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc b/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc
index 12a56c73e0498..8d2db364114ac 100644
--- a/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc
+++ b/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc
@@ -8,6 +8,7 @@
// the last line of main function. The problem doesn't reproduce with ASan because
// quarantine prohibits memory block reuse for different allocations.
// XFAIL: lsan-x86
+// XFAIL: ubsan
#include <sanitizer/common_interface_defs.h>
#include <stdio.h>
diff --git a/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_fd_test.cc b/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_fd_test.cc
index af7eea1d7de2d..cc7de193f0a41 100644
--- a/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_fd_test.cc
+++ b/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_fd_test.cc
@@ -5,10 +5,7 @@
// RUN: not %run %t %t-out && FileCheck < %t-out %s
// REQUIRES: stable-runtime
-// FIXME: implement SEGV handler in other sanitizers, not just asan.
-// XFAIL: msan
-// XFAIL: lsan
-// XFAIL: tsan
+// XFAIL: android && asan
#include <sanitizer/common_interface_defs.h>
#include <stdio.h>
diff --git a/test/sanitizer_common/TestCases/Posix/weak_hook_test.cc b/test/sanitizer_common/TestCases/Posix/weak_hook_test.cc
index d5667649bb9c4..9176a524dbe89 100644
--- a/test/sanitizer_common/TestCases/Posix/weak_hook_test.cc
+++ b/test/sanitizer_common/TestCases/Posix/weak_hook_test.cc
@@ -4,6 +4,7 @@
// Hooks are not implemented for lsan.
// XFAIL: lsan
+// XFAIL: ubsan
#include <string.h>
#include <assert.h>
diff --git a/test/sanitizer_common/TestCases/corelimit.cc b/test/sanitizer_common/TestCases/corelimit.cc
index 0a86e5b7b7fe5..eb02afc01a1ba 100644
--- a/test/sanitizer_common/TestCases/corelimit.cc
+++ b/test/sanitizer_common/TestCases/corelimit.cc
@@ -1,5 +1,5 @@
// RUN: %clangxx -O0 %s -o %t && %run %t
-// UNSUPPORTED: lsan
+// UNSUPPORTED: lsan,ubsan
#include <assert.h>
#include <sys/time.h>
diff --git a/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc b/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc
index f5a18e6721cf5..69ccb7234fabc 100644
--- a/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc
+++ b/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc
@@ -1,8 +1,10 @@
// RUN: %clangxx -DSHARED %s -shared -o %T/get_module_and_offset_for_pc.so -fPIC
// RUN: %clangxx -DSO_DIR=\"%T\" -O0 %s -ldl -o %t
// RUN: %run %t 2>&1 | FileCheck %s
+
// UNSUPPORTED: i386-darwin
-//
+// XFAIL: android
+
// Tests __sanitizer_get_module_and_offset_for_pc.
#include <assert.h>
diff --git a/test/sanitizer_common/TestCases/malloc_hook.cc b/test/sanitizer_common/TestCases/malloc_hook.cc
index 59cd620b3f634..853bb66ac5c4d 100644
--- a/test/sanitizer_common/TestCases/malloc_hook.cc
+++ b/test/sanitizer_common/TestCases/malloc_hook.cc
@@ -2,6 +2,7 @@
// Malloc/free hooks are not supported on Windows.
// XFAIL: win32
+// XFAIL: ubsan
#include <stdlib.h>
#include <unistd.h>
diff --git a/test/sanitizer_common/TestCases/options-include.cc b/test/sanitizer_common/TestCases/options-include.cc
index 5b0b6d52585ac..3d9127b7f23dc 100644
--- a/test/sanitizer_common/TestCases/options-include.cc
+++ b/test/sanitizer_common/TestCases/options-include.cc
@@ -34,6 +34,8 @@
// RUN: %env_tool_opts=include_if_exists='"%t.options-not-found.%b"' %run %t 2>&1 | tee %t.out
// RUN: FileCheck %s --check-prefix=CHECK-WITHOUT-HELP --check-prefix=CHECK-FOUND < %t.out
+// Android tests run on remote device so includes will not work.
+// UNSUPPORTED: android
#include <stdio.h>
diff --git a/test/sanitizer_common/TestCases/print-stack-trace.cc b/test/sanitizer_common/TestCases/print-stack-trace.cc
index 0055b279666e5..fce8503663af8 100644
--- a/test/sanitizer_common/TestCases/print-stack-trace.cc
+++ b/test/sanitizer_common/TestCases/print-stack-trace.cc
@@ -1,8 +1,10 @@
// RUN: %clangxx -O0 %s -o %t && %env_tool_opts=stack_trace_format=DEFAULT %run %t 2>&1 | FileCheck %s
// RUN: %clangxx -O3 %s -o %t && %env_tool_opts=stack_trace_format=DEFAULT %run %t 2>&1 | FileCheck %s
-// RUN: %env_tool_opts=stack_trace_format='"frame:%n lineno:%l"' %run %t 2>&1 | FileCheck %s --check-prefix=CUSTOM
+// RUN: %env_tool_opts=stack_trace_format=frame%n_lineno%l %run %t 2>&1 | FileCheck %s --check-prefix=CUSTOM
// RUN: %env_tool_opts=symbolize_inline_frames=false:stack_trace_format=DEFAULT %run %t 2>&1 | FileCheck %s --check-prefix=NOINLINE
+// UNSUPPORTED: darwin
+
#include <sanitizer/common_interface_defs.h>
static inline void FooBarBaz() {
@@ -17,8 +19,8 @@ int main() {
// CHECK: {{ #1 0x.* in FooBarBaz(\(\))? .*}}print-stack-trace.cc:[[@LINE-8]]
// CHECK: {{ #2 0x.* in main.*}}print-stack-trace.cc:[[@LINE-5]]
-// CUSTOM: frame:1 lineno:[[@LINE-11]]
-// CUSTOM: frame:2 lineno:[[@LINE-8]]
+// CUSTOM: frame1_lineno[[@LINE-11]]
+// CUSTOM: frame2_lineno[[@LINE-8]]
// NOINLINE: #0 0x{{.*}} in __sanitizer_print_stack_trace
// NOINLINE: #1 0x{{.*}} in main{{.*}}print-stack-trace.cc:[[@LINE-15]]
diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc
index b7246ebf27510..58a64d1a92dc8 100644
--- a/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc
+++ b/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter.cc
@@ -1,11 +1,14 @@
-// Tests -fsanitize-coverage=inline-8bit-counters
+// Tests -fsanitize-coverage=inline-8bit-counters,pc-table
//
// REQUIRES: has_sancovcc,stable-runtime
// UNSUPPORTED: i386-darwin
//
-// RUN: %clangxx -O0 %s -fsanitize-coverage=inline-8bit-counters 2>&1
+// RUN: %clangxx -O0 %s -fsanitize-coverage=inline-8bit-counters,pc-table -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+// XFAIL: tsan
#include <stdio.h>
+#include <stdint.h>
#include <assert.h>
const char *first_counter;
@@ -17,7 +20,24 @@ void __sanitizer_cov_8bit_counters_init(const char *start, const char *end) {
first_counter = start;
}
+uintptr_t FirstPC;
+uintptr_t FirstPCFlag;
+
+extern "C" void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
+ const uintptr_t *pcs_end) {
+ const uintptr_t *B = (const uintptr_t *)pcs_beg;
+ const uintptr_t *E = (const uintptr_t *)pcs_end;
+ assert(B + 1 < E);
+ FirstPC = B[0];
+ FirstPCFlag = B[1];
+}
+
+
int main() {
assert(first_counter);
assert(*first_counter == 1);
+ assert(FirstPC == (uintptr_t)&main);
+ assert(FirstPCFlag == 1);
+ fprintf(stderr, "PASS\n");
+ // CHECK: PASS
}
diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc
index 8751930345e55..9604da222f8e9 100644
--- a/test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc
+++ b/test/sanitizer_common/TestCases/sanitizer_coverage_no_prune.cc
@@ -1,9 +1,10 @@
// Tests -fsanitize-coverage=no-prune
-//
+
// REQUIRES: has_sancovcc,stable-runtime
// UNSUPPORTED: i386-darwin
-// XFAIL: tsan
-//
+// XFAIL: ubsan,tsan
+// XFAIL: android && asan
+
// RUN: %clangxx -O0 %s -S -o - -emit-llvm -fsanitize-coverage=trace-pc,bb,no-prune 2>&1 | grep "call void @__sanitizer_cov_trace_pc" | count 3
// RUN: %clangxx -O0 %s -S -o - -emit-llvm -fsanitize-coverage=trace-pc,bb 2>&1 | grep "call void @__sanitizer_cov_trace_pc" | count 2
// RUN: %clangxx -O0 %s -S -o - -emit-llvm -fsanitize-coverage=trace-pc,no-prune 2>&1 | grep "call void @__sanitizer_cov_trace_pc" | count 4
diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_stack_depth.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_stack_depth.cc
new file mode 100644
index 0000000000000..90959ef5b0287
--- /dev/null
+++ b/test/sanitizer_common/TestCases/sanitizer_coverage_stack_depth.cc
@@ -0,0 +1,32 @@
+// Tests -fsanitize-coverage=stack-depth
+//
+// XFAIL: tsan
+//
+// RUN: %clangxx -O0 -std=c++11 -fsanitize-coverage=stack-depth %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s --implicit-check-not Assertion{{.*}}failed
+// RUN: %clangxx -O0 -std=c++11 -fsanitize-coverage=trace-pc-guard,stack-depth \
+// RUN: %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s --implicit-check-not Assertion{{.*}}failed
+
+#include <cstdint>
+#include <cstdio>
+#include <cassert>
+
+thread_local uintptr_t __sancov_lowest_stack;
+uintptr_t last_stack;
+
+void foo(int recurse) {
+ assert(__sancov_lowest_stack < last_stack);
+ last_stack = __sancov_lowest_stack;
+ if (recurse <= 0) return;
+ foo(recurse - 1);
+}
+
+int main() {
+ last_stack = __sancov_lowest_stack;
+ foo(100);
+ printf("Success!\n");
+ return 0;
+}
+
+// CHECK: Success!
diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc
index 6185177a169a4..7a2eca8bcd90a 100644
--- a/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc
+++ b/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc
@@ -1,8 +1,10 @@
// Tests trace pc guard coverage collection.
-//
+
// REQUIRES: has_sancovcc,stable-runtime
+// UNSUPPORTED: ubsan
// XFAIL: tsan,darwin,powerpc64,s390x,mips
-//
+// XFAIL: android && asan
+
// RUN: DIR=%t_workdir
// RUN: CLANG_ARGS="-O0 -fsanitize-coverage=trace-pc-guard"
// RUN: rm -rf $DIR
@@ -68,5 +70,5 @@ int baz() {
//
// CHECK-SANCOV: Ignoring {{.*}}_1.so and its coverage because __sanitizer_cov* functions were not found.
// CHECK-SANCOV: Ignoring {{.*}}_2.so and its coverage because __sanitizer_cov* functions were not found.
-// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard-dso.cc:29 foo
-// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard-dso.cc:34 main
+// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard-dso.cc:[[@LINE-42]] foo
+// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard-dso.cc:[[@LINE-38]] main
diff --git a/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc b/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc
index 2d6d00b6a0cdb..1adbf653bb76c 100644
--- a/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc
+++ b/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc
@@ -1,9 +1,10 @@
// Tests trace pc guard coverage collection.
-//
+
// REQUIRES: has_sancovcc,stable-runtime
-// UNSUPPORTED: i386-darwin
+// UNSUPPORTED: ubsan,i386-darwin
// XFAIL: tsan,powerpc64,s390x,mips
-//
+// XFAIL: android && asan
+
// RUN: DIR=%t_workdir
// RUN: rm -rf $DIR
// RUN: mkdir -p $DIR
@@ -15,9 +16,7 @@
// RUN: %env_tool_opts=coverage=0 %t 2>&1 | FileCheck --check-prefix=CHECK-NOCOV %s
// RUN: rm -rf $DIR
// Make some room to stabilize line numbers
-//
-//
-//
+
#include <stdio.h>
int foo() {
@@ -36,7 +35,7 @@ int main() {
// CHECK-NEXT: foo
// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard.{{.*}}.sancov: 2 PCs written
//
-// CHECK-SANCOV: sanitizer_coverage_trace_pc_guard.cc:23 foo
-// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard.cc:28 main
+// CHECK-SANCOV: sanitizer_coverage_trace_pc_guard.cc:[[@LINE-16]] foo
+// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard.cc:[[@LINE-12]] main
//
// CHECK-NOCOV-NOT: SanitizerCoverage
diff --git a/test/asan/android_commands/android_common.py b/test/sanitizer_common/android_commands/android_common.py
index 41994bb87a14b..fc26ee25835c6 100644
--- a/test/asan/android_commands/android_common.py
+++ b/test/sanitizer_common/android_commands/android_common.py
@@ -1,4 +1,4 @@
-import os, subprocess, tempfile
+import os, sys, subprocess, tempfile
import time
ANDROID_TMPDIR = '/data/local/tmp/Output'
@@ -8,6 +8,11 @@ verbose = False
if os.environ.get('ANDROID_RUN_VERBOSE') == '1':
verbose = True
+def host_to_device_path(path):
+ rel = os.path.relpath(path, "/")
+ dev = os.path.join(ANDROID_TMPDIR, rel)
+ return dev
+
def adb(args, attempts = 1):
if verbose:
print args
@@ -37,5 +42,5 @@ def pull_from_device(path):
return text
def push_to_device(path):
- dst_path = os.path.join(ANDROID_TMPDIR, os.path.basename(path))
+ dst_path = host_to_device_path(path)
adb(['push', path, dst_path], 5)
diff --git a/test/asan/android_commands/android_compile.py b/test/sanitizer_common/android_commands/android_compile.py
index 4b880886b0c1e..4b880886b0c1e 100755
--- a/test/asan/android_commands/android_compile.py
+++ b/test/sanitizer_common/android_commands/android_compile.py
diff --git a/test/asan/android_commands/android_run.py b/test/sanitizer_common/android_commands/android_run.py
index 7e599453d1c47..8a97aa5f7b1b3 100755
--- a/test/asan/android_commands/android_run.py
+++ b/test/sanitizer_common/android_commands/android_run.py
@@ -5,15 +5,14 @@ from android_common import *
ANDROID_TMPDIR = '/data/local/tmp/Output'
-here = os.path.abspath(os.path.dirname(sys.argv[0]))
-device_binary = os.path.join(ANDROID_TMPDIR, os.path.basename(sys.argv[0]))
+device_binary = host_to_device_path(sys.argv[0])
def build_env():
args = []
# Android linker ignores RPATH. Set LD_LIBRARY_PATH to Output dir.
args.append('LD_LIBRARY_PATH=%s' % (ANDROID_TMPDIR,))
for (key, value) in os.environ.items():
- if key in ['ASAN_OPTIONS', 'ASAN_ACTIVATION_OPTIONS']:
+ if key in ['ASAN_ACTIVATION_OPTIONS', 'SCUDO_OPTIONS'] or key.endswith('SAN_OPTIONS'):
args.append('%s="%s"' % (key, value))
return ' '.join(args)
diff --git a/test/sanitizer_common/lit.common.cfg b/test/sanitizer_common/lit.common.cfg
index da720a8504dbe..c7a1682f74042 100644
--- a/test/sanitizer_common/lit.common.cfg
+++ b/test/sanitizer_common/lit.common.cfg
@@ -18,21 +18,27 @@ elif config.tool_name == "msan":
elif config.tool_name == "lsan":
tool_cflags = ["-fsanitize=leak"]
tool_options = "LSAN_OPTIONS"
+elif config.tool_name == "ubsan":
+ tool_cflags = ["-fsanitize=undefined"]
+ tool_options = "UBSAN_OPTIONS"
else:
lit_config.fatal("Unknown tool for sanitizer_common tests: %r" % config.tool_name)
config.available_features.add(config.tool_name)
-if config.target_arch not in ['arm', 'armhf', 'aarch64']:
- config.available_features.add('stable-runtime')
-
-if config.host_os == 'Linux' and config.tool_name == "lsan" and (config.target_arch == 'i386' or config.target_arch == 'i686'):
+if config.host_os == 'Linux' and config.tool_name == "lsan" and config.target_arch == 'i386':
config.available_features.add("lsan-x86")
if config.host_os == 'Darwin':
# On Darwin, we default to `abort_on_error=1`, which would make tests run
# much slower. Let's override this and run lit tests with 'abort_on_error=0'.
default_tool_options += ['abort_on_error=0']
+elif config.android:
+ # The same as on Darwin, we default to "abort_on_error=1" which slows down
+ # testing. Also, all existing tests are using "not" instead of "not --crash"
+ # which does not work for abort()-terminated programs.
+ default_tool_options += ['abort_on_error=0']
+
default_tool_options_str = ':'.join(default_tool_options)
if default_tool_options_str:
config.environment[tool_options] = default_tool_options_str
diff --git a/test/scudo/CMakeLists.txt b/test/scudo/CMakeLists.txt
index a8990999722e1..513168b189d69 100644
--- a/test/scudo/CMakeLists.txt
+++ b/test/scudo/CMakeLists.txt
@@ -15,7 +15,15 @@ configure_lit_site_cfg(
set(SCUDO_TEST_ARCH ${SCUDO_SUPPORTED_ARCH})
foreach(arch ${SCUDO_TEST_ARCH})
- set(SCUDO_TEST_TARGET_ARCH ${arch})
+ if(ANDROID)
+ if (${arch} STREQUAL "i386")
+ set(SCUDO_TEST_TARGET_ARCH i686-android)
+ else()
+ set(SCUDO_TEST_TARGET_ARCH ${arch}-android)
+ endif()
+ else()
+ set(SCUDO_TEST_TARGET_ARCH ${arch})
+ endif()
string(TOLOWER "-${arch}" SCUDO_TEST_CONFIG_SUFFIX)
get_test_cc_for_arch(${arch} SCUDO_TEST_TARGET_CC SCUDO_TEST_TARGET_CFLAGS)
string(TOUPPER ${arch} ARCH_UPPER_CASE)
diff --git a/test/scudo/alignment.cpp b/test/scudo/alignment.c
index 125ad8cbe76f5..6235d50608db2 100644
--- a/test/scudo/alignment.cpp
+++ b/test/scudo/alignment.c
@@ -15,7 +15,7 @@ int main(int argc, char **argv)
if (!strcmp(argv[1], "pointers")) {
void *p = malloc(1U << 16);
assert(p);
- free(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p) | 1));
+ free((void *)((uintptr_t)p | 1));
}
return 0;
}
diff --git a/test/scudo/double-free.cpp b/test/scudo/double-free.cpp
index ddc520505ed11..56118038cf1f3 100644
--- a/test/scudo/double-free.cpp
+++ b/test/scudo/double-free.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_scudo %s -o %t
+// RUN: %clangxx_scudo %s -o %t
// RUN: not %run %t malloc 2>&1 | FileCheck %s
// RUN: not %run %t new 2>&1 | FileCheck %s
// RUN: not %run %t newarray 2>&1 | FileCheck %s
diff --git a/test/scudo/interface.cpp b/test/scudo/interface.cpp
index e9575adf31008..73ea0a738e43f 100644
--- a/test/scudo/interface.cpp
+++ b/test/scudo/interface.cpp
@@ -1,17 +1,22 @@
-// RUN: %clang_scudo %s -lstdc++ -o %t
-// RUN: %run %t ownership 2>&1
-// RUN: %run %t ownership-and-size 2>&1
-// RUN: %run %t heap-size 2>&1
+// RUN: %clangxx_scudo %s -lstdc++ -o %t
+// RUN: %run %t ownership 2>&1
+// RUN: %run %t ownership-and-size 2>&1
+// RUN: %run %t heap-size 2>&1
+// RUN: %env_scudo_opts="allocator_may_return_null=1" %run %t soft-limit 2>&1
+// RUN: %env_scudo_opts="allocator_may_return_null=1" not %run %t hard-limit 2>&1
+// UNSUPPORTED: armhf-linux
// Tests that the sanitizer interface functions behave appropriately.
#include <stdlib.h>
#include <assert.h>
#include <string.h>
+#include <unistd.h>
#include <vector>
#include <sanitizer/allocator_interface.h>
+#include <sanitizer/scudo_interface.h>
int main(int argc, char **argv)
{
@@ -42,6 +47,41 @@ int main(int argc, char **argv)
// allocator function.
assert(__sanitizer_get_heap_size() >= 0);
}
+ if (!strcmp(argv[1], "soft-limit")) {
+ // Verifies that setting the soft RSS limit at runtime works as expected.
+ std::vector<void *> pointers;
+ size_t size = 1 << 19; // 512Kb
+ for (int i = 0; i < 5; i++)
+ pointers.push_back(malloc(size));
+ // Set the soft RSS limit to 1Mb.
+ __scudo_set_rss_limit(1, 0);
+ usleep(20000);
+ // The following allocation should return NULL.
+ void *p = malloc(size);
+ assert(!p);
+ // Remove the soft RSS limit.
+ __scudo_set_rss_limit(0, 0);
+ // The following allocation should succeed.
+ p = malloc(size);
+ assert(p);
+ free(p);
+ while (!pointers.empty()) {
+ free(pointers.back());
+ pointers.pop_back();
+ }
+ }
+ if (!strcmp(argv[1], "hard-limit")) {
+ // Verifies that setting the hard RSS limit at runtime works as expected.
+ std::vector<void *> pointers;
+ size_t size = 1 << 19; // 512Kb
+ for (int i = 0; i < 5; i++)
+ pointers.push_back(malloc(size));
+ // Set the hard RSS limit to 1Mb
+ __scudo_set_rss_limit(1, 1);
+ usleep(20000);
+ // The following should trigger our death.
+ void *p = malloc(size);
+ }
return 0;
}
diff --git a/test/scudo/lit.cfg b/test/scudo/lit.cfg
index adf16f57bbbd8..028bf721b89e9 100644
--- a/test/scudo/lit.cfg
+++ b/test/scudo/lit.cfg
@@ -8,32 +8,53 @@ config.name = 'Scudo' + config.name_suffix
# Setup source root.
config.test_source_root = os.path.dirname(__file__)
-# Path to the static library
-base_lib = os.path.join(config.compiler_rt_libdir,
- "libclang_rt.scudo-%s.a" % config.target_arch)
-whole_archive = "-Wl,-whole-archive %s -Wl,-no-whole-archive " % base_lib
+# Path to the shared & static libraries
+shared_libscudo = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo-%s.so" % config.target_arch)
+static_libscudo = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo-%s.a" % config.target_arch)
+static_libscudo_cxx = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo_cxx-%s.a" % config.target_arch)
+
+whole_archive = "-Wl,-whole-archive %s -Wl,-no-whole-archive " % static_libscudo
+whole_archive_cxx = "-Wl,-whole-archive %s -Wl,-no-whole-archive " % static_libscudo_cxx
# Test suffixes.
config.suffixes = ['.c', '.cc', '.cpp']
-# C flags.
+# C & CXX flags.
c_flags = ([config.target_cflags] +
- ["-std=c++11",
- "-pthread",
+ ["-pthread",
"-fPIE",
"-pie",
"-O0",
"-UNDEBUG",
"-ldl",
- "-lrt",
"-Wl,--gc-sections"])
+# Android doesn't want -lrt.
+if not config.android:
+ c_flags += ["-lrt"]
+
+cxx_flags = (c_flags + config.cxx_mode_flags + ["-std=c++11"])
+
def build_invocation(compile_flags):
- return " " + " ".join([config.clang] + compile_flags) + " "
+ return " " + " ".join([config.clang] + compile_flags) + " "
# Add clang substitutions.
-config.substitutions.append( ("%clang_scudo ",
- build_invocation(c_flags) + whole_archive) )
+config.substitutions.append(("%clang ", build_invocation(c_flags)))
+config.substitutions.append(("%clang_scudo ", build_invocation(c_flags) + whole_archive))
+config.substitutions.append(("%clangxx_scudo ", build_invocation(cxx_flags) + whole_archive + whole_archive_cxx))
+config.substitutions.append(("%shared_libscudo", shared_libscudo))
+
+# Platform-specific default SCUDO_OPTIONS for lit tests.
+default_scudo_opts = ''
+if config.android:
+ # Android defaults to abort_on_error=1, which doesn't work for us.
+ default_scudo_opts = 'abort_on_error=0'
+
+if default_scudo_opts:
+ config.environment['SCUDO_OPTIONS'] = default_scudo_opts
+ default_scudo_opts += ':'
+config.substitutions.append(('%env_scudo_opts=',
+ 'env SCUDO_OPTIONS=' + default_scudo_opts))
# Hardened Allocator tests are currently supported on Linux only.
if config.host_os not in ['Linux']:
diff --git a/test/scudo/malloc.cpp b/test/scudo/malloc.cpp
index 50e52590f5651..6c6a6c464f29a 100644
--- a/test/scudo/malloc.cpp
+++ b/test/scudo/malloc.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_scudo %s -lstdc++ -o %t
+// RUN: %clangxx_scudo %s -lstdc++ -o %t
// RUN: %run %t 2>&1
// Tests that a regular workflow of allocation, memory fill and free works as
diff --git a/test/scudo/memalign.cpp b/test/scudo/memalign.c
index 82c54af8b0e49..1fe6e3ec7eed5 100644
--- a/test/scudo/memalign.cpp
+++ b/test/scudo/memalign.c
@@ -1,6 +1,7 @@
// RUN: %clang_scudo %s -o %t
-// RUN: %run %t valid 2>&1
-// RUN: %run %t invalid 2>&1
+// RUN: %run %t valid 2>&1
+// RUN: not %run %t invalid 2>&1
+// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1
// Tests that the various aligned allocation functions work as intended. Also
// tests for the condition where the alignment is not a power of 2.
@@ -8,21 +9,17 @@
#include <assert.h>
#include <errno.h>
#include <malloc.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-
-// Reduce the size of the quarantine, or the test can run out of aligned memory
-// on 32-bit for the larger alignments.
-extern "C" const char *__scudo_default_options() {
- return "QuarantineSizeMb=1";
-}
+#include <unistd.h>
// Sometimes the headers may not have this...
-extern "C" void *aligned_alloc (size_t alignment, size_t size);
+void *aligned_alloc(size_t alignment, size_t size);
int main(int argc, char **argv)
{
- void *p = nullptr;
+ void *p = NULL;
size_t alignment = 1U << 12;
size_t size = 1U << 12;
int err;
@@ -32,9 +29,11 @@ int main(int argc, char **argv)
if (!strcmp(argv[1], "valid")) {
posix_memalign(&p, alignment, size);
assert(p);
+ assert(((uintptr_t)p & (alignment - 1)) == 0);
free(p);
p = aligned_alloc(alignment, size);
assert(p);
+ assert(((uintptr_t)p & (alignment - 1)) == 0);
free(p);
// Tests various combinations of alignment and sizes
for (int i = (sizeof(void *) == 4) ? 3 : 4; i < 19; i++) {
@@ -44,6 +43,7 @@ int main(int argc, char **argv)
for (int k = 0; k < 3; k++) {
p = memalign(alignment, size - (2 * sizeof(void *) * k));
assert(p);
+ assert(((uintptr_t)p & (alignment - 1)) == 0);
free(p);
}
}
@@ -54,6 +54,7 @@ int main(int argc, char **argv)
for (int k = 0; k < 3; k++) {
p = memalign(alignment, 0x1000 - (2 * sizeof(void *) * k));
assert(p);
+ assert(((uintptr_t)p & (alignment - 1)) == 0);
free(p);
}
}
diff --git a/test/scudo/mismatch.cpp b/test/scudo/mismatch.cpp
index 15dce83ce18aa..b49e0ea46f12e 100644
--- a/test/scudo/mismatch.cpp
+++ b/test/scudo/mismatch.cpp
@@ -1,10 +1,12 @@
-// RUN: %clang_scudo %s -o %t
-// RUN: SCUDO_OPTIONS=DeallocationTypeMismatch=1 not %run %t mallocdel 2>&1 | FileCheck %s
-// RUN: SCUDO_OPTIONS=DeallocationTypeMismatch=0 %run %t mallocdel 2>&1
-// RUN: SCUDO_OPTIONS=DeallocationTypeMismatch=1 not %run %t newfree 2>&1 | FileCheck %s
-// RUN: SCUDO_OPTIONS=DeallocationTypeMismatch=0 %run %t newfree 2>&1
-// RUN: SCUDO_OPTIONS=DeallocationTypeMismatch=1 not %run %t memaligndel 2>&1 | FileCheck %s
-// RUN: SCUDO_OPTIONS=DeallocationTypeMismatch=0 %run %t memaligndel 2>&1
+// RUN: %clangxx_scudo %s -o %t
+// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t mallocdel 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s
+// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t mallocdel 2>&1
+// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t newfree 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s
+// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t newfree 2>&1
+// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t memaligndel 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s
+// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t memaligndel 2>&1
+// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t memalignrealloc 2>&1 | FileCheck --check-prefix=CHECK-realloc %s
+// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t memalignrealloc 2>&1
// Tests that type mismatches between allocation and deallocation functions are
// caught when the related option is set.
@@ -32,7 +34,14 @@ int main(int argc, char **argv)
assert(p);
delete p;
}
+ if (!strcmp(argv[1], "memalignrealloc")) {
+ void *p = memalign(16, 16);
+ assert(p);
+ p = realloc(p, 32);
+ free(p);
+ }
return 0;
}
-// CHECK: ERROR: allocation type mismatch on address
+// CHECK-dealloc: ERROR: allocation type mismatch when deallocating address
+// CHECK-realloc: ERROR: allocation type mismatch when reallocating address
diff --git a/test/scudo/options.cpp b/test/scudo/options.cpp
index f4afe7d79bfcd..605b632413372 100644
--- a/test/scudo/options.cpp
+++ b/test/scudo/options.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_scudo %s -o %t
-// RUN: %run %t 2>&1
-// RUN: SCUDO_OPTIONS=DeallocationTypeMismatch=0 %run %t 2>&1
-// RUN: SCUDO_OPTIONS=DeallocationTypeMismatch=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_scudo %s -o %t
+// RUN: %run %t 2>&1
+// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t 2>&1
+// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t 2>&1 | FileCheck %s
// Tests that the options can be passed using getScudoDefaultOptions, and that
// the environment ones take precedence over them.
@@ -22,4 +22,4 @@ int main(int argc, char **argv)
return 0;
}
-// CHECK: ERROR: allocation type mismatch on address
+// CHECK: ERROR: allocation type mismatch when deallocating address
diff --git a/test/scudo/overflow.cpp b/test/scudo/overflow.c
index d12824578524e..c5a58f87f3058 100644
--- a/test/scudo/overflow.cpp
+++ b/test/scudo/overflow.c
@@ -1,6 +1,6 @@
// RUN: %clang_scudo %s -o %t
-// RUN: not %run %t malloc 2>&1 | FileCheck %s
-// RUN: SCUDO_OPTIONS=QuarantineSizeMb=1 not %run %t quarantine 2>&1 | FileCheck %s
+// RUN: not %run %t malloc 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=QuarantineSizeKb=64 not %run %t quarantine 2>&1 | FileCheck %s
// Tests that header corruption of an allocated or quarantined chunk is caught.
@@ -29,7 +29,7 @@ int main(int argc, char **argv)
((char *)p)[-(offset + 2)] ^= 1;
// Trigger the quarantine recycle
for (int i = 0; i < 0x100; i++) {
- p = malloc(1U << 16);
+ p = malloc(1U << 8);
free(p);
}
}
diff --git a/test/scudo/preinit.cpp b/test/scudo/preinit.c
index b8c01a401dd7f..792b2368e37d0 100644
--- a/test/scudo/preinit.cpp
+++ b/test/scudo/preinit.c
@@ -4,11 +4,15 @@
// Verifies that calling malloc in a preinit_array function succeeds, and that
// the resulting pointer can be freed at program termination.
+// On some Android versions, calling mmap() from a preinit function segfaults.
+// It looks like __mmap2.S ends up calling a NULL function pointer.
+// UNSUPPORTED: android
+
#include <assert.h>
#include <stdlib.h>
#include <string.h>
-static void *global_p = nullptr;
+static void *global_p = NULL;
void __init(void) {
global_p = malloc(1);
diff --git a/test/scudo/preload.cpp b/test/scudo/preload.cpp
new file mode 100644
index 0000000000000..b41a70e472b3e
--- /dev/null
+++ b/test/scudo/preload.cpp
@@ -0,0 +1,20 @@
+// Test that the preloaded runtime works without linking the static library.
+
+// RUN: %clang %s -lstdc++ -o %t
+// RUN: env LD_PRELOAD=%shared_libscudo not %run %t 2>&1 | FileCheck %s
+
+// This way of setting LD_PRELOAD does not work with Android test runner.
+// REQUIRES: !android
+
+#include <assert.h>
+
+int main(int argc, char *argv[]) {
+ int *p = new int;
+ assert(p);
+ *p = 0;
+ delete p;
+ delete p;
+ return 0;
+}
+
+// CHECK: ERROR: invalid chunk state
diff --git a/test/scudo/quarantine.c b/test/scudo/quarantine.c
new file mode 100644
index 0000000000000..ddbb92005b841
--- /dev/null
+++ b/test/scudo/quarantine.c
@@ -0,0 +1,124 @@
+// RUN: %clang_scudo %s -o %t
+// RUN: %env_scudo_opts="QuarantineSizeMb=1:QuarantineSizeKb=64" not %run %t unused 2>&1
+// RUN: %env_scudo_opts="QuarantineSizeMb=1:QuarantineChunksUpToSize=256" not %run %t unused 2>&1
+// RUN: %env_scudo_opts="QuarantineSizeKb=0:ThreadLocalQuarantineSizeKb=0" %run %t zeroquarantine 2>&1
+// RUN: %env_scudo_opts=QuarantineSizeKb=64 %run %t smallquarantine 2>&1
+// RUN: %env_scudo_opts=QuarantineChunksUpToSize=256 %run %t threshold 2>&1
+// RUN: %env_scudo_opts="QuarantineSizeMb=1" %run %t oldquarantine 2>&1
+
+// Tests that the quarantine prevents a chunk from being reused right away.
+// Also tests that a chunk will eventually become available again for
+// allocation when the recycling criteria has been met. Finally, tests the
+// threshold up to which a chunk is quarantine, and the old quarantine behavior.
+
+#include <assert.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sanitizer/allocator_interface.h>
+
+int main(int argc, char **argv)
+{
+ void *p, *old_p;
+ size_t allocated_bytes, size = 1U << 8, alignment = 1U << 8;
+
+ assert(argc == 2);
+ // First, warm up the allocator for the classes used.
+ p = malloc(size);
+ assert(p);
+ free(p);
+ p = malloc(size + 1);
+ assert(p);
+ free(p);
+ assert(posix_memalign(&p, alignment, size) == 0);
+ assert(p);
+ free(p);
+ assert(posix_memalign(&p, alignment, size + 1) == 0);
+ assert(p);
+ free(p);
+
+ if (!strcmp(argv[1], "zeroquarantine")) {
+ // Verifies that a chunk is deallocated right away when the local and
+ // global quarantine sizes are 0.
+ allocated_bytes = __sanitizer_get_current_allocated_bytes();
+ p = malloc(size);
+ assert(p);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ free(p);
+ assert(__sanitizer_get_current_allocated_bytes() == allocated_bytes);
+ }
+ if (!strcmp(argv[1], "smallquarantine")) {
+ // The delayed freelist will prevent a chunk from being available right
+ // away.
+ p = malloc(size);
+ assert(p);
+ old_p = p;
+ free(p);
+ p = malloc(size);
+ assert(p);
+ assert(old_p != p);
+ free(p);
+
+ // Eventually the chunk should become available again.
+ char found = 0;
+ for (int i = 0; i < 0x200 && !found; i++) {
+ p = malloc(size);
+ assert(p);
+ found = (p == old_p);
+ free(p);
+ }
+ assert(found);
+ }
+ if (!strcmp(argv[1], "threshold")) {
+ // Verifies that a chunk of size greater than the threshold will be freed
+ // right away. Alignment has no impact on the threshold.
+ allocated_bytes = __sanitizer_get_current_allocated_bytes();
+ p = malloc(size + 1);
+ assert(p);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ free(p);
+ assert(__sanitizer_get_current_allocated_bytes() == allocated_bytes);
+ assert(posix_memalign(&p, alignment, size + 1) == 0);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ free(p);
+ assert(__sanitizer_get_current_allocated_bytes() == allocated_bytes);
+ // Verifies that a chunk of size lower or equal to the threshold will be
+ // quarantined.
+ p = malloc(size);
+ assert(p);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ free(p);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ allocated_bytes = __sanitizer_get_current_allocated_bytes();
+ assert(posix_memalign(&p, alignment, size) == 0);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ free(p);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ }
+ if (!strcmp(argv[1], "oldquarantine")) {
+ // Verifies that we quarantine everything if the deprecated quarantine
+ // option is specified. Alignment has no impact on the threshold.
+ allocated_bytes = __sanitizer_get_current_allocated_bytes();
+ p = malloc(size);
+ assert(p);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ free(p);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ allocated_bytes = __sanitizer_get_current_allocated_bytes();
+ assert(posix_memalign(&p, alignment, size) == 0);
+ assert(p);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ free(p);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ // Secondary backed allocation.
+ allocated_bytes = __sanitizer_get_current_allocated_bytes();
+ p = malloc(1U << 19);
+ assert(p);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ free(p);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
+ }
+
+ return 0;
+}
diff --git a/test/scudo/quarantine.cpp b/test/scudo/quarantine.cpp
deleted file mode 100644
index 39ce1bd91d31b..0000000000000
--- a/test/scudo/quarantine.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-// RUN: %clang_scudo %s -o %t
-// RUN: SCUDO_OPTIONS="QuarantineSizeMb=0:ThreadLocalQuarantineSizeKb=0" %run %t zeroquarantine 2>&1
-// RUN: SCUDO_OPTIONS=QuarantineSizeMb=1 %run %t smallquarantine 2>&1
-
-// Tests that the quarantine prevents a chunk from being reused right away.
-// Also tests that a chunk will eventually become available again for
-// allocation when the recycling criteria has been met.
-
-#include <assert.h>
-#include <malloc.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sanitizer/allocator_interface.h>
-
-int main(int argc, char **argv)
-{
- void *p, *old_p;
- size_t allocated_bytes, size = 1U << 16;
-
- assert(argc == 2);
-
- if (!strcmp(argv[1], "zeroquarantine")) {
- // Verifies that a chunk is deallocated right away when the local and
- // global quarantine sizes are 0.
- allocated_bytes = __sanitizer_get_current_allocated_bytes();
- p = malloc(size);
- assert(p);
- assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
- free(p);
- assert(__sanitizer_get_current_allocated_bytes() == allocated_bytes);
- }
- if (!strcmp(argv[1], "smallquarantine")) {
- // The delayed freelist will prevent a chunk from being available right
- // away.
- p = malloc(size);
- assert(p);
- old_p = p;
- free(p);
- p = malloc(size);
- assert(p);
- assert(old_p != p);
- free(p);
-
- // Eventually the chunk should become available again.
- bool found = false;
- for (int i = 0; i < 0x100 && found == false; i++) {
- p = malloc(size);
- assert(p);
- found = (p == old_p);
- free(p);
- }
- assert(found == true);
- }
-
- return 0;
-}
diff --git a/test/scudo/random_shuffle.cpp b/test/scudo/random_shuffle.cpp
index 05a4326150176..f886cb1504e15 100644
--- a/test/scudo/random_shuffle.cpp
+++ b/test/scudo/random_shuffle.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_scudo %s -o %t
+// RUN: %clangxx_scudo %s -o %t
// RUN: rm -rf %T/random_shuffle_tmp_dir
// RUN: mkdir %T/random_shuffle_tmp_dir
// RUN: %run %t 100 > %T/random_shuffle_tmp_dir/out1
@@ -7,7 +7,6 @@
// RUN: %run %t 10000 > %T/random_shuffle_tmp_dir/out2
// RUN: not diff %T/random_shuffle_tmp_dir/out?
// RUN: rm -rf %T/random_shuffle_tmp_dir
-// UNSUPPORTED: i386-linux,i686-linux,arm-linux,armhf-linux,aarch64-linux,mips-linux,mipsel-linux,mips64-linux,mips64el-linux
// Tests that the allocator shuffles the chunks before returning to the user.
diff --git a/test/scudo/realloc.cpp b/test/scudo/realloc.cpp
index da377205f10ff..254c67a2cca4f 100644
--- a/test/scudo/realloc.cpp
+++ b/test/scudo/realloc.cpp
@@ -1,14 +1,13 @@
-// RUN: %clang_scudo %s -lstdc++ -o %t
-// RUN: %run %t pointers 2>&1
-// RUN: %run %t contents 2>&1
-// RUN: not %run %t memalign 2>&1 | FileCheck %s
+// RUN: %clangxx_scudo %s -lstdc++ -o %t
+// RUN: %run %t pointers 2>&1
+// RUN: %run %t contents 2>&1
+// RUN: %run %t usablesize 2>&1
// Tests that our reallocation function returns the same pointer when the
// requested size can fit into the previously allocated chunk. Also tests that
// a new chunk is returned if the size is greater, and that the contents of the
-// chunk are left unchanged.
-// As a final test, make sure that a chunk allocated by memalign cannot be
-// reallocated.
+// chunk are left unchanged. Finally, checks that realloc copies the usable
+// size of the old chunk to the new one (as opposed to the requested size).
#include <assert.h>
#include <malloc.h>
@@ -24,42 +23,65 @@ int main(int argc, char **argv)
assert(argc == 2);
- for (size_t size : sizes) {
- if (!strcmp(argv[1], "pointers")) {
- old_p = p = realloc(nullptr, size);
- assert(p);
- size = malloc_usable_size(p);
- // Our realloc implementation will return the same pointer if the size
- // requested is lower than or equal to the usable size of the associated
- // chunk.
- p = realloc(p, size - 1);
- assert(p == old_p);
+ if (!strcmp(argv[1], "usablesize")) {
+ // This tests a sketchy behavior inherited from poorly written libraries
+ // that have become somewhat standard. When realloc'ing a chunk, the
+ // copied contents should span the usable size of the chunk, not the
+ // requested size.
+ size_t size = 496, usable_size;
+ p = nullptr;
+ // Make sure we get a chunk with a usable size actually larger than size.
+ do {
+ if (p) free(p);
+ size += 16;
+ p = malloc(size);
+ usable_size = malloc_usable_size(p);
+ assert(usable_size >= size);
+ } while (usable_size == size);
+ for (int i = 0; i < usable_size; i++)
+ reinterpret_cast<char *>(p)[i] = 'A';
+ old_p = p;
+ // Make sure we get a different chunk so that the data is actually copied.
+ do {
+ size *= 2;
p = realloc(p, size);
- assert(p == old_p);
- // And a new one if the size is greater.
- p = realloc(p, size + 1);
- assert(p != old_p);
- // A size of 0 will free the chunk and return nullptr.
- p = realloc(p, 0);
- assert(!p);
- old_p = nullptr;
- }
- if (!strcmp(argv[1], "contents")) {
- p = realloc(nullptr, size);
assert(p);
- for (int i = 0; i < size; i++)
- reinterpret_cast<char *>(p)[i] = 'A';
- p = realloc(p, size + 1);
- // The contents of the reallocated chunk must match the original one.
- for (int i = 0; i < size; i++)
- assert(reinterpret_cast<char *>(p)[i] == 'A');
- }
- if (!strcmp(argv[1], "memalign")) {
- // A chunk coming from memalign cannot be reallocated.
- p = memalign(16, size);
- assert(p);
- p = realloc(p, size);
- free(p);
+ } while (p == old_p);
+ // The contents of the new chunk must match the old one up to usable_size.
+ for (int i = 0; i < usable_size; i++)
+ assert(reinterpret_cast<char *>(p)[i] == 'A');
+ free(p);
+ } else {
+ for (size_t size : sizes) {
+ if (!strcmp(argv[1], "pointers")) {
+ old_p = p = realloc(nullptr, size);
+ assert(p);
+ size = malloc_usable_size(p);
+ // Our realloc implementation will return the same pointer if the size
+ // requested is lower than or equal to the usable size of the associated
+ // chunk.
+ p = realloc(p, size - 1);
+ assert(p == old_p);
+ p = realloc(p, size);
+ assert(p == old_p);
+ // And a new one if the size is greater.
+ p = realloc(p, size + 1);
+ assert(p != old_p);
+ // A size of 0 will free the chunk and return nullptr.
+ p = realloc(p, 0);
+ assert(!p);
+ old_p = nullptr;
+ }
+ if (!strcmp(argv[1], "contents")) {
+ p = realloc(nullptr, size);
+ assert(p);
+ for (int i = 0; i < size; i++)
+ reinterpret_cast<char *>(p)[i] = 'A';
+ p = realloc(p, size + 1);
+ // The contents of the reallocated chunk must match the original one.
+ for (int i = 0; i < size; i++)
+ assert(reinterpret_cast<char *>(p)[i] == 'A');
+ }
}
}
return 0;
diff --git a/test/scudo/rss.c b/test/scudo/rss.c
new file mode 100644
index 0000000000000..4376290ad0cd6
--- /dev/null
+++ b/test/scudo/rss.c
@@ -0,0 +1,56 @@
+// RUN: %clang_scudo %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nolimit
+// RUN: %env_scudo_opts="soft_rss_limit_mb=256" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nolimit
+// RUN: %env_scudo_opts="hard_rss_limit_mb=256" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nolimit
+// RUN: %env_scudo_opts="soft_rss_limit_mb=64:allocator_may_return_null=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit
+// RUN: %env_scudo_opts="soft_rss_limit_mb=64:allocator_may_return_null=1" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit-returnnull
+// RUN: %env_scudo_opts="soft_rss_limit_mb=64:allocator_may_return_null=0:can_use_proc_maps_statm=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit
+// RUN: %env_scudo_opts="soft_rss_limit_mb=64:allocator_may_return_null=1:can_use_proc_maps_statm=0" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-softlimit-returnnull
+// RUN: %env_scudo_opts="hard_rss_limit_mb=64:allocator_may_return_null=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit
+// RUN: %env_scudo_opts="hard_rss_limit_mb=64:allocator_may_return_null=1" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit
+// RUN: %env_scudo_opts="hard_rss_limit_mb=64:allocator_may_return_null=0:can_use_proc_maps_statm=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit
+// RUN: %env_scudo_opts="hard_rss_limit_mb=64:allocator_may_return_null=1:can_use_proc_maps_statm=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-hardlimit
+
+// Tests that the soft and hard RSS limits work as intended. Without limit or
+// with a high limit, the test should pass without any malloc returning NULL or
+// the program dying.
+// If a limit is specified, it should return some NULL or die depending on
+// allocator_may_return_null. This should also work without statm.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static const size_t kNumAllocs = 128;
+static const size_t kAllocSize = 1 << 20; // 1MB.
+
+static void *allocs[kNumAllocs];
+
+int main(int argc, char *argv[]) {
+ int returned_null = 0;
+ for (int i = 0; i < kNumAllocs; i++) {
+ if ((i & 0xf) == 0)
+ usleep(50000);
+ allocs[i] = malloc(kAllocSize);
+ if (allocs[i])
+ memset(allocs[i], 0xff, kAllocSize); // Dirty the pages.
+ else
+ returned_null++;
+ }
+ for (int i = 0; i < kNumAllocs; i++)
+ free(allocs[i]);
+ if (returned_null == 0)
+ printf("All malloc calls succeeded\n");
+ else
+ printf("%d malloc calls returned NULL\n", returned_null);
+ return 0;
+}
+
+// CHECK-nolimit: All malloc calls succeeded
+// CHECK-softlimit: soft RSS limit exhausted
+// CHECK-softlimit-NOT: malloc calls
+// CHECK-softlimit-returnnull: soft RSS limit exhausted
+// CHECK-softlimit-returnnull: malloc calls returned NULL
+// CHECK-hardlimit: hard RSS limit exhausted
+// CHECK-hardlimit-NOT: malloc calls
diff --git a/test/scudo/secondary.cpp b/test/scudo/secondary.c
index dc14f8ca846ee..b770ca076b707 100644
--- a/test/scudo/secondary.cpp
+++ b/test/scudo/secondary.c
@@ -36,7 +36,7 @@ int main(int argc, char **argv)
assert(p);
memset(p, 'A', size); // This should not trigger anything.
// Set up the SIGSEGV handler now, as the rest should trigger an AV.
- sigaction(SIGSEGV, &a, nullptr);
+ sigaction(SIGSEGV, &a, NULL);
if (!strcmp(argv[1], "after")) {
for (int i = 0; i < page_size; i++)
p[size + i] = 'A';
diff --git a/test/scudo/sized-delete.cpp b/test/scudo/sized-delete.cpp
index e467f556520e5..85df05e2f809c 100644
--- a/test/scudo/sized-delete.cpp
+++ b/test/scudo/sized-delete.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_scudo -fsized-deallocation %s -o %t
-// RUN: SCUDO_OPTIONS=DeleteSizeMismatch=1 %run %t gooddel 2>&1
-// RUN: SCUDO_OPTIONS=DeleteSizeMismatch=1 not %run %t baddel 2>&1 | FileCheck %s
-// RUN: SCUDO_OPTIONS=DeleteSizeMismatch=0 %run %t baddel 2>&1
-// RUN: SCUDO_OPTIONS=DeleteSizeMismatch=1 %run %t gooddelarr 2>&1
-// RUN: SCUDO_OPTIONS=DeleteSizeMismatch=1 not %run %t baddelarr 2>&1 | FileCheck %s
-// RUN: SCUDO_OPTIONS=DeleteSizeMismatch=0 %run %t baddelarr 2>&1
+// RUN: %clangxx_scudo -fsized-deallocation %s -o %t
+// RUN: %env_scudo_opts=DeleteSizeMismatch=1 %run %t gooddel 2>&1
+// RUN: %env_scudo_opts=DeleteSizeMismatch=1 not %run %t baddel 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=DeleteSizeMismatch=0 %run %t baddel 2>&1
+// RUN: %env_scudo_opts=DeleteSizeMismatch=1 %run %t gooddelarr 2>&1
+// RUN: %env_scudo_opts=DeleteSizeMismatch=1 not %run %t baddelarr 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=DeleteSizeMismatch=0 %run %t baddelarr 2>&1
// Ensures that the sized delete operator errors out when the appropriate
// option is passed and the sizes do not match between allocation and
diff --git a/test/scudo/sizes.cpp b/test/scudo/sizes.cpp
index a0994c2515a2e..73fc71f25c541 100644
--- a/test/scudo/sizes.cpp
+++ b/test/scudo/sizes.cpp
@@ -1,13 +1,13 @@
-// RUN: %clang_scudo %s -lstdc++ -o %t
-// RUN: SCUDO_OPTIONS=allocator_may_return_null=0 not %run %t malloc 2>&1 | FileCheck %s
-// RUN: SCUDO_OPTIONS=allocator_may_return_null=1 %run %t malloc 2>&1
-// RUN: SCUDO_OPTIONS=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s
-// RUN: SCUDO_OPTIONS=allocator_may_return_null=1 %run %t calloc 2>&1
-// RUN: SCUDO_OPTIONS=allocator_may_return_null=0 not %run %t new 2>&1 | FileCheck %s
-// RUN: SCUDO_OPTIONS=allocator_may_return_null=1 not %run %t new 2>&1 | FileCheck %s
-// RUN: SCUDO_OPTIONS=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 | FileCheck %s
-// RUN: SCUDO_OPTIONS=allocator_may_return_null=1 %run %t new-nothrow 2>&1
-// RUN: %run %t usable 2>&1
+// RUN: %clangxx_scudo %s -lstdc++ -o %t
+// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t malloc 2>&1
+// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t calloc 2>&1
+// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=allocator_may_return_null=1 not %run %t new 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 | FileCheck %s
+// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t new-nothrow 2>&1
+// RUN: %run %t usable 2>&1
// Tests for various edge cases related to sizes, notably the maximum size the
// allocator can allocate. Tests that an integer overflow in the parameters of
diff --git a/test/scudo/threads.cpp b/test/scudo/threads.c
index d9f4a86c1acf3..b34e6f0f79a2d 100644
--- a/test/scudo/threads.cpp
+++ b/test/scudo/threads.c
@@ -1,6 +1,6 @@
// RUN: %clang_scudo %s -o %t
-// RUN: SCUDO_OPTIONS="QuarantineSizeMb=0:ThreadLocalQuarantineSizeKb=0" %run %t 5 1000000 2>&1
-// RUN: SCUDO_OPTIONS="QuarantineSizeMb=1:ThreadLocalQuarantineSizeKb=64" %run %t 5 1000000 2>&1
+// RUN: %env_scudo_opts="QuarantineSizeKb=0:ThreadLocalQuarantineSizeKb=0" %run %t 5 1000000 2>&1
+// RUN: %env_scudo_opts="QuarantineSizeKb=1024:ThreadLocalQuarantineSizeKb=64" %run %t 5 1000000 2>&1
// Tests parallel allocations and deallocations of memory chunks from a number
// of concurrent threads, with and without quarantine.
@@ -20,7 +20,7 @@ pthread_t tid[kMaxNumThreads];
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-bool go = false;
+char go = 0;
void *thread_fun(void *arg) {
pthread_mutex_lock(&mutex);
@@ -51,7 +51,7 @@ int main(int argc, char** argv) {
for (int i = 0; i < num_threads; i++)
pthread_create(&tid[i], 0, thread_fun, 0);
pthread_mutex_lock(&mutex);
- go = true;
+ go = 1;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
for (int i = 0; i < num_threads; i++)
diff --git a/test/scudo/tsd_destruction.c b/test/scudo/tsd_destruction.c
new file mode 100644
index 0000000000000..1b0d0eff9f11b
--- /dev/null
+++ b/test/scudo/tsd_destruction.c
@@ -0,0 +1,42 @@
+// RUN: %clang_scudo %s -o %t
+// RUN: %run %t 2>&1
+
+#include <locale.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Some of glibc's own thread local data is destroyed after a user's thread
+// local destructors are called, via __libc_thread_freeres. This might involve
+// calling free, as is the case for strerror_thread_freeres.
+// If there is no prior heap operation in the thread, this free would end up
+// initializing some thread specific data that would never be destroyed
+// properly, while still being deallocated when the TLS goes away. As a result,
+// a program could SEGV, usually in
+// __sanitizer::AllocatorGlobalStats::Unregister, where one of the doubly
+// linked list links would refer to a now unmapped memory area.
+
+// This test reproduces those circumstances. Success means executing without
+// a segmentation fault.
+
+const int kNumThreads = 16;
+pthread_t tid[kNumThreads];
+
+void *thread_func(void *arg) {
+ uintptr_t i = (uintptr_t)arg;
+ if ((i & 1) == 0) free(malloc(16));
+ // Calling strerror_l allows for strerror_thread_freeres to be called.
+ strerror_l(0, LC_GLOBAL_LOCALE);
+ return 0;
+}
+
+int main(int argc, char** argv) {
+ for (uintptr_t j = 0; j < 8; j++) {
+ for (uintptr_t i = 0; i < kNumThreads; i++)
+ pthread_create(&tid[i], 0, thread_func, (void *)i);
+ for (uintptr_t i = 0; i < kNumThreads; i++)
+ pthread_join(tid[i], 0);
+ }
+ return 0;
+}
diff --git a/test/scudo/valloc.c b/test/scudo/valloc.c
new file mode 100644
index 0000000000000..132c4f2802204
--- /dev/null
+++ b/test/scudo/valloc.c
@@ -0,0 +1,65 @@
+// RUN: %clang_scudo %s -o %t
+// RUN: %run %t valid 2>&1
+// RUN: not %run %t invalid 2>&1
+// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1
+// UNSUPPORTED: android, armhf-linux
+
+// Tests that valloc and pvalloc work as intended.
+
+#include <assert.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+size_t round_up_to(size_t size, size_t alignment) {
+ return (size + alignment - 1) & ~(alignment - 1);
+}
+
+int main(int argc, char **argv)
+{
+ void *p = NULL;
+ size_t size, page_size;
+
+ assert(argc == 2);
+
+ page_size = sysconf(_SC_PAGESIZE);
+ // Check that the page size is a power of two.
+ assert((page_size & (page_size - 1)) == 0);
+
+ if (!strcmp(argv[1], "valid")) {
+ for (int i = (sizeof(void *) == 4) ? 3 : 4; i < 21; i++) {
+ size = 1U << i;
+ p = valloc(size - (2 * sizeof(void *)));
+ assert(p);
+ assert(((uintptr_t)p & (page_size - 1)) == 0);
+ free(p);
+ p = pvalloc(size - (2 * sizeof(void *)));
+ assert(p);
+ assert(((uintptr_t)p & (page_size - 1)) == 0);
+ assert(malloc_usable_size(p) >= round_up_to(size, page_size));
+ free(p);
+ p = valloc(size);
+ assert(p);
+ assert(((uintptr_t)p & (page_size - 1)) == 0);
+ free(p);
+ p = pvalloc(size);
+ assert(p);
+ assert(((uintptr_t)p & (page_size - 1)) == 0);
+ assert(malloc_usable_size(p) >= round_up_to(size, page_size));
+ free(p);
+ }
+ }
+ if (!strcmp(argv[1], "invalid")) {
+ // Size passed to pvalloc overflows when rounded up.
+ p = pvalloc((size_t)-1);
+ assert(!p);
+ assert(errno == ENOMEM);
+ errno = 0;
+ p = pvalloc((size_t)-page_size);
+ assert(!p);
+ assert(errno == ENOMEM);
+ }
+ return 0;
+}
diff --git a/test/tsan/CMakeLists.txt b/test/tsan/CMakeLists.txt
index a689086129521..2b1d3004b1def 100644
--- a/test/tsan/CMakeLists.txt
+++ b/test/tsan/CMakeLists.txt
@@ -7,9 +7,9 @@ endif()
if(NOT COMPILER_RT_STANDALONE_BUILD)
list(APPEND TSAN_TEST_DEPS tsan)
endif()
-if(COMPILER_RT_HAS_LIBCXX_SOURCES AND
+if(COMPILER_RT_LIBCXX_PATH AND
COMPILER_RT_TEST_COMPILER_ID STREQUAL "Clang"
- AND NOT APPLE)
+ AND NOT APPLE AND NOT ANDROID)
list(APPEND TSAN_TEST_DEPS libcxx_tsan)
set(TSAN_HAS_LIBCXX True)
else()
diff --git a/test/tsan/Darwin/xpc-race.mm b/test/tsan/Darwin/xpc-race.mm
index a1e214c12b7df..872c9ee73e138 100644
--- a/test/tsan/Darwin/xpc-race.mm
+++ b/test/tsan/Darwin/xpc-race.mm
@@ -1,22 +1,26 @@
-// RUN: %clang_tsan %s -o %t -framework Foundation
+// RUN: %clangxx_tsan %s -o %t -framework Foundation
// RUN: %deflake %run %t 2>&1 | FileCheck %s
// UNSUPPORTED: ios
#import <Foundation/Foundation.h>
#import <xpc/xpc.h>
+#import <stdatomic.h>
#import "../test.h"
long global;
-long received_msgs;
+_Atomic(long) msg_counter;
+_Atomic(long) processed_msgs;
xpc_connection_t server_conn;
xpc_connection_t client_conns[2];
int main(int argc, const char *argv[]) {
@autoreleasepool {
- NSLog(@"Hello world.");
+ fprintf(stderr, "Hello world.\n");
+ // CHECK: Hello world.
+
barrier_init(&barrier, 2);
dispatch_queue_t server_q = dispatch_queue_create("server.queue", DISPATCH_QUEUE_CONCURRENT);
@@ -24,21 +28,34 @@ int main(int argc, const char *argv[]) {
server_conn = xpc_connection_create(NULL, server_q);
xpc_connection_set_event_handler(server_conn, ^(xpc_object_t client) {
- NSLog(@"server event handler, client = %@", client);
+ fprintf(stderr, "server event handler, client = %p\n", client);
if (client == XPC_ERROR_CONNECTION_INTERRUPTED || client == XPC_ERROR_CONNECTION_INVALID) {
return;
}
xpc_connection_set_event_handler(client, ^(xpc_object_t object) {
- NSLog(@"received message: %@", object);
+ fprintf(stderr, "received message: %p\n", object);
- barrier_wait(&barrier);
- global = 42;
+ long msg_number = atomic_fetch_add_explicit(&msg_counter, 1, memory_order_relaxed);
- dispatch_sync(dispatch_get_main_queue(), ^{
- received_msgs++;
+ if (msg_number == 0)
+ barrier_wait(&barrier);
+
+ global++;
+ // CHECK: WARNING: ThreadSanitizer: data race
+ // CHECK: Write of size 8
+ // CHECK: #0 {{.*}}xpc-race.mm:[[@LINE-3]]
+ // CHECK: Previous write of size 8
+ // CHECK: #0 {{.*}}xpc-race.mm:[[@LINE-5]]
+ // CHECK: Location is global 'global'
+
+ if (msg_number == 1)
+ barrier_wait(&barrier);
- if (received_msgs >= 2) {
+ atomic_fetch_add(&processed_msgs, 1);
+
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ if (processed_msgs >= 2) {
xpc_connection_cancel(client_conns[0]);
xpc_connection_cancel(client_conns[1]);
xpc_connection_cancel(server_conn);
@@ -55,12 +72,12 @@ int main(int argc, const char *argv[]) {
for (int i = 0; i < 2; i++) {
client_conns[i] = xpc_connection_create_from_endpoint(endpoint);
xpc_connection_set_event_handler(client_conns[i], ^(xpc_object_t event) {
- NSLog(@"client event handler, event = %@", event);
+ fprintf(stderr, "client event handler, event = %p\n", event);
});
xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_string(msg, "hello", "world");
- NSLog(@"sending message: %@", msg);
+ fprintf(stderr, "sending message: %p\n", msg);
xpc_connection_send_message(client_conns[i], msg);
xpc_connection_resume(client_conns[i]);
@@ -68,16 +85,8 @@ int main(int argc, const char *argv[]) {
CFRunLoopRun();
- NSLog(@"Done.");
+ fprintf(stderr, "Done.\n");
+ // CHECK: Done.
}
return 0;
}
-
-// CHECK: Hello world.
-// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK: Write of size 8
-// CHECK: #0 {{.*}}xpc-race.mm:36
-// CHECK: Previous write of size 8
-// CHECK: #0 {{.*}}xpc-race.mm:36
-// CHECK: Location is global 'global'
-// CHECK: Done.
diff --git a/test/tsan/Linux/double_race.cc b/test/tsan/Linux/double_race.cc
new file mode 100644
index 0000000000000..2b4af35a2676e
--- /dev/null
+++ b/test/tsan/Linux/double_race.cc
@@ -0,0 +1,52 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
+#include "../test.h"
+#include <memory.h>
+
+// A reproducer for a known issue.
+// See reference to double_race.cc in tsan_rtl_report.cc for an explanation.
+
+char buf[16];
+volatile int nreport;
+
+void __sanitizer_report_error_summary(const char *summary) {
+ nreport++;
+}
+
+const int kEventPCBits = 61;
+
+extern "C" bool __tsan_symbolize_external(unsigned long pc, char *func_buf,
+ unsigned long func_siz,
+ char *file_buf,
+ unsigned long file_siz, int *line,
+ int *col) {
+ if (pc >> kEventPCBits) {
+ printf("bad PC passed to __tsan_symbolize_external: %lx\n", pc);
+ _exit(1);
+ }
+ return true;
+}
+
+void *Thread(void *arg) {
+ barrier_wait(&barrier);
+ memset(buf, 2, sizeof(buf));
+ return 0;
+}
+
+int main() {
+ barrier_init(&barrier, 2);
+ pthread_t t;
+ pthread_create(&t, 0, Thread, 0);
+ memset(buf, 1, sizeof(buf));
+ barrier_wait(&barrier);
+ pthread_join(t, 0);
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 8 at {{.*}} by thread T1:
+// CHECK: #0 memset
+// CHECK: #1 Thread
+// CHECK-NOT: bad PC passed to __tsan_symbolize_external
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 8 at {{.*}} by thread T1:
+// CHECK: #0 Thread
diff --git a/test/tsan/Linux/user_malloc.cc b/test/tsan/Linux/user_malloc.cc
index 6d51a9dd7d9b2..b470e6c543f87 100644
--- a/test/tsan/Linux/user_malloc.cc
+++ b/test/tsan/Linux/user_malloc.cc
@@ -1,5 +1,12 @@
// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+
// UNSUPPORTED: powerpc64le
+
+// FIXME: Remove the test or find how to fix this.
+// On some distributions, probably with newer glibc, tsan initialization calls
+// dlsym which then calls malloc and crashes because of tsan is not initialized.
+// UNSUPPORTED: linux
+
#include <stdio.h>
// Defined by tsan.
diff --git a/test/tsan/allocator_returns_null.cc b/test/tsan/allocator_returns_null.cc
index 852dda035f23a..5e2e2e9a53c73 100644
--- a/test/tsan/allocator_returns_null.cc
+++ b/test/tsan/allocator_returns_null.cc
@@ -37,9 +37,10 @@
// RUN: | FileCheck %s --check-prefix=CHECK-nnNULL
#include <assert.h>
-#include <string.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <limits>
#include <new>
@@ -51,6 +52,7 @@ int main(int argc, char **argv) {
const char *action = argv[1];
fprintf(stderr, "%s:\n", action);
+ // The limit enforced in tsan_mman.cc, user_alloc_internal function.
static const size_t kMaxAllowedMallocSizePlusOne = (1ULL << 40) + 1;
void *x = 0;
@@ -78,10 +80,13 @@ int main(int argc, char **argv) {
assert(0);
}
+ fprintf(stderr, "errno: %d\n", errno);
+
// The NULL pointer is printed differently on different systems, while (long)0
// is always the same.
fprintf(stderr, "x: %lx\n", (long)x);
free(x);
+
return x != 0;
}
@@ -101,14 +106,19 @@ int main(int argc, char **argv) {
// CHECK-nnCRASH: ThreadSanitizer's allocator is terminating the process
// CHECK-mNULL: malloc:
+// CHECK-mNULL: errno: 12
// CHECK-mNULL: x: 0
// CHECK-cNULL: calloc:
+// CHECK-cNULL: errno: 12
// CHECK-cNULL: x: 0
// CHECK-coNULL: calloc-overflow:
+// CHECK-coNULL: errno: 12
// CHECK-coNULL: x: 0
// CHECK-rNULL: realloc:
+// CHECK-rNULL: errno: 12
// CHECK-rNULL: x: 0
// CHECK-mrNULL: realloc-after-malloc:
+// CHECK-mrNULL: errno: 12
// CHECK-mrNULL: x: 0
// CHECK-nnNULL: new-nothrow:
// CHECK-nnNULL: x: 0
diff --git a/test/tsan/atexit3.cc b/test/tsan/atexit3.cc
new file mode 100644
index 0000000000000..43ba5bbf6919f
--- /dev/null
+++ b/test/tsan/atexit3.cc
@@ -0,0 +1,41 @@
+// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static void atexit5() {
+ fprintf(stderr, "5");
+}
+
+static void atexit4() {
+ fprintf(stderr, "4");
+}
+
+static void atexit3() {
+ fprintf(stderr, "3");
+}
+
+static void atexit2() {
+ fprintf(stderr, "2");
+}
+
+static void atexit1() {
+ fprintf(stderr, "1");
+}
+
+static void atexit0() {
+ fprintf(stderr, "\n");
+}
+
+int main() {
+ atexit(atexit0);
+ atexit(atexit1);
+ atexit(atexit2);
+ atexit(atexit3);
+ atexit(atexit4);
+ atexit(atexit5);
+}
+
+// CHECK-NOT: FATAL: ThreadSanitizer
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: 54321
diff --git a/test/tsan/cond_cancel.c b/test/tsan/cond_cancel.c
index fb6a66136b8af..5c497155cb69e 100644
--- a/test/tsan/cond_cancel.c
+++ b/test/tsan/cond_cancel.c
@@ -8,7 +8,7 @@
// (defined in sanitizer_thread_registry.cc). It might seem a bug on glibc,
// however the same version GLIBC-2.17 will not make fail the test on
// powerpc64 BE (VMA=46)
-// XFAIL: powerpc64-unknown-linux-gnu
+// UNSUPPORTED: powerpc64-unknown-linux-gnu
#include "test.h"
diff --git a/test/tsan/custom_mutex.h b/test/tsan/custom_mutex.h
index e3ac7a9a52a7f..8e226a170ec4f 100644
--- a/test/tsan/custom_mutex.h
+++ b/test/tsan/custom_mutex.h
@@ -6,15 +6,16 @@
// A very primitive mutex annotated with tsan annotations.
class Mutex {
public:
- Mutex(bool prof, unsigned flags)
+ Mutex(bool prof, unsigned create_flags, unsigned destroy_flags=0)
: prof_(prof)
, locked_(false)
- , seq_(0) {
- __tsan_mutex_create(this, flags);
+ , seq_(0)
+ , destroy_flags_(destroy_flags) {
+ __tsan_mutex_create(this, create_flags);
}
~Mutex() {
- __tsan_mutex_destroy(this, 0);
+ __tsan_mutex_destroy(this, destroy_flags_);
}
void Lock() {
@@ -57,6 +58,7 @@ class Mutex {
const bool prof_;
std::atomic<bool> locked_;
int seq_;
+ unsigned destroy_flags_;
// This models mutex profiling subsystem.
static Mutex prof_mu_;
diff --git a/test/tsan/custom_mutex4.cc b/test/tsan/custom_mutex4.cc
new file mode 100644
index 0000000000000..539a8be803c60
--- /dev/null
+++ b/test/tsan/custom_mutex4.cc
@@ -0,0 +1,33 @@
+// RUN: %clangxx_tsan -O1 --std=c++11 %s -o %t && %run %t 2>&1 | FileCheck %s
+#include "custom_mutex.h"
+
+#include <type_traits>
+
+// Test that the destruction events of a mutex are ignored when the
+// annotations request this.
+//
+// Use after destruction is UB, but __tsan_mutex_linker_init and
+// __tsan_mutex_not_static exist to support global variables of mutex type,
+// which might be accessed during program shutdown after the class's destructor
+// has run.
+
+int main() {
+ std::aligned_storage<sizeof(Mutex), alignof(Mutex)>::type mu1_store;
+ Mutex* mu1 = reinterpret_cast<Mutex*>(&mu1_store);
+ new(&mu1_store) Mutex(false, __tsan_mutex_linker_init);
+ mu1->Lock();
+ mu1->~Mutex();
+ mu1->Unlock();
+
+ std::aligned_storage<sizeof(Mutex), alignof(Mutex)>::type mu2_store;
+ Mutex* mu2 = reinterpret_cast<Mutex*>(&mu2_store);
+ new(&mu2_store) Mutex(false, 0, __tsan_mutex_not_static);
+ mu2->Lock();
+ mu2->~Mutex();
+ mu2->Unlock();
+
+ fprintf(stderr, "DONE\n");
+ return 0;
+}
+
+// CHECK: DONE
diff --git a/test/tsan/custom_mutex5.cc b/test/tsan/custom_mutex5.cc
new file mode 100644
index 0000000000000..ad906e38aeb19
--- /dev/null
+++ b/test/tsan/custom_mutex5.cc
@@ -0,0 +1,33 @@
+// RUN: %clangxx_tsan -O1 --std=c++11 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
+#include "custom_mutex.h"
+
+#include <type_traits>
+
+// Test that we detect the destruction of an in-use mutex when the
+// thread annotations don't otherwise disable the check.
+
+int main() {
+ std::aligned_storage<sizeof(Mutex), alignof(Mutex)>::type mu1_store;
+ Mutex* mu1 = reinterpret_cast<Mutex*>(&mu1_store);
+ new(&mu1_store) Mutex(false, 0);
+ mu1->Lock();
+ mu1->~Mutex();
+ mu1->Unlock();
+
+ std::aligned_storage<sizeof(Mutex), alignof(Mutex)>::type mu2_store;
+ Mutex* mu2 = reinterpret_cast<Mutex*>(&mu2_store);
+ new(&mu2_store)
+ Mutex(false, __tsan_mutex_not_static, __tsan_mutex_not_static);
+ mu2->Lock();
+ mu2->~Mutex();
+ mu2->Unlock();
+
+ fprintf(stderr, "DONE\n");
+ return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: destroy of a locked mutex
+// CHECK: main {{.*}}custom_mutex5.cc:14
+// CHECK: WARNING: ThreadSanitizer: destroy of a locked mutex
+// CHECK: main {{.*}}custom_mutex5.cc:22
+// CHECK: DONE
diff --git a/test/tsan/lit.cfg b/test/tsan/lit.cfg
index 0ab62db0907fd..fdbafefbc66fd 100644
--- a/test/tsan/lit.cfg
+++ b/test/tsan/lit.cfg
@@ -66,7 +66,7 @@ if config.has_libcxx and config.host_os != 'Darwin':
"-Wl,-rpath=%s" % libcxx_libdir]
def build_invocation(compile_flags):
- return " " + " ".join([config.compile_wrapper, config.clang] + compile_flags) + " "
+ return " " + " ".join([config.clang] + compile_flags) + " "
config.substitutions.append( ("%clang_tsan ", build_invocation(clang_tsan_cflags)) )
config.substitutions.append( ("%clangxx_tsan ", build_invocation(clang_tsan_cxxflags)) )
@@ -79,14 +79,11 @@ config.substitutions.append( ("%deflake ", os.path.join(os.path.dirname(__file__
# Default test suffixes.
config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm']
-# ThreadSanitizer tests are currently supported on FreeBSD, Linux and Darwin.
-if config.host_os not in ['FreeBSD', 'Linux', 'Darwin']:
+if config.host_os not in ['FreeBSD', 'Linux', 'Darwin', 'NetBSD']:
config.unsupported = True
-# Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL
-# because the test hangs.
-if config.target_arch != 'aarch64':
- config.available_features.add('stable-runtime')
+if config.android:
+ config.unsupported = True
if config.host_os == 'Darwin' and config.target_arch in ["x86_64", "x86_64h"]:
config.parallelism_group = "darwin-64bit-sanitizer"
diff --git a/test/tsan/map32bit.cc b/test/tsan/map32bit.cc
index 3b4f8990016e8..8aef27bc1900d 100644
--- a/test/tsan/map32bit.cc
+++ b/test/tsan/map32bit.cc
@@ -12,8 +12,8 @@
// XFAIL: aarch64
// XFAIL: powerpc64
-// MAP_32BIT doesn't exist on OS X.
-// UNSUPPORTED: darwin
+// MAP_32BIT doesn't exist on OS X and NetBSD.
+// UNSUPPORTED: darwin,netbsd
void *Thread(void *ptr) {
*(int*)ptr = 42;
@@ -45,4 +45,3 @@ int main() {
// CHECK: WARNING: ThreadSanitizer: data race
// CHECK: DONE
-
diff --git a/test/tsan/signal_pause.cc b/test/tsan/signal_pause.cc
new file mode 100644
index 0000000000000..cbcef9491e9e4
--- /dev/null
+++ b/test/tsan/signal_pause.cc
@@ -0,0 +1,35 @@
+// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+// Test that pause loop handles signals.
+
+#include "test.h"
+#include <signal.h>
+#include <errno.h>
+
+void handler(int signum) {
+ write(2, "DONE\n", 5);
+ _exit(0);
+}
+
+void *thread(void *arg) {
+ for (;;)
+ pause();
+ return 0;
+}
+
+int main(int argc, char** argv) {
+ struct sigaction act = {};
+ act.sa_handler = &handler;
+ if (sigaction(SIGUSR1, &act, 0)) {
+ fprintf(stderr, "sigaction failed %d\n", errno);
+ return 1;
+ }
+ pthread_t th;
+ pthread_create(&th, 0, thread, 0);
+ sleep(1); // give it time to block in pause
+ pthread_kill(th, SIGUSR1);
+ sleep(10); // signal handler must exit the process while we are here
+ return 0;
+}
+
+// CHECK: DONE
diff --git a/test/tsan/strerror_r.cc b/test/tsan/strerror_r.cc
index 06c92d3bb641d..ad482013012c2 100644
--- a/test/tsan/strerror_r.cc
+++ b/test/tsan/strerror_r.cc
@@ -11,7 +11,8 @@
char buffer[1000];
void *Thread(void *p) {
- return strerror_r(TEST_ERROR, buffer, sizeof(buffer));
+ strerror_r(TEST_ERROR, buffer, sizeof(buffer));
+ return buffer;
}
int main() {
diff --git a/test/tsan/thread_name.cc b/test/tsan/thread_name.cc
index 80d30b82d8b5f..17caa62ef4401 100644
--- a/test/tsan/thread_name.cc
+++ b/test/tsan/thread_name.cc
@@ -3,10 +3,14 @@
#if defined(__linux__)
#define USE_PTHREAD_SETNAME_NP __GLIBC_PREREQ(2, 12)
+#define tsan_pthread_setname_np pthread_setname_np
#elif defined(__FreeBSD__)
#include <pthread_np.h>
#define USE_PTHREAD_SETNAME_NP 1
-#define pthread_setname_np pthread_set_name_np
+#define tasn_pthread_setname_np pthread_set_name_np
+#elif defined(__NetBSD__)
+#define USE_PTHREAD_SETNAME_NP 1
+#define tsan_pthread_setname_np(a, b) pthread_setname_np((a), "%s", (void *)(b))
#else
#define USE_PTHREAD_SETNAME_NP 0
#endif
@@ -24,7 +28,7 @@ void *Thread1(void *x) {
void *Thread2(void *x) {
#if USE_PTHREAD_SETNAME_NP
- pthread_setname_np(pthread_self(), "Thread2");
+ tsan_pthread_setname_np(pthread_self(), "Thread2");
#else
AnnotateThreadName(__FILE__, __LINE__, "Thread2");
#endif
diff --git a/test/tsan/thread_name2.cc b/test/tsan/thread_name2.cc
index d7ed0f0d1952f..9ebac29ddb5ed 100644
--- a/test/tsan/thread_name2.cc
+++ b/test/tsan/thread_name2.cc
@@ -6,7 +6,11 @@
#if defined(__FreeBSD__)
#include <pthread_np.h>
-#define pthread_setname_np pthread_set_name_np
+#define tsan_pthread_setname_np pthread_set_name_np
+#elif defined(__NetBSD__)
+#define tsan_pthread_setname_np(a, b) pthread_setname_np((a), "%s", (void *)(b))
+#else
+#define tsan_pthread_setname_np pthread_setname_np
#endif
long long Global;
@@ -18,7 +22,7 @@ void *Thread1(void *x) {
}
void *Thread2(void *x) {
- pthread_setname_np(pthread_self(), "foobar2");
+ tsan_pthread_setname_np(pthread_self(), "foobar2");
Global--;
barrier_wait(&barrier);
return 0;
@@ -29,7 +33,7 @@ int main() {
pthread_t t[2];
pthread_create(&t[0], 0, Thread1, 0);
pthread_create(&t[1], 0, Thread2, 0);
- pthread_setname_np(t[0], "foobar1");
+ tsan_pthread_setname_np(t[0], "foobar1");
barrier_wait(&barrier);
pthread_join(t[0], NULL);
pthread_join(t[1], NULL);
diff --git a/test/tsan/tls_race.cc b/test/tsan/tls_race.cc
index b43a514cc8aa8..dd37ff01d9751 100644
--- a/test/tsan/tls_race.cc
+++ b/test/tsan/tls_race.cc
@@ -20,4 +20,5 @@ int main() {
// CHECK: WARNING: ThreadSanitizer: data race
// CHECK-Linux: Location is TLS of main thread.
// CHECK-FreeBSD: Location is TLS of main thread.
+// CHECK-NetBSD: Location is TLS of main thread.
// CHECK-Darwin: Location is heap block of size 4
diff --git a/test/tsan/tls_race2.cc b/test/tsan/tls_race2.cc
index b04ff67881009..f3139b69fc082 100644
--- a/test/tsan/tls_race2.cc
+++ b/test/tsan/tls_race2.cc
@@ -27,4 +27,5 @@ int main() {
// CHECK: WARNING: ThreadSanitizer: data race
// CHECK-Linux: Location is TLS of thread T1.
// CHECK-FreeBSD: Location is TLS of thread T1.
+// CHECK-NetBSD: Location is TLS of thread T1.
// CHECK-Darwin: Location is heap block of size 4
diff --git a/test/ubsan/CMakeLists.txt b/test/ubsan/CMakeLists.txt
index f4b73e87f56bb..7791681472fda 100644
--- a/test/ubsan/CMakeLists.txt
+++ b/test/ubsan/CMakeLists.txt
@@ -3,9 +3,20 @@ set(UBSAN_LIT_TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(UBSAN_TESTSUITES)
set(UBSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
-macro(add_ubsan_testsuite test_mode sanitizer arch)
+macro(add_ubsan_testsuite test_mode sanitizer arch lld thinlto)
set(UBSAN_LIT_TEST_MODE "${test_mode}")
- set(CONFIG_NAME ${UBSAN_LIT_TEST_MODE}-${arch})
+ set(CONFIG_NAME ${UBSAN_LIT_TEST_MODE})
+ if (${lld})
+ set(CONFIG_NAME ${CONFIG_NAME}-lld)
+ list(APPEND UBSAN_TEST_DEPS lld)
+ endif()
+ if (${thinlto})
+ set(CONFIG_NAME ${CONFIG_NAME}-thinlto)
+ list(APPEND UBSAN_TEST_DEPS LTO)
+ endif()
+ set(UBSAN_TEST_USE_LLD ${lld})
+ set(UBSAN_TEST_USE_THINLTO ${thinlto})
+ set(CONFIG_NAME ${CONFIG_NAME}-${arch})
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
@@ -15,6 +26,14 @@ macro(add_ubsan_testsuite test_mode sanitizer arch)
endif()
endmacro()
+macro(add_ubsan_testsuites test_mode sanitizer arch)
+ add_ubsan_testsuite(${test_mode} ${sanitizer} ${arch} False False)
+
+ if(COMPILER_RT_HAS_LLD AND arch STREQUAL "x86_64" AND NOT (APPLE OR WIN32))
+ add_ubsan_testsuite(${test_mode} ${sanitizer} ${arch} True False)
+ endif()
+endmacro()
+
set(UBSAN_TEST_ARCH ${UBSAN_SUPPORTED_ARCH})
if(APPLE)
darwin_filter_host_archs(UBSAN_SUPPORTED_ARCH UBSAN_TEST_ARCH)
@@ -23,23 +42,32 @@ endif()
foreach(arch ${UBSAN_TEST_ARCH})
set(UBSAN_TEST_TARGET_ARCH ${arch})
get_test_cc_for_arch(${arch} UBSAN_TEST_TARGET_CC UBSAN_TEST_TARGET_CFLAGS)
- add_ubsan_testsuite("Standalone" ubsan ${arch})
+ add_ubsan_testsuites("Standalone" ubsan ${arch})
if(COMPILER_RT_HAS_ASAN AND ";${ASAN_SUPPORTED_ARCH};" MATCHES ";${arch};")
# TODO(wwchrome): Re-enable ubsan for asan win 64-bit when ready.
# Disable ubsan with AddressSanitizer tests for Windows 64-bit.
if(NOT OS_NAME MATCHES "Windows" OR CMAKE_SIZEOF_VOID_P EQUAL 4)
- add_ubsan_testsuite("AddressSanitizer" asan ${arch})
+ add_ubsan_testsuites("AddressSanitizer" asan ${arch})
endif()
endif()
if(COMPILER_RT_HAS_MSAN AND ";${MSAN_SUPPORTED_ARCH};" MATCHES ";${arch};")
- add_ubsan_testsuite("MemorySanitizer" msan ${arch})
+ add_ubsan_testsuites("MemorySanitizer" msan ${arch})
endif()
- if(COMPILER_RT_HAS_TSAN AND ";${TSAN_SUPPORTED_ARCH};" MATCHES ";${arch};")
- add_ubsan_testsuite("ThreadSanitizer" tsan ${arch})
+ if(COMPILER_RT_HAS_TSAN AND ";${TSAN_SUPPORTED_ARCH};" MATCHES ";${arch};" AND NOT ANDROID)
+ add_ubsan_testsuites("ThreadSanitizer" tsan ${arch})
endif()
endforeach()
+if(APPLE)
+ foreach(arch ${UBSAN_TEST_ARCH})
+ set(UBSAN_TEST_TARGET_ARCH ${arch})
+ get_test_cc_for_arch(${arch} UBSAN_TEST_TARGET_CC UBSAN_TEST_TARGET_CFLAGS)
+ set(UBSAN_TEST_TARGET_CFLAGS "${UBSAN_TEST_TARGET_CFLAGS} -lc++abi")
+ add_ubsan_testsuites("StandaloneStatic" ubsan ${arch})
+ endforeach()
+endif()
+
add_lit_testsuite(check-ubsan "Running UndefinedBehaviorSanitizer tests"
${UBSAN_TESTSUITES}
DEPENDS ${UBSAN_TEST_DEPS})
diff --git a/test/ubsan/TestCases/Float/cast-overflow.cpp b/test/ubsan/TestCases/Float/cast-overflow.cpp
index 85c5049b40ab4..a53c663b13674 100644
--- a/test/ubsan/TestCases/Float/cast-overflow.cpp
+++ b/test/ubsan/TestCases/Float/cast-overflow.cpp
@@ -18,11 +18,17 @@
# define BYTE_ORDER __DARWIN_BYTE_ORDER
# define BIG_ENDIAN __DARWIN_BIG_ENDIAN
# define LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
# include <sys/endian.h>
-# define BYTE_ORDER _BYTE_ORDER
-# define BIG_ENDIAN _BIG_ENDIAN
-# define LITTLE_ENDIAN _LITTLE_ENDIAN
+# ifndef BYTE_ORDER
+# define BYTE_ORDER _BYTE_ORDER
+# endif
+# ifndef BIG_ENDIAN
+# define BIG_ENDIAN _BIG_ENDIAN
+# endif
+# ifndef LITTLE_ENDIAN
+# define LITTLE_ENDIAN _LITTLE_ENDIAN
+# endif
#elif defined(_WIN32)
# define BYTE_ORDER 0
# define BIG_ENDIAN 1
diff --git a/test/ubsan/TestCases/Integer/suppressions.cpp b/test/ubsan/TestCases/Integer/suppressions.cpp
index a9e660111bee0..f72d82edf278c 100644
--- a/test/ubsan/TestCases/Integer/suppressions.cpp
+++ b/test/ubsan/TestCases/Integer/suppressions.cpp
@@ -3,6 +3,7 @@
// Suppression by symbol name (unsigned-integer-overflow:do_overflow below)
// requires the compiler-rt runtime to be able to symbolize stack addresses.
// REQUIRES: can-symbolize
+// UNSUPPORTED: android
// Fails without any suppression.
// RUN: %env_ubsan_opts=halt_on_error=1 not %run %t 2>&1 | FileCheck %s
diff --git a/test/ubsan/TestCases/Misc/Inputs/no-interception-dso.c b/test/ubsan/TestCases/Misc/Inputs/no-interception-dso.c
new file mode 100644
index 0000000000000..5ccc9b63d7c28
--- /dev/null
+++ b/test/ubsan/TestCases/Misc/Inputs/no-interception-dso.c
@@ -0,0 +1,3 @@
+int dso_function(int i) {
+ return i + 1;
+}
diff --git a/test/ubsan/TestCases/Misc/bounds.cpp b/test/ubsan/TestCases/Misc/bounds.cpp
index 199690dad2a24..9f890f290b349 100644
--- a/test/ubsan/TestCases/Misc/bounds.cpp
+++ b/test/ubsan/TestCases/Misc/bounds.cpp
@@ -5,7 +5,23 @@
// RUN: %run %t 0 3 0 2>&1 | FileCheck %s --check-prefix=CHECK-B-3
// RUN: %run %t 0 0 4 2>&1 | FileCheck %s --check-prefix=CHECK-C-4
+int get_int(int *const p __attribute__((pass_object_size(0))), int i) {
+ // CHECK-A-2: bounds.cpp:[[@LINE+1]]:10: runtime error: index 2 out of bounds for type 'int *'
+ return p[i];
+}
+
+int get_double(double *const p __attribute__((pass_object_size(0))), int i) {
+ // CHECK-A-2: bounds.cpp:[[@LINE+1]]:10: runtime error: index 2 out of bounds for type 'double *'
+ return p[i];
+}
+
int main(int argc, char **argv) {
+ int bar[2];
+ get_int(bar, argv[1][0] - '0');
+
+ double baz[2];
+ get_double(baz, argv[1][0] - '0');
+
int arr[2][3][4] = {};
return arr[argv[1][0] - '0'][argv[2][0] - '0'][argv[3][0] - '0'];
diff --git a/test/ubsan/TestCases/Misc/builtins.cpp b/test/ubsan/TestCases/Misc/builtins.cpp
new file mode 100644
index 0000000000000..18c68b5917a5d
--- /dev/null
+++ b/test/ubsan/TestCases/Misc/builtins.cpp
@@ -0,0 +1,35 @@
+// REQUIRES: arch=x86_64
+//
+// RUN: %clangxx -fsanitize=builtin -w %s -O3 -o %t
+// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=RECOVER
+// RUN: %clangxx -fsanitize=builtin -fno-sanitize-recover=builtin -w %s -O3 -o %t.abort
+// RUN: not %run %t.abort 2>&1 | FileCheck %s --check-prefix=ABORT
+
+void check_ctz(int n) {
+ // ABORT: builtins.cpp:[[@LINE+2]]:17: runtime error: passing zero to ctz(), which is not a valid argument
+ // RECOVER: builtins.cpp:[[@LINE+1]]:17: runtime error: passing zero to ctz(), which is not a valid argument
+ __builtin_ctz(n);
+
+ // RECOVER: builtins.cpp:[[@LINE+1]]:18: runtime error: passing zero to ctz(), which is not a valid argument
+ __builtin_ctzl(n);
+
+ // RECOVER: builtins.cpp:[[@LINE+1]]:19: runtime error: passing zero to ctz(), which is not a valid argument
+ __builtin_ctzll(n);
+}
+
+void check_clz(int n) {
+ // RECOVER: builtins.cpp:[[@LINE+1]]:17: runtime error: passing zero to clz(), which is not a valid argument
+ __builtin_clz(n);
+
+ // RECOVER: builtins.cpp:[[@LINE+1]]:18: runtime error: passing zero to clz(), which is not a valid argument
+ __builtin_clzl(n);
+
+ // RECOVER: builtins.cpp:[[@LINE+1]]:19: runtime error: passing zero to clz(), which is not a valid argument
+ __builtin_clzll(n);
+}
+
+int main() {
+ check_ctz(0);
+ check_clz(0);
+ return 0;
+}
diff --git a/test/ubsan/TestCases/Misc/coverage-levels.cc b/test/ubsan/TestCases/Misc/coverage-levels.cc
index f96b487a487f4..05c19937ddf88 100644
--- a/test/ubsan/TestCases/Misc/coverage-levels.cc
+++ b/test/ubsan/TestCases/Misc/coverage-levels.cc
@@ -22,6 +22,7 @@
// Coverage is not yet implemented in TSan.
// XFAIL: ubsan-tsan
+// UNSUPPORTED: ubsan-standalone-static
volatile int sink;
int main(int argc, char **argv) {
diff --git a/test/ubsan/TestCases/Misc/no-interception.cpp b/test/ubsan/TestCases/Misc/no-interception.cpp
new file mode 100644
index 0000000000000..c82fed3bf3f69
--- /dev/null
+++ b/test/ubsan/TestCases/Misc/no-interception.cpp
@@ -0,0 +1,20 @@
+// REQUIRES: android
+
+// Tests that ubsan can detect errors on Android if libc appears before the
+// runtime in the library search order, which means that we cannot intercept
+// symbols.
+
+// RUN: %clangxx %p/Inputs/no-interception-dso.c -fsanitize=undefined -fPIC -shared -o %dynamiclib %ld_flags_rpath_so
+
+// Make sure that libc is first in DT_NEEDED.
+// RUN: %clangxx %s -lc -o %t %ld_flags_rpath_exe
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <limits.h>
+
+int dso_function(int);
+
+int main(int argc, char **argv) {
+ // CHECK: signed integer overflow
+ dso_function(INT_MAX);
+}
diff --git a/test/ubsan/TestCases/TypeCheck/Function/function.cpp b/test/ubsan/TestCases/TypeCheck/Function/function.cpp
index 6e7e314bf7e27..25b2bdc32c7aa 100644
--- a/test/ubsan/TestCases/TypeCheck/Function/function.cpp
+++ b/test/ubsan/TestCases/TypeCheck/Function/function.cpp
@@ -2,9 +2,7 @@
// RUN: %run %t 2>&1 | FileCheck %s
// Verify that we can disable symbolization if needed:
// RUN: %env_ubsan_opts=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM
-
-// -fsanitize=function is unsupported on Darwin yet.
-// XFAIL: darwin
+// XFAIL: win32,win64
#include <stdint.h>
@@ -18,9 +16,9 @@ void make_valid_call() {
}
void make_invalid_call() {
- // CHECK: function.cpp:25:3: runtime error: call to function f() through pointer to incorrect function type 'void (*)(int)'
- // CHECK-NEXT: function.cpp:11: note: f() defined here
- // NOSYM: function.cpp:25:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int)'
+ // CHECK: function.cpp:[[@LINE+4]]:3: runtime error: call to function f() through pointer to incorrect function type 'void (*)(int)'
+ // CHECK-NEXT: function.cpp:[[@LINE-11]]: note: f() defined here
+ // NOSYM: function.cpp:[[@LINE+2]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int)'
// NOSYM-NEXT: ({{.*}}+0x{{.*}}): note: (unknown) defined here
reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(f))(42);
}
diff --git a/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg b/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg
index 27c61a34387cd..a10159995f41c 100644
--- a/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg
+++ b/test/ubsan/TestCases/TypeCheck/Function/lit.local.cfg
@@ -1,3 +1,3 @@
# The function type checker is only supported on x86 and x86_64 for now.
-if config.root.host_arch not in ['x86', 'x86_64']:
+if config.target_arch not in ['x86', 'x86_64']:
config.unsupported = True
diff --git a/test/ubsan/TestCases/TypeCheck/Linux/PR33221.cpp b/test/ubsan/TestCases/TypeCheck/Linux/PR33221.cpp
index e026e8d057f22..a5e61c2d2439a 100644
--- a/test/ubsan/TestCases/TypeCheck/Linux/PR33221.cpp
+++ b/test/ubsan/TestCases/TypeCheck/Linux/PR33221.cpp
@@ -22,7 +22,7 @@ public:
int main() {
int page_size = getpagesize();
- void *non_accessible = mmap(nullptr, page_size, PROT_NONE,
+ void *non_accessible = mmap(nullptr, page_size * 2, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (non_accessible == MAP_FAILED)
diff --git a/test/ubsan/TestCases/TypeCheck/PR33221.cpp b/test/ubsan/TestCases/TypeCheck/PR33221.cpp
index c691e5fb2b0e2..65cbf5d000d9e 100644
--- a/test/ubsan/TestCases/TypeCheck/PR33221.cpp
+++ b/test/ubsan/TestCases/TypeCheck/PR33221.cpp
@@ -1,7 +1,8 @@
-// RUN: %clangxx -frtti -fsanitize=vptr -g %s -O3 -o %t
+// RUN: %clangxx -frtti -fsanitize=null,vptr -g %s -O3 -o %t
// RUN: %run %t 2>&1 | FileCheck %s
// REQUIRES: cxxabi
+// UNSUPPORTED: win32
#include <string.h>
diff --git a/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp b/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp
index 37ffe5b705f0d..f0659f4394388 100644
--- a/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp
+++ b/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp
@@ -1,4 +1,4 @@
-// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t
+// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr,null -g %s -O3 -o %t
// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-CORRUPTED-VTABLE --strict-whitespace
// UNSUPPORTED: win32
diff --git a/test/ubsan/TestCases/TypeCheck/vptr-non-unique-typeinfo.cpp b/test/ubsan/TestCases/TypeCheck/vptr-non-unique-typeinfo.cpp
index 8ab7bfcaa9449..7bc19bdae8fa4 100644
--- a/test/ubsan/TestCases/TypeCheck/vptr-non-unique-typeinfo.cpp
+++ b/test/ubsan/TestCases/TypeCheck/vptr-non-unique-typeinfo.cpp
@@ -1,8 +1,9 @@
-// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -I%p/Helpers -g %s -fPIC -shared -o %t-lib.so -DBUILD_SO
-// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -I%p/Helpers -g %s -O3 -o %t %t-lib.so
+// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -I%p/Helpers -g %s -fPIC -shared -o %dynamiclib -DBUILD_SO %ld_flags_rpath_so
+// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -I%p/Helpers -g %s -O3 -o %t %ld_flags_rpath_exe
// RUN: %run %t
//
// REQUIRES: cxxabi
+// UNSUPPORTED: win32
struct X {
virtual ~X() {}
diff --git a/test/ubsan/TestCases/TypeCheck/vptr-virtual-base-construction.cpp b/test/ubsan/TestCases/TypeCheck/vptr-virtual-base-construction.cpp
index dc27d9f39ce36..a86960d12ad70 100644
--- a/test/ubsan/TestCases/TypeCheck/vptr-virtual-base-construction.cpp
+++ b/test/ubsan/TestCases/TypeCheck/vptr-virtual-base-construction.cpp
@@ -2,6 +2,7 @@
// RUN: %run %t
// REQUIRES: cxxabi
+// UNSUPPORTED: win32
int volatile n;
diff --git a/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp b/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp
index 09deac1437245..aa0123c46e9cc 100644
--- a/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp
+++ b/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp
@@ -1,7 +1,8 @@
-// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t
+// RUN: %clangxx -frtti -fsanitize=null,vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
// REQUIRES: cxxabi
+// UNSUPPORTED: win32
struct S { virtual int f() { return 0; } };
struct T : virtual S {};
diff --git a/test/ubsan/TestCases/TypeCheck/vptr.cpp b/test/ubsan/TestCases/TypeCheck/vptr.cpp
index 53a79c9fc7ee3..1db41ddd0f2db 100644
--- a/test/ubsan/TestCases/TypeCheck/vptr.cpp
+++ b/test/ubsan/TestCases/TypeCheck/vptr.cpp
@@ -1,4 +1,4 @@
-// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t -mllvm -enable-tail-merge=false
+// RUN: %clangxx -frtti -fsanitize=null,vptr -fno-sanitize-recover=null,vptr -g %s -O3 -o %t -mllvm -enable-tail-merge=false
// RUN: %run %t rT && %run %t mT && %run %t fT && %run %t cT
// RUN: %run %t rU && %run %t mU && %run %t fU && %run %t cU
// RUN: %run %t rS && %run %t rV && %run %t oV
@@ -9,7 +9,9 @@
// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t fV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace
// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t cV 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --check-prefix=CHECK-%os-DOWNCAST --strict-whitespace
// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t oU 2>&1 | FileCheck %s --check-prefix=CHECK-OFFSET --check-prefix=CHECK-%os-OFFSET --strict-whitespace
-// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --check-prefix=CHECK-%os-NULL-MEMBER --strict-whitespace
+// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-INVALID-MEMBER --check-prefix=CHECK-%os-NULL-MEMBER --strict-whitespace
+// RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-INVALID-MEMBER --check-prefix=CHECK-%os-NULL-MEMBER --strict-whitespace
+// RUN: not %run %t nN 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMFUN --strict-whitespace
// RUN: (echo "vptr_check:S"; echo "vptr_check:T"; echo "vptr_check:U") > %t.supp
// RUN: %env_ubsan_opts=suppressions='"%t.supp"' %run %t mS
@@ -24,6 +26,9 @@
// RUN: %env_ubsan_opts=suppressions='"%t.loc-supp"' not %run %t x- 2>&1 | FileCheck %s --check-prefix=CHECK-LOC-SUPPRESS
// REQUIRES: stable-runtime, cxxabi
+// UNSUPPORTED: win32
+// Suppressions file not pushed to the device.
+// UNSUPPORTED: android
#include <new>
#include <assert.h>
#include <stdio.h>
@@ -99,6 +104,9 @@ int main(int argc, char **argv) {
case 'V':
p = reinterpret_cast<T*>(new U);
break;
+ case 'N':
+ p = 0;
+ break;
}
access_p(p, argv[1][0]);
@@ -134,11 +142,11 @@ int access_p(T *p, char type) {
// CHECK-Linux-MEMBER: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE+1]]
return p->b;
- // CHECK-NULL-MEMBER: vptr.cpp:[[@LINE-2]]:15: runtime error: member access within address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
- // CHECK-NULL-MEMBER-NEXT: [[PTR]]: note: object has invalid vptr
- // CHECK-NULL-MEMBER-NEXT: {{^ ?.. .. .. .. ?00 00 00 00 ?00 00 00 00 ?}}
- // CHECK-NULL-MEMBER-NEXT: {{^ \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
- // CHECK-NULL-MEMBER-NEXT: {{^ invalid vptr}}
+ // CHECK-INVALID-MEMBER: vptr.cpp:[[@LINE-2]]:15: runtime error: member access within address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
+ // CHECK-INVALID-MEMBER-NEXT: [[PTR]]: note: object has invalid vptr
+ // CHECK-INVALID-MEMBER-NEXT: {{^ ?.. .. .. .. ?00 00 00 00 ?00 00 00 00 ?}}
+ // CHECK-INVALID-MEMBER-NEXT: {{^ \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
+ // CHECK-INVALID-MEMBER-NEXT: {{^ invalid vptr}}
// CHECK-Linux-NULL-MEMBER: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE-7]]
case 'f':
@@ -168,6 +176,10 @@ int access_p(T *p, char type) {
// CHECK-Linux-DOWNCAST: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE+1]]
(void)static_cast<T*>(reinterpret_cast<S*>(p));
return 0;
+
+ case 'n':
+ // CHECK-NULL-MEMFUN: vptr.cpp:[[@LINE+1]]:15: runtime error: member call on null pointer of type 'T'
+ return p->g();
}
return 0;
}
diff --git a/test/ubsan/lit.common.cfg b/test/ubsan/lit.common.cfg
index e3a1367e748ac..83475a2dc36c0 100644
--- a/test/ubsan/lit.common.cfg
+++ b/test/ubsan/lit.common.cfg
@@ -11,27 +11,29 @@ def get_required_attr(config, attr_name):
"to lit.site.cfg " % attr_name)
return attr_value
+# Setup config name.
+config.name = 'UBSan-' + config.name_suffix
+
# Setup source root.
config.test_source_root = os.path.dirname(__file__)
-default_ubsan_opts = []
+default_ubsan_opts = list(config.default_sanitizer_opts)
# Choose between standalone and UBSan+ASan modes.
ubsan_lit_test_mode = get_required_attr(config, 'ubsan_lit_test_mode')
if ubsan_lit_test_mode == "Standalone":
- config.name = 'UBSan-Standalone-' + config.target_arch
config.available_features.add("ubsan-standalone")
clang_ubsan_cflags = []
+elif ubsan_lit_test_mode == "StandaloneStatic":
+ config.available_features.add("ubsan-standalone-static")
+ clang_ubsan_cflags = ['-static-libsan']
elif ubsan_lit_test_mode == "AddressSanitizer":
- config.name = 'UBSan-ASan-' + config.target_arch
config.available_features.add("ubsan-asan")
clang_ubsan_cflags = ["-fsanitize=address"]
default_ubsan_opts += ['detect_leaks=0']
elif ubsan_lit_test_mode == "MemorySanitizer":
- config.name = 'UBSan-MSan-' + config.target_arch
config.available_features.add("ubsan-msan")
clang_ubsan_cflags = ["-fsanitize=memory"]
elif ubsan_lit_test_mode == "ThreadSanitizer":
- config.name = 'UBSan-TSan-' + config.target_arch
config.available_features.add("ubsan-tsan")
clang_ubsan_cflags = ["-fsanitize=thread"]
else:
@@ -41,11 +43,7 @@ else:
if config.target_arch == 's390x':
# On SystemZ we need -mbackchain to make the fast unwinder work.
clang_ubsan_cflags.append("-mbackchain")
-if config.host_os == 'Darwin':
- # On Darwin, we default to `abort_on_error=1`, which would make tests run
- # much slower. Let's override this and run lit tests with 'abort_on_error=0'.
- default_ubsan_opts += ['abort_on_error=0']
- default_ubsan_opts += ['log_to_syslog=0']
+
default_ubsan_opts_str = ':'.join(default_ubsan_opts)
if default_ubsan_opts_str:
config.environment['UBSAN_OPTIONS'] = default_ubsan_opts_str
@@ -70,10 +68,9 @@ config.substitutions.append( ("%gmlt ", " ".join(config.debug_info_flags) + " ")
config.suffixes = ['.c', '.cc', '.cpp']
# Check that the host supports UndefinedBehaviorSanitizer tests
-if config.host_os not in ['Linux', 'Darwin', 'FreeBSD', 'Windows']:
+if config.host_os not in ['Linux', 'Darwin', 'FreeBSD', 'Windows', 'NetBSD']:
config.unsupported = True
-# Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL
-# because the test hangs or fails on one configuration and not the other.
-if config.target_arch.startswith('arm') == False and config.target_arch != 'aarch64':
- config.available_features.add('stable-runtime')
+config.available_features.add('arch=' + config.target_arch)
+
+config.excludes = ['Inputs']
diff --git a/test/ubsan/lit.site.cfg.in b/test/ubsan/lit.site.cfg.in
index d8242163af109..a4d7b50edafc4 100644
--- a/test/ubsan/lit.site.cfg.in
+++ b/test/ubsan/lit.site.cfg.in
@@ -1,9 +1,12 @@
@LIT_SITE_CFG_IN_HEADER@
# Tool-specific config options.
+config.name_suffix = "@CONFIG_NAME@"
config.ubsan_lit_test_mode = "@UBSAN_LIT_TEST_MODE@"
config.target_cflags = "@UBSAN_TEST_TARGET_CFLAGS@"
config.target_arch = "@UBSAN_TEST_TARGET_ARCH@"
+config.use_lld = @UBSAN_TEST_USE_LLD@
+config.use_thinlto = @UBSAN_TEST_USE_THINLTO@
# Load common config for all compiler-rt lit tests.
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
diff --git a/test/ubsan_minimal/CMakeLists.txt b/test/ubsan_minimal/CMakeLists.txt
new file mode 100644
index 0000000000000..712654e945186
--- /dev/null
+++ b/test/ubsan_minimal/CMakeLists.txt
@@ -0,0 +1,26 @@
+set(UBSAN_LIT_TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+
+set(UBSAN_TEST_ARCH ${UBSAN_SUPPORTED_ARCH})
+if(APPLE)
+ darwin_filter_host_archs(UBSAN_SUPPORTED_ARCH UBSAN_TEST_ARCH)
+endif()
+
+set(UBSAN_TESTSUITES)
+set(UBSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+if(NOT COMPILER_RT_STANDALONE_BUILD)
+ list(APPEND UBSAN_TEST_DEPS ubsan-minimal)
+endif()
+
+foreach(arch ${UBSAN_TEST_ARCH})
+ get_test_cc_for_arch(${arch} UBSAN_TEST_TARGET_CC UBSAN_TEST_TARGET_CFLAGS)
+ set(CONFIG_NAME ${arch})
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
+ list(APPEND UBSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+endforeach()
+
+add_lit_testsuite(check-ubsan-minimal "Running UndefinedBehaviorSanitizerMinimal tests"
+ ${UBSAN_TESTSUITES}
+ DEPENDS ${UBSAN_TEST_DEPS})
+set_target_properties(check-ubsan-minimal PROPERTIES FOLDER "Compiler-RT Misc")
diff --git a/test/ubsan_minimal/TestCases/recover-dedup-limit.cpp b/test/ubsan_minimal/TestCases/recover-dedup-limit.cpp
new file mode 100644
index 0000000000000..faa2b66ad80f9
--- /dev/null
+++ b/test/ubsan_minimal/TestCases/recover-dedup-limit.cpp
@@ -0,0 +1,41 @@
+// RUN: %clangxx -fsanitize=signed-integer-overflow -fsanitize-recover=all %s -o %t && %run %t 2>&1 | FileCheck %s
+
+#include <stdint.h>
+
+#define OVERFLOW \
+ x = 0x7FFFFFFE; \
+ x += __LINE__
+
+int main() {
+ int32_t x;
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+ OVERFLOW; // CHECK: add-overflow
+
+ // CHECK-NOT: add-overflow
+ OVERFLOW; // CHECK: too many errors
+ // CHECK-NOT: add-overflow
+ OVERFLOW;
+ OVERFLOW;
+ OVERFLOW;
+}
diff --git a/test/ubsan_minimal/TestCases/recover-dedup.cpp b/test/ubsan_minimal/TestCases/recover-dedup.cpp
new file mode 100644
index 0000000000000..4dfd6991ef117
--- /dev/null
+++ b/test/ubsan_minimal/TestCases/recover-dedup.cpp
@@ -0,0 +1,39 @@
+// RUN: %clangxx -w -fsanitize=signed-integer-overflow,nullability-return,returns-nonnull-attribute -fsanitize-recover=all %s -o %t && %run %t 2>&1 | FileCheck %s
+
+#include <stdint.h>
+#include <stdio.h>
+
+int *_Nonnull h() {
+ // CHECK: nullability-return
+ return NULL;
+}
+
+__attribute__((returns_nonnull))
+int *i() {
+ // CHECK: nonnull-return
+ return NULL;
+}
+
+__attribute__((noinline))
+int f(int x, int y) {
+ // CHECK: mul-overflow
+ return x * y;
+}
+
+__attribute__((noinline))
+int g(int x, int y) {
+ // CHECK: mul-overflow
+ return x * (y + 1);
+}
+
+int main() {
+ h();
+ i();
+ int x = 2;
+ for (int i = 0; i < 10; ++i)
+ x = f(x, x);
+ x = 2;
+ for (int i = 0; i < 10; ++i)
+ x = g(x, x);
+ // CHECK-NOT: mul-overflow
+}
diff --git a/test/ubsan_minimal/TestCases/test-darwin-interface.c b/test/ubsan_minimal/TestCases/test-darwin-interface.c
new file mode 100644
index 0000000000000..1da049f9a35c3
--- /dev/null
+++ b/test/ubsan_minimal/TestCases/test-darwin-interface.c
@@ -0,0 +1,16 @@
+// Check that the ubsan and ubsan-minimal runtimes have the same symbols,
+// making exceptions as necessary.
+//
+// REQUIRES: x86_64-darwin
+
+// RUN: nm -jgU `%clangxx -fsanitize-minimal-runtime -fsanitize=undefined %s -o %t '-###' 2>&1 | grep "libclang_rt.ubsan_minimal_osx_dynamic.dylib" | sed -e 's/.*"\(.*libclang_rt.ubsan_minimal_osx_dynamic.dylib\)".*/\1/'` | grep "^___ubsan_handle" \
+// RUN: | sed 's/_minimal//g' \
+// RUN: > %t.minimal.symlist
+//
+// RUN: nm -jgU `%clangxx -fno-sanitize-minimal-runtime -fsanitize=undefined %s -o %t '-###' 2>&1 | grep "libclang_rt.ubsan_osx_dynamic.dylib" | sed -e 's/.*"\(.*libclang_rt.ubsan_osx_dynamic.dylib\)".*/\1/'` | grep "^___ubsan_handle" \
+// RUN: | grep -vE "^___ubsan_handle_dynamic_type_cache_miss" \
+// RUN: | grep -vE "^___ubsan_handle_cfi_bad_type" \
+// RUN: | sed 's/_v1//g' \
+// RUN: > %t.full.symlist
+//
+// RUN: diff %t.minimal.symlist %t.full.symlist
diff --git a/test/ubsan_minimal/TestCases/uadd-overflow.cpp b/test/ubsan_minimal/TestCases/uadd-overflow.cpp
new file mode 100644
index 0000000000000..0345750123250
--- /dev/null
+++ b/test/ubsan_minimal/TestCases/uadd-overflow.cpp
@@ -0,0 +1,10 @@
+// RUN: %clangxx -fsanitize=unsigned-integer-overflow %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx -fsanitize=unsigned-integer-overflow -fno-sanitize-recover=all %s -o %t && not --crash %run %t 2>&1 | FileCheck %s
+
+#include <stdint.h>
+
+int main() {
+ uint32_t k = 0x87654321;
+ k += 0xedcba987;
+ // CHECK: add-overflow
+}
diff --git a/test/ubsan_minimal/lit.common.cfg b/test/ubsan_minimal/lit.common.cfg
new file mode 100644
index 0000000000000..e8b42bb823c89
--- /dev/null
+++ b/test/ubsan_minimal/lit.common.cfg
@@ -0,0 +1,40 @@
+# -*- Python -*-
+
+import os
+
+def get_required_attr(config, attr_name):
+ attr_value = getattr(config, attr_name, None)
+ if attr_value == None:
+ lit_config.fatal(
+ "No attribute %r in test configuration! You may need to run "
+ "tests from your build directory or add this attribute "
+ "to lit.site.cfg " % attr_name)
+ return attr_value
+
+# Setup source root.
+config.test_source_root = os.path.dirname(__file__)
+config.name = 'UBSan-Minimal-' + config.target_arch
+
+def build_invocation(compile_flags):
+ return " " + " ".join([config.clang] + compile_flags) + " "
+
+target_cflags = [get_required_attr(config, "target_cflags")]
+clang_ubsan_cflags = ["-fsanitize-minimal-runtime"] + target_cflags
+clang_ubsan_cxxflags = config.cxx_mode_flags + clang_ubsan_cflags
+
+# Define %clang and %clangxx substitutions to use in test RUN lines.
+config.substitutions.append( ("%clang ", build_invocation(clang_ubsan_cflags)) )
+config.substitutions.append( ("%clangxx ", build_invocation(clang_ubsan_cxxflags)) )
+
+# Default test suffixes.
+config.suffixes = ['.c', '.cc', '.cpp']
+
+# Check that the host supports UndefinedBehaviorSanitizerMinimal tests
+if config.host_os not in ['Linux', 'FreeBSD', 'NetBSD', 'Darwin']: # TODO: Windows
+ config.unsupported = True
+
+# Don't target x86_64h if the test machine can't execute x86_64h binaries.
+if '-arch x86_64h' in target_cflags and 'x86_64h' not in config.available_features:
+ config.unsupported = True
+
+config.available_features.add('arch=' + config.target_arch)
diff --git a/test/ubsan_minimal/lit.site.cfg.in b/test/ubsan_minimal/lit.site.cfg.in
new file mode 100644
index 0000000000000..d4dd68ef21355
--- /dev/null
+++ b/test/ubsan_minimal/lit.site.cfg.in
@@ -0,0 +1,11 @@
+@LIT_SITE_CFG_IN_HEADER@
+
+# Tool-specific config options.
+config.target_cflags = "@UBSAN_TEST_TARGET_CFLAGS@"
+config.target_arch = "@UBSAN_TEST_TARGET_ARCH@"
+
+# Load common config for all compiler-rt lit tests.
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
+
+# Load tool-specific config that would do the real work.
+lit_config.load_config(config, "@UBSAN_LIT_TESTS_DIR@/lit.common.cfg")
diff --git a/test/xray/TestCases/Linux/arg1-logger.cc b/test/xray/TestCases/Linux/arg1-logger.cc
index 955347b153ec7..25dda13fb23d9 100644
--- a/test/xray/TestCases/Linux/arg1-logger.cc
+++ b/test/xray/TestCases/Linux/arg1-logger.cc
@@ -2,11 +2,13 @@
// using a custom logging function.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
-// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=arg1-logger-" %run %t 2>&1 | FileCheck %s
+// RUN: rm arg1-logger-* || true
+// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_naive_log=true \
+// RUN: xray_logfile_base=arg1-logger-" %run %t 2>&1 | FileCheck %s
//
// After all that, clean up the XRay log file.
//
-// RUN: rm arg1-logger-*
+// RUN: rm arg1-logger-* || true
//
// At the time of writing, the ARM trampolines weren't written yet.
// XFAIL: arm || aarch64 || mips
@@ -29,7 +31,7 @@ int main() {
__xray_set_handler_arg1(arg1logger);
foo(nullptr);
- // CHECK: Arg1: 0, XRayEntryType 0
+ // CHECK: Arg1: 0, XRayEntryType 3
__xray_remove_handler_arg1();
foo((void *) 0xBADC0DE);
@@ -37,7 +39,7 @@ int main() {
__xray_set_handler_arg1(arg1logger);
foo((void *) 0xDEADBEEFCAFE);
- // CHECK-NEXT: Arg1: deadbeefcafe, XRayEntryType 0
+ // CHECK-NEXT: Arg1: deadbeefcafe, XRayEntryType 3
foo((void *) -1);
- // CHECK-NEXT: Arg1: ffffffffffffffff, XRayEntryType 0
+ // CHECK-NEXT: Arg1: ffffffffffffffff, XRayEntryType 3
}
diff --git a/test/xray/TestCases/Linux/argv0-log-file-name.cc b/test/xray/TestCases/Linux/argv0-log-file-name.cc
index 2960c57181e05..2f9a234f80644 100644
--- a/test/xray/TestCases/Linux/argv0-log-file-name.cc
+++ b/test/xray/TestCases/Linux/argv0-log-file-name.cc
@@ -6,6 +6,8 @@
// RUN: ls | FileCheck xray.log.file.name
// RUN: rm xray-log.* xray.log.file.name
+// UNSUPPORTED: target-is-mips64,target-is-mips64el
+
#include <cstdio>
#include <libgen.h>
diff --git a/test/xray/TestCases/Linux/basic-filtering.cc b/test/xray/TestCases/Linux/basic-filtering.cc
new file mode 100644
index 0000000000000..b758859cf6cb9
--- /dev/null
+++ b/test/xray/TestCases/Linux/basic-filtering.cc
@@ -0,0 +1,51 @@
+// Check to make sure that we are actually filtering records from the basic mode
+// logging implementation.
+
+// RUN: %clangxx_xray -std=c++11 %s -o %t -g
+// RUN: rm basic-filtering-* || true
+// RUN: XRAY_OPTIONS="patch_premain=true xray_naive_log=true verbosity=1 \
+// RUN: xray_logfile_base=basic-filtering- \
+// RUN: xray_naive_log_func_duration_threshold_us=1000 \
+// RUN: xray_naive_log_max_stack_depth=2" %run %t 2>&1 | \
+// RUN: FileCheck %s
+// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \
+// RUN: "`ls basic-filtering-* | head -1`" | \
+// RUN: FileCheck %s --check-prefix TRACE
+// RUN: rm basic-filtering-* || true
+//
+// REQUIRES: x86_64-linux
+// REQUIRES: built-in-llvm-tree
+
+#include <cstdio>
+#include <time.h>
+
+[[clang::xray_always_instrument]] void __attribute__((noinline)) filtered() {
+ printf("filtered was called.\n");
+}
+
+[[clang::xray_always_instrument]] void __attribute__((noinline)) beyond_stack() {
+ printf("beyond stack was called.\n");
+}
+
+[[clang::xray_always_instrument]] void __attribute__((noinline))
+always_shows() {
+ struct timespec sleep;
+ sleep.tv_nsec = 2000000;
+ sleep.tv_sec = 0;
+ struct timespec rem;
+ while (nanosleep(&sleep, &rem) == -1)
+ sleep = rem;
+ printf("always_shows was called.\n");
+ beyond_stack();
+}
+
+[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {
+ filtered(); // CHECK: filtered was called.
+ always_shows(); // CHECK: always_shows was called.
+ // CHECK: beyond stack was called.
+}
+
+// TRACE-NOT: - { type: 0, func-id: {{.*}}, function: {{.*filtered.*}}, {{.*}} }
+// TRACE-NOT: - { type: 0, func-id: {{.*}}, function: {{.*beyond_stack.*}}, {{.*}} }
+// TRACE-DAG: - { type: 0, func-id: [[FID:[0-9]+]], function: {{.*always_shows.*}}, cpu: {{.*}}, thread: {{.*}}, kind: function-enter, tsc: {{[0-9]+}} }
+// TRACE-DAG: - { type: 0, func-id: [[FID]], function: {{.*always_shows.*}}, cpu: {{.*}}, thread: {{.*}}, kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
diff --git a/test/xray/TestCases/Linux/common-trampoline-alignment.cc b/test/xray/TestCases/Linux/common-trampoline-alignment.cc
new file mode 100644
index 0000000000000..5d1cc1e9b4516
--- /dev/null
+++ b/test/xray/TestCases/Linux/common-trampoline-alignment.cc
@@ -0,0 +1,57 @@
+// Make sure that we're aligning the stack properly to support handlers that
+// expect 16-byte alignment of the stack.
+//
+// RUN: %clangxx_xray -std=c++11 %s -o %t
+// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false" \
+// RUN: %run %t 2>&1
+// REQUIRES: x86_64-linux
+// REQUIRES: built-in-llvm-tree
+#include "xray/xray_interface.h"
+#include <stdio.h>
+#include <xmmintrin.h>
+
+[[clang::xray_never_instrument]] __attribute__((weak)) __m128 f(__m128 *i) {
+ return *i;
+}
+
+[[clang::xray_always_instrument]] __attribute__((noinline)) void noarg() {
+ __m128 v = {};
+ f(&v);
+}
+
+[[ clang::xray_always_instrument, clang::xray_log_args(1) ]]
+__attribute__((noinline)) void arg1(int) {
+ __m128 v = {};
+ f(&v);
+}
+
+[[clang::xray_always_instrument]] __attribute__((noinline))
+void no_alignment() {}
+
+[[clang::xray_never_instrument]] void noarg_handler(int32_t,
+ XRayEntryType) {
+ printf("noarg handler called\n");
+ __m128 v = {};
+ f(&v);
+}
+
+[[clang::xray_never_instrument]] void arg1_handler(int32_t, XRayEntryType,
+ uint64_t) {
+ printf("arg1 handler called\n");
+ __m128 v = {};
+ f(&v);
+}
+
+int main(int argc, char *argv[]) {
+ __xray_set_handler(noarg_handler);
+ __xray_set_handler_arg1(arg1_handler);
+ __xray_patch();
+ noarg(); // CHECK: noarg handler called
+ arg1(argc); // CHECK: arg1 handler called
+ no_alignment();
+ __xray_unpatch();
+ __xray_remove_handler();
+ __xray_remove_handler_arg1();
+ noarg();
+ arg1(argc);
+}
diff --git a/test/xray/TestCases/Linux/coverage-sample.cc b/test/xray/TestCases/Linux/coverage-sample.cc
index 623b4e34541b6..62c13ba3d42a9 100644
--- a/test/xray/TestCases/Linux/coverage-sample.cc
+++ b/test/xray/TestCases/Linux/coverage-sample.cc
@@ -3,10 +3,13 @@
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false" %run %t | FileCheck %s
+// UNSUPPORTED: target-is-mips64,target-is-mips64el
+
#include "xray/xray_interface.h"
#include <set>
#include <cstdio>
+#include <cassert>
std::set<int32_t> function_ids;
@@ -34,9 +37,9 @@ std::set<int32_t> function_ids;
[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {
__xray_set_handler(coverage_handler);
- __xray_patch();
+ assert(__xray_patch() == XRayPatchingStatus::SUCCESS);
foo();
- __xray_unpatch();
+ assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS);
// print out the function_ids.
printf("first pass.\n");
@@ -56,11 +59,11 @@ std::set<int32_t> function_ids;
// patch the functions we've called before.
for (const auto id : called_fns)
- __xray_patch_function(id);
+ assert(__xray_patch_function(id) == XRayPatchingStatus::SUCCESS);
// then call them again.
foo();
- __xray_unpatch();
+ assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS);
// confirm that we've seen the same functions again.
printf("second pass.\n");
@@ -74,10 +77,10 @@ std::set<int32_t> function_ids;
// Now we want to make sure that if we unpatch one, that we're only going to
// see two calls of the coverage_handler.
function_ids.clear();
- __xray_patch();
- __xray_unpatch_function(1);
+ assert(__xray_patch() == XRayPatchingStatus::SUCCESS);
+ assert(__xray_unpatch_function(1) == XRayPatchingStatus::SUCCESS);
foo();
- __xray_unpatch();
+ assert(__xray_unpatch() == XRayPatchingStatus::SUCCESS);
// confirm that we don't see function id one called anymore.
printf("missing 1.\n");
diff --git a/test/xray/TestCases/Linux/custom-event-handler-alignment.cc b/test/xray/TestCases/Linux/custom-event-handler-alignment.cc
new file mode 100644
index 0000000000000..447f6e4f2b425
--- /dev/null
+++ b/test/xray/TestCases/Linux/custom-event-handler-alignment.cc
@@ -0,0 +1,42 @@
+// Make sure we're aligning the stack properly when lowering the custom event
+// calls.
+//
+// RUN: %clangxx_xray -std=c++11 %s -o %t
+// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false" \
+// RUN: %run %t 2>&1
+// REQUIRES: x86_64-linux
+// REQUIRES: built-in-llvm-tree
+#include <xmmintrin.h>
+#include <stdio.h>
+#include "xray/xray_interface.h"
+
+[[clang::xray_never_instrument]] __attribute__((weak)) __m128 f(__m128 *i) {
+ return *i;
+}
+
+[[clang::xray_always_instrument]] void foo() {
+ __xray_customevent(0, 0);
+ __m128 v = {};
+ f(&v);
+}
+
+[[clang::xray_always_instrument]] void bar() {
+ __xray_customevent(0, 0);
+}
+
+void printer(void* ptr, size_t size) {
+ printf("handler called\n");
+ __m128 v = {};
+ f(&v);
+}
+
+int main(int argc, char* argv[]) {
+ __xray_set_customevent_handler(printer);
+ __xray_patch();
+ foo(); // CHECK: handler called
+ bar(); // CHECK: handler called
+ __xray_unpatch();
+ __xray_remove_customevent_handler();
+ foo();
+ bar();
+}
diff --git a/test/xray/TestCases/Linux/custom-event-logging.cc b/test/xray/TestCases/Linux/custom-event-logging.cc
index 9bb5d44e11117..48fd62034194a 100644
--- a/test/xray/TestCases/Linux/custom-event-logging.cc
+++ b/test/xray/TestCases/Linux/custom-event-logging.cc
@@ -2,6 +2,8 @@
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false xray_logfile_base=custom-event-logging.xray-" %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_xray -std=c++11 -fpic -fpie %s -o %t
+// RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false xray_logfile_base=custom-event-logging.xray-" %run %t 2>&1 | FileCheck %s
// FIXME: Support this in non-x86_64 as well
// REQUIRES: x86_64-linux
// REQUIRES: built-in-llvm-tree
diff --git a/test/xray/TestCases/Linux/fdr-mode.cc b/test/xray/TestCases/Linux/fdr-mode.cc
index f1e087673a8a4..744c051cfb2c7 100644
--- a/test/xray/TestCases/Linux/fdr-mode.cc
+++ b/test/xray/TestCases/Linux/fdr-mode.cc
@@ -30,6 +30,9 @@ thread_local uint64_t var = 0;
[[clang::xray_always_instrument]] void __attribute__((noinline)) fA() { fB(); }
+[[clang::xray_always_instrument, clang::xray_log_args(1)]]
+void __attribute__((noinline)) fArg(int) { }
+
int main(int argc, char *argv[]) {
using namespace __xray;
FDRLoggingOptions Options;
@@ -52,6 +55,7 @@ int main(int argc, char *argv[]) {
fC();
fB();
fA();
+ fArg(1);
});
other_thread.join();
std::cout << "Joined" << std::endl;
@@ -69,24 +73,31 @@ int main(int argc, char *argv[]) {
// Check that we're able to see two threads, each entering and exiting fA().
// TRACE-DAG: - { type: 0, func-id: [[FIDA:[0-9]+]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
-// TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-exit, tsc: {{[0-9]+}} }
+// TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
-// TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-exit, tsc: {{[0-9]+}} }
+// TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
//
// Do the same as above for fC()
// TRACE-DAG: - { type: 0, func-id: [[FIDC:[0-9]+]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
-// TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-exit, tsc: {{[0-9]+}} }
+// TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
-// TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-exit, tsc: {{[0-9]+}} }
+// TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// Do the same as above for fB()
// TRACE-DAG: - { type: 0, func-id: [[FIDB:[0-9]+]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
-// TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-exit, tsc: {{[0-9]+}} }
+// TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
-// TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-exit, tsc: {{[0-9]+}} }
+// TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} }
+
+// TRACE-DAG: - { type: 0, func-id: [[FIDARG:[0-9]+]], function: 'fArg(int)', args: [ 1 ], cpu: {{.*}}, thread: [[THREAD2]], kind: function-enter-arg, tsc: {{[0-9]+}} }
+// TRACE-DAG: - { type: 0, func-id: [[FIDARG]], function: 'fArg(int)', cpu: {{.*}}, thread: [[THREAD2]], kind: function-exit, tsc: {{[0-9]+}} }
// Assert that when unwriting is enabled with a high threshold time, all the function records are erased. A CPU switch could erroneously fail this test, but
// is unlikely given the test program.
-// UNWRITE: header
+// Even with a high threshold, arg1 logging is never unwritten.
+// UNWRITE: header:
+// UNWRITE: records:
+// UNWRITE-NEXT: - { type: 0, func-id: [[FIDARG:[0-9]+]], function: 'fArg(int)', args: [ 1 ], cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter-arg, tsc: {{[0-9]+}} }
+// UNWRITE-NEXT: - { type: 0, func-id: [[FIDARG]], function: 'fArg(int)', cpu: {{.*}}, thread: [[THREAD2]], kind: function-exit, tsc: {{[0-9]+}} }
// UNWRITE-NOT: function-enter
-// UNWRITE-NOT: function-exit
+// UNWRITE-NOT: function-{{exit|tail-exit}}
diff --git a/test/xray/TestCases/Linux/fdr-single-thread.cc b/test/xray/TestCases/Linux/fdr-single-thread.cc
new file mode 100644
index 0000000000000..dd50f485f82bf
--- /dev/null
+++ b/test/xray/TestCases/Linux/fdr-single-thread.cc
@@ -0,0 +1,38 @@
+// RUN: %clangxx_xray -g -std=c++11 %s -o %t
+// RUN: rm fdr-logging-1thr-* || true
+// RUN: XRAY_OPTIONS=XRAY_OPTIONS="verbosity=1 patch_premain=true \
+// RUN: xray_naive_log=false xray_fdr_log=true \
+// RUN: xray_fdr_log_func_duration_threshold_us=0 \
+// RUN: xray_logfile_base=fdr-logging-1thr-" %run %t 2>&1
+// RUN: %llvm_xray convert --output-format=yaml --symbolize --instr_map=%t \
+// RUN: "`ls fdr-logging-1thr-* | head -n1`" | FileCheck %s
+// RUN: rm fdr-logging-1thr-*
+//
+// REQUIRES: x86_64-linux
+
+#include "xray/xray_log_interface.h"
+#include <cassert>
+
+constexpr auto kBufferSize = 16384;
+constexpr auto kBufferMax = 10;
+
+[[clang::xray_always_instrument]] void __attribute__((noinline)) fn() { }
+
+int main(int argc, char *argv[]) {
+ using namespace __xray;
+ FDRLoggingOptions Opts;
+
+ auto status = __xray_log_init(kBufferSize, kBufferMax, &Opts, sizeof(Opts));
+ assert(status == XRayLogInitStatus::XRAY_LOG_INITIALIZED);
+
+ __xray_patch();
+ fn();
+ __xray_unpatch();
+ assert(__xray_log_finalize() == XRAY_LOG_FINALIZED);
+ assert(__xray_log_flushLog() == XRAY_LOG_FLUSHED);
+ return 0;
+}
+
+// CHECK: records:
+// CHECK-NEXT: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*fn.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
+// CHECK-NEXT: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*fn.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-exit, tsc: {{[0-9]+}} }
diff --git a/test/xray/TestCases/Linux/fdr-thread-order.cc b/test/xray/TestCases/Linux/fdr-thread-order.cc
index b43a0fe4033b5..8e8c421dcc661 100644
--- a/test/xray/TestCases/Linux/fdr-thread-order.cc
+++ b/test/xray/TestCases/Linux/fdr-thread-order.cc
@@ -1,41 +1,67 @@
// RUN: %clangxx_xray -g -std=c++11 %s -o %t
// RUN: rm fdr-thread-order.* || true
-// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false xray_logfile_base=fdr-thread-order. xray_fdr_log=true verbosity=1 xray_fdr_log_func_duration_threshold_us=0" %run %t 2>&1 | FileCheck %s
-// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t "`ls fdr-thread-order.* | head -1`" | FileCheck %s --check-prefix TRACE
+// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false \
+// RUN: xray_logfile_base=fdr-thread-order. xray_fdr_log=true verbosity=1 \
+// RUN: xray_fdr_log_func_duration_threshold_us=0" %run %t 2>&1 | \
+// RUN: FileCheck %s
+// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \
+// RUN: "`ls fdr-thread-order.* | head -1`"
+// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \
+// RUN: "`ls fdr-thread-order.* | head -1`" | \
+// RUN: FileCheck %s --check-prefix TRACE
// RUN: rm fdr-thread-order.*
// FIXME: Make llvm-xray work on non-x86_64 as well.
// REQUIRES: x86_64-linux
// REQUIRES: built-in-llvm-tree
#include "xray/xray_log_interface.h"
-#include <thread>
+#include <atomic>
#include <cassert>
+#include <thread>
constexpr auto kBufferSize = 16384;
constexpr auto kBufferMax = 10;
-thread_local uint64_t var = 0;
-[[clang::xray_always_instrument]] void __attribute__((noinline)) f1() { ++var; }
-[[clang::xray_always_instrument]] void __attribute__((noinline)) f2() { ++var; }
+std::atomic<uint64_t> var{0};
+
+[[clang::xray_always_instrument]] void __attribute__((noinline)) f1() {
+ for (auto i = 0; i < 1 << 20; ++i)
+ ++var;
+}
+
+[[clang::xray_always_instrument]] void __attribute__((noinline)) f2() {
+ for (auto i = 0; i < 1 << 20; ++i)
+ ++var;
+}
int main(int argc, char *argv[]) {
using namespace __xray;
FDRLoggingOptions Options;
+ __xray_patch();
assert(__xray_log_init(kBufferSize, kBufferMax, &Options,
sizeof(FDRLoggingOptions)) ==
XRayLogInitStatus::XRAY_LOG_INITIALIZED);
- __xray_patch();
- std::thread t1([] { f1(); });
- std::thread t2([] { f2(); });
- t1.join();
- t2.join();
+
+ std::atomic_thread_fence(std::memory_order_acq_rel);
+
+ {
+ std::thread t1([] { f1(); });
+ std::thread t2([] { f2(); });
+ t1.join();
+ t2.join();
+ }
+
+ std::atomic_thread_fence(std::memory_order_acq_rel);
__xray_log_finalize();
__xray_log_flushLog();
- // CHECK: =={{[0-9]+}}==XRay: Log file in '{{.*}}'
+ __xray_unpatch();
+ return var > 0 ? 0 : 1;
+ // CHECK: {{.*}}XRay: Log file in '{{.*}}'
+ // CHECK-NOT: Failed
}
// We want to make sure that the order of the function log doesn't matter.
// TRACE-DAG: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*f1.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
// TRACE-DAG: - { type: 0, func-id: [[FID2:[0-9]+]], function: {{.*f2.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} }
-// TRACE-DAG: - { type: 0, func-id: [[FID1]], function: {{.*f1.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-exit, tsc: {{[0-9]+}} }
-// TRACE-DAG: - { type: 0, func-id: [[FID2]], function: {{.*f2.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-exit, tsc: {{[0-9]+}} }
+// TRACE-DAG: - { type: 0, func-id: [[FID1]], function: {{.*f1.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: {{function-exit|function-tail-exit}}, tsc: {{[0-9]+}} }
+// TRACE-DAG: - { type: 0, func-id: [[FID2]], function: {{.*f2.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: {{function-exit|function-tail-exit}}, tsc: {{[0-9]+}} }
diff --git a/test/xray/TestCases/Linux/fixedsize-logging.cc b/test/xray/TestCases/Linux/fixedsize-logging.cc
index eb32afe93d1ff..a2a41ce60d6eb 100644
--- a/test/xray/TestCases/Linux/fixedsize-logging.cc
+++ b/test/xray/TestCases/Linux/fixedsize-logging.cc
@@ -7,6 +7,8 @@
//
// RUN: rm fixedsize-logging-*
+// UNSUPPORTED: target-is-mips64,target-is-mips64el
+
#include <cstdio>
[[clang::xray_always_instrument]] void foo() {
diff --git a/test/xray/TestCases/Linux/func-id-utils.cc b/test/xray/TestCases/Linux/func-id-utils.cc
index 17185c34c01e6..412753666019a 100644
--- a/test/xray/TestCases/Linux/func-id-utils.cc
+++ b/test/xray/TestCases/Linux/func-id-utils.cc
@@ -4,6 +4,8 @@
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false" %run %t
+// UNSUPPORTED: target-is-mips64,target-is-mips64el
+
#include "xray/xray_interface.h"
#include <algorithm>
#include <cassert>
diff --git a/test/xray/TestCases/Linux/logging-modes.cc b/test/xray/TestCases/Linux/logging-modes.cc
new file mode 100644
index 0000000000000..22f6942b75953
--- /dev/null
+++ b/test/xray/TestCases/Linux/logging-modes.cc
@@ -0,0 +1,59 @@
+// Check that we can install an implementation associated with a mode.
+//
+// RUN: %clangxx_xray -std=c++11 %s -o %t
+// RUN: %run %t | FileCheck %s
+//
+// UNSUPPORTED: target-is-mips64,target-is-mips64el
+
+#include "xray/xray_interface.h"
+#include "xray/xray_log_interface.h"
+#include <cassert>
+#include <cstdio>
+
+[[clang::xray_never_instrument]] void printing_handler(int32_t fid,
+ XRayEntryType) {
+ thread_local volatile bool printing = false;
+ if (printing)
+ return;
+ printing = true;
+ std::printf("printing %d\n", fid);
+ printing = false;
+}
+
+[[clang::xray_never_instrument]] XRayLogInitStatus
+printing_init(size_t, size_t, void *, size_t) {
+ return XRayLogInitStatus::XRAY_LOG_INITIALIZED;
+}
+
+[[clang::xray_never_instrument]] XRayLogInitStatus printing_finalize() {
+ return XRayLogInitStatus::XRAY_LOG_FINALIZED;
+}
+
+[[clang::xray_never_instrument]] XRayLogFlushStatus printing_flush_log() {
+ return XRayLogFlushStatus::XRAY_LOG_FLUSHED;
+}
+
+[[clang::xray_always_instrument]] void callme() { std::printf("called me!\n"); }
+
+static bool unused = [] {
+ assert(__xray_log_register_mode("custom",
+ {printing_init, printing_finalize,
+ printing_handler, printing_flush_log}) ==
+ XRayLogRegisterStatus::XRAY_REGISTRATION_OK);
+ return true;
+}();
+
+int main(int argc, char **argv) {
+ assert(__xray_log_select_mode("custom") ==
+ XRayLogRegisterStatus::XRAY_REGISTRATION_OK);
+ assert(__xray_patch() == XRayPatchingStatus::SUCCESS);
+ assert(__xray_log_init(0, 0, nullptr, 0) ==
+ XRayLogInitStatus::XRAY_LOG_INITIALIZED);
+ // CHECK: printing {{.*}}
+ callme(); // CHECK: called me!
+ // CHECK: printing {{.*}}
+ assert(__xray_log_finalize() == XRayLogInitStatus::XRAY_LOG_FINALIZED);
+ assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED);
+ assert(__xray_log_select_mode("not-found") ==
+ XRayLogRegisterStatus::XRAY_MODE_NOT_FOUND);
+}
diff --git a/test/xray/TestCases/Linux/optional-inmemory-log.cc b/test/xray/TestCases/Linux/optional-inmemory-log.cc
index f459d5ab813f7..feaaa41247500 100644
--- a/test/xray/TestCases/Linux/optional-inmemory-log.cc
+++ b/test/xray/TestCases/Linux/optional-inmemory-log.cc
@@ -8,6 +8,8 @@
//
// RUN: rm -f optional-inmemory-log.xray-*
+// UNSUPPORTED: target-is-mips64,target-is-mips64el
+
#include <cstdio>
[[clang::xray_always_instrument]] void foo() {
diff --git a/test/xray/TestCases/Linux/patching-unpatching.cc b/test/xray/TestCases/Linux/patching-unpatching.cc
index 05478a4880562..a7ea58f6dc69f 100644
--- a/test/xray/TestCases/Linux/patching-unpatching.cc
+++ b/test/xray/TestCases/Linux/patching-unpatching.cc
@@ -4,6 +4,8 @@
// RUN: %clangxx_xray -fxray-instrument -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=false" %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: target-is-mips64,target-is-mips64el
+
#include "xray/xray_interface.h"
#include <cstdio>
diff --git a/test/xray/TestCases/Linux/pic_test.cc b/test/xray/TestCases/Linux/pic_test.cc
index 09c40b9e03177..4de1ad3d6da9f 100644
--- a/test/xray/TestCases/Linux/pic_test.cc
+++ b/test/xray/TestCases/Linux/pic_test.cc
@@ -1,10 +1,15 @@
// Test to check if we handle pic code properly.
-// RUN: %clangxx_xray -fxray-instrument -std=c++11 -fpic %s -o %t
-// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=pic-test-logging-" %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_xray -fxray-instrument -std=c++11 -ffunction-sections \
+// RUN: -fdata-sections -fpic -fpie -Wl,--gc-sections %s -o %t
+// RUN: rm pic-test-logging-* || true
+// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_naive_log=true \
+// RUN: xray_logfile_base=pic-test-logging-" %run %t 2>&1 | FileCheck %s
// After all that, clean up the output xray log.
//
-// RUN: rm pic-test-logging-*
+// RUN: rm pic-test-logging-* || true
+
+// UNSUPPORTED: target-is-mips64,target-is-mips64el
#include <cstdio>
diff --git a/test/xray/TestCases/Linux/quiet-start.cc b/test/xray/TestCases/Linux/quiet-start.cc
new file mode 100644
index 0000000000000..e26fa63aa5baa
--- /dev/null
+++ b/test/xray/TestCases/Linux/quiet-start.cc
@@ -0,0 +1,26 @@
+// Ensure that we have a quiet startup when we don't have the XRay
+// instrumentation sleds.
+//
+// RUN: %clangxx -std=c++11 %s -o %t %xraylib
+// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1" %run %t 2>&1 | \
+// RUN: FileCheck %s --check-prefix NOISY
+// RUN: XRAY_OPTIONS="patch_premain=true verbosity=0" %run %t 2>&1 | \
+// RUN: FileCheck %s --check-prefix QUIET
+// RUN: XRAY_OPTIONS="" %run %t 2>&1 | FileCheck %s --check-prefix DEFAULT
+//
+// FIXME: Understand how to make this work on other platforms
+// REQUIRES: built-in-llvm-tree
+// REQUIRES: x86_64-linux
+#include <iostream>
+
+using namespace std;
+
+int main(int, char**) {
+ // NOISY: {{.*}}XRay instrumentation map missing. Not initializing XRay.
+ // QUIET-NOT: {{.*}}XRay instrumentation map missing. Not initializing XRay.
+ // DEFAULT-NOT: {{.*}}XRay instrumentation map missing. Not initializing XRay.
+ cout << "Hello, XRay!" << endl;
+ // NOISY: Hello, XRay!
+ // QUIET: Hello, XRay!
+ // DEFAULT: Hello, XRay!
+}
diff --git a/test/xray/Unit/lit.site.cfg.in b/test/xray/Unit/lit.site.cfg.in
index 75ea8889bf99c..be860deafd084 100644
--- a/test/xray/Unit/lit.site.cfg.in
+++ b/test/xray/Unit/lit.site.cfg.in
@@ -13,4 +13,4 @@ config.test_source_root = config.test_exec_root
# Do not patch the XRay unit tests pre-main, and also make the error logging
# verbose to get a more accurate error logging mechanism.
-config.environment['XRAY_OPTIONS'] = 'patch_premain=false verbose=1'
+config.environment['XRAY_OPTIONS'] = 'patch_premain=false'
diff --git a/test/xray/lit.cfg b/test/xray/lit.cfg
index b07dcbd791f86..d5e40975da569 100644
--- a/test/xray/lit.cfg
+++ b/test/xray/lit.cfg
@@ -31,6 +31,11 @@ config.substitutions.append(
('%clangxx_xray', build_invocation(clang_xray_cxxflags)))
config.substitutions.append(
('%llvm_xray', llvm_xray))
+config.substitutions.append(
+ ('%xraylib',
+ ('-lm -lpthread -ldl -lrt -L%s '
+ '-Wl,-whole-archive -lclang_rt.xray-%s -Wl,-no-whole-archive')
+ % (config.compiler_rt_libdir, config.host_arch)))
# Default test suffixes.
config.suffixes = ['.c', '.cc', '.cpp']
@@ -43,8 +48,3 @@ elif '64' not in config.host_arch:
config.unsupported = True
else:
config.unsupported = True
-
-# Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL
-# e.g. because the test sometimes passes, sometimes fails.
-if config.target_arch != 'aarch64':
- config.available_features.add('stable-runtime')
diff --git a/test/xray/lit.site.cfg.in b/test/xray/lit.site.cfg.in
index 73c4eff6ee25f..bc4acb6d3b857 100644
--- a/test/xray/lit.site.cfg.in
+++ b/test/xray/lit.site.cfg.in
@@ -17,4 +17,4 @@ if config.built_with_llvm:
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
# Load tool-specific config that would do the real work.
-lit_config.load_config(config, "@XRAY_LIT_SOURCE_DIR@/lit.cfg")
+lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg")