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
diff --git a/rust/Android.bp b/rust/Android.bp
index df731db..ad3040a 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -15,6 +15,7 @@
"clippy.go",
"compiler.go",
"coverage.go",
+ "fuzz.go",
"image.go",
"library.go",
"prebuilt.go",
@@ -22,6 +23,7 @@
"project_json.go",
"protobuf.go",
"rust.go",
+ "sanitize.go",
"strip.go",
"source_provider.go",
"test.go",
@@ -34,6 +36,7 @@
"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 baeab69..77d339a 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -86,7 +86,7 @@
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 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 bcea6cc..2d9575c 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -146,6 +146,7 @@
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 21b22a4..5066428 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -26,8 +26,8 @@
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 @@
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 adfe917..42c1c02 100644
--- a/rust/config/arm_device.go
+++ b/rust/config/arm_device.go
@@ -72,6 +72,10 @@
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 616d88b..9525c38 100644
--- a/rust/config/toolchain.go
+++ b/rust/config/toolchain.go
@@ -34,6 +34,8 @@
Supported() bool
Bionic() bool
+
+ LibclangRuntimeLibraryArch() string
}
type toolchainBase struct {
@@ -106,6 +108,36 @@
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 5f6e85a..94b719f 100644
--- a/rust/config/x86_64_device.go
+++ b/rust/config/x86_64_device.go
@@ -77,6 +77,10 @@
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 daeeb14..aae1125 100644
--- a/rust/config/x86_device.go
+++ b/rust/config/x86_device.go
@@ -80,6 +80,10 @@
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 e7f26ce..b63e14d 100644
--- a/rust/config/x86_linux_host.go
+++ b/rust/config/x86_linux_host.go
@@ -103,6 +103,14 @@
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 0000000..da8f209
--- /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 0000000..f93ccc7
--- /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 0c6ec99..f753e7f 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -51,6 +51,8 @@
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 83add87..cda01d8 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -42,6 +42,10 @@
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 @@
compiler compiler
coverage *coverage
clippy *clippy
+ sanitize *sanitize
cachedToolchain config.Toolchain
sourceProvider SourceProvider
subAndroidMkOnce map[SubAndroidMkProvider]bool
@@ -125,7 +130,9 @@
}
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 @@
&cc.CoverageProperties{},
&cc.RustBindgenClangProperties{},
&ClippyProperties{},
+ &SanitizeProperties{},
)
android.InitDefaultsModule(module)
@@ -548,6 +556,9 @@
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 @@
module := newBaseModule(hod, multilib)
module.coverage = &coverage{}
module.clippy = &clippy{}
+ module.sanitize = &sanitize{}
return module
}
@@ -680,6 +692,9 @@
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 @@
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 @@
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 0000000..67460ba
--- /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 07f557a..bb511b6 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -87,6 +87,13 @@
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 @@
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 @@
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)