Add sanitizer tests for musl

Add tests that verify sanitizer behaviors for musl.

Test: sanitize_test.go
Change-Id: I1f0a51cc103ac14d1738cb223e216ee0e32d8550
This commit is contained in:
Colin Cross
2023-02-15 12:20:19 -08:00
parent 9e87f0a6ea
commit 5dc62c9456
5 changed files with 164 additions and 23 deletions

View File

@@ -401,7 +401,7 @@ func TestArchMutator(t *testing.T) {
{ {
name: "same arch host and host cross", name: "same arch host and host cross",
preparer: FixtureModifyConfig(func(config Config) { preparer: FixtureModifyConfig(func(config Config) {
modifyTestConfigForMusl(config) ModifyTestConfigForMusl(config)
modifyTestConfigForMuslArm64HostCross(config) modifyTestConfigForMuslArm64HostCross(config)
}), }),
fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"}, fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
@@ -705,7 +705,7 @@ func TestArchProperties(t *testing.T) {
{ {
name: "linux_musl", name: "linux_musl",
goOS: "linux", goOS: "linux",
preparer: FixtureModifyConfig(modifyTestConfigForMusl), preparer: FixtureModifyConfig(ModifyTestConfigForMusl),
results: []result{ results: []result{
{ {
module: "foo", module: "foo",

View File

@@ -16,6 +16,7 @@ package android
import ( import (
"fmt" "fmt"
"runtime"
"strings" "strings"
"testing" "testing"
) )
@@ -379,6 +380,12 @@ func FixtureModifyProductVariables(mutator func(variables FixtureProductVariable
}) })
} }
var PrepareForSkipTestOnMac = newSimpleFixturePreparer(func(fixture *fixture) {
if runtime.GOOS != "linux" {
fixture.t.Skip("Test is only supported on linux.")
}
})
// PrepareForDebug_DO_NOT_SUBMIT puts the fixture into debug which will cause it to output its // PrepareForDebug_DO_NOT_SUBMIT puts the fixture into debug which will cause it to output its
// state before running the test. // state before running the test.
// //

View File

@@ -109,7 +109,8 @@ func modifyTestConfigToSupportArchMutator(testConfig Config) {
config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon") config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon")
} }
func modifyTestConfigForMusl(config Config) { // ModifyTestConfigForMusl takes a Config returned by TestConfig and changes the host targets from glibc to musl.
func ModifyTestConfigForMusl(config Config) {
delete(config.Targets, config.BuildOS) delete(config.Targets, config.BuildOS)
config.productVariables.HostMusl = boolPtr(true) config.productVariables.HostMusl = boolPtr(true)
determineBuildOS(config.config) determineBuildOS(config.config)

View File

@@ -28,12 +28,22 @@ import (
var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(` var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(`
cc_library_shared { cc_library_shared {
name: "libclang_rt.asan", 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(` var prepareForTsanTest = android.FixtureAddFile("tsan/Android.bp", []byte(`
cc_library_shared { cc_library_shared {
name: "libclang_rt.tsan", name: "libclang_rt.tsan",
host_supported: true,
} }
`)) `))
@@ -54,6 +64,19 @@ func expectSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.T
} }
} }
// 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 := ctx.ModuleProvider(to.Module(), SharedLibraryInfoProvider).(SharedLibraryInfo)
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 // expectStaticLinkDep verifies that the from module links against the to module as a
// static library. // static library.
func expectStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) { func expectStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
@@ -68,6 +91,20 @@ func expectStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.T
} }
// 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 := ctx.ModuleProvider(to.Module(), StaticLibraryInfoProvider).(StaticLibraryInfo)
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 // expectInstallDep verifies that the install rule of the from module depends on the
// install rule of the to module. // install rule of the to module.
func expectInstallDep(t *testing.T, from, to android.TestingModule) { func expectInstallDep(t *testing.T, from, to android.TestingModule) {
@@ -85,6 +122,13 @@ func expectInstallDep(t *testing.T, from, to android.TestingModule) {
} }
} }
type expectedRuntimeLinkage int
const (
RUNTIME_LINKAGE_NONE = expectedRuntimeLinkage(0)
RUNTIME_LINKAGE_SHARED = iota
)
func TestAsan(t *testing.T) { func TestAsan(t *testing.T) {
t.Parallel() t.Parallel()
bp := ` bp := `
@@ -162,12 +206,14 @@ func TestAsan(t *testing.T) {
` `
result := android.GroupFixturePreparers( preparer := android.GroupFixturePreparers(
prepareForCcTest, prepareForCcTest,
prepareForAsanTest, prepareForAsanTest,
).RunTestWithBp(t, bp) )
buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
check := func(t *testing.T, result *android.TestResult, variant string) { check := func(t *testing.T, variant string, runtimeLinkage expectedRuntimeLinkage, preparer android.FixturePreparer) {
result := preparer.RunTestWithBp(t, bp)
ctx := result.TestContext ctx := result.TestContext
asanVariant := variant + "_asan" asanVariant := variant + "_asan"
sharedVariant := variant + "_shared" sharedVariant := variant + "_shared"
@@ -198,6 +244,8 @@ func TestAsan(t *testing.T) {
libStaticAsan := result.ModuleForTests("libstatic_asan", staticAsanVariant) libStaticAsan := result.ModuleForTests("libstatic_asan", staticAsanVariant)
libStaticAsanNoAsanVariant := result.ModuleForTests("libstatic_asan", staticVariant) libStaticAsanNoAsanVariant := result.ModuleForTests("libstatic_asan", staticVariant)
libAsanSharedRuntime := result.ModuleForTests("libclang_rt.asan", sharedVariant)
expectSharedLinkDep(t, ctx, binWithAsan, libShared) expectSharedLinkDep(t, ctx, binWithAsan, libShared)
expectSharedLinkDep(t, ctx, binWithAsan, libAsan) expectSharedLinkDep(t, ctx, binWithAsan, libAsan)
expectSharedLinkDep(t, ctx, libShared, libTransitive) expectSharedLinkDep(t, ctx, libShared, libTransitive)
@@ -227,10 +275,28 @@ func TestAsan(t *testing.T) {
expectInstallDep(t, binNoAsan, libTransitive) expectInstallDep(t, binNoAsan, libTransitive)
expectInstallDep(t, libShared, libTransitive) expectInstallDep(t, libShared, libTransitive)
expectInstallDep(t, libAsan, 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)
}
} }
t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) }) t.Run("host", func(t *testing.T) { check(t, buildOS, RUNTIME_LINKAGE_NONE, preparer) })
t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") }) 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_SHARED,
android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
})
} }
func TestTsan(t *testing.T) { func TestTsan(t *testing.T) {
@@ -278,12 +344,14 @@ func TestTsan(t *testing.T) {
} }
` `
result := android.GroupFixturePreparers( preparer := android.GroupFixturePreparers(
prepareForCcTest, prepareForCcTest,
prepareForTsanTest, prepareForTsanTest,
).RunTestWithBp(t, bp) )
buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
check := func(t *testing.T, result *android.TestResult, variant string) { check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
result := preparer.RunTestWithBp(t, bp)
ctx := result.TestContext ctx := result.TestContext
tsanVariant := variant + "_tsan" tsanVariant := variant + "_tsan"
sharedVariant := variant + "_shared" sharedVariant := variant + "_shared"
@@ -311,8 +379,11 @@ func TestTsan(t *testing.T) {
expectSharedLinkDep(t, ctx, libTsan, libTransitive) expectSharedLinkDep(t, ctx, libTsan, libTransitive)
} }
t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) }) t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") }) 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) { func TestMiscUndefined(t *testing.T) {
@@ -369,11 +440,13 @@ func TestMiscUndefined(t *testing.T) {
} }
` `
result := android.GroupFixturePreparers( preparer := android.GroupFixturePreparers(
prepareForCcTest, prepareForCcTest,
).RunTestWithBp(t, bp) )
buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
check := func(t *testing.T, result *android.TestResult, variant string) { check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
result := preparer.RunTestWithBp(t, bp)
ctx := result.TestContext ctx := result.TestContext
staticVariant := variant + "_static" staticVariant := variant + "_static"
@@ -415,8 +488,11 @@ func TestMiscUndefined(t *testing.T) {
expectStaticLinkDep(t, ctx, binNoUbsan, libUbsan) expectStaticLinkDep(t, ctx, binNoUbsan, libUbsan)
} }
t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) }) t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") }) 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) { func TestFuzz(t *testing.T) {
@@ -647,11 +723,13 @@ func TestUbsan(t *testing.T) {
} }
` `
result := android.GroupFixturePreparers( preparer := android.GroupFixturePreparers(
prepareForCcTest, prepareForCcTest,
).RunTestWithBp(t, bp) )
buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
check := func(t *testing.T, result *android.TestResult, variant string) { check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
result := preparer.RunTestWithBp(t, bp)
staticVariant := variant + "_static" staticVariant := variant + "_static"
sharedVariant := variant + "_shared" sharedVariant := variant + "_shared"
@@ -705,8 +783,11 @@ func TestUbsan(t *testing.T) {
"-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base()) "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
} }
t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) }) t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") }) 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 type MemtagNoteType int

View File

@@ -70,6 +70,7 @@ func commonDefaultModules() string {
return ` return `
cc_defaults { cc_defaults {
name: "toolchain_libs_defaults", name: "toolchain_libs_defaults",
host_supported: true,
vendor_available: true, vendor_available: true,
product_available: true, product_available: true,
recovery_available: true, recovery_available: true,
@@ -134,6 +135,12 @@ func commonDefaultModules() string {
srcs: [""], srcs: [""],
} }
cc_prebuilt_library_static {
name: "libclang_rt.ubsan_standalone.static",
defaults: ["toolchain_libs_defaults"],
srcs: [""],
}
cc_prebuilt_library_static { cc_prebuilt_library_static {
name: "libclang_rt.ubsan_minimal", name: "libclang_rt.ubsan_minimal",
defaults: ["toolchain_libs_defaults"], defaults: ["toolchain_libs_defaults"],
@@ -151,6 +158,12 @@ func commonDefaultModules() string {
linux_glibc_x86: { linux_glibc_x86: {
srcs: ["libclang_rt.ubsan_minimal.x86.a"], srcs: ["libclang_rt.ubsan_minimal.x86.a"],
}, },
linux_musl_x86_64: {
srcs: ["libclang_rt.ubsan_minimal.x86_64.a"],
},
linux_musl_x86: {
srcs: ["libclang_rt.ubsan_minimal.x86.a"],
},
}, },
} }
@@ -619,6 +632,45 @@ var PrepareForTestWithCcIncludeVndk = android.GroupFixturePreparers(
}), }),
) )
// PrepareForTestWithHostMusl sets the host configuration to musl libc instead of glibc. It also disables the test
// on mac, which doesn't support musl libc, and adds musl modules.
var PrepareForTestWithHostMusl = android.GroupFixturePreparers(
android.FixtureModifyConfig(android.ModifyTestConfigForMusl),
android.PrepareForSkipTestOnMac,
android.FixtureAddTextFile("external/musl/Android.bp", `
cc_defaults {
name: "libc_musl_crt_defaults",
host_supported: true,
device_supported: false,
}
cc_object {
name: "libc_musl_crtbegin_so",
defaults: ["libc_musl_crt_defaults"],
}
cc_object {
name: "libc_musl_crtend_so",
defaults: ["libc_musl_crt_defaults"],
}
cc_object {
name: "libc_musl_crtbegin_dynamic",
defaults: ["libc_musl_crt_defaults"],
}
cc_object {
name: "libc_musl_crtbegin_static",
defaults: ["libc_musl_crt_defaults"],
}
cc_object {
name: "libc_musl_crtend",
defaults: ["libc_musl_crt_defaults"],
}
`),
)
// TestConfig is the legacy way of creating a test Config for testing cc modules. // TestConfig is the legacy way of creating a test Config for testing cc modules.
// //
// See testCc for an explanation as to how to stop using this deprecated method. // See testCc for an explanation as to how to stop using this deprecated method.