Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 48a2d110 authored by Colin Cross's avatar Colin Cross Committed by Gerrit Code Review
Browse files

Merge "Don't propagate ASAN through shared library dependencies"

parents ca8f6800 af98f582
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ bootstrap_go_package {
        "object_test.go",
        "prebuilt_test.go",
        "proto_test.go",
        "sanitize_test.go",
        "test_data_test.go",
        "vendor_public_library_test.go",
        "vendor_snapshot_test.go",
+2 −2
Original line number Diff line number Diff line
@@ -902,7 +902,7 @@ func sanitizerDepsMutator(t SanitizerType) func(android.TopDownMutatorContext) {
					if d, ok := child.(PlatformSanitizeable); ok && d.SanitizePropDefined() &&
						!d.SanitizeNever() &&
						!d.IsSanitizerExplicitlyDisabled(t) {
						if t == cfi || t == Hwasan || t == scs {
						if t == cfi || t == Hwasan || t == scs || t == Asan {
							if d.StaticallyLinked() && d.SanitizerSupported(t) {
								// Rust does not support some of these sanitizers, so we need to check if it's
								// supported before setting this true.
@@ -1261,7 +1261,7 @@ func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) {
				modules[0].(PlatformSanitizeable).SetSanitizer(t, true)
			} else if c.IsSanitizerEnabled(t) || c.SanitizeDep() {
				isSanitizerEnabled := c.IsSanitizerEnabled(t)
				if c.StaticallyLinked() || c.Header() || t == Asan || t == Fuzzer {
				if c.StaticallyLinked() || c.Header() || t == Fuzzer {
					// Static and header libs are split into non-sanitized and sanitized variants.
					// Shared libs are not split. However, for asan and fuzzer, we split even for shared
					// libs because a library sanitized for asan/fuzzer can't be linked from a library

cc/sanitize_test.go

0 → 100644
+204 −0
Original line number Diff line number Diff line
// 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 (
	"testing"

	"android/soong/android"
)

var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(`
	cc_library_shared {
		name: "libclang_rt.asan-aarch64-android",
	}

	cc_library_shared {
		name: "libclang_rt.asan-arm-android",
	}
`))

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

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

		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,
			}
		}
	`

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

	check := func(t *testing.T, result *android.TestResult, variant string) {
		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("bin_with_asan", asanVariant)
		binNoAsan := result.ModuleForTests("bin_no_asan", variant)

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

		// Shared library that requests asan
		libAsan := result.ModuleForTests("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("libstatic", staticAsanVariant)
		libStaticNoAsanVariant := result.ModuleForTests("libstatic", staticVariant)

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

		// expectSharedLinkDep verifies that the from module links against the to module as a
		// shared library.
		expectSharedLinkDep := func(from, to android.TestingModule) {
			t.Helper()
			fromLink := from.Description("link")
			toLink := to.Description("strip")

			if g, w := fromLink.OrderOnly.Strings(), toLink.Output.String(); !android.InList(w, g) {
				t.Errorf("%s should 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.
		expectStaticLinkDep := func(from, to android.TestingModule) {
			t.Helper()
			fromLink := from.Description("link")
			toLink := to.Description("static link")

			if g, w := fromLink.Implicits.Strings(), toLink.Output.String(); !android.InList(w, g) {
				t.Errorf("%s should 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.
		expectInstallDep := func(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)
			}
		}

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

		expectStaticLinkDep(binWithAsan, libStaticAsanVariant)
		expectStaticLinkDep(binWithAsan, libNoAsan)

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

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

		expectStaticLinkDep(binNoAsan, libStaticNoAsanVariant)
		expectStaticLinkDep(binNoAsan, libNoAsan)

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

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