From 6cd99e6ab45dce7b1a3b865bacf76ce54651bd07 Mon Sep 17 00:00:00 2001 From: Ivan Lozano Date: Tue, 11 Feb 2020 08:24:25 -0500 Subject: [PATCH] Add Rust fuzzing support. Add a rust_fuzz module which builds a libfuzzer binary that enabes asan+sancov. This relies on the libfuzzer-sys crate. Bug: 147140513 Test: Local rust_fuzz example builds, fuzzes with asan+sancov. Change-Id: I57db3b8d25869791824ccfab768d13b0bb9d42fa --- rust/Android.bp | 3 + rust/builder.go | 6 +- rust/compiler.go | 1 + rust/config/arm64_device.go | 8 +- rust/config/arm_device.go | 4 + rust/config/toolchain.go | 32 +++++ rust/config/x86_64_device.go | 4 + rust/config/x86_device.go | 4 + rust/config/x86_linux_host.go | 8 ++ rust/fuzz.go | 96 +++++++++++++ rust/fuzz_test.go | 66 +++++++++ rust/proc_macro.go | 2 + rust/rust.go | 24 +++- rust/sanitize.go | 258 ++++++++++++++++++++++++++++++++++ rust/testing.go | 15 +- 15 files changed, 524 insertions(+), 7 deletions(-) create mode 100644 rust/fuzz.go create mode 100644 rust/fuzz_test.go create mode 100644 rust/sanitize.go diff --git a/rust/Android.bp b/rust/Android.bp index df731db4b..ad3040afd 100644 --- a/rust/Android.bp +++ b/rust/Android.bp @@ -15,6 +15,7 @@ bootstrap_go_package { "clippy.go", "compiler.go", "coverage.go", + "fuzz.go", "image.go", "library.go", "prebuilt.go", @@ -22,6 +23,7 @@ bootstrap_go_package { "project_json.go", "protobuf.go", "rust.go", + "sanitize.go", "strip.go", "source_provider.go", "test.go", @@ -34,6 +36,7 @@ bootstrap_go_package { "clippy_test.go", "compiler_test.go", "coverage_test.go", + "fuzz_test.go", "image_test.go", "library_test.go", "project_json_test.go", diff --git a/rust/builder.go b/rust/builder.go index baeab69e9..77d339aa5 100644 --- a/rust/builder.go +++ b/rust/builder.go @@ -86,7 +86,7 @@ func init() { func TransformSrcToBinary(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, linkDirs []string) buildOutput { - flags.RustFlags = append(flags.RustFlags, "-C lto") + flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto") return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "bin", linkDirs) } @@ -103,13 +103,13 @@ func TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, func TransformSrctoStatic(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, linkDirs []string) buildOutput { - flags.RustFlags = append(flags.RustFlags, "-C lto") + flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto") return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "staticlib", linkDirs) } func TransformSrctoShared(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, linkDirs []string) buildOutput { - flags.RustFlags = append(flags.RustFlags, "-C lto") + flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto") return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "cdylib", linkDirs) } diff --git a/rust/compiler.go b/rust/compiler.go index bcea6cccc..2d9575c0e 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -146,6 +146,7 @@ type baseCompiler struct { relative string path android.InstallPath location installLocation + sanitize *sanitize coverageOutputZipFile android.OptionalPath distFile android.OptionalPath diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go index 21b22a4d5..506642861 100644 --- a/rust/config/arm64_device.go +++ b/rust/config/arm64_device.go @@ -26,8 +26,8 @@ var ( Arm64LinkFlags = []string{} Arm64ArchVariantRustFlags = map[string][]string{ - "armv8-a": []string{}, - "armv8-2a": []string{}, + "armv8-a": []string{}, + "armv8-2a": []string{}, "armv8-2a-dotprod": []string{}, } ) @@ -71,6 +71,10 @@ func (t *toolchainArm64) Supported() bool { return true } +func (toolchainArm64) LibclangRuntimeLibraryArch() string { + return "aarch64" +} + func Arm64ToolchainFactory(arch android.Arch) Toolchain { archVariant := arch.ArchVariant if archVariant == "" { diff --git a/rust/config/arm_device.go b/rust/config/arm_device.go index adfe917a1..42c1c0256 100644 --- a/rust/config/arm_device.go +++ b/rust/config/arm_device.go @@ -72,6 +72,10 @@ func (t *toolchainArm) Supported() bool { return true } +func (toolchainArm) LibclangRuntimeLibraryArch() string { + return "arm" +} + func ArmToolchainFactory(arch android.Arch) Toolchain { toolchainRustFlags := []string{ "${config.ArmToolchainRustFlags}", diff --git a/rust/config/toolchain.go b/rust/config/toolchain.go index 616d88b89..9525c38aa 100644 --- a/rust/config/toolchain.go +++ b/rust/config/toolchain.go @@ -34,6 +34,8 @@ type Toolchain interface { Supported() bool Bionic() bool + + LibclangRuntimeLibraryArch() string } type toolchainBase struct { @@ -106,6 +108,36 @@ func (toolchainBase) Supported() bool { return false } +func (toolchainBase) LibclangRuntimeLibraryArch() string { + return "" +} + +func LibFuzzerRuntimeLibrary(t Toolchain) string { + return LibclangRuntimeLibrary(t, "fuzzer") +} + +func LibclangRuntimeLibrary(t Toolchain, library string) string { + arch := t.LibclangRuntimeLibraryArch() + if arch == "" { + return "" + } + if !t.Bionic() { + return "libclang_rt." + library + "-" + arch + } + return "libclang_rt." + library + "-" + arch + "-android" +} + +func LibRustRuntimeLibrary(t Toolchain, library string) string { + arch := t.LibclangRuntimeLibraryArch() + if arch == "" { + return "" + } + if !t.Bionic() { + return "librustc_rt." + library + "-" + arch + } + return "librustc_rt." + library + "-" + arch + "-android" +} + func toolchainBaseFactory() Toolchain { return &toolchainBase{} } diff --git a/rust/config/x86_64_device.go b/rust/config/x86_64_device.go index 5f6e85a08..94b719fb5 100644 --- a/rust/config/x86_64_device.go +++ b/rust/config/x86_64_device.go @@ -77,6 +77,10 @@ func (t *toolchainX86_64) Supported() bool { return true } +func (toolchainX86_64) LibclangRuntimeLibraryArch() string { + return "x86_64" +} + func x86_64ToolchainFactory(arch android.Arch) Toolchain { toolchainRustFlags := []string{ "${config.X86_64ToolchainRustFlags}", diff --git a/rust/config/x86_device.go b/rust/config/x86_device.go index daeeb1476..aae11252f 100644 --- a/rust/config/x86_device.go +++ b/rust/config/x86_device.go @@ -80,6 +80,10 @@ func (t *toolchainX86) Supported() bool { return true } +func (toolchainX86) LibclangRuntimeLibraryArch() string { + return "i686" +} + func x86ToolchainFactory(arch android.Arch) Toolchain { toolchainRustFlags := []string{ "${config.X86ToolchainRustFlags}", diff --git a/rust/config/x86_linux_host.go b/rust/config/x86_linux_host.go index e7f26ce5c..b63e14d25 100644 --- a/rust/config/x86_linux_host.go +++ b/rust/config/x86_linux_host.go @@ -103,6 +103,14 @@ func (t *toolchainLinuxX86) Name() string { return "x86" } +func (toolchainLinuxX86) LibclangRuntimeLibraryArch() string { + return "i386" +} + +func (toolchainLinuxX8664) LibclangRuntimeLibraryArch() string { + return "x86_64" +} + func (t *toolchainLinuxX86) RustTriple() string { return "i686-unknown-linux-gnu" } diff --git a/rust/fuzz.go b/rust/fuzz.go new file mode 100644 index 000000000..da8f209fc --- /dev/null +++ b/rust/fuzz.go @@ -0,0 +1,96 @@ +// Copyright 2020 The Android Open Source Project +// +// 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 rust + +import ( + "android/soong/android" + "android/soong/cc" + "android/soong/rust/config" +) + +func init() { + android.RegisterModuleType("rust_fuzz", RustFuzzFactory) +} + +type fuzzDecorator struct { + *binaryDecorator + + Properties cc.FuzzProperties + dictionary android.Path + corpus android.Paths + corpusIntermediateDir android.Path + config android.Path + data android.Paths + dataIntermediateDir android.Path +} + +var _ compiler = (*binaryDecorator)(nil) + +// rust_binary produces a binary that is runnable on a device. +func RustFuzzFactory() android.Module { + module, _ := NewRustFuzz(android.HostAndDeviceSupported) + return module.Init() +} + +func NewRustFuzz(hod android.HostOrDeviceSupported) (*Module, *fuzzDecorator) { + module, binary := NewRustBinary(hod) + fuzz := &fuzzDecorator{ + binaryDecorator: binary, + } + + // Change the defaults for the binaryDecorator's baseCompiler + fuzz.binaryDecorator.baseCompiler.dir = "fuzz" + fuzz.binaryDecorator.baseCompiler.dir64 = "fuzz" + fuzz.binaryDecorator.baseCompiler.location = InstallInData + module.sanitize.SetSanitizer(cc.Fuzzer, true) + module.compiler = fuzz + return module, fuzz +} + +func (fuzzer *fuzzDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags { + flags = fuzzer.binaryDecorator.compilerFlags(ctx, flags) + + // `../lib` for installed fuzz targets (both host and device), and `./lib` for fuzz target packages. + flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/../lib`) + flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/lib`) + + return flags +} + +func (fuzzer *fuzzDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { + deps.StaticLibs = append(deps.StaticLibs, + config.LibFuzzerRuntimeLibrary(ctx.toolchain())) + deps.SharedLibs = append(deps.SharedLibs, + config.LibclangRuntimeLibrary(ctx.toolchain(), "asan")) + deps.SharedLibs = append(deps.SharedLibs, "libc++") + deps.Rlibs = append(deps.Rlibs, "liblibfuzzer_sys") + + deps = fuzzer.binaryDecorator.compilerDeps(ctx, deps) + + return deps +} + +func (fuzzer *fuzzDecorator) compilerProps() []interface{} { + return append(fuzzer.binaryDecorator.compilerProps(), + &fuzzer.Properties) +} + +func (fuzzer *fuzzDecorator) stdLinkage(ctx *depsContext) RustLinkage { + return RlibLinkage +} + +func (fuzzer *fuzzDecorator) autoDep(ctx BaseModuleContext) autoDep { + return rlibAutoDep +} diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go new file mode 100644 index 000000000..f93ccc79f --- /dev/null +++ b/rust/fuzz_test.go @@ -0,0 +1,66 @@ +// Copyright 2020 The Android Open Source Project +// +// 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 rust + +import ( + "strings" + "testing" + + "android/soong/android" +) + +func TestRustFuzz(t *testing.T) { + ctx := testRust(t, ` + rust_library { + name: "libtest_fuzzing", + crate_name: "test_fuzzing", + srcs: ["foo.rs"], + } + rust_fuzz { + name: "fuzz_libtest", + srcs: ["foo.rs"], + rustlibs: ["libtest_fuzzing"], + } + `) + + // Check that appropriate dependencies are added and that the rustlib linkage is correct. + fuzz_libtest_mod := ctx.ModuleForTests("fuzz_libtest", "android_arm64_armv8-a_fuzzer").Module().(*Module) + if !android.InList("libclang_rt.asan-aarch64-android", fuzz_libtest_mod.Properties.AndroidMkSharedLibs) { + t.Errorf("libclang_rt.asan-aarch64-android shared library dependency missing for rust_fuzz module.") + } + if !android.InList("liblibfuzzer_sys.rlib-std", fuzz_libtest_mod.Properties.AndroidMkRlibs) { + t.Errorf("liblibfuzzer_sys rlib library dependency missing for rust_fuzz module. %#v", fuzz_libtest_mod.Properties.AndroidMkRlibs) + } + if !android.InList("libtest_fuzzing.rlib-std", fuzz_libtest_mod.Properties.AndroidMkRlibs) { + t.Errorf("rustlibs not linked as rlib for rust_fuzz module.") + } + + // Check that compiler flags are set appropriately . + fuzz_libtest := ctx.ModuleForTests("fuzz_libtest", "android_arm64_armv8-a_fuzzer").Output("fuzz_libtest") + if !strings.Contains(fuzz_libtest.Args["rustcFlags"], "-Z sanitizer=address") || + !strings.Contains(fuzz_libtest.Args["rustcFlags"], "-C passes='sancov'") || + !strings.Contains(fuzz_libtest.Args["rustcFlags"], "--cfg fuzzing") { + t.Errorf("rust_fuzz module does not contain the expected flags (sancov, cfg fuzzing, address sanitizer).") + + } + + // Check that dependencies have 'fuzzer' variants produced for them as well. + libtest_fuzzer := ctx.ModuleForTests("libtest_fuzzing", "android_arm64_armv8-a_rlib_rlib-std_fuzzer").Output("libtest_fuzzing.rlib") + if !strings.Contains(libtest_fuzzer.Args["rustcFlags"], "-Z sanitizer=address") || + !strings.Contains(libtest_fuzzer.Args["rustcFlags"], "-C passes='sancov'") || + !strings.Contains(libtest_fuzzer.Args["rustcFlags"], "--cfg fuzzing") { + t.Errorf("rust_fuzz dependent library does not contain the expected flags (sancov, cfg fuzzing, address sanitizer).") + } +} diff --git a/rust/proc_macro.go b/rust/proc_macro.go index 0c6ec9953..f753e7f43 100644 --- a/rust/proc_macro.go +++ b/rust/proc_macro.go @@ -51,6 +51,8 @@ func NewProcMacro(hod android.HostOrDeviceSupported) (*Module, *procMacroDecorat flagExporter: NewFlagExporter(), } + // Don't sanitize procMacros + module.sanitize = nil module.compiler = procMacro return module, procMacro diff --git a/rust/rust.go b/rust/rust.go index 83add87b7..cda01d82c 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -42,6 +42,10 @@ func init() { ctx.BottomUp("rust_libraries", LibraryMutator).Parallel() ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel() ctx.BottomUp("rust_begin", BeginMutator).Parallel() + + }) + android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { + ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel() }) pctx.Import("android/soong/rust/config") pctx.ImportAs("cc_config", "android/soong/cc/config") @@ -97,6 +101,7 @@ type Module struct { compiler compiler coverage *coverage clippy *clippy + sanitize *sanitize cachedToolchain config.Toolchain sourceProvider SourceProvider subAndroidMkOnce map[SubAndroidMkProvider]bool @@ -125,7 +130,9 @@ func (mod *Module) SetHideFromMake() { } func (mod *Module) SanitizePropDefined() bool { - return false + // Because compiler is not set for some Rust modules where sanitize might be set, check that compiler is also not + // nil since we need compiler to actually sanitize. + return mod.sanitize != nil && mod.compiler != nil } func (mod *Module) IsDependencyRoot() bool { @@ -420,6 +427,7 @@ func DefaultsFactory(props ...interface{}) android.Module { &cc.CoverageProperties{}, &cc.RustBindgenClangProperties{}, &ClippyProperties{}, + &SanitizeProperties{}, ) android.InitDefaultsModule(module) @@ -548,6 +556,9 @@ func (mod *Module) Init() android.Module { if mod.sourceProvider != nil { mod.AddProperties(mod.sourceProvider.SourceProviderProps()...) } + if mod.sanitize != nil { + mod.AddProperties(mod.sanitize.props()...) + } android.InitAndroidArchModule(mod, mod.hod, mod.multilib) android.InitApexModule(mod) @@ -566,6 +577,7 @@ func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Mo module := newBaseModule(hod, multilib) module.coverage = &coverage{} module.clippy = &clippy{} + module.sanitize = &sanitize{} return module } @@ -680,6 +692,9 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { if mod.clippy != nil { flags, deps = mod.clippy.flags(ctx, flags, deps) } + if mod.sanitize != nil { + flags, deps = mod.sanitize.flags(ctx, flags, deps) + } // SourceProvider needs to call GenerateSource() before compiler calls // compile() so it can provide the source. A SourceProvider has @@ -723,6 +738,10 @@ func (mod *Module) deps(ctx DepsContext) Deps { deps = mod.coverage.deps(ctx, deps) } + if mod.sanitize != nil { + deps = mod.sanitize.deps(ctx, deps) + } + deps.Rlibs = android.LastUniqueStrings(deps.Rlibs) deps.Dylibs = android.LastUniqueStrings(deps.Dylibs) deps.Rustlibs = android.LastUniqueStrings(deps.Rustlibs) @@ -783,6 +802,9 @@ func (mod *Module) begin(ctx BaseModuleContext) { if mod.coverage != nil { mod.coverage.begin(ctx) } + if mod.sanitize != nil { + mod.sanitize.begin(ctx) + } } func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { diff --git a/rust/sanitize.go b/rust/sanitize.go new file mode 100644 index 000000000..67460bac4 --- /dev/null +++ b/rust/sanitize.go @@ -0,0 +1,258 @@ +// Copyright 2020 The Android Open Source Project +// +// 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 rust + +import ( + "android/soong/android" + "android/soong/cc" + "android/soong/rust/config" + "fmt" + "github.com/google/blueprint" +) + +type SanitizeProperties struct { + // enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer + Sanitize struct { + Address *bool `android:"arch_variant"` + Fuzzer *bool `android:"arch_variant"` + Never *bool `android:"arch_variant"` + } + SanitizerEnabled bool `blueprint:"mutated"` + SanitizeDep bool `blueprint:"mutated"` + + // Used when we need to place libraries in their own directory, such as ASAN. + InSanitizerDir bool `blueprint:"mutated"` +} + +var fuzzerFlags = []string{ + "-C passes='sancov'", + + "--cfg fuzzing", + "-C llvm-args=-sanitizer-coverage-level=4", + "-C llvm-args=-sanitizer-coverage-trace-compares", + "-C llvm-args=-sanitizer-coverage-inline-8bit-counters", + "-C llvm-args=-sanitizer-coverage-trace-geps", + "-C llvm-args=-sanitizer-coverage-prune-blocks=0", + "-C llvm-args=-sanitizer-coverage-pc-table", + "-C link-dead-code=y", + "-Z sanitizer=address", + + // Sancov breaks with lto + // TODO: Remove when https://bugs.llvm.org/show_bug.cgi?id=41734 is resolved and sancov works with LTO + "-C lto=no", +} + +var asanFlags = []string{ + "-Z sanitizer=address", +} + +func boolPtr(v bool) *bool { + if v { + return &v + } else { + return nil + } +} + +func init() { +} +func (sanitize *sanitize) props() []interface{} { + return []interface{}{&sanitize.Properties} +} + +func (sanitize *sanitize) begin(ctx BaseModuleContext) { + s := sanitize.Properties.Sanitize + + // TODO:(b/178369775) + // For now sanitizing is only supported on devices + if ctx.Os() == android.Android && Bool(s.Fuzzer) { + sanitize.Properties.SanitizerEnabled = true + } + + if ctx.Os() == android.Android && Bool(s.Address) { + sanitize.Properties.SanitizerEnabled = true + } +} + +type sanitize struct { + Properties SanitizeProperties +} + +func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) { + if !sanitize.Properties.SanitizerEnabled { + return flags, deps + } + if Bool(sanitize.Properties.Sanitize.Fuzzer) { + flags.RustFlags = append(flags.RustFlags, fuzzerFlags...) + } + if Bool(sanitize.Properties.Sanitize.Address) { + flags.RustFlags = append(flags.RustFlags, asanFlags...) + } + return flags, deps +} + +func (sanitize *sanitize) deps(ctx BaseModuleContext, deps Deps) Deps { + return deps +} + +func rustSanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { + if mod, ok := mctx.Module().(*Module); ok && mod.sanitize != nil { + if !mod.Enabled() { + return + } + if Bool(mod.sanitize.Properties.Sanitize.Fuzzer) || Bool(mod.sanitize.Properties.Sanitize.Address) { + mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{ + {Mutator: "link", Variation: "shared"}, + }...), cc.SharedDepTag(), config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")) + } + } +} + +func (sanitize *sanitize) SetSanitizer(t cc.SanitizerType, b bool) { + sanitizerSet := false + switch t { + case cc.Fuzzer: + sanitize.Properties.Sanitize.Fuzzer = boolPtr(b) + sanitizerSet = true + case cc.Asan: + sanitize.Properties.Sanitize.Address = boolPtr(b) + sanitizerSet = true + default: + panic(fmt.Errorf("setting unsupported sanitizerType %d", t)) + } + if b && sanitizerSet { + sanitize.Properties.SanitizerEnabled = true + } +} + +// Check if the sanitizer is explicitly disabled (as opposed to nil by +// virtue of not being set). +func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t cc.SanitizerType) bool { + if sanitize == nil { + return false + } + if Bool(sanitize.Properties.Sanitize.Never) { + return true + } + sanitizerVal := sanitize.getSanitizerBoolPtr(t) + return sanitizerVal != nil && *sanitizerVal == false +} + +// There isn't an analog of the method above (ie:isSanitizerExplicitlyEnabled) +// because enabling a sanitizer either directly (via the blueprint) or +// indirectly (via a mutator) sets the bool ptr to true, and you can't +// distinguish between the cases. It isn't needed though - both cases can be +// treated identically. +func (sanitize *sanitize) isSanitizerEnabled(t cc.SanitizerType) bool { + if sanitize == nil || !sanitize.Properties.SanitizerEnabled { + return false + } + + sanitizerVal := sanitize.getSanitizerBoolPtr(t) + return sanitizerVal != nil && *sanitizerVal == true +} + +func (sanitize *sanitize) getSanitizerBoolPtr(t cc.SanitizerType) *bool { + switch t { + case cc.Fuzzer: + return sanitize.Properties.Sanitize.Fuzzer + case cc.Asan: + return sanitize.Properties.Sanitize.Address + default: + return nil + } +} + +func (mod *Module) SanitizerSupported(t cc.SanitizerType) bool { + if mod.Host() { + return false + } + switch t { + case cc.Fuzzer: + return true + case cc.Asan: + return true + default: + return false + } +} + +func (mod *Module) IsSanitizerEnabled(t cc.SanitizerType) bool { + return mod.sanitize.isSanitizerEnabled(t) +} + +func (mod *Module) IsSanitizerExplicitlyDisabled(t cc.SanitizerType) bool { + if mod.Host() { + return true + } + + // TODO(b/178365482): Rust/CC interop doesn't work just yet; don't sanitize rust_ffi modules until + // linkage issues are resolved. + if lib, ok := mod.compiler.(libraryInterface); ok { + if lib.shared() || lib.static() { + return true + } + } + + return mod.sanitize.isSanitizerExplicitlyDisabled(t) +} + +func (mod *Module) SanitizeDep() bool { + return mod.sanitize.Properties.SanitizeDep +} + +func (mod *Module) SetSanitizer(t cc.SanitizerType, b bool) { + if !Bool(mod.sanitize.Properties.Sanitize.Never) { + mod.sanitize.SetSanitizer(t, b) + } +} + +func (mod *Module) SetSanitizeDep(b bool) { + mod.sanitize.Properties.SanitizeDep = b +} + +func (mod *Module) StaticallyLinked() bool { + if lib, ok := mod.compiler.(libraryInterface); ok { + if lib.rlib() || lib.static() { + return true + } + } else if Bool(mod.compiler.(*binaryDecorator).Properties.Static_executable) { + return true + } + return false +} + +func (mod *Module) SetInSanitizerDir() { + mod.sanitize.Properties.InSanitizerDir = true +} + +func (mod *Module) SanitizeNever() bool { + return Bool(mod.sanitize.Properties.Sanitize.Never) +} + +var _ cc.PlatformSanitizeable = (*Module)(nil) + +func IsSanitizableDependencyTag(tag blueprint.DependencyTag) bool { + switch t := tag.(type) { + case dependencyTag: + return t.library + default: + return cc.IsSanitizableDependencyTag(tag) + } +} + +func (m *Module) SanitizableDepTagChecker() cc.SantizableDependencyTagChecker { + return IsSanitizableDependencyTag +} diff --git a/rust/testing.go b/rust/testing.go index 07f557ab8..bb511b648 100644 --- a/rust/testing.go +++ b/rust/testing.go @@ -87,6 +87,13 @@ func GatherRequiredDepsForTest() string { system_shared_libs: [], export_include_dirs: ["libprotobuf-cpp-full-includes"], } + cc_library { + name: "libclang_rt.asan-aarch64-android", + no_libcrt: true, + nocrt: true, + system_shared_libs: [], + export_include_dirs: ["libprotobuf-cpp-full-includes"], + } rust_library { name: "libstd", crate_name: "std", @@ -129,7 +136,12 @@ func GatherRequiredDepsForTest() string { srcs: ["foo.rs"], host_supported: true, } - + rust_library { + name: "liblibfuzzer_sys", + crate_name: "libfuzzer_sys", + srcs:["foo.rs"], + host_supported: true, + } ` return bp } @@ -147,6 +159,7 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { ctx.RegisterModuleType("rust_library_host", RustLibraryHostFactory) ctx.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory) ctx.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory) + ctx.RegisterModuleType("rust_fuzz", RustFuzzFactory) ctx.RegisterModuleType("rust_ffi", RustFFIFactory) ctx.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory) ctx.RegisterModuleType("rust_ffi_static", RustFFIStaticFactory)