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