Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  sanitize_test.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2021 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cc

import (
 "fmt"
 "reflect"
 "runtime"
 "strings"
 "testing"

 "android/soong/android"
)

var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(`
 cc_library_shared {
  name: "libclang_rt.asan",
  host_supported: true,
 }
 cc_library_static {
  name: "libclang_rt.asan.static",
  host_supported: true,
 }
 cc_library_static {
  name: "libclang_rt.asan_cxx.static",
  host_supported: true,
 }
`))

var prepareForTsanTest = android.FixtureAddFile("tsan/Android.bp", []byte(`
 cc_library_shared {
  name: "libclang_rt.tsan",
  host_supported: true,
 }
`))

type providerInterface interface {
 android.OtherModuleProviderContext
}

// expectSharedLinkDep verifies that the from module links against the to module as a
// shared library.
func expectSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
 t.Helper()
 fromLink := from.Description("link")
 toInfo, _ := android.OtherModuleProvider(ctx, to.Module(), SharedLibraryInfoProvider)

 if g, w := fromLink.OrderOnly.Strings(), toInfo.SharedLibrary.RelativeToTop().String(); !android.InList(w, g) {
  t.Errorf("%s should link against %s, expected %q, got %q",
   from.Module(), to.Module(), w, g)
 }
}

// expectNoSharedLinkDep verifies that the from module links against the to module as a
// shared library.
func expectNoSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
 t.Helper()
 fromLink := from.Description("link")
 toInfo, _ := android.OtherModuleProvider(ctx, to.Module(), SharedLibraryInfoProvider)

 if g, w := fromLink.OrderOnly.Strings(), toInfo.SharedLibrary.RelativeToTop().String(); android.InList(w, g) {
  t.Errorf("%s should not link against %s, expected %q, got %q",
   from.Module(), to.Module(), w, g)
 }
}

// expectStaticLinkDep verifies that the from module links against the to module as a
// static library.
func expectStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
 t.Helper()
 fromLink := from.Description("link")
 toInfo, _ := android.OtherModuleProvider(ctx, to.Module(), StaticLibraryInfoProvider)

 if g, w := fromLink.Implicits.Strings(), toInfo.StaticLibrary.RelativeToTop().String(); !android.InList(w, g) {
  t.Errorf("%s should link against %s, expected %q, got %q",
   from.Module(), to.Module(), w, g)
 }

}

// expectNoStaticLinkDep verifies that the from module links against the to module as a
// static library.
func expectNoStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
 t.Helper()
 fromLink := from.Description("link")
 toInfo, _ := android.OtherModuleProvider(ctx, to.Module(), StaticLibraryInfoProvider)

 if g, w := fromLink.Implicits.Strings(), toInfo.StaticLibrary.RelativeToTop().String(); android.InList(w, g) {
  t.Errorf("%s should not link against %s, expected %q, got %q",
   from.Module(), to.Module(), w, g)
 }

}

// expectInstallDep verifies that the install rule of the from module depends on the
// install rule of the to module.
func expectInstallDep(t *testing.T, from, to android.TestingModule) {
 t.Helper()
 fromInstalled := from.Description("install")
 toInstalled := to.Description("install")

 // combine implicits and order-only dependencies, host uses implicit but device uses
 // order-only.
 got := append(fromInstalled.Implicits.Strings(), fromInstalled.OrderOnly.Strings()...)
 want := toInstalled.Output.String()
 if !android.InList(want, got) {
  t.Errorf("%s installation should depend on %s, expected %q, got %q",
   from.Module(), to.Module(), want, got)
 }
}

type expectedRuntimeLinkage int

const (
 RUNTIME_LINKAGE_NONE   = expectedRuntimeLinkage(0)
 RUNTIME_LINKAGE_SHARED = iota
 RUNTIME_LINKAGE_STATIC
)

