Fix fuzzer builds [#2].
- Updates the fuzzer builds to use SANITIZE_TARGET='fuzzer' instead of
'coverage'.
- Removed an old dependency that made fuzzer builds without ASan
an error.
- Fixed up the build flags to allow fuzzers to be built. Previously, the
coverage flags were manually provided. As the toolchain has moved on,
these flags are no longer compatible with libFuzzer, and so I've updated
them to use the correct, compatible flags.
- Added a dependency mutator for fuzzer coverage.
Bug: 121042685
Test: With all patches in the bug merged, build a fuzzer using
'SANITIZE_TARGET=fuzzer mmma <your_fuzzer>'.
This is the qt-dev-plus-aosp cherrypick of aosp/954925. See the AOSP
commit for further information.
Change-Id: Ib6246980f77bc4babe587b1e88038aa12228fa83
diff --git a/cc/sanitize.go b/cc/sanitize.go
index b7f12c9..6859f39 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -78,6 +78,7 @@
intOverflow
cfi
scs
+ fuzzer
)
// Name of the sanitizer variation for this sanitizer type
@@ -95,6 +96,8 @@
return "cfi"
case scs:
return "scs"
+ case fuzzer:
+ return "fuzzer"
default:
panic(fmt.Errorf("unknown sanitizerType %d", t))
}
@@ -115,6 +118,8 @@
return "cfi"
case scs:
return "shadow-call-stack"
+ case fuzzer:
+ return "fuzzer"
default:
panic(fmt.Errorf("unknown sanitizerType %d", t))
}
@@ -134,7 +139,7 @@
Undefined *bool `android:"arch_variant"`
All_undefined *bool `android:"arch_variant"`
Misc_undefined []string `android:"arch_variant"`
- Coverage *bool `android:"arch_variant"`
+ Fuzzer *bool `android:"arch_variant"`
Safestack *bool `android:"arch_variant"`
Cfi *bool `android:"arch_variant"`
Integer_overflow *bool `android:"arch_variant"`
@@ -224,22 +229,16 @@
s.Undefined = boolPtr(true)
}
- if found, globalSanitizers = removeFromList("address", globalSanitizers); found {
- if s.Address == nil {
- s.Address = boolPtr(true)
- } else if *s.Address == false {
- // Coverage w/o address is an error. If globalSanitizers includes both, and the module
- // disables address, then disable coverage as well.
- _, globalSanitizers = removeFromList("coverage", globalSanitizers)
- }
+ if found, globalSanitizers = removeFromList("address", globalSanitizers); found && s.Address == nil {
+ s.Address = boolPtr(true)
}
if found, globalSanitizers = removeFromList("thread", globalSanitizers); found && s.Thread == nil {
s.Thread = boolPtr(true)
}
- if found, globalSanitizers = removeFromList("coverage", globalSanitizers); found && s.Coverage == nil {
- s.Coverage = boolPtr(true)
+ if found, globalSanitizers = removeFromList("fuzzer", globalSanitizers); found && s.Fuzzer == nil {
+ s.Fuzzer = boolPtr(true)
}
if found, globalSanitizers = removeFromList("safe-stack", globalSanitizers); found && s.Safestack == nil {
@@ -347,7 +346,7 @@
if ctx.staticBinary() {
s.Address = nil
- s.Coverage = nil
+ s.Fuzzer = nil
s.Thread = nil
}
@@ -363,7 +362,7 @@
}
if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
- Bool(s.Coverage) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
+ Bool(s.Fuzzer) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs)) {
sanitize.Properties.SanitizerEnabled = true
}
@@ -378,10 +377,10 @@
s.Thread = nil
}
- if Bool(s.Coverage) {
- if !Bool(s.Address) {
- ctx.ModuleErrorf(`Use of "coverage" also requires "address"`)
- }
+ // TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is
+ // mutually incompatible.
+ if Bool(s.Fuzzer) {
+ s.Cfi = nil
}
}
@@ -462,8 +461,13 @@
flags.CFlags = append(flags.CFlags, hwasanCflags...)
}
- if Bool(sanitize.Properties.Sanitize.Coverage) {
- flags.CFlags = append(flags.CFlags, "-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp")
+ if Bool(sanitize.Properties.Sanitize.Fuzzer) {
+ flags.CFlags = append(flags.CFlags, "-fsanitize=fuzzer-no-link")
+ flags.LdFlags = append(flags.LdFlags, "-fsanitize=fuzzer-no-link")
+
+ // TODO(b/131771163): LTO and Fuzzer support is mutually incompatible.
+ _, flags.LdFlags = removeFromList("-flto", flags.LdFlags)
+ flags.LdFlags = append(flags.LdFlags, "-fno-lto")
}
if Bool(sanitize.Properties.Sanitize.Cfi) {
@@ -498,20 +502,26 @@
flags.CFlags = append(flags.CFlags, sanitizeArg)
flags.AsFlags = append(flags.AsFlags, sanitizeArg)
if ctx.Host() {
- flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover=all")
- flags.LdFlags = append(flags.LdFlags, sanitizeArg)
// Host sanitizers only link symbols in the final executable, so
// there will always be undefined symbols in intermediate libraries.
_, flags.LdFlags = removeFromList("-Wl,--no-undefined", flags.LdFlags)
+ flags.LdFlags = append(flags.LdFlags, sanitizeArg)
} else {
- flags.CFlags = append(flags.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
-
if enableMinimalRuntime(sanitize) {
flags.CFlags = append(flags.CFlags, strings.Join(minimalRuntimeFlags, " "))
flags.libFlags = append([]string{minimalRuntimePath}, flags.libFlags...)
flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,"+minimalRuntimeLib)
}
}
+
+ if Bool(sanitize.Properties.Sanitize.Fuzzer) {
+ // When fuzzing, we wish to crash with diagnostics on any bug.
+ flags.CFlags = append(flags.CFlags, "-fno-sanitize-trap=all", "-fno-sanitize-recover=all")
+ } else if ctx.Host() {
+ flags.CFlags = append(flags.CFlags, "-fno-sanitize-recover=all")
+ } else {
+ flags.CFlags = append(flags.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
+ }
// http://b/119329758, Android core does not boot up with this sanitizer yet.
if toDisableImplicitIntegerChange(flags.CFlags) {
flags.CFlags = append(flags.CFlags, "-fno-sanitize=implicit-integer-sign-change")
@@ -574,6 +584,8 @@
return sanitize.Properties.Sanitize.Cfi
case scs:
return sanitize.Properties.Sanitize.Scs
+ case fuzzer:
+ return sanitize.Properties.Sanitize.Fuzzer
default:
panic(fmt.Errorf("unknown sanitizerType %d", t))
}
@@ -584,22 +596,21 @@
!sanitize.isSanitizerEnabled(hwasan) &&
!sanitize.isSanitizerEnabled(tsan) &&
!sanitize.isSanitizerEnabled(cfi) &&
- !sanitize.isSanitizerEnabled(scs)
+ !sanitize.isSanitizerEnabled(scs) &&
+ !sanitize.isSanitizerEnabled(fuzzer)
}
func (sanitize *sanitize) isVariantOnProductionDevice() bool {
return !sanitize.isSanitizerEnabled(asan) &&
!sanitize.isSanitizerEnabled(hwasan) &&
- !sanitize.isSanitizerEnabled(tsan)
+ !sanitize.isSanitizerEnabled(tsan) &&
+ !sanitize.isSanitizerEnabled(fuzzer)
}
func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) {
switch t {
case asan:
sanitize.Properties.Sanitize.Address = boolPtr(b)
- if !b {
- sanitize.Properties.Sanitize.Coverage = nil
- }
case hwasan:
sanitize.Properties.Sanitize.Hwaddress = boolPtr(b)
case tsan:
@@ -610,6 +621,8 @@
sanitize.Properties.Sanitize.Cfi = boolPtr(b)
case scs:
sanitize.Properties.Sanitize.Scs = boolPtr(b)
+ case fuzzer:
+ sanitize.Properties.Sanitize.Fuzzer = boolPtr(b)
default:
panic(fmt.Errorf("unknown sanitizerType %d", t))
}
@@ -794,6 +807,10 @@
sanitizers = append(sanitizers, "shadow-call-stack")
}
+ if Bool(c.sanitize.Properties.Sanitize.Fuzzer) {
+ sanitizers = append(sanitizers, "fuzzer-no-link")
+ }
+
// Save the list of sanitizers. These will be used again when generating
// the build rules (for Cflags, etc.)
c.sanitize.Properties.Sanitizers = sanitizers
@@ -932,6 +949,19 @@
modules[1].(*Module).Properties.HideFromMake = true
}
}
+ } else if t == fuzzer {
+ // TODO(b/131771163): CFI and fuzzer support are mutually incompatible
+ // as CFI pulls in LTO.
+ if mctx.Device() {
+ modules[1].(*Module).sanitize.SetSanitizer(cfi, false)
+ }
+ if isSanitizerEnabled {
+ modules[0].(*Module).Properties.PreventInstall = true
+ modules[0].(*Module).Properties.HideFromMake = true
+ } else {
+ modules[1].(*Module).Properties.PreventInstall = true
+ modules[1].(*Module).Properties.HideFromMake = true
+ }
} else if t == hwasan {
if mctx.Device() {
// CFI and HWASAN are currently mutually exclusive so disable
@@ -997,6 +1027,7 @@
func enableMinimalRuntime(sanitize *sanitize) bool {
if !Bool(sanitize.Properties.Sanitize.Address) &&
!Bool(sanitize.Properties.Sanitize.Hwaddress) &&
+ !Bool(sanitize.Properties.Sanitize.Fuzzer) &&
(Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
len(sanitize.Properties.Sanitize.Misc_undefined) > 0) &&
!(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||