• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2021 Google Inc. All rights reserved.
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
15package cc
16
17import (
18	"fmt"
19	"runtime"
20	"strings"
21	"testing"
22
23	"android/soong/android"
24
25	"github.com/google/blueprint"
26)
27
28var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(`
29	cc_library_shared {
30		name: "libclang_rt.asan",
31		host_supported: true,
32	}
33	cc_library_static {
34		name: "libclang_rt.asan.static",
35		host_supported: true,
36	}
37	cc_library_static {
38		name: "libclang_rt.asan_cxx.static",
39		host_supported: true,
40	}
41`))
42
43var prepareForTsanTest = android.FixtureAddFile("tsan/Android.bp", []byte(`
44	cc_library_shared {
45		name: "libclang_rt.tsan",
46		host_supported: true,
47	}
48`))
49
50type providerInterface interface {
51	ModuleProvider(blueprint.Module, blueprint.ProviderKey) interface{}
52}
53
54// expectSharedLinkDep verifies that the from module links against the to module as a
55// shared library.
56func expectSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
57	t.Helper()
58	fromLink := from.Description("link")
59	toInfo := ctx.ModuleProvider(to.Module(), SharedLibraryInfoProvider).(SharedLibraryInfo)
60
61	if g, w := fromLink.OrderOnly.Strings(), toInfo.SharedLibrary.RelativeToTop().String(); !android.InList(w, g) {
62		t.Errorf("%s should link against %s, expected %q, got %q",
63			from.Module(), to.Module(), w, g)
64	}
65}
66
67// expectNoSharedLinkDep verifies that the from module links against the to module as a
68// shared library.
69func expectNoSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
70	t.Helper()
71	fromLink := from.Description("link")
72	toInfo := ctx.ModuleProvider(to.Module(), SharedLibraryInfoProvider).(SharedLibraryInfo)
73
74	if g, w := fromLink.OrderOnly.Strings(), toInfo.SharedLibrary.RelativeToTop().String(); android.InList(w, g) {
75		t.Errorf("%s should not link against %s, expected %q, got %q",
76			from.Module(), to.Module(), w, g)
77	}
78}
79
80// expectStaticLinkDep verifies that the from module links against the to module as a
81// static library.
82func expectStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
83	t.Helper()
84	fromLink := from.Description("link")
85	toInfo := ctx.ModuleProvider(to.Module(), StaticLibraryInfoProvider).(StaticLibraryInfo)
86
87	if g, w := fromLink.Implicits.Strings(), toInfo.StaticLibrary.RelativeToTop().String(); !android.InList(w, g) {
88		t.Errorf("%s should link against %s, expected %q, got %q",
89			from.Module(), to.Module(), w, g)
90	}
91
92}
93
94// expectNoStaticLinkDep verifies that the from module links against the to module as a
95// static library.
96func expectNoStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
97	t.Helper()
98	fromLink := from.Description("link")
99	toInfo := ctx.ModuleProvider(to.Module(), StaticLibraryInfoProvider).(StaticLibraryInfo)
100
101	if g, w := fromLink.Implicits.Strings(), toInfo.StaticLibrary.RelativeToTop().String(); android.InList(w, g) {
102		t.Errorf("%s should not link against %s, expected %q, got %q",
103			from.Module(), to.Module(), w, g)
104	}
105
106}
107
108// expectInstallDep verifies that the install rule of the from module depends on the
109// install rule of the to module.
110func expectInstallDep(t *testing.T, from, to android.TestingModule) {
111	t.Helper()
112	fromInstalled := from.Description("install")
113	toInstalled := to.Description("install")
114
115	// combine implicits and order-only dependencies, host uses implicit but device uses
116	// order-only.
117	got := append(fromInstalled.Implicits.Strings(), fromInstalled.OrderOnly.Strings()...)
118	want := toInstalled.Output.String()
119	if !android.InList(want, got) {
120		t.Errorf("%s installation should depend on %s, expected %q, got %q",
121			from.Module(), to.Module(), want, got)
122	}
123}
124
125type expectedRuntimeLinkage int
126
127const (
128	RUNTIME_LINKAGE_NONE   = expectedRuntimeLinkage(0)
129	RUNTIME_LINKAGE_SHARED = iota
130	RUNTIME_LINKAGE_STATIC
131)
132
133func TestAsan(t *testing.T) {
134	t.Parallel()
135	bp := `
136		cc_binary {
137			name: "bin_with_asan",
138			host_supported: true,
139			shared_libs: [
140				"libshared",
141				"libasan",
142			],
143			static_libs: [
144				"libstatic",
145				"libnoasan",
146				"libstatic_asan",
147			],
148			sanitize: {
149				address: true,
150			}
151		}
152
153		cc_binary {
154			name: "bin_no_asan",
155			host_supported: true,
156			shared_libs: [
157				"libshared",
158				"libasan",
159			],
160			static_libs: [
161				"libstatic",
162				"libnoasan",
163				"libstatic_asan",
164			],
165		}
166
167		cc_library_shared {
168			name: "libshared",
169			host_supported: true,
170			shared_libs: ["libtransitive"],
171		}
172
173		cc_library_shared {
174			name: "libasan",
175			host_supported: true,
176			shared_libs: ["libtransitive"],
177			sanitize: {
178				address: true,
179			}
180		}
181
182		cc_library_shared {
183			name: "libtransitive",
184			host_supported: true,
185		}
186
187		cc_library_static {
188			name: "libstatic",
189			host_supported: true,
190		}
191
192		cc_library_static {
193			name: "libnoasan",
194			host_supported: true,
195			sanitize: {
196				address: false,
197			}
198		}
199
200		cc_library_static {
201			name: "libstatic_asan",
202			host_supported: true,
203			sanitize: {
204				address: true,
205			}
206		}
207
208	`
209
210	preparer := android.GroupFixturePreparers(
211		prepareForCcTest,
212		prepareForAsanTest,
213	)
214	buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
215
216	check := func(t *testing.T, variant string, runtimeLinkage expectedRuntimeLinkage, preparer android.FixturePreparer) {
217		result := preparer.RunTestWithBp(t, bp)
218		ctx := result.TestContext
219		asanVariant := variant + "_asan"
220		sharedVariant := variant + "_shared"
221		sharedAsanVariant := sharedVariant + "_asan"
222		staticVariant := variant + "_static"
223		staticAsanVariant := staticVariant + "_asan"
224
225		// The binaries, one with asan and one without
226		binWithAsan := result.ModuleForTests("bin_with_asan", asanVariant)
227		binNoAsan := result.ModuleForTests("bin_no_asan", variant)
228
229		// Shared libraries that don't request asan
230		libShared := result.ModuleForTests("libshared", sharedVariant)
231		libTransitive := result.ModuleForTests("libtransitive", sharedVariant)
232
233		// Shared library that requests asan
234		libAsan := result.ModuleForTests("libasan", sharedAsanVariant)
235
236		// Static library that uses an asan variant for bin_with_asan and a non-asan variant
237		// for bin_no_asan.
238		libStaticAsanVariant := result.ModuleForTests("libstatic", staticAsanVariant)
239		libStaticNoAsanVariant := result.ModuleForTests("libstatic", staticVariant)
240
241		// Static library that never uses asan.
242		libNoAsan := result.ModuleForTests("libnoasan", staticVariant)
243
244		// Static library that specifies asan
245		libStaticAsan := result.ModuleForTests("libstatic_asan", staticAsanVariant)
246		libStaticAsanNoAsanVariant := result.ModuleForTests("libstatic_asan", staticVariant)
247
248		libAsanSharedRuntime := result.ModuleForTests("libclang_rt.asan", sharedVariant)
249		libAsanStaticRuntime := result.ModuleForTests("libclang_rt.asan.static", staticVariant)
250		libAsanStaticCxxRuntime := result.ModuleForTests("libclang_rt.asan_cxx.static", staticVariant)
251
252		expectSharedLinkDep(t, ctx, binWithAsan, libShared)
253		expectSharedLinkDep(t, ctx, binWithAsan, libAsan)
254		expectSharedLinkDep(t, ctx, libShared, libTransitive)
255		expectSharedLinkDep(t, ctx, libAsan, libTransitive)
256
257		expectStaticLinkDep(t, ctx, binWithAsan, libStaticAsanVariant)
258		expectStaticLinkDep(t, ctx, binWithAsan, libNoAsan)
259		expectStaticLinkDep(t, ctx, binWithAsan, libStaticAsan)
260
261		expectInstallDep(t, binWithAsan, libShared)
262		expectInstallDep(t, binWithAsan, libAsan)
263		expectInstallDep(t, binWithAsan, libTransitive)
264		expectInstallDep(t, libShared, libTransitive)
265		expectInstallDep(t, libAsan, libTransitive)
266
267		expectSharedLinkDep(t, ctx, binNoAsan, libShared)
268		expectSharedLinkDep(t, ctx, binNoAsan, libAsan)
269		expectSharedLinkDep(t, ctx, libShared, libTransitive)
270		expectSharedLinkDep(t, ctx, libAsan, libTransitive)
271
272		expectStaticLinkDep(t, ctx, binNoAsan, libStaticNoAsanVariant)
273		expectStaticLinkDep(t, ctx, binNoAsan, libNoAsan)
274		expectStaticLinkDep(t, ctx, binNoAsan, libStaticAsanNoAsanVariant)
275
276		expectInstallDep(t, binNoAsan, libShared)
277		expectInstallDep(t, binNoAsan, libAsan)
278		expectInstallDep(t, binNoAsan, libTransitive)
279		expectInstallDep(t, libShared, libTransitive)
280		expectInstallDep(t, libAsan, libTransitive)
281
282		if runtimeLinkage == RUNTIME_LINKAGE_SHARED {
283			expectSharedLinkDep(t, ctx, binWithAsan, libAsanSharedRuntime)
284			expectNoSharedLinkDep(t, ctx, binNoAsan, libAsanSharedRuntime)
285			expectSharedLinkDep(t, ctx, libAsan, libAsanSharedRuntime)
286			expectNoSharedLinkDep(t, ctx, libShared, libAsanSharedRuntime)
287			expectNoSharedLinkDep(t, ctx, libTransitive, libAsanSharedRuntime)
288		} else {
289			expectNoSharedLinkDep(t, ctx, binWithAsan, libAsanSharedRuntime)
290			expectNoSharedLinkDep(t, ctx, binNoAsan, libAsanSharedRuntime)
291			expectNoSharedLinkDep(t, ctx, libAsan, libAsanSharedRuntime)
292			expectNoSharedLinkDep(t, ctx, libShared, libAsanSharedRuntime)
293			expectNoSharedLinkDep(t, ctx, libTransitive, libAsanSharedRuntime)
294		}
295
296		if runtimeLinkage == RUNTIME_LINKAGE_STATIC {
297			expectStaticLinkDep(t, ctx, binWithAsan, libAsanStaticRuntime)
298			expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticRuntime)
299			expectStaticLinkDep(t, ctx, libAsan, libAsanStaticRuntime)
300			expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticRuntime)
301			expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticRuntime)
302
303			expectStaticLinkDep(t, ctx, binWithAsan, libAsanStaticCxxRuntime)
304			expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticCxxRuntime)
305			expectStaticLinkDep(t, ctx, libAsan, libAsanStaticCxxRuntime)
306			expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticCxxRuntime)
307			expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticCxxRuntime)
308		} else {
309			expectNoStaticLinkDep(t, ctx, binWithAsan, libAsanStaticRuntime)
310			expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticRuntime)
311			expectNoStaticLinkDep(t, ctx, libAsan, libAsanStaticRuntime)
312			expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticRuntime)
313			expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticRuntime)
314
315			expectNoStaticLinkDep(t, ctx, binWithAsan, libAsanStaticCxxRuntime)
316			expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticCxxRuntime)
317			expectNoStaticLinkDep(t, ctx, libAsan, libAsanStaticCxxRuntime)
318			expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticCxxRuntime)
319			expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticCxxRuntime)
320		}
321	}
322
323	t.Run("host", func(t *testing.T) { check(t, buildOS, RUNTIME_LINKAGE_NONE, preparer) })
324	t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", RUNTIME_LINKAGE_SHARED, preparer) })
325	t.Run("host musl", func(t *testing.T) {
326		check(t, "linux_musl_x86_64", RUNTIME_LINKAGE_STATIC,
327			android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
328	})
329}
330
331func TestTsan(t *testing.T) {
332	t.Parallel()
333	bp := `
334	cc_binary {
335		name: "bin_with_tsan",
336		host_supported: true,
337		shared_libs: [
338			"libshared",
339			"libtsan",
340		],
341		sanitize: {
342			thread: true,
343		}
344	}
345
346	cc_binary {
347		name: "bin_no_tsan",
348		host_supported: true,
349		shared_libs: [
350			"libshared",
351			"libtsan",
352		],
353	}
354
355	cc_library_shared {
356		name: "libshared",
357		host_supported: true,
358		shared_libs: ["libtransitive"],
359	}
360
361	cc_library_shared {
362		name: "libtsan",
363		host_supported: true,
364		shared_libs: ["libtransitive"],
365		sanitize: {
366			thread: true,
367		}
368	}
369
370	cc_library_shared {
371		name: "libtransitive",
372		host_supported: true,
373	}
374`
375
376	preparer := android.GroupFixturePreparers(
377		prepareForCcTest,
378		prepareForTsanTest,
379	)
380	buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
381
382	check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
383		result := preparer.RunTestWithBp(t, bp)
384		ctx := result.TestContext
385		tsanVariant := variant + "_tsan"
386		sharedVariant := variant + "_shared"
387		sharedTsanVariant := sharedVariant + "_tsan"
388
389		// The binaries, one with tsan and one without
390		binWithTsan := result.ModuleForTests("bin_with_tsan", tsanVariant)
391		binNoTsan := result.ModuleForTests("bin_no_tsan", variant)
392
393		// Shared libraries that don't request tsan
394		libShared := result.ModuleForTests("libshared", sharedVariant)
395		libTransitive := result.ModuleForTests("libtransitive", sharedVariant)
396
397		// Shared library that requests tsan
398		libTsan := result.ModuleForTests("libtsan", sharedTsanVariant)
399
400		expectSharedLinkDep(t, ctx, binWithTsan, libShared)
401		expectSharedLinkDep(t, ctx, binWithTsan, libTsan)
402		expectSharedLinkDep(t, ctx, libShared, libTransitive)
403		expectSharedLinkDep(t, ctx, libTsan, libTransitive)
404
405		expectSharedLinkDep(t, ctx, binNoTsan, libShared)
406		expectSharedLinkDep(t, ctx, binNoTsan, libTsan)
407		expectSharedLinkDep(t, ctx, libShared, libTransitive)
408		expectSharedLinkDep(t, ctx, libTsan, libTransitive)
409	}
410
411	t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
412	t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", preparer) })
413	t.Run("host musl", func(t *testing.T) {
414		check(t, "linux_musl_x86_64", android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
415	})
416}
417
418func TestMiscUndefined(t *testing.T) {
419	if runtime.GOOS != "linux" {
420		t.Skip("requires linux")
421	}
422
423	t.Parallel()
424	bp := `
425	cc_binary {
426		name: "bin_with_ubsan",
427		srcs: ["src.cc"],
428		host_supported: true,
429		static_libs: [
430			"libstatic",
431			"libubsan",
432		],
433		sanitize: {
434			misc_undefined: ["integer"],
435		}
436	}
437
438	cc_binary {
439		name: "bin_no_ubsan",
440		host_supported: true,
441		srcs: ["src.cc"],
442		static_libs: [
443			"libstatic",
444			"libubsan",
445		],
446	}
447
448	cc_library_static {
449		name: "libstatic",
450		host_supported: true,
451		srcs: ["src.cc"],
452		static_libs: ["libtransitive"],
453	}
454
455	cc_library_static {
456		name: "libubsan",
457		host_supported: true,
458		srcs: ["src.cc"],
459		whole_static_libs: ["libtransitive"],
460		sanitize: {
461			misc_undefined: ["integer"],
462		}
463	}
464
465	cc_library_static {
466		name: "libtransitive",
467		host_supported: true,
468		srcs: ["src.cc"],
469	}
470`
471
472	preparer := android.GroupFixturePreparers(
473		prepareForCcTest,
474	)
475	buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
476
477	check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
478		result := preparer.RunTestWithBp(t, bp)
479		ctx := result.TestContext
480		staticVariant := variant + "_static"
481
482		// The binaries, one with ubsan and one without
483		binWithUbsan := result.ModuleForTests("bin_with_ubsan", variant)
484		binNoUbsan := result.ModuleForTests("bin_no_ubsan", variant)
485
486		// Static libraries that don't request ubsan
487		libStatic := result.ModuleForTests("libstatic", staticVariant)
488		libTransitive := result.ModuleForTests("libtransitive", staticVariant)
489
490		libUbsan := result.ModuleForTests("libubsan", staticVariant)
491
492		libUbsanMinimal := result.ModuleForTests("libclang_rt.ubsan_minimal", staticVariant)
493
494		expectStaticLinkDep(t, ctx, binWithUbsan, libStatic)
495		expectStaticLinkDep(t, ctx, binWithUbsan, libUbsan)
496		expectStaticLinkDep(t, ctx, binWithUbsan, libUbsanMinimal)
497
498		miscUndefinedSanFlag := "-fsanitize=integer"
499		binWithUbsanCflags := binWithUbsan.Rule("cc").Args["cFlags"]
500		if !strings.Contains(binWithUbsanCflags, miscUndefinedSanFlag) {
501			t.Errorf("'bin_with_ubsan' Expected %q to be in flags %q, was not", miscUndefinedSanFlag, binWithUbsanCflags)
502		}
503		libStaticCflags := libStatic.Rule("cc").Args["cFlags"]
504		if strings.Contains(libStaticCflags, miscUndefinedSanFlag) {
505			t.Errorf("'libstatic' Expected %q to NOT be in flags %q, was", miscUndefinedSanFlag, binWithUbsanCflags)
506		}
507		libUbsanCflags := libUbsan.Rule("cc").Args["cFlags"]
508		if !strings.Contains(libUbsanCflags, miscUndefinedSanFlag) {
509			t.Errorf("'libubsan' Expected %q to be in flags %q, was not", miscUndefinedSanFlag, binWithUbsanCflags)
510		}
511		libTransitiveCflags := libTransitive.Rule("cc").Args["cFlags"]
512		if strings.Contains(libTransitiveCflags, miscUndefinedSanFlag) {
513			t.Errorf("'libtransitive': Expected %q to NOT be in flags %q, was", miscUndefinedSanFlag, binWithUbsanCflags)
514		}
515
516		expectStaticLinkDep(t, ctx, binNoUbsan, libStatic)
517		expectStaticLinkDep(t, ctx, binNoUbsan, libUbsan)
518	}
519
520	t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
521	t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", preparer) })
522	t.Run("host musl", func(t *testing.T) {
523		check(t, "linux_musl_x86_64", android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
524	})
525}
526
527func TestFuzz(t *testing.T) {
528	t.Parallel()
529	bp := `
530		cc_binary {
531			name: "bin_with_fuzzer",
532			host_supported: true,
533			shared_libs: [
534				"libshared",
535				"libfuzzer",
536			],
537			static_libs: [
538				"libstatic",
539				"libnofuzzer",
540				"libstatic_fuzzer",
541			],
542			sanitize: {
543				fuzzer: true,
544			}
545		}
546
547		cc_binary {
548			name: "bin_no_fuzzer",
549			host_supported: true,
550			shared_libs: [
551				"libshared",
552				"libfuzzer",
553			],
554			static_libs: [
555				"libstatic",
556				"libnofuzzer",
557				"libstatic_fuzzer",
558			],
559		}
560
561		cc_library_shared {
562			name: "libshared",
563			host_supported: true,
564			shared_libs: ["libtransitive"],
565		}
566
567		cc_library_shared {
568			name: "libfuzzer",
569			host_supported: true,
570			shared_libs: ["libtransitive"],
571			sanitize: {
572				fuzzer: true,
573			}
574		}
575
576		cc_library_shared {
577			name: "libtransitive",
578			host_supported: true,
579		}
580
581		cc_library_static {
582			name: "libstatic",
583			host_supported: true,
584		}
585
586		cc_library_static {
587			name: "libnofuzzer",
588			host_supported: true,
589			sanitize: {
590				fuzzer: false,
591			}
592		}
593
594		cc_library_static {
595			name: "libstatic_fuzzer",
596			host_supported: true,
597		}
598
599	`
600
601	result := android.GroupFixturePreparers(
602		prepareForCcTest,
603	).RunTestWithBp(t, bp)
604
605	check := func(t *testing.T, result *android.TestResult, variant string) {
606		ctx := result.TestContext
607		fuzzerVariant := variant + "_fuzzer"
608		sharedVariant := variant + "_shared"
609		sharedFuzzerVariant := sharedVariant + "_fuzzer"
610		staticVariant := variant + "_static"
611		staticFuzzerVariant := staticVariant + "_fuzzer"
612
613		// The binaries, one with fuzzer and one without
614		binWithFuzzer := result.ModuleForTests("bin_with_fuzzer", fuzzerVariant)
615		binNoFuzzer := result.ModuleForTests("bin_no_fuzzer", variant)
616
617		// Shared libraries that don't request fuzzer
618		libShared := result.ModuleForTests("libshared", sharedVariant)
619		libTransitive := result.ModuleForTests("libtransitive", sharedVariant)
620
621		// Shared libraries that don't request fuzzer
622		libSharedFuzzer := result.ModuleForTests("libshared", sharedFuzzerVariant)
623		libTransitiveFuzzer := result.ModuleForTests("libtransitive", sharedFuzzerVariant)
624
625		// Shared library that requests fuzzer
626		libFuzzer := result.ModuleForTests("libfuzzer", sharedFuzzerVariant)
627
628		// Static library that uses an fuzzer variant for bin_with_fuzzer and a non-fuzzer variant
629		// for bin_no_fuzzer.
630		libStaticFuzzerVariant := result.ModuleForTests("libstatic", staticFuzzerVariant)
631		libStaticNoFuzzerVariant := result.ModuleForTests("libstatic", staticVariant)
632
633		// Static library that never uses fuzzer.
634		libNoFuzzer := result.ModuleForTests("libnofuzzer", staticVariant)
635
636		// Static library that specifies fuzzer
637		libStaticFuzzer := result.ModuleForTests("libstatic_fuzzer", staticFuzzerVariant)
638		libStaticFuzzerNoFuzzerVariant := result.ModuleForTests("libstatic_fuzzer", staticVariant)
639
640		expectSharedLinkDep(t, ctx, binWithFuzzer, libSharedFuzzer)
641		expectSharedLinkDep(t, ctx, binWithFuzzer, libFuzzer)
642		expectSharedLinkDep(t, ctx, libSharedFuzzer, libTransitiveFuzzer)
643		expectSharedLinkDep(t, ctx, libFuzzer, libTransitiveFuzzer)
644
645		expectStaticLinkDep(t, ctx, binWithFuzzer, libStaticFuzzerVariant)
646		expectStaticLinkDep(t, ctx, binWithFuzzer, libNoFuzzer)
647		expectStaticLinkDep(t, ctx, binWithFuzzer, libStaticFuzzer)
648
649		expectSharedLinkDep(t, ctx, binNoFuzzer, libShared)
650		expectSharedLinkDep(t, ctx, binNoFuzzer, libFuzzer)
651		expectSharedLinkDep(t, ctx, libShared, libTransitive)
652		expectSharedLinkDep(t, ctx, libFuzzer, libTransitiveFuzzer)
653
654		expectStaticLinkDep(t, ctx, binNoFuzzer, libStaticNoFuzzerVariant)
655		expectStaticLinkDep(t, ctx, binNoFuzzer, libNoFuzzer)
656		expectStaticLinkDep(t, ctx, binNoFuzzer, libStaticFuzzerNoFuzzerVariant)
657	}
658
659	t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
660}
661
662func TestUbsan(t *testing.T) {
663	t.Parallel()
664	if runtime.GOOS != "linux" {
665		t.Skip("requires linux")
666	}
667
668	bp := `
669		cc_binary {
670			name: "bin_with_ubsan",
671			host_supported: true,
672			shared_libs: [
673				"libshared",
674			],
675			static_libs: [
676				"libstatic",
677				"libnoubsan",
678			],
679			sanitize: {
680				undefined: true,
681			}
682		}
683
684		cc_binary {
685			name: "bin_depends_ubsan_static",
686			host_supported: true,
687			shared_libs: [
688				"libshared",
689			],
690			static_libs: [
691				"libstatic",
692				"libubsan",
693				"libnoubsan",
694			],
695		}
696
697		cc_binary {
698			name: "bin_depends_ubsan_shared",
699			host_supported: true,
700			shared_libs: [
701				"libsharedubsan",
702			],
703		}
704
705		cc_binary {
706			name: "bin_no_ubsan",
707			host_supported: true,
708			shared_libs: [
709				"libshared",
710			],
711			static_libs: [
712				"libstatic",
713				"libnoubsan",
714			],
715		}
716
717		cc_library_shared {
718			name: "libshared",
719			host_supported: true,
720			shared_libs: ["libtransitive"],
721		}
722
723		cc_library_shared {
724			name: "libtransitive",
725			host_supported: true,
726		}
727
728		cc_library_shared {
729			name: "libsharedubsan",
730			host_supported: true,
731			sanitize: {
732				undefined: true,
733			}
734		}
735
736		cc_library_static {
737			name: "libubsan",
738			host_supported: true,
739			sanitize: {
740				undefined: true,
741			}
742		}
743
744		cc_library_static {
745			name: "libstatic",
746			host_supported: true,
747		}
748
749		cc_library_static {
750			name: "libnoubsan",
751			host_supported: true,
752		}
753	`
754
755	preparer := android.GroupFixturePreparers(
756		prepareForCcTest,
757	)
758	buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
759
760	check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
761		result := preparer.RunTestWithBp(t, bp)
762		staticVariant := variant + "_static"
763		sharedVariant := variant + "_shared"
764
765		minimalRuntime := result.ModuleForTests("libclang_rt.ubsan_minimal", staticVariant)
766
767		// The binaries, one with ubsan and one without
768		binWithUbsan := result.ModuleForTests("bin_with_ubsan", variant)
769		binDependsUbsan := result.ModuleForTests("bin_depends_ubsan_static", variant)
770		libSharedUbsan := result.ModuleForTests("libsharedubsan", sharedVariant)
771		binDependsUbsanShared := result.ModuleForTests("bin_depends_ubsan_shared", variant)
772		binNoUbsan := result.ModuleForTests("bin_no_ubsan", variant)
773
774		android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in bin_with_ubsan static libs",
775			strings.Split(binWithUbsan.Rule("ld").Args["libFlags"], " "),
776			minimalRuntime.OutputFiles(t, "")[0].String())
777
778		android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in bin_depends_ubsan_static static libs",
779			strings.Split(binDependsUbsan.Rule("ld").Args["libFlags"], " "),
780			minimalRuntime.OutputFiles(t, "")[0].String())
781
782		android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in libsharedubsan static libs",
783			strings.Split(libSharedUbsan.Rule("ld").Args["libFlags"], " "),
784			minimalRuntime.OutputFiles(t, "")[0].String())
785
786		android.AssertStringListDoesNotContain(t, "unexpected libclang_rt.ubsan_minimal in bin_depends_ubsan_shared static libs",
787			strings.Split(binDependsUbsanShared.Rule("ld").Args["libFlags"], " "),
788			minimalRuntime.OutputFiles(t, "")[0].String())
789
790		android.AssertStringListDoesNotContain(t, "unexpected libclang_rt.ubsan_minimal in bin_no_ubsan static libs",
791			strings.Split(binNoUbsan.Rule("ld").Args["libFlags"], " "),
792			minimalRuntime.OutputFiles(t, "")[0].String())
793
794		android.AssertStringListContains(t, "missing -Wl,--exclude-libs for minimal runtime in bin_with_ubsan",
795			strings.Split(binWithUbsan.Rule("ld").Args["ldFlags"], " "),
796			"-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
797
798		android.AssertStringListContains(t, "missing -Wl,--exclude-libs for minimal runtime in bin_depends_ubsan_static static libs",
799			strings.Split(binDependsUbsan.Rule("ld").Args["ldFlags"], " "),
800			"-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
801
802		android.AssertStringListContains(t, "missing -Wl,--exclude-libs for minimal runtime in libsharedubsan static libs",
803			strings.Split(libSharedUbsan.Rule("ld").Args["ldFlags"], " "),
804			"-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
805
806		android.AssertStringListDoesNotContain(t, "unexpected -Wl,--exclude-libs for minimal runtime in bin_depends_ubsan_shared static libs",
807			strings.Split(binDependsUbsanShared.Rule("ld").Args["ldFlags"], " "),
808			"-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
809
810		android.AssertStringListDoesNotContain(t, "unexpected -Wl,--exclude-libs for minimal runtime in bin_no_ubsan static libs",
811			strings.Split(binNoUbsan.Rule("ld").Args["ldFlags"], " "),
812			"-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
813	}
814
815	t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
816	t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", preparer) })
817	t.Run("host musl", func(t *testing.T) {
818		check(t, "linux_musl_x86_64", android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
819	})
820}
821
822type MemtagNoteType int
823
824const (
825	None MemtagNoteType = iota + 1
826	Sync
827	Async
828)
829
830func (t MemtagNoteType) str() string {
831	switch t {
832	case None:
833		return "none"
834	case Sync:
835		return "sync"
836	case Async:
837		return "async"
838	default:
839		panic("type_note_invalid")
840	}
841}
842
843func checkHasMemtagNote(t *testing.T, m android.TestingModule, expected MemtagNoteType) {
844	t.Helper()
845
846	found := None
847	ldFlags := m.Rule("ld").Args["ldFlags"]
848	if strings.Contains(ldFlags, "-fsanitize-memtag-mode=async") {
849		found = Async
850	} else if strings.Contains(ldFlags, "-fsanitize-memtag-mode=sync") {
851		found = Sync
852	}
853
854	if found != expected {
855		t.Errorf("Wrong Memtag note in target %q: found %q, expected %q", m.Module().(*Module).Name(), found.str(), expected.str())
856	}
857}
858
859var prepareForTestWithMemtagHeap = android.GroupFixturePreparers(
860	android.FixtureModifyMockFS(func(fs android.MockFS) {
861		templateBp := `
862		cc_test {
863			name: "unset_test_%[1]s",
864			gtest: false,
865		}
866
867		cc_test {
868			name: "no_memtag_test_%[1]s",
869			gtest: false,
870			sanitize: { memtag_heap: false },
871		}
872
873		cc_test {
874			name: "set_memtag_test_%[1]s",
875			gtest: false,
876			sanitize: { memtag_heap: true },
877		}
878
879		cc_test {
880			name: "set_memtag_set_async_test_%[1]s",
881			gtest: false,
882			sanitize: { memtag_heap: true, diag: { memtag_heap: false }  },
883		}
884
885		cc_test {
886			name: "set_memtag_set_sync_test_%[1]s",
887			gtest: false,
888			sanitize: { memtag_heap: true, diag: { memtag_heap: true }  },
889		}
890
891		cc_test {
892			name: "unset_memtag_set_sync_test_%[1]s",
893			gtest: false,
894			sanitize: { diag: { memtag_heap: true }  },
895		}
896
897		cc_binary {
898			name: "unset_binary_%[1]s",
899		}
900
901		cc_binary {
902			name: "no_memtag_binary_%[1]s",
903			sanitize: { memtag_heap: false },
904		}
905
906		cc_binary {
907			name: "set_memtag_binary_%[1]s",
908			sanitize: { memtag_heap: true },
909		}
910
911		cc_binary {
912			name: "set_memtag_set_async_binary_%[1]s",
913			sanitize: { memtag_heap: true, diag: { memtag_heap: false }  },
914		}
915
916		cc_binary {
917			name: "set_memtag_set_sync_binary_%[1]s",
918			sanitize: { memtag_heap: true, diag: { memtag_heap: true }  },
919		}
920
921		cc_binary {
922			name: "unset_memtag_set_sync_binary_%[1]s",
923			sanitize: { diag: { memtag_heap: true }  },
924		}
925		`
926		subdirNoOverrideBp := fmt.Sprintf(templateBp, "no_override")
927		subdirOverrideDefaultDisableBp := fmt.Sprintf(templateBp, "override_default_disable")
928		subdirSyncBp := fmt.Sprintf(templateBp, "override_default_sync")
929		subdirAsyncBp := fmt.Sprintf(templateBp, "override_default_async")
930
931		fs.Merge(android.MockFS{
932			"subdir_no_override/Android.bp":              []byte(subdirNoOverrideBp),
933			"subdir_override_default_disable/Android.bp": []byte(subdirOverrideDefaultDisableBp),
934			"subdir_sync/Android.bp":                     []byte(subdirSyncBp),
935			"subdir_async/Android.bp":                    []byte(subdirAsyncBp),
936		})
937	}),
938	android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
939		variables.MemtagHeapExcludePaths = []string{"subdir_override_default_disable"}
940		// "subdir_override_default_disable" is covered by both include and override_default_disable paths. override_default_disable wins.
941		variables.MemtagHeapSyncIncludePaths = []string{"subdir_sync", "subdir_override_default_disable"}
942		variables.MemtagHeapAsyncIncludePaths = []string{"subdir_async", "subdir_override_default_disable"}
943	}),
944)
945
946func TestSanitizeMemtagHeap(t *testing.T) {
947	t.Parallel()
948	variant := "android_arm64_armv8-a"
949
950	result := android.GroupFixturePreparers(
951		prepareForCcTest,
952		prepareForTestWithMemtagHeap,
953	).RunTest(t)
954	ctx := result.TestContext
955
956	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_no_override", variant), None)
957	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_async", variant), None)
958	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_disable", variant), None)
959	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_sync", variant), None)
960
961	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_no_override", variant), None)
962	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_async", variant), None)
963	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_disable", variant), None)
964	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_sync", variant), None)
965
966	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_no_override", variant), Async)
967	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_async", variant), Async)
968	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_disable", variant), Async)
969	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_sync", variant), Sync)
970
971	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_no_override", variant), Sync)
972	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_async", variant), Sync)
973	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_disable", variant), Sync)
974	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_sync", variant), Sync)
975
976	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_no_override", variant), Async)
977	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_async", variant), Async)
978	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_disable", variant), Async)
979	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_sync", variant), Async)
980
981	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_no_override", variant), Async)
982	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_async", variant), Async)
983	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_disable", variant), Async)
984	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_sync", variant), Async)
985
986	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_no_override", variant), Sync)
987	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_async", variant), Sync)
988	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_disable", variant), Sync)
989	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_sync", variant), Sync)
990
991	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_no_override", variant), Sync)
992	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_async", variant), Sync)
993	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_disable", variant), Sync)
994	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_sync", variant), Sync)
995
996	// should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
997	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_no_override", variant), None)
998	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_async", variant), Sync)
999	// should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
1000	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_disable", variant), None)
1001	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
1002
1003	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_no_override", variant), Sync)
1004	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_async", variant), Sync)
1005	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_disable", variant), Sync)
1006	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_sync", variant), Sync)
1007
1008	checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_no_override", variant), None)
1009	checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_async", variant), Async)
1010	checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_disable", variant), None)
1011	checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_sync", variant), Sync)
1012
1013	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_no_override", variant), Sync)
1014	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_async", variant), Sync)
1015	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync)
1016	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync)
1017}
1018
1019func TestSanitizeMemtagHeapWithSanitizeDevice(t *testing.T) {
1020	t.Parallel()
1021	variant := "android_arm64_armv8-a"
1022
1023	result := android.GroupFixturePreparers(
1024		prepareForCcTest,
1025		prepareForTestWithMemtagHeap,
1026		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1027			variables.SanitizeDevice = []string{"memtag_heap"}
1028		}),
1029	).RunTest(t)
1030	ctx := result.TestContext
1031
1032	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_no_override", variant), None)
1033	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_async", variant), None)
1034	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_disable", variant), None)
1035	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_sync", variant), None)
1036
1037	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_no_override", variant), None)
1038	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_async", variant), None)
1039	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_disable", variant), None)
1040	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_sync", variant), None)
1041
1042	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_no_override", variant), Async)
1043	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_async", variant), Async)
1044	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_disable", variant), Async)
1045	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_sync", variant), Sync)
1046
1047	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_no_override", variant), Sync)
1048	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_async", variant), Sync)
1049	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_disable", variant), Sync)
1050	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_sync", variant), Sync)
1051
1052	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_no_override", variant), Async)
1053	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_async", variant), Async)
1054	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_disable", variant), Async)
1055	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_sync", variant), Async)
1056
1057	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_no_override", variant), Async)
1058	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_async", variant), Async)
1059	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_disable", variant), Async)
1060	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_sync", variant), Async)
1061
1062	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_no_override", variant), Sync)
1063	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_async", variant), Sync)
1064	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_disable", variant), Sync)
1065	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_sync", variant), Sync)
1066
1067	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_no_override", variant), Sync)
1068	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_async", variant), Sync)
1069	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_disable", variant), Sync)
1070	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_sync", variant), Sync)
1071
1072	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_no_override", variant), Sync)
1073	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_async", variant), Sync)
1074	// should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
1075	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_disable", variant), None)
1076	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
1077
1078	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_no_override", variant), Sync)
1079	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_async", variant), Sync)
1080	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_disable", variant), Sync)
1081	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_sync", variant), Sync)
1082
1083	checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_no_override", variant), Async)
1084	checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_async", variant), Async)
1085	checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_disable", variant), None)
1086	checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_sync", variant), Sync)
1087
1088	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_no_override", variant), Sync)
1089	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_async", variant), Sync)
1090	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync)
1091	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync)
1092}
1093
1094func TestSanitizeMemtagHeapWithSanitizeDeviceDiag(t *testing.T) {
1095	t.Parallel()
1096	variant := "android_arm64_armv8-a"
1097
1098	result := android.GroupFixturePreparers(
1099		prepareForCcTest,
1100		prepareForTestWithMemtagHeap,
1101		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1102			variables.SanitizeDevice = []string{"memtag_heap"}
1103			variables.SanitizeDeviceDiag = []string{"memtag_heap"}
1104		}),
1105	).RunTest(t)
1106	ctx := result.TestContext
1107
1108	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_no_override", variant), None)
1109	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_async", variant), None)
1110	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_disable", variant), None)
1111	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_sync", variant), None)
1112
1113	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_no_override", variant), None)
1114	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_async", variant), None)
1115	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_disable", variant), None)
1116	checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_sync", variant), None)
1117
1118	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_no_override", variant), Sync)
1119	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_async", variant), Sync)
1120	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_disable", variant), Sync)
1121	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_sync", variant), Sync)
1122
1123	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_no_override", variant), Sync)
1124	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_async", variant), Sync)
1125	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_disable", variant), Sync)
1126	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_sync", variant), Sync)
1127
1128	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_no_override", variant), Async)
1129	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_async", variant), Async)
1130	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_disable", variant), Async)
1131	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_sync", variant), Async)
1132
1133	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_no_override", variant), Async)
1134	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_async", variant), Async)
1135	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_disable", variant), Async)
1136	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_sync", variant), Async)
1137
1138	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_no_override", variant), Sync)
1139	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_async", variant), Sync)
1140	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_disable", variant), Sync)
1141	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_sync", variant), Sync)
1142
1143	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_no_override", variant), Sync)
1144	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_async", variant), Sync)
1145	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_disable", variant), Sync)
1146	checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_sync", variant), Sync)
1147
1148	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_no_override", variant), Sync)
1149	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_async", variant), Sync)
1150	// should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
1151	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_disable", variant), None)
1152	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
1153
1154	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_no_override", variant), Sync)
1155	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_async", variant), Sync)
1156	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_disable", variant), Sync)
1157	checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_sync", variant), Sync)
1158
1159	checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_no_override", variant), Sync)
1160	checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_async", variant), Sync)
1161	checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_disable", variant), None)
1162	checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_sync", variant), Sync)
1163
1164	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_no_override", variant), Sync)
1165	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_async", variant), Sync)
1166	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync)
1167	checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync)
1168}
1169
1170func TestCfi(t *testing.T) {
1171	t.Parallel()
1172
1173	bp := `
1174	cc_library_shared {
1175		name: "shared_with_cfi",
1176		static_libs: [
1177			"static_dep_with_cfi",
1178			"static_dep_no_cfi",
1179		],
1180		sanitize: {
1181			cfi: true,
1182		},
1183	}
1184
1185	cc_library_shared {
1186		name: "shared_no_cfi",
1187		static_libs: [
1188			"static_dep_with_cfi",
1189			"static_dep_no_cfi",
1190		],
1191	}
1192
1193	cc_library_static {
1194		name: "static_dep_with_cfi",
1195		sanitize: {
1196			cfi: true,
1197		},
1198	}
1199
1200	cc_library_static {
1201		name: "static_dep_no_cfi",
1202	}
1203
1204	cc_library_shared {
1205		name: "shared_rdep_no_cfi",
1206		static_libs: ["static_dep_with_cfi_2"],
1207	}
1208
1209	cc_library_static {
1210		name: "static_dep_with_cfi_2",
1211		sanitize: {
1212			cfi: true,
1213		},
1214	}
1215`
1216	preparer := android.GroupFixturePreparers(
1217		prepareForCcTest,
1218	)
1219	result := preparer.RunTestWithBp(t, bp)
1220	ctx := result.TestContext
1221
1222	buildOs := "android_arm64_armv8-a"
1223	shared_suffix := "_shared"
1224	cfi_suffix := "_cfi"
1225	static_suffix := "_static"
1226
1227	sharedWithCfiLib := result.ModuleForTests("shared_with_cfi", buildOs+shared_suffix+cfi_suffix)
1228	sharedNoCfiLib := result.ModuleForTests("shared_no_cfi", buildOs+shared_suffix)
1229	staticWithCfiLib := result.ModuleForTests("static_dep_with_cfi", buildOs+static_suffix)
1230	staticWithCfiLibCfiVariant := result.ModuleForTests("static_dep_with_cfi", buildOs+static_suffix+cfi_suffix)
1231	staticNoCfiLib := result.ModuleForTests("static_dep_no_cfi", buildOs+static_suffix)
1232	staticNoCfiLibCfiVariant := result.ModuleForTests("static_dep_no_cfi", buildOs+static_suffix+cfi_suffix)
1233	sharedRdepNoCfi := result.ModuleForTests("shared_rdep_no_cfi", buildOs+shared_suffix)
1234	staticDepWithCfi2Lib := result.ModuleForTests("static_dep_with_cfi_2", buildOs+static_suffix)
1235
1236	// Confirm assumptions about propagation of CFI enablement
1237	expectStaticLinkDep(t, ctx, sharedWithCfiLib, staticWithCfiLibCfiVariant)
1238	expectStaticLinkDep(t, ctx, sharedNoCfiLib, staticWithCfiLib)
1239	expectStaticLinkDep(t, ctx, sharedWithCfiLib, staticNoCfiLibCfiVariant)
1240	expectStaticLinkDep(t, ctx, sharedNoCfiLib, staticNoCfiLib)
1241	expectStaticLinkDep(t, ctx, sharedRdepNoCfi, staticDepWithCfi2Lib)
1242
1243	// Confirm that non-CFI variants do not add CFI flags
1244	bazLibCflags := staticWithCfiLib.Rule("cc").Args["cFlags"]
1245	if strings.Contains(bazLibCflags, "-fsanitize-cfi-cross-dso") {
1246		t.Errorf("non-CFI variant of baz not expected to contain CFI flags ")
1247	}
1248}
1249