func TestAsan(t *testing.T) {
 t.Parallel()
 bp := `
  cc_binary {
   name: "bin_with_asan",
   host_supported: true,
   shared_libs: [
    "libshared",
    "libasan",
   ],
   static_libs: [
    "libstatic",
    "libnoasan",
    "libstatic_asan",
   ],
   sanitize: {
    address: true,
   }
  }

  cc_binary {
   name: "bin_no_asan",
   host_supported: true,
   shared_libs: [
    "libshared",
    "libasan",
   ],
   static_libs: [
    "libstatic",
    "libnoasan",
    "libstatic_asan",
   ],
  }

  cc_library_shared {
   name: "libshared",
   host_supported: true,
   shared_libs: ["libtransitive"],
  }

  cc_library_shared {
   name: "libasan",
   host_supported: true,
   shared_libs: ["libtransitive"],
   sanitize: {
    address: true,
   }
  }

  cc_library_shared {
   name: "libtransitive",
   host_supported: true,
  }

  cc_library_static {
   name: "libstatic",
   host_supported: true,
  }

  cc_library_static {
   name: "libnoasan",
   host_supported: true,
   sanitize: {
    address: false,
   }
  }

  cc_library_static {
   name: "libstatic_asan",
   host_supported: true,
   sanitize: {
    address: true,
   }
  }

 `

 preparer := android.GroupFixturePreparers(
  prepareForCcTest,
  prepareForAsanTest,
 )
 buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()

 check := func(t *testing.T, variant string, runtimeLinkage expectedRuntimeLinkage, preparer android.FixturePreparer) {
  result := preparer.RunTestWithBp(t, bp)
  ctx := result.TestContext
  asanVariant := variant + "_asan"
  sharedVariant := variant + "_shared"
  sharedAsanVariant := sharedVariant + "_asan"
  staticVariant := variant + "_static"
  staticAsanVariant := staticVariant + "_asan"

  // The binaries, one with asan and one without
  binWithAsan := result.ModuleForTests(t, "bin_with_asan", asanVariant)
  binNoAsan := result.ModuleForTests(t, "bin_no_asan", variant)

  // Shared libraries that don't request asan
  libShared := result.ModuleForTests(t, "libshared", sharedVariant)
  libTransitive := result.ModuleForTests(t, "libtransitive", sharedVariant)

  // Shared library that requests asan
  libAsan := result.ModuleForTests(t, "libasan", sharedAsanVariant)

  // Static library that uses an asan variant for bin_with_asan and a non-asan variant
  // for bin_no_asan.
  libStaticAsanVariant := result.ModuleForTests(t, "libstatic", staticAsanVariant)
  libStaticNoAsanVariant := result.ModuleForTests(t, "libstatic", staticVariant)

  // Static library that never uses asan.
  libNoAsan := result.ModuleForTests(t, "libnoasan", staticVariant)

  // Static library that specifies asan
  libStaticAsan := result.ModuleForTests(t, "libstatic_asan", staticAsanVariant)
  libStaticAsanNoAsanVariant := result.ModuleForTests(t, "libstatic_asan", staticVariant)

  libAsanSharedRuntime := result.ModuleForTests(t, "libclang_rt.asan", sharedVariant)
  libAsanStaticRuntime := result.ModuleForTests(t, "libclang_rt.asan.static", staticVariant)
  libAsanStaticCxxRuntime := result.ModuleForTests(t, "libclang_rt.asan_cxx.static", staticVariant)

  expectSharedLinkDep(t, ctx, binWithAsan, libShared)
  expectSharedLinkDep(t, ctx, binWithAsan, libAsan)
  expectSharedLinkDep(t, ctx, libShared, libTransitive)
  expectSharedLinkDep(t, ctx, libAsan, libTransitive)

  expectStaticLinkDep(t, ctx, binWithAsan, libStaticAsanVariant)
  expectStaticLinkDep(t, ctx, binWithAsan, libNoAsan)
  expectStaticLinkDep(t, ctx, binWithAsan, libStaticAsan)

  expectInstallDep(t, binWithAsan, libShared)
  expectInstallDep(t, binWithAsan, libAsan)
  expectInstallDep(t, binWithAsan, libTransitive)
  expectInstallDep(t, libShared, libTransitive)
  expectInstallDep(t, libAsan, libTransitive)

  expectSharedLinkDep(t, ctx, binNoAsan, libShared)
  expectSharedLinkDep(t, ctx, binNoAsan, libAsan)
  expectSharedLinkDep(t, ctx, libShared, libTransitive)
  expectSharedLinkDep(t, ctx, libAsan, libTransitive)

  expectStaticLinkDep(t, ctx, binNoAsan, libStaticNoAsanVariant)
  expectStaticLinkDep(t, ctx, binNoAsan, libNoAsan)
  expectStaticLinkDep(t, ctx, binNoAsan, libStaticAsanNoAsanVariant)

  expectInstallDep(t, binNoAsan, libShared)
  expectInstallDep(t, binNoAsan, libAsan)
  expectInstallDep(t, binNoAsan, libTransitive)
  expectInstallDep(t, libShared, libTransitive)
  expectInstallDep(t, libAsan, libTransitive)

  if runtimeLinkage == RUNTIME_LINKAGE_SHARED {
   expectSharedLinkDep(t, ctx, binWithAsan, libAsanSharedRuntime)
   expectNoSharedLinkDep(t, ctx, binNoAsan, libAsanSharedRuntime)
   expectSharedLinkDep(t, ctx, libAsan, libAsanSharedRuntime)
   expectNoSharedLinkDep(t, ctx, libShared, libAsanSharedRuntime)
   expectNoSharedLinkDep(t, ctx, libTransitive, libAsanSharedRuntime)
  } else {
   expectNoSharedLinkDep(t, ctx, binWithAsan, libAsanSharedRuntime)
   expectNoSharedLinkDep(t, ctx, binNoAsan, libAsanSharedRuntime)
   expectNoSharedLinkDep(t, ctx, libAsan, libAsanSharedRuntime)
   expectNoSharedLinkDep(t, ctx, libShared, libAsanSharedRuntime)
   expectNoSharedLinkDep(t, ctx, libTransitive, libAsanSharedRuntime)
  }

  if runtimeLinkage == RUNTIME_LINKAGE_STATIC {
   expectStaticLinkDep(t, ctx, binWithAsan, libAsanStaticRuntime)
   expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticRuntime)
   expectStaticLinkDep(t, ctx, libAsan, libAsanStaticRuntime)
   expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticRuntime)
   expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticRuntime)

   expectStaticLinkDep(t, ctx, binWithAsan, libAsanStaticCxxRuntime)
   expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticCxxRuntime)
   expectStaticLinkDep(t, ctx, libAsan, libAsanStaticCxxRuntime)
   expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticCxxRuntime)
   expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticCxxRuntime)
  } else {
   expectNoStaticLinkDep(t, ctx, binWithAsan, libAsanStaticRuntime)
   expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticRuntime)
   expectNoStaticLinkDep(t, ctx, libAsan, libAsanStaticRuntime)
   expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticRuntime)
   expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticRuntime)

   expectNoStaticLinkDep(t, ctx, binWithAsan, libAsanStaticCxxRuntime)
   expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticCxxRuntime)
   expectNoStaticLinkDep(t, ctx, libAsan, libAsanStaticCxxRuntime)
   expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticCxxRuntime)
   expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticCxxRuntime)
  }
 }

 t.Run("host", func(t *testing.T) { check(t, buildOS, RUNTIME_LINKAGE_NONE, preparer) })
 t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", RUNTIME_LINKAGE_SHARED, preparer) })
 t.Run("host musl", func(t *testing.T) {
  check(t, "linux_musl_x86_64", RUNTIME_LINKAGE_STATIC,
   android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
 })
}

