1# Copyright (C) 2023 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15# This logic checks for the enablement of sanitizers to update the relevant 16# config_setting for the purpose of controlling the addition of sanitizer 17# blocklists. 18 19load("@bazel_skylib//lib:unittest.bzl", "analysistest") 20load("//build/bazel/rules/cc:cc_binary.bzl", "cc_binary") 21load("//build/bazel/rules/cc:cc_library_shared.bzl", "cc_library_shared") 22load("//build/bazel/rules/cc:cc_library_static.bzl", "cc_library_static") 23load( 24 "//build/bazel/rules/cc/testing:transitions.bzl", 25 "compile_action_argv_aspect_generator", 26 "transition_deps_test_attrs", 27 "transition_deps_test_impl", 28) 29 30static_cpp_suffix = "_cpp" 31shared_and_binary_cpp_suffix = "__internal_root_cpp" 32 33_compile_action_argv_aspect = compile_action_argv_aspect_generator({ 34 "_cc_library_combiner": ["deps", "roots", "includes"], 35 "_cc_includes": ["deps"], 36 "_cc_library_shared_proxy": ["deps"], 37 "stripped_binary": ["androidmk_deps"], 38}) 39 40sanitizer_blocklist_test = analysistest.make( 41 transition_deps_test_impl, 42 attrs = transition_deps_test_attrs, 43 extra_target_under_test_aspects = [_compile_action_argv_aspect], 44) 45 46sanitizer_blocklist_name = "foo_blocklist.txt" 47sanitizer_blocklist_flag = ( 48 "-fsanitize-ignorelist=build/bazel/rules/cc/" + 49 sanitizer_blocklist_name 50) 51 52# TODO: b/294868620 - This select can be made into a normal list when completing 53# the bug 54sanitizer_blocklist_select = select({ 55 "//build/bazel/rules/cc:sanitizers_enabled": [sanitizer_blocklist_flag], 56 "//conditions:default": [], 57}) 58 59def test_sanitizer_blocklist_with_ubsan_static(): 60 name = "sanitizer_blocklist_with_ubsan_static" 61 cc_library_static( 62 name = name, 63 srcs = ["foo.cpp"], 64 features = ["ubsan_integer"], 65 copts = sanitizer_blocklist_select, 66 additional_compiler_inputs = [sanitizer_blocklist_name], 67 tags = ["manual"], 68 ) 69 70 test_name = name + "_test" 71 sanitizer_blocklist_test( 72 name = test_name, 73 target_under_test = name, 74 targets_with_flag = [name + static_cpp_suffix], 75 flags = [sanitizer_blocklist_flag], 76 ) 77 78 return test_name 79 80def test_sanitizer_blocklist_with_cfi_static(): 81 name = "sanitizer_blocklist_with_cfi_static" 82 cc_library_static( 83 name = name, 84 srcs = ["foo.cpp"], 85 features = ["android_cfi"], 86 copts = sanitizer_blocklist_select, 87 additional_compiler_inputs = [sanitizer_blocklist_name], 88 tags = ["manual"], 89 ) 90 91 test_name = name + "_test" 92 sanitizer_blocklist_test( 93 name = test_name, 94 target_under_test = name, 95 targets_with_flag = [name + static_cpp_suffix], 96 flags = [sanitizer_blocklist_flag], 97 ) 98 99 return test_name 100 101def test_no_sanitizer_blocklist_without_sanitizer_static(): 102 name = "no_sanitizer_blocklist_without_sanitizer_static" 103 cc_library_static( 104 name = name, 105 srcs = ["foo.cpp"], 106 copts = sanitizer_blocklist_select, 107 additional_compiler_inputs = [sanitizer_blocklist_name], 108 tags = ["manual"], 109 ) 110 111 test_name = name + "_test" 112 sanitizer_blocklist_test( 113 name = test_name, 114 target_under_test = name, 115 targets_without_flag = [name + static_cpp_suffix], 116 flags = [sanitizer_blocklist_flag], 117 ) 118 119 return test_name 120 121def test_sanitizer_blocklist_with_ubsan_shared(): 122 name = "sanitizer_blocklist_with_ubsan_shared" 123 cc_library_shared( 124 name = name, 125 srcs = ["foo.cpp"], 126 features = ["ubsan_integer"], 127 copts = sanitizer_blocklist_select, 128 additional_compiler_inputs = [sanitizer_blocklist_name], 129 tags = ["manual"], 130 ) 131 132 test_name = name + "_test" 133 sanitizer_blocklist_test( 134 name = test_name, 135 target_under_test = name, 136 targets_with_flag = [name + shared_and_binary_cpp_suffix], 137 flags = [sanitizer_blocklist_flag], 138 ) 139 140 return test_name 141 142def test_sanitizer_blocklist_with_cfi_shared(): 143 name = "sanitizer_blocklist_with_cfi_shared" 144 cc_library_shared( 145 name = name, 146 srcs = ["foo.cpp"], 147 features = ["android_cfi"], 148 copts = sanitizer_blocklist_select, 149 additional_compiler_inputs = [sanitizer_blocklist_name], 150 tags = ["manual"], 151 ) 152 153 test_name = name + "_test" 154 sanitizer_blocklist_test( 155 name = test_name, 156 target_under_test = name, 157 targets_with_flag = [name + shared_and_binary_cpp_suffix], 158 flags = [sanitizer_blocklist_flag], 159 ) 160 161 return test_name 162 163def test_no_sanitizer_blocklist_without_sanitizer_shared(): 164 name = "no_sanitizer_blocklist_without_sanitizer_shared" 165 cc_library_shared( 166 name = name, 167 srcs = ["foo.cpp"], 168 copts = sanitizer_blocklist_select, 169 additional_compiler_inputs = [sanitizer_blocklist_name], 170 tags = ["manual"], 171 ) 172 173 test_name = name + "_test" 174 sanitizer_blocklist_test( 175 name = test_name, 176 target_under_test = name, 177 targets_without_flag = [name + shared_and_binary_cpp_suffix], 178 flags = [sanitizer_blocklist_flag], 179 ) 180 181 return test_name 182 183def test_sanitizer_blocklist_with_ubsan_binary(): 184 name = "sanitizer_blocklist_with_ubsan_binary" 185 cc_binary( 186 name = name, 187 srcs = ["foo.cpp"], 188 features = ["ubsan_integer"], 189 copts = sanitizer_blocklist_select, 190 additional_compiler_inputs = [sanitizer_blocklist_name], 191 tags = ["manual"], 192 ) 193 194 test_name = name + "_test" 195 sanitizer_blocklist_test( 196 name = test_name, 197 target_under_test = name, 198 targets_with_flag = [name + shared_and_binary_cpp_suffix], 199 flags = [sanitizer_blocklist_flag], 200 ) 201 202 return test_name 203 204def test_sanitizer_blocklist_with_cfi_binary(): 205 name = "sanitizer_blocklist_with_cfi_binary" 206 cc_binary( 207 name = name, 208 srcs = ["foo.cpp"], 209 features = ["android_cfi"], 210 copts = sanitizer_blocklist_select, 211 additional_compiler_inputs = [sanitizer_blocklist_name], 212 tags = ["manual"], 213 ) 214 215 test_name = name + "_test" 216 sanitizer_blocklist_test( 217 name = test_name, 218 target_under_test = name, 219 targets_with_flag = [name + shared_and_binary_cpp_suffix], 220 flags = [sanitizer_blocklist_flag], 221 ) 222 223 return test_name 224 225def test_no_sanitizer_blocklist_without_sanitizer_binary(): 226 name = "no_sanitizer_blocklist_without_sanitizer_binary" 227 cc_binary( 228 name = name, 229 srcs = ["foo.cpp"], 230 copts = sanitizer_blocklist_select, 231 additional_compiler_inputs = [sanitizer_blocklist_name], 232 tags = ["manual"], 233 ) 234 235 test_name = name + "_test" 236 sanitizer_blocklist_test( 237 name = test_name, 238 target_under_test = name, 239 targets_without_flag = [name + shared_and_binary_cpp_suffix], 240 flags = [sanitizer_blocklist_flag], 241 ) 242 243 return test_name 244 245def test_sanitizer_blocklist_on_dep_with_cfi(): 246 name = "sanitizer_blocklist_on_dep_with_cfi" 247 requested_target_name = name + "_requested_target" 248 dep_name = name + "_dep" 249 cc_library_shared( 250 name = requested_target_name, 251 deps = [dep_name], 252 features = ["android_cfi"], 253 tags = ["manual"], 254 ) 255 cc_library_static( 256 name = dep_name, 257 srcs = ["foo.cpp"], 258 copts = sanitizer_blocklist_select, 259 additional_compiler_inputs = [sanitizer_blocklist_name], 260 tags = ["manual"], 261 ) 262 263 test_name = name + "_test" 264 sanitizer_blocklist_test( 265 name = test_name, 266 target_under_test = requested_target_name, 267 targets_with_flag = [dep_name + static_cpp_suffix], 268 flags = [sanitizer_blocklist_flag], 269 ) 270 271 return test_name 272 273def test_no_sanitizer_blocklist_on_dep_without_cfi(): 274 name = "no_sanitizer_blocklist_on_dep_without_cfi" 275 requested_target_name = name + "_requested_target" 276 dep_name = name + "_dep" 277 cc_library_shared( 278 name = requested_target_name, 279 deps = [dep_name], 280 tags = ["manual"], 281 ) 282 cc_library_static( 283 name = dep_name, 284 srcs = ["foo.cpp"], 285 copts = sanitizer_blocklist_select, 286 additional_compiler_inputs = [sanitizer_blocklist_name], 287 tags = ["manual"], 288 ) 289 290 test_name = name + "_test" 291 sanitizer_blocklist_test( 292 name = test_name, 293 target_under_test = requested_target_name, 294 targets_without_flag = [dep_name + static_cpp_suffix], 295 flags = [sanitizer_blocklist_flag], 296 ) 297 298 return test_name 299 300# We test this because UBSan propagates the runtime up its rdep graph 301def test_no_sanitizer_blocklist_on_rdep_with_ubsan(): 302 name = "no_sanitizer_blocklist_on_rdep_with_ubsan" 303 requested_target_name = name + "_requested_target" 304 dep_name = name + "_dep" 305 cc_library_static( 306 name = requested_target_name, 307 srcs = ["foo.cpp"], 308 deps = [dep_name], 309 copts = sanitizer_blocklist_select, 310 additional_compiler_inputs = [sanitizer_blocklist_name], 311 tags = ["manual"], 312 ) 313 cc_library_shared( 314 name = dep_name, 315 srcs = ["bar.cpp"], 316 features = ["ubsan_integer"], 317 tags = ["manual"], 318 ) 319 320 test_name = name + "_test" 321 sanitizer_blocklist_test( 322 name = test_name, 323 target_under_test = requested_target_name, 324 targets_without_flag = [requested_target_name + static_cpp_suffix], 325 flags = [sanitizer_blocklist_flag], 326 ) 327 328 return test_name 329 330def test_sanitizer_blocklist_multiple_deps(): 331 name = "sanitizer_blocklist_multiple_deps" 332 requested_target_name = name + "_requested_target" 333 dep_name = name + "_dep" 334 dep_of_dep_name = name + "_dep_of_dep" 335 other_dep_name = name + "_other_dep" 336 cc_library_shared( 337 name = requested_target_name, 338 srcs = ["foo.cpp"], 339 implementation_deps = [dep_name, other_dep_name], 340 features = ["android_cfi"], 341 tags = ["manual"], 342 ) 343 344 cc_library_static( 345 name = dep_name, 346 srcs = ["bar.cpp"], 347 implementation_dynamic_deps = [dep_of_dep_name], 348 features = ["android_cfi"], 349 copts = sanitizer_blocklist_select, 350 additional_compiler_inputs = [sanitizer_blocklist_name], 351 tags = ["manual"], 352 ) 353 354 cc_library_shared( 355 name = other_dep_name, 356 srcs = ["blah.cpp"], 357 implementation_dynamic_deps = [dep_of_dep_name], 358 tags = ["manual"], 359 ) 360 361 cc_library_shared( 362 name = dep_of_dep_name, 363 srcs = ["baz.cpp"], 364 features = ["android_cfi"], 365 tags = ["manual"], 366 ) 367 368 test_name = name + "_test" 369 sanitizer_blocklist_test( 370 name = test_name, 371 target_under_test = requested_target_name, 372 targets_with_flag = [dep_name + static_cpp_suffix], 373 flags = [sanitizer_blocklist_flag], 374 ) 375 376 return test_name 377 378def sanitizer_blocklist_test_suite(name): 379 native.test_suite( 380 name = name, 381 tests = [ 382 test_sanitizer_blocklist_with_ubsan_static(), 383 test_sanitizer_blocklist_with_cfi_static(), 384 test_no_sanitizer_blocklist_without_sanitizer_static(), 385 test_sanitizer_blocklist_with_ubsan_shared(), 386 test_sanitizer_blocklist_with_cfi_shared(), 387 test_no_sanitizer_blocklist_without_sanitizer_shared(), 388 test_sanitizer_blocklist_with_ubsan_binary(), 389 test_sanitizer_blocklist_with_cfi_binary(), 390 test_no_sanitizer_blocklist_without_sanitizer_binary(), 391 test_sanitizer_blocklist_on_dep_with_cfi(), 392 test_no_sanitizer_blocklist_on_dep_without_cfi(), 393 test_no_sanitizer_blocklist_on_rdep_with_ubsan(), 394 test_sanitizer_blocklist_multiple_deps(), 395 ], 396 ) 397