File tree Expand file tree Collapse file tree 8 files changed +186
-0
lines changed Expand file tree Collapse file tree 8 files changed +186
-0
lines changed Original file line number Diff line number Diff line change @@ -123,3 +123,7 @@ endif()
123123if (WIN32 )
124124 set (ALL_ORC_SUPPORTED_ARCH ${X86_64} )
125125endif ()
126+
127+ if (OS_NAME MATCHES "Linux" )
128+ set (ALL_PFP_SUPPORTED_ARCH ${X86_64} ${ARM64} )
129+ endif ()
Original file line number Diff line number Diff line change @@ -686,6 +686,9 @@ if(APPLE)
686686 list_intersect(ORC_SUPPORTED_ARCH
687687 ALL_ORC_SUPPORTED_ARCH
688688 SANITIZER_COMMON_SUPPORTED_ARCH)
689+ list_intersect(PFP_SUPPORTED_ARCH
690+ ALL_PFP_SUPPORTED_ARCH
691+ SANITIZER_COMMON_SUPPORTED_ARCH)
689692
690693else ()
691694 # Architectures supported by compiler-rt libraries.
@@ -721,6 +724,7 @@ else()
721724 filter_available_targets(GWP_ASAN_SUPPORTED_ARCH ${ALL_GWP_ASAN_SUPPORTED_ARCH} )
722725 filter_available_targets(NSAN_SUPPORTED_ARCH ${ALL_NSAN_SUPPORTED_ARCH} )
723726 filter_available_targets(ORC_SUPPORTED_ARCH ${ALL_ORC_SUPPORTED_ARCH} )
727+ filter_available_targets(PFP_SUPPORTED_ARCH ${ALL_PFP_SUPPORTED_ARCH} )
724728endif ()
725729
726730if (MSVC )
Original file line number Diff line number Diff line change @@ -106,6 +106,7 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS)
106106 # ShadowCallStack does not yet provide a runtime with compiler-rt, the tests
107107 # include their own minimal runtime
108108 add_subdirectory (shadowcallstack)
109+ add_subdirectory (pfp)
109110endif ()
110111
111112# Now that we've traversed all the directories and know all the lit testsuites,
Original file line number Diff line number Diff line change 1+ set (PFP_TESTSUITES)
2+ set (PFP_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} unwind compiler-rt)
3+ if (COMPILER_RT_HAS_LLD AND TARGET lld)
4+ list (APPEND PFP_TEST_DEPS lld)
5+ endif ()
6+
7+ macro (add_pfp_testsuite arch thinlto)
8+ set (PFP_TEST_TARGET_ARCH ${arch} )
9+ get_test_cc_for_arch(${arch} PFP_TEST_TARGET_CC PFP_TEST_TARGET_CFLAGS)
10+
11+ string (TOUPPER ${arch} CONFIG_NAME)
12+
13+ if (${thinlto} )
14+ set (PFP_TEST_USE_THINLTO ${thinlto} )
15+ set (CONFIG_NAME "thinlto-${CONFIG_NAME} " )
16+ list (APPEND PFP_TEST_DEPS LTO)
17+ endif ()
18+ set (PFP_TEST_USE_THINLTO ${thinlto} )
19+
20+ configure_lit_site_cfg(
21+ ${CMAKE_CURRENT_SOURCE_DIR} /lit.site.cfg.py.in
22+ ${CMAKE_CURRENT_BINARY_DIR} /${CONFIG_NAME} /lit.site.cfg.py)
23+ list (APPEND PFP_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR} /${CONFIG_NAME} )
24+ endmacro ()
25+
26+ set (PFP_TEST_ARCH ${PFP_SUPPORTED_ARCH} )
27+
28+ foreach (arch ${PFP_TEST_ARCH} )
29+ add_pfp_testsuite(${arch} False )
30+ add_pfp_testsuite(${arch} True )
31+ endforeach ()
32+
33+ add_lit_testsuite(check-pfp "Running the PointerFieldProtection tests"
34+ ${PFP_TESTSUITES}
35+ DEPENDS ${PFP_TEST_DEPS} )
36+
Original file line number Diff line number Diff line change 1+ # -*- Python -*-
2+
3+ import os
4+
5+ from lit .llvm import llvm_config
6+ from lit .llvm .subst import ToolSubst , FindTool
7+
8+ # Setup config name.
9+ config .name = "pfp" + config .name_suffix
10+
11+ # Default test suffixes.
12+ config .suffixes = [".c" , ".cpp" ]
13+
14+ # Setup source root.
15+ config .test_source_root = os .path .dirname (__file__ )
16+ # Setup default compiler flags used with -fsanitize=memory option.
17+ clang_cflags = [config .target_cflags ] + config .debug_info_flags
18+ clang_cxxflags = config .cxx_mode_flags + clang_cflags
19+ clang_pfp_tagged_common_cflags = clang_cflags + [
20+ "-fexperimental-pointer-field-protection=tagged"
21+ ]
22+
23+
24+ clang_pfp_cxxflags = config .cxx_mode_flags + clang_pfp_tagged_common_cflags
25+ clang_pfp_cxxflags = clang_pfp_cxxflags + ["-fuse-ld=lld --rtlib=compiler-rt --unwindlib=libunwind -static-libgcc" ]
26+
27+
28+ def build_invocation (compile_flags , with_lto = False ):
29+ lto_flags = []
30+ if with_lto and config .lto_supported :
31+ lto_flags += config .lto_flags
32+
33+ return " " + " " .join ([config .clang ] + lto_flags + compile_flags ) + " "
34+
35+
36+ config .substitutions .append (("%clangxx " , build_invocation (clang_cxxflags )))
37+ config .substitutions .append (("%clangxx_pfp " , build_invocation (clang_pfp_cxxflags , config .use_thinlto )))
Original file line number Diff line number Diff line change 1+ @LIT_SITE_CFG_IN_HEADER@
2+
3+ # Tool-specific config options.
4+ config.name_suffix = "@PFP_TEST_CONFIG_SUFFIX@"
5+ config.target_cflags = "@PFP_TEST_TARGET_CFLAGS@"
6+ config.target_arch = "@PFP_TEST_TARGET_ARCH@"
7+ config.use_lld = True
8+ config.use_thinlto = @PFP_TEST_USE_THINLTO@
9+ config.libunwind_shared = "@LIBUNWIND_ENABLE_SHARED@"
10+ config.libunwind_install_dir = "@LLVM_BINARY_DIR@/@LIBUNWIND_INSTALL_LIBRARY_DIR@"
11+
12+ # Load common config for all compiler-rt lit tests.
13+ lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
14+
15+ # Load tool-specific config that would do the real work.
16+ lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg.py")
Original file line number Diff line number Diff line change 1+ // RUN: %clangxx_pfp %s -o %t1
2+ // RUN: %run %t1 2>&1
3+ // RUN: %clangxx %s -o %t2
4+ // RUN: %run %t2 2>&1
5+
6+ #include < iostream>
7+
8+ // Struct1.ptr and Struct2.ptr have different locks.
9+ struct Struct1 {
10+ int *ptr;
11+ Struct1 () : num(1 ), ptr(&num) {}
12+
13+ private:
14+ int num;
15+ };
16+
17+ struct Struct2 {
18+ int *ptr;
19+ Struct2 () : num(2 ), ptr(&num) {}
20+
21+ private:
22+ int num;
23+ };
24+
25+ Struct1 *new_object1 () {
26+ Struct1 *ptr = new Struct1;
27+ return ptr;
28+ }
29+
30+ Struct2 *new_object2 () {
31+ Struct2 *ptr = new Struct2;
32+ return ptr;
33+ }
34+
35+ int main () {
36+ Struct1 *obj1 = new_object1 ();
37+ Struct2 *obj2 = new_object2 ();
38+ std::cout << " Struct2: " << *(obj2->ptr ) << " \n " ;
39+ std::cout << " Struct1: " << *(obj1->ptr ) << " \n " ;
40+ delete obj1;
41+ delete obj2;
42+ return 0 ;
43+ }
Original file line number Diff line number Diff line change 1+ // RUN: %clangxx_pfp %s -o %t1
2+ // RUN: %expect_crash %run %t1 2>&1
3+ // RUN: %clangxx %s -o %t2
4+ // RUN: %run %t2 2>&1
5+
6+ #include < iostream>
7+
8+ // Struct1.ptr and Struct2.ptr have different locks.
9+ struct Struct1 {
10+ int *ptr;
11+ Struct1 () : num(1 ), ptr(&num) {}
12+
13+ private:
14+ int num;
15+ };
16+
17+ struct Struct2 {
18+ int *ptr;
19+ Struct2 () : num(2 ), ptr(&num) {}
20+
21+ private:
22+ int num;
23+ };
24+
25+ Struct1 *new_object1 () {
26+ Struct1 *ptr = new Struct1;
27+ return ptr;
28+ }
29+
30+ Struct2 *new_object2 () {
31+ Struct2 *ptr = new Struct2;
32+ return ptr;
33+ }
34+
35+ int main () {
36+ Struct1 *obj1 = new_object1 ();
37+ delete obj1;
38+ // obj1's memory will be reused.
39+ Struct2 *obj2 = new_object2 ();
40+ std::cout << " Struct2: " << *(obj2->ptr ) << " \n " ;
41+ // Uses a wrong lock. The Program should crash when "-fexperimental-pointer-field-protection=tagged".
42+ std::cout << " Struct1: " << *(obj1->ptr ) << " \n " ;
43+ delete obj2;
44+ return 0 ;
45+ }
You can’t perform that action at this time.
0 commit comments