func TestTsan(t *testing.T) {
 t.Parallel()
 bp := `
 cc_binary {
  name: "bin_with_tsan",
  host_supported: true,
  shared_libs: [
   "libshared",
   "libtsan",
  ],
  sanitize: {
   thread: true,
  }
 }

 cc_binary {
  name: "bin_no_tsan",
  host_supported: true,
  shared_libs: [
   "libshared",
   "libtsan",
  ],
 }

 cc_library_shared {
  name: "libshared",
  host_supported: true,
  shared_libs: ["libtransitive"],
 }

 cc_library_shared {
  name: "libtsan",
  host_supported: true,
  shared_libs: ["libtransitive"],
  sanitize: {
   thread: true,
  }
 }

 cc_library_shared {
  name: "libtransitive",
  host_supported: true,
 }
`

 preparer := android.GroupFixturePreparers(
  prepareForCcTest,
  prepareForTsanTest,
 )
 buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()

 check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
  result := preparer.RunTestWithBp(t, bp)
  ctx := result.TestContext
  tsanVariant := variant + "_tsan"
  sharedVariant := variant + "_shared"
  sharedTsanVariant := sharedVariant + "_tsan"

  // The binaries, one with tsan and one without
  binWithTsan := result.ModuleForTests(t, "bin_with_tsan", tsanVariant)
  binNoTsan := result.ModuleForTests(t, "bin_no_tsan", variant)

  // Shared libraries that don't request tsan
  libShared := result.ModuleForTests(t, "libshared", sharedVariant)
  libTransitive := result.ModuleForTests(t, "libtransitive", sharedVariant)

  // Shared library that requests tsan
  libTsan := result.ModuleForTests(t, "libtsan", sharedTsanVariant)

  expectSharedLinkDep(t, ctx, binWithTsan, libShared)
  expectSharedLinkDep(t, ctx, binWithTsan, libTsan)
  expectSharedLinkDep(t, ctx, libShared, libTransitive)
  expectSharedLinkDep(t, ctx, libTsan, libTransitive)

  expectSharedLinkDep(t, ctx, binNoTsan, libShared)
  expectSharedLinkDep(t, ctx, binNoTsan, libTsan)
  expectSharedLinkDep(t, ctx, libShared, libTransitive)
  expectSharedLinkDep(t, ctx, libTsan, libTransitive)
 }

 t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
 t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", preparer) })
 t.Run("host musl", func(t *testing.T) {
  check(t, "linux_musl_x86_64", android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
 })
}

func TestMiscUndefined(t *testing.T) {
 if runtime.GOOS != "linux" {
  t.Skip("requires linux")
 }

 t.Parallel()
 bp := `
 cc_binary {
  name: "bin_with_ubsan",
  srcs: ["src.cc"],
  host_supported: true,
  static_libs: [
   "libstatic",
   "libubsan",
  ],
  sanitize: {
   misc_undefined: ["integer"],
  }
 }

 cc_binary {
  name: "bin_no_ubsan",
  host_supported: true,
  srcs: ["src.cc"],
  static_libs: [
   "libstatic",
   "libubsan",
  ],
 }

 cc_library_static {
  name: "libstatic",
  host_supported: true,
  srcs: ["src.cc"],
  static_libs: ["libtransitive"],
 }

 cc_library_static {
  name: "libubsan",
  host_supported: true,
  srcs: ["src.cc"],
  whole_static_libs: ["libtransitive"],
  sanitize: {
   misc_undefined: ["integer"],
  }
 }

 cc_library_static {
  name: "libtransitive",
  host_supported: true,
  srcs: ["src.cc"],
 }
`

 preparer := android.GroupFixturePreparers(
  prepareForCcTest,
 )
 buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()

 check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
  result := preparer.RunTestWithBp(t, bp)
  ctx := result.TestContext
  staticVariant := variant + "_static"

  // The binaries, one with ubsan and one without
  binWithUbsan := result.ModuleForTests(t, "bin_with_ubsan", variant)
  binNoUbsan := result.ModuleForTests(t, "bin_no_ubsan", variant)

  // Static libraries that don't request ubsan
  libStatic := result.ModuleForTests(t, "libstatic", staticVariant)
  libTransitive := result.ModuleForTests(t, "libtransitive", staticVariant)

  libUbsan := result.ModuleForTests(t, "libubsan", staticVariant)

  libUbsanMinimal := result.ModuleForTests(t, "libclang_rt.ubsan_minimal", staticVariant)

  expectStaticLinkDep(t, ctx, binWithUbsan, libStatic)
  expectStaticLinkDep(t, ctx, binWithUbsan, libUbsan)
  expectStaticLinkDep(t, ctx, binWithUbsan, libUbsanMinimal)

  miscUndefinedSanFlag := "-fsanitize=integer"
  binWithUbsanCflags := binWithUbsan.Rule("cc").Args["cFlags"]
  if !strings.Contains(binWithUbsanCflags, miscUndefinedSanFlag) {
   t.Errorf("'bin_with_ubsan' Expected %q to be in flags %q, was not", miscUndefinedSanFlag, binWithUbsanCflags)
  }
  libStaticCflags := libStatic.Rule("cc").Args["cFlags"]
  if strings.Contains(libStaticCflags, miscUndefinedSanFlag) {
   t.Errorf("'libstatic' Expected %q to NOT be in flags %q, was", miscUndefinedSanFlag, binWithUbsanCflags)
  }
  libUbsanCflags := libUbsan.Rule("cc").Args["cFlags"]
  if !strings.Contains(libUbsanCflags, miscUndefinedSanFlag) {
   t.Errorf("'libubsan' Expected %q to be in flags %q, was not", miscUndefinedSanFlag, binWithUbsanCflags)
  }
  libTransitiveCflags := libTransitive.Rule("cc").Args["cFlags"]
  if strings.Contains(libTransitiveCflags, miscUndefinedSanFlag) {
   t.Errorf("'libtransitive': Expected %q to NOT be in flags %q, was", miscUndefinedSanFlag, binWithUbsanCflags)
  }

  expectStaticLinkDep(t, ctx, binNoUbsan, libStatic)
  expectStaticLinkDep(t, ctx, binNoUbsan, libUbsan)
 }

 t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
 t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", preparer) })
 t.Run("host musl", func(t *testing.T) {
  check(t, "linux_musl_x86_64", android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
 })
}

func TestFuzz(t *testing.T) {
 t.Parallel()
 bp := `
  cc_binary {
   name: "bin_with_fuzzer",
   host_supported: true,
   shared_libs: [
    "libshared",
    "libfuzzer",
   ],
   static_libs: [
    "libstatic",
    "libnofuzzer",
    "libstatic_fuzzer",
   ],
   sanitize: {
    fuzzer: true,
   }
  }

  cc_binary {
   name: "bin_no_fuzzer",
   host_supported: true,
   shared_libs: [
    "libshared",
    "libfuzzer",
   ],
   static_libs: [
    "libstatic",
    "libnofuzzer",
    "libstatic_fuzzer",
   ],
  }

  cc_library_shared {
   name: "libshared",
   host_supported: true,
   shared_libs: ["libtransitive"],
  }

  cc_library_shared {
   name: "libfuzzer",
   host_supported: true,
   shared_libs: ["libtransitive"],
   sanitize: {
    fuzzer: true,
   }
  }

  cc_library_shared {
   name: "libtransitive",
   host_supported: true,
  }

  cc_library_static {
   name: "libstatic",
   host_supported: true,
  }

  cc_library_static {
   name: "libnofuzzer",
   host_supported: true,
   sanitize: {
    fuzzer: false,
   }
  }

  cc_library_static {
   name: "libstatic_fuzzer",
   host_supported: true,
  }

 `

 result := android.GroupFixturePreparers(
  prepareForCcTest,
 ).RunTestWithBp(t, bp)

 check := func(t *testing.T, result *android.TestResult, variant string) {
  ctx := result.TestContext
  fuzzerVariant := variant + "_fuzzer"
  sharedVariant := variant + "_shared"
  sharedFuzzerVariant := sharedVariant + "_fuzzer"
  staticVariant := variant + "_static"
  staticFuzzerVariant := staticVariant + "_fuzzer"

  // The binaries, one with fuzzer and one without
  binWithFuzzer := result.ModuleForTests(t, "bin_with_fuzzer", fuzzerVariant)
  binNoFuzzer := result.ModuleForTests(t, "bin_no_fuzzer", variant)

  // Shared libraries that don't request fuzzer
  libShared := result.ModuleForTests(t, "libshared", sharedVariant)
  libTransitive := result.ModuleForTests(t, "libtransitive", sharedVariant)

  // Shared libraries that don't request fuzzer
  libSharedFuzzer := result.ModuleForTests(t, "libshared", sharedFuzzerVariant)
  libTransitiveFuzzer := result.ModuleForTests(t, "libtransitive", sharedFuzzerVariant)

  // Shared library that requests fuzzer
  libFuzzer := result.ModuleForTests(t, "libfuzzer", sharedFuzzerVariant)

  // Static library that uses an fuzzer variant for bin_with_fuzzer and a non-fuzzer variant
  // for bin_no_fuzzer.
  libStaticFuzzerVariant := result.ModuleForTests(t, "libstatic", staticFuzzerVariant)
  libStaticNoFuzzerVariant := result.ModuleForTests(t, "libstatic", staticVariant)

  // Static library that never uses fuzzer.
  libNoFuzzer := result.ModuleForTests(t, "libnofuzzer", staticVariant)

  // Static library that specifies fuzzer
  libStaticFuzzer := result.ModuleForTests(t, "libstatic_fuzzer", staticFuzzerVariant)
  libStaticFuzzerNoFuzzerVariant := result.ModuleForTests(t, "libstatic_fuzzer", staticVariant)

  expectSharedLinkDep(t, ctx, binWithFuzzer, libSharedFuzzer)
  expectSharedLinkDep(t, ctx, binWithFuzzer, libFuzzer)
  expectSharedLinkDep(t, ctx, libSharedFuzzer, libTransitiveFuzzer)
  expectSharedLinkDep(t, ctx, libFuzzer, libTransitiveFuzzer)

  expectStaticLinkDep(t, ctx, binWithFuzzer, libStaticFuzzerVariant)
  expectStaticLinkDep(t, ctx, binWithFuzzer, libNoFuzzer)
  expectStaticLinkDep(t, ctx, binWithFuzzer, libStaticFuzzer)

  expectSharedLinkDep(t, ctx, binNoFuzzer, libShared)
  expectSharedLinkDep(t, ctx, binNoFuzzer, libFuzzer)
  expectSharedLinkDep(t, ctx, libShared, libTransitive)
  expectSharedLinkDep(t, ctx, libFuzzer, libTransitiveFuzzer)

  expectStaticLinkDep(t, ctx, binNoFuzzer, libStaticNoFuzzerVariant)
  expectStaticLinkDep(t, ctx, binNoFuzzer, libNoFuzzer)
  expectStaticLinkDep(t, ctx, binNoFuzzer, libStaticFuzzerNoFuzzerVariant)
 }

 t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
}

func TestUbsan(t *testing.T) {
 t.Parallel()
 if runtime.GOOS != "linux" {
  t.Skip("requires linux")
 }

 bp := `
  cc_binary {
   name: "bin_with_ubsan",
   host_supported: true,
   shared_libs: [
    "libshared",
   ],
   static_libs: [
    "libstatic",
    "libnoubsan",
   ],
   sanitize: {
    undefined: true,
   }
  }

  cc_binary {
   name: "bin_depends_ubsan_static",
   host_supported: true,
   shared_libs: [
    "libshared",
   ],
   static_libs: [
    "libstatic",
    "libubsan",
    "libnoubsan",
   ],
  }

  cc_binary {
   name: "bin_depends_ubsan_shared",
   host_supported: true,
   shared_libs: [
    "libsharedubsan",
   ],
  }

  cc_binary {
   name: "bin_no_ubsan",
   host_supported: true,
   shared_libs: [
    "libshared",
   ],
   static_libs: [
    "libstatic",
    "libnoubsan",
   ],
  }

  cc_binary {
   name: "static_bin_with_ubsan_dep",
   static_executable: true,
   host_supported: true,
   static_libs: [
    "libubsan_diag",
   ],
  }

  cc_library_shared {
   name: "libshared",
   host_supported: true,
   shared_libs: ["libtransitive"],
  }

  cc_library_shared {
   name: "libtransitive",
   host_supported: true,
  }

  cc_library_shared {
   name: "libsharedubsan",
   host_supported: true,
   sanitize: {
    undefined: true,
   }
  }

  cc_library_static {
   name: "libubsan",
   host_supported: true,
   sanitize: {
    undefined: true,
   }
  }

  cc_library_static {
   name: "libubsan_diag",
   host_supported: true,
   sanitize: {
    undefined: true,
    diag: {
     undefined: true,
    },
   },
  }

  cc_library_static {
   name: "libstatic",
   host_supported: true,
  }

  cc_library_static {
   name: "libnoubsan",
   host_supported: true,
  }
 `

 preparer := android.GroupFixturePreparers(
  prepareForCcTest,
 )
 buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()

 check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
  result := preparer.RunTestWithBp(t, bp)
  staticVariant := variant + "_static"
  sharedVariant := variant + "_shared"

  minimalRuntime := result.ModuleForTests(t, "libclang_rt.ubsan_minimal", staticVariant)
  standaloneRuntime := result.ModuleForTests(t, "libclang_rt.ubsan_standalone.static", staticVariant)

  // The binaries, one with ubsan and one without
  binWithUbsan := result.ModuleForTests(t, "bin_with_ubsan", variant)
  binDependsUbsan := result.ModuleForTests(t, "bin_depends_ubsan_static", variant)
  libSharedUbsan := result.ModuleForTests(t, "libsharedubsan", sharedVariant)
  binDependsUbsanShared := result.ModuleForTests(t, "bin_depends_ubsan_shared", variant)
  binNoUbsan := result.ModuleForTests(t, "bin_no_ubsan", variant)
  staticBin := result.ModuleForTests(t, "static_bin_with_ubsan_dep", variant)

  android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in bin_with_ubsan static libs",
   strings.Split(binWithUbsan.Rule("ld").Args["libFlags"], " "),
   minimalRuntime.OutputFiles(result.TestContext, t, "")[0].String())

  android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in bin_depends_ubsan_static static libs",
   strings.Split(binDependsUbsan.Rule("ld").Args["libFlags"], " "),
   minimalRuntime.OutputFiles(result.TestContext, t, "")[0].String())

  android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in libsharedubsan static libs",
   strings.Split(libSharedUbsan.Rule("ld").Args["libFlags"], " "),
   minimalRuntime.OutputFiles(result.TestContext, t, "")[0].String())

  android.AssertStringListDoesNotContain(t, "unexpected libclang_rt.ubsan_minimal in bin_depends_ubsan_shared static libs",
   strings.Split(binDependsUbsanShared.Rule("ld").Args["libFlags"], " "),
   minimalRuntime.OutputFiles(result.TestContext, t, "")[0].String())

  android.AssertStringListDoesNotContain(t, "unexpected libclang_rt.ubsan_minimal in bin_no_ubsan static libs",
   strings.Split(binNoUbsan.Rule("ld").Args["libFlags"], " "),
   minimalRuntime.OutputFiles(result.TestContext, t, "")[0].String())

  android.AssertStringListContains(t, "missing -Wl,--exclude-libs for minimal runtime in bin_with_ubsan",
   strings.Split(binWithUbsan.Rule("ld").Args["ldFlags"], " "),
   "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(result.TestContext, t, "")[0].Base())

  android.AssertStringListContains(t, "missing -Wl,--exclude-libs for minimal runtime in bin_depends_ubsan_static static libs",
   strings.Split(binDependsUbsan.Rule("ld").Args["ldFlags"], " "),
   "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(result.TestContext, t, "")[0].Base())

  android.AssertStringListContains(t, "missing -Wl,--exclude-libs for minimal runtime in libsharedubsan static libs",
   strings.Split(libSharedUbsan.Rule("ld").Args["ldFlags"], " "),
   "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(result.TestContext, t, "")[0].Base())

  android.AssertStringListDoesNotContain(t, "unexpected -Wl,--exclude-libs for minimal runtime in bin_depends_ubsan_shared static libs",
   strings.Split(binDependsUbsanShared.Rule("ld").Args["ldFlags"], " "),
   "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(result.TestContext, t, "")[0].Base())

  android.AssertStringListDoesNotContain(t, "unexpected -Wl,--exclude-libs for minimal runtime in bin_no_ubsan static libs",
   strings.Split(binNoUbsan.Rule("ld").Args["ldFlags"], " "),
   "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(result.TestContext, t, "")[0].Base())

  android.AssertStringListContains(t, "missing libclang_rt.ubsan_standalone.static in static_bin_with_ubsan_dep static libs",
   strings.Split(staticBin.Rule("ld").Args["libFlags"], " "),
   standaloneRuntime.OutputFiles(result.TestContext, t, "")[0].String())

 }

 t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
 t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", preparer) })
 t.Run("host musl", func(t *testing.T) {
  check(t, "linux_musl_x86_64", android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
 })
}

type MemtagNoteType int

const (
 None MemtagNoteType = iota + 1
 Sync
 Async
)

func (t MemtagNoteType) str() string {
 switch t {
 case None:
  return "none"
 case Sync:
  return "sync"
 case Async:
  return "async"
 default:
  panic("type_note_invalid")
 }
}

func checkHasMemtagNote(t *testing.T, m android.TestingModule, expected MemtagNoteType) {
 t.Helper()

 found := None
 ldFlags := m.Rule("ld").Args["ldFlags"]
 if strings.Contains(ldFlags, "-fsanitize-memtag-mode=async") {
  found = Async
 } else if strings.Contains(ldFlags, "-fsanitize-memtag-mode=sync") {
  found = Sync
 }

 if found != expected {
  t.Errorf("Wrong Memtag note in target %q: found %q, expected %q", m.Module().(*Module).Name(), found.str(), expected.str())
 }
}

var prepareForTestWithMemtagHeap = android.GroupFixturePreparers(
 android.FixtureModifyMockFS(func(fs android.MockFS) {
  templateBp := `
  cc_test {
   name: "unset_test_%[1]s",
   gtest: false,
  }

  cc_test {
   name: "no_memtag_test_%[1]s",
   gtest: false,
   sanitize: { memtag_heap: false },
  }

  cc_test {
   name: "set_memtag_test_%[1]s",
   gtest: false,
   sanitize: { memtag_heap: true },
  }

  cc_test {
   name: "set_memtag_set_async_test_%[1]s",
   gtest: false,
   sanitize: { memtag_heap: true, diag: { memtag_heap: false }  },
  }

  cc_test {
   name: "set_memtag_set_sync_test_%[1]s",
   gtest: false,
   sanitize: { memtag_heap: true, diag: { memtag_heap: true }  },
  }

  cc_test {
   name: "unset_memtag_set_sync_test_%[1]s",
   gtest: false,
   sanitize: { diag: { memtag_heap: true }  },
  }

  cc_binary {
   name: "unset_binary_%[1]s",
  }

  cc_binary {
   name: "no_memtag_binary_%[1]s",
   sanitize: { memtag_heap: false },
  }

  cc_binary {
   name: "set_memtag_binary_%[1]s",
   sanitize: { memtag_heap: true },
  }

  cc_binary {
   name: "set_memtag_set_async_binary_%[1]s",
   sanitize: { memtag_heap: true, diag: { memtag_heap: false }  },
  }

  cc_binary {
   name: "set_memtag_set_sync_binary_%[1]s",
   sanitize: { memtag_heap: true, diag: { memtag_heap: true }  },
  }

  cc_binary {
   name: "unset_memtag_set_sync_binary_%[1]s",
   sanitize: { diag: { memtag_heap: true }  },
  }
  `
  subdirNoOverrideBp := fmt.Sprintf(templateBp, "no_override")
  subdirOverrideDefaultDisableBp := fmt.Sprintf(templateBp, "override_default_disable")
  subdirSyncBp := fmt.Sprintf(templateBp, "override_default_sync")
  subdirAsyncBp := fmt.Sprintf(templateBp, "override_default_async")

  fs.Merge(android.MockFS{
   "subdir_no_override/Android.bp":              []byte(subdirNoOverrideBp),
   "subdir_override_default_disable/Android.bp": []byte(subdirOverrideDefaultDisableBp),
   "subdir_sync/Android.bp":                     []byte(subdirSyncBp),
   "subdir_async/Android.bp":                    []byte(subdirAsyncBp),
  })
 }),
 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
  variables.MemtagHeapExcludePaths = []string{"subdir_override_default_disable"}
  // "subdir_override_default_disable" is covered by both include and override_default_disable paths. override_default_disable wins.
  variables.MemtagHeapSyncIncludePaths = []string{"subdir_sync", "subdir_override_default_disable"}
  variables.MemtagHeapAsyncIncludePaths = []string{"subdir_async", "subdir_override_default_disable"}
 }),
)

func TestSanitizeMemtagHeap(t *testing.T) {
 t.Parallel()
 variant := "android_arm64_armv8-a"

 result := android.GroupFixturePreparers(
  prepareForCcTest,
  prepareForTestWithMemtagHeap,
 ).RunTest(t)
 ctx := result.TestContext

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_no_override", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_async", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_disable", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_sync", variant), None)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_no_override", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_async", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_disable", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_sync", variant), None)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_no_override", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_async", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_disable", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_no_override", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_async", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_disable", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_sync", variant), Async)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_no_override", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_async", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_disable", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_sync", variant), Async)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_sync", variant), Sync)

 // should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_no_override", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_async", variant), Sync)
 // should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_disable", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_no_override", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_async", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_disable", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_sync", variant), Sync)
}

func TestSanitizeMemtagHeapWithSanitizeDevice(t *testing.T) {
 t.Parallel()
 variant := "android_arm64_armv8-a"

 result := android.GroupFixturePreparers(
  prepareForCcTest,
  prepareForTestWithMemtagHeap,
  android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
   variables.SanitizeDevice = []string{"memtag_heap"}
  }),
 ).RunTest(t)
 ctx := result.TestContext

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_no_override", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_async", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_disable", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_sync", variant), None)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_no_override", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_async", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_disable", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_sync", variant), None)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_no_override", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_async", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_disable", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_no_override", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_async", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_disable", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_sync", variant), Async)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_no_override", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_async", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_disable", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_sync", variant), Async)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_async", variant), Sync)
 // should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_disable", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_no_override", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_async", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_disable", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_sync", variant), Sync)
}

func TestSanitizeMemtagHeapWithSanitizeDeviceDiag(t *testing.T) {
 t.Parallel()
 variant := "android_arm64_armv8-a"

 result := android.GroupFixturePreparers(
  prepareForCcTest,
  prepareForTestWithMemtagHeap,
  android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
   variables.SanitizeDevice = []string{"memtag_heap"}
   variables.SanitizeDeviceDiag = []string{"memtag_heap"}
  }),
 ).RunTest(t)
 ctx := result.TestContext

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_no_override", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_async", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_disable", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_sync", variant), None)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_no_override", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_async", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_disable", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_sync", variant), None)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_no_override", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_async", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_disable", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_sync", variant), Async)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_no_override", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_async", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_disable", variant), Async)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_sync", variant), Async)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_async", variant), Sync)
 // should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_disable", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_disable", variant), None)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_sync", variant), Sync)

 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_no_override", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_async", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_disable", variant), Sync)
 checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_sync", variant), Sync)
}

func TestCfi(t *testing.T) {
 t.Parallel()

 bp := `
 cc_library_shared {
  name: "shared_with_cfi",
  static_libs: [
   "static_dep_with_cfi",
   "static_dep_no_cfi",
  ],
  sanitize: {
   cfi: true,
  },
 }

 cc_library_shared {
  name: "shared_no_cfi",
  static_libs: [
   "static_dep_with_cfi",
   "static_dep_no_cfi",
  ],
 }

 cc_library_static {
  name: "static_dep_with_cfi",
  sanitize: {
   cfi: true,
  },
 }

 cc_library_static {
  name: "static_dep_no_cfi",
 }

 cc_library_shared {
  name: "shared_rdep_no_cfi",
  static_libs: ["static_dep_with_cfi_2"],
 }

 cc_library_static {
  name: "static_dep_with_cfi_2",
  sanitize: {
   cfi: true,
  },
 }
`
 preparer := android.GroupFixturePreparers(
  prepareForCcTest,
 )
 result := preparer.RunTestWithBp(t, bp)
 ctx := result.TestContext

 buildOs := "android_arm64_armv8-a"
 shared_suffix := "_shared"
 cfi_suffix := "_cfi"
 static_suffix := "_static"

 sharedWithCfiLib := result.ModuleForTests(t, "shared_with_cfi", buildOs+shared_suffix+cfi_suffix)
 sharedNoCfiLib := result.ModuleForTests(t, "shared_no_cfi", buildOs+shared_suffix)
 staticWithCfiLib := result.ModuleForTests(t, "static_dep_with_cfi", buildOs+static_suffix)
 staticWithCfiLibCfiVariant := result.ModuleForTests(t, "static_dep_with_cfi", buildOs+static_suffix+cfi_suffix)
 staticNoCfiLib := result.ModuleForTests(t, "static_dep_no_cfi", buildOs+static_suffix)
 staticNoCfiLibCfiVariant := result.ModuleForTests(t, "static_dep_no_cfi", buildOs+static_suffix+cfi_suffix)
 sharedRdepNoCfi := result.ModuleForTests(t, "shared_rdep_no_cfi", buildOs+shared_suffix)
 staticDepWithCfi2Lib := result.ModuleForTests(t, "static_dep_with_cfi_2", buildOs+static_suffix)

 // Confirm assumptions about propagation of CFI enablement
 expectStaticLinkDep(t, ctx, sharedWithCfiLib, staticWithCfiLibCfiVariant)
 expectStaticLinkDep(t, ctx, sharedNoCfiLib, staticWithCfiLib)
 expectStaticLinkDep(t, ctx, sharedWithCfiLib, staticNoCfiLibCfiVariant)
 expectStaticLinkDep(t, ctx, sharedNoCfiLib, staticNoCfiLib)
 expectStaticLinkDep(t, ctx, sharedRdepNoCfi, staticDepWithCfi2Lib)

 // Confirm that non-CFI variants do not add CFI flags
 bazLibCflags := staticWithCfiLib.Rule("cc").Args["cFlags"]
 if strings.Contains(bazLibCflags, "-fsanitize-cfi-cross-dso") {
  t.Errorf("non-CFI variant of baz not expected to contain CFI flags ")
 }
}

func TestHwasan(t *testing.T) {
 t.Parallel()

 bp := `
 cc_library_shared {
  name: "shared_with_hwaddress",
  static_libs: [
   "static_dep_with_hwaddress",
   "static_dep_no_hwaddress",
  ],
  sanitize: {
   hwaddress: true,
  },
  sdk_version: "current",
   stl: "c++_shared",
   split_all_variants: true,
 }

 cc_library_static {
  name: "static_dep_with_hwaddress",
  sanitize: {
   hwaddress: true,
  },
  sdk_version: "current",
   stl: "c++_shared",
   split_all_variants: true,
 }

 cc_library_static {
  name: "static_dep_no_hwaddress",
  sdk_version: "current",
   stl: "c++_shared",
   split_all_variants: true,
 }
`

 androidArm := "android_arm_armv7-a-neon"
 androidArm64 := "android_arm64_armv8-a"
 androidX86 := "android_x86_silvermont"
 sharedSuffix := "_shared"
 hwasanSuffix := "_hwasan"
 staticSuffix := "_static"
 sdkSuffix := "_sdk"

 sharedWithHwasanVariant := sharedSuffix + hwasanSuffix
 sharedWithSdkVariant := sdkSuffix + sharedSuffix
 staticWithHwasanVariant := staticSuffix + hwasanSuffix
 staticWithSdkVariant := sdkSuffix + staticSuffix

 testCases := []struct {
  buildOs          string
  extraPreparer    android.FixturePreparer
  expectedVariants map[string][]string
 }{
  {
   buildOs: androidArm64,
   expectedVariants: map[string][]string{
    "shared_with_hwaddress": []string{
     androidArm64 + sharedWithHwasanVariant,
     androidArm64 + sharedWithSdkVariant,
     androidArm + sharedSuffix,
     androidArm + sharedWithSdkVariant,
    },
    "static_dep_with_hwaddress": []string{
     androidArm64 + staticSuffix,
     androidArm64 + staticWithHwasanVariant,
     androidArm64 + staticWithSdkVariant,
     androidArm + staticSuffix,
     androidArm + staticWithSdkVariant,
    },
    "static_dep_no_hwaddress": []string{
     androidArm64 + staticSuffix,
     androidArm64 + staticWithHwasanVariant,
     androidArm64 + staticWithSdkVariant,
     androidArm + staticSuffix,
     androidArm + staticWithSdkVariant,
    },
   },
  },
  {
   buildOs: androidX86,
   extraPreparer: android.FixtureModifyConfig(func(config android.Config) {
    config.Targets[android.Android] = []android.Target{
     {
      Os:   android.Android,
      Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}},
     },
    }
   }),
   expectedVariants: map[string][]string{
    "shared_with_hwaddress": []string{
     androidX86 + sharedSuffix,
     androidX86 + sharedWithSdkVariant,
    },
    "static_dep_with_hwaddress": []string{
     androidX86 + staticSuffix,
     androidX86 + staticWithSdkVariant,
    },
    "static_dep_no_hwaddress": []string{
     androidX86 + staticSuffix,
     androidX86 + staticWithSdkVariant,
    },
   },
  },
 }

 for _, tc := range testCases {
  preparer := android.GroupFixturePreparers(
   prepareForCcTest,
   android.OptionalFixturePreparer(tc.extraPreparer),
  )
  result := preparer.RunTestWithBp(t, bp)

  for m, v := range tc.expectedVariants {
   variants := result.ModuleVariantsForTests(m)
   if !reflect.DeepEqual(variants, v) {
    t.Errorf("Expected variants of %q to be %q, but got %q", m, v, variants)
   }
  }
 }
}

[Dauer der Verarbeitung: 0.29 Sekunden, vorverarbeitet 2026-06-28]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik