diff options
| -rw-r--r-- | apex/androidmk.go | 34 | ||||
| -rw-r--r-- | apex/apex.go | 20 | ||||
| -rw-r--r-- | apex/builder.go | 50 | ||||
| -rw-r--r-- | apex/prebuilt.go | 41 | ||||
| -rw-r--r-- | apex/vndk.go | 43 | ||||
| -rw-r--r-- | cc/sanitize.go | 29 | ||||
| -rw-r--r-- | mk2rbc/mk2rbc.go | 38 | ||||
| -rw-r--r-- | rust/Android.bp | 1 | ||||
| -rw-r--r-- | rust/androidmk.go | 1 | ||||
| -rw-r--r-- | rust/binary.go | 5 | ||||
| -rw-r--r-- | rust/compiler.go | 4 | ||||
| -rw-r--r-- | rust/config/allowed_list.go | 1 | ||||
| -rw-r--r-- | rust/fuzz.go | 2 | ||||
| -rw-r--r-- | rust/prebuilt.go | 22 | ||||
| -rw-r--r-- | rust/rust.go | 7 | ||||
| -rw-r--r-- | rust/rust_test.go | 7 | ||||
| -rw-r--r-- | rust/sanitize.go | 189 | ||||
| -rw-r--r-- | rust/sanitize_test.go | 365 | ||||
| -rw-r--r-- | rust/test.go | 4 | ||||
| -rw-r--r-- | rust/testing.go | 86 | ||||
| -rw-r--r-- | rust/vendor_snapshot_test.go | 34 | ||||
| -rw-r--r-- | scripts/Android.bp | 94 | ||||
| -rwxr-xr-x | scripts/manifest.py | 2 | ||||
| -rwxr-xr-x | scripts/manifest_check.py | 4 | ||||
| -rwxr-xr-x | scripts/manifest_fixer.py | 2 | ||||
| -rwxr-xr-x | scripts/manifest_fixer_test.py | 109 | ||||
| -rw-r--r-- | scripts/test_config_fixer.py | 2 | ||||
| -rw-r--r-- | scripts/test_config_fixer_test.py | 6 |
28 files changed, 831 insertions, 371 deletions
diff --git a/apex/androidmk.go b/apex/androidmk.go index d612f1e6a..80237fb5f 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -103,6 +103,18 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo return moduleNames } + var postInstallCommands []string + for _, fi := range a.filesInfo { + if a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform() { + // TODO(jiyong): pathOnDevice should come from fi.module, not being calculated here + linkTarget := filepath.Join("/system", fi.path()) + linkPath := filepath.Join(a.installDir.ToMakePath().String(), apexBundleName, fi.path()) + mkdirCmd := "mkdir -p " + filepath.Dir(linkPath) + linkCmd := "ln -sfn " + linkTarget + " " + linkPath + postInstallCommands = append(postInstallCommands, mkdirCmd, linkCmd) + } + } + seenDataOutPaths := make(map[string]bool) for _, fi := range a.filesInfo { @@ -176,8 +188,6 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo // we will have duplicated notice entries. fmt.Fprintln(w, "LOCAL_NO_NOTICE_FILE := true") } - fmt.Fprintln(w, "LOCAL_SOONG_INSTALLED_MODULE :=", filepath.Join(modulePath, fi.stem())) - fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", fi.builtFile.String()+":"+filepath.Join(modulePath, fi.stem())) fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", fi.builtFile.String()) fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", fi.class.nameInMake()) if fi.module != nil { @@ -287,10 +297,18 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo if len(patterns) > 0 { fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES :=", strings.Join(patterns, " ")) } + if len(a.compatSymlinks) > 0 { + // For flattened apexes, compat symlinks are attached to apex_manifest.json which is guaranteed for every apex + postInstallCommands = append(postInstallCommands, a.compatSymlinks...) + } } // File_contexts of flattened APEXes should be merged into file_contexts.bin fmt.Fprintln(w, "LOCAL_FILE_CONTEXTS :=", a.fileContexts) + + if len(postInstallCommands) > 0 { + fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(postInstallCommands, " && ")) + } } fmt.Fprintln(w, "include $(BUILD_PREBUILT)") } @@ -371,8 +389,6 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { } fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+stemSuffix) fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable()) - fmt.Fprintln(w, "LOCAL_SOONG_INSTALLED_MODULE :=", a.installedFile.String()) - fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", a.outputFile.String()+":"+a.installedFile.String()) // Because apex writes .mk with Custom(), we need to write manually some common properties // which are available via data.Entries @@ -397,6 +413,16 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.requiredDeps, " ")) } a.writeRequiredModules(w, name) + var postInstallCommands []string + if a.prebuiltFileToDelete != "" { + postInstallCommands = append(postInstallCommands, "rm -rf "+ + filepath.Join(a.installDir.ToMakePath().String(), a.prebuiltFileToDelete)) + } + // For unflattened apexes, compat symlinks are attached to apex package itself as LOCAL_POST_INSTALL_CMD + postInstallCommands = append(postInstallCommands, a.compatSymlinks...) + if len(postInstallCommands) > 0 { + fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(postInstallCommands, " && ")) + } if a.mergedNotices.Merged.Valid() { fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", a.mergedNotices.Merged.Path().String()) diff --git a/apex/apex.go b/apex/apex.go index 0bc48be23..33188cbcb 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -399,14 +399,14 @@ type apexBundle struct { // vendor/google/build/build_unbundled_mainline_module.sh for more detail. bundleModuleFile android.WritablePath - // Target directory to install this APEX. Usually out/target/product/<device>/<partition>/apex. + // Target path to install this APEX. Usually out/target/product/<device>/<partition>/apex. installDir android.InstallPath - // Path where this APEX was installed. - installedFile android.InstallPath - - // Installed locations of symlinks for backward compatibility. - compatSymlinks android.InstallPaths + // List of commands to create symlinks for backward compatibility. These commands will be + // attached as LOCAL_POST_INSTALL_CMD to apex package itself (for unflattened build) or + // apex_manifest (for flattened build) so that compat symlinks are always installed + // regardless of TARGET_FLATTEN_APEX setting. + compatSymlinks []string // Text file having the list of individual files that are included in this APEX. Used for // debugging purpose. @@ -431,10 +431,6 @@ type apexBundle struct { modulePaths []string } -func (*apexBundle) InstallBypassMake() bool { - return true -} - // apexFileClass represents a type of file that can be included in APEX. type apexFileClass int @@ -2090,9 +2086,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.linkToSystemLib = false } - if a.properties.ApexType != zipApex { - a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx, a.primaryApexType) - } + a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx) //////////////////////////////////////////////////////////////////////////////////////////// // 4) generate the build rules to create the APEX. This is done in builder.go. diff --git a/apex/builder.go b/apex/builder.go index 4b0ac0c45..e22d69411 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -823,55 +823,47 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { a.outputFile = signedCompressedOutputFile } - installSuffix := suffix - if a.isCompressed { - installSuffix = imageCapexSuffix - } - // Install to $OUT/soong/{target,host}/.../apex. - a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile, - a.compatSymlinks.Paths()...) + ctx.InstallFile(a.installDir, a.Name()+suffix, a.outputFile) // installed-files.txt is dist'ed a.installedFilesFile = a.buildInstalledFilesFile(ctx, a.outputFile, imageDir) } +// Context "decorator", overriding the InstallBypassMake method to always reply `true`. +type flattenedApexContext struct { + android.ModuleContext +} + +func (c *flattenedApexContext) InstallBypassMake() bool { + return true +} + // buildFlattenedApex creates rules for a flattened APEX. Flattened APEX actually doesn't have a // single output file. It is a phony target for all the files under /system/apex/<name> directory. // This function creates the installation rules for the files. func (a *apexBundle) buildFlattenedApex(ctx android.ModuleContext) { bundleName := a.Name() - installedSymlinks := append(android.InstallPaths(nil), a.compatSymlinks...) if a.installable() { for _, fi := range a.filesInfo { dir := filepath.Join("apex", bundleName, fi.installDir) - installDir := android.PathForModuleInstall(ctx, dir) - if a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform() { - // TODO(jiyong): pathOnDevice should come from fi.module, not being calculated here - pathOnDevice := filepath.Join("/system", fi.path()) - installedSymlinks = append(installedSymlinks, - ctx.InstallAbsoluteSymlink(installDir, fi.stem(), pathOnDevice)) - } else { - target := ctx.InstallFile(installDir, fi.stem(), fi.builtFile) - for _, sym := range fi.symlinks { - installedSymlinks = append(installedSymlinks, - ctx.InstallSymlink(installDir, sym, target)) - } + target := ctx.InstallFile(android.PathForModuleInstall(ctx, dir), fi.stem(), fi.builtFile) + for _, sym := range fi.symlinks { + ctx.InstallSymlink(android.PathForModuleInstall(ctx, dir), sym, target) } } - - // Create install rules for the files added in GenerateAndroidBuildActions after - // buildFlattenedApex is called. Add the links to system libs (if any) as dependencies - // of the apex_manifest.pb file since it is always present. - dir := filepath.Join("apex", bundleName) - installDir := android.PathForModuleInstall(ctx, dir) - ctx.InstallFile(installDir, "apex_manifest.pb", a.manifestPbOut, installedSymlinks.Paths()...) - ctx.InstallFile(installDir, "apex_pubkey", a.publicKeyFile) } a.fileContexts = a.buildFileContexts(ctx) - a.outputFile = android.PathForModuleInstall(ctx, "apex", bundleName) + // Temporarily wrap the original `ctx` into a `flattenedApexContext` to have it reply true + // to `InstallBypassMake()` (thus making the call `android.PathForModuleInstall` below use + // `android.pathForInstallInMakeDir` instead of `android.PathForOutput`) to return the + // correct path to the flattened APEX (as its contents is installed by Make, not Soong). + // TODO(jiyong): Why do we need to set outputFile for flattened APEX? We don't seem to use + // it and it actually points to a path that can never be built. Remove this. + factx := flattenedApexContext{ctx} + a.outputFile = android.PathForModuleInstall(&factx, "apex", bundleName) } // getCertificateAndPrivateKey retrieves the cert and the private key that will be used to sign diff --git a/apex/prebuilt.go b/apex/prebuilt.go index 5b070c6fb..61e7a0be3 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -17,13 +17,11 @@ package apex import ( "fmt" "io" - "path/filepath" "strconv" "strings" "android/soong/android" "android/soong/java" - "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) @@ -55,17 +53,18 @@ type prebuiltCommon struct { installDir android.InstallPath installFilename string - installedFile android.InstallPath outputApex android.WritablePath // A list of apexFile objects created in prebuiltCommon.initApexFilesForAndroidMk which are used // to create make modules in prebuiltCommon.AndroidMkEntries. apexFilesForAndroidMk []apexFile - // Installed locations of symlinks for backward compatibility. - compatSymlinks android.InstallPaths + // list of commands to create symlinks for backward compatibility. + // these commands will be attached as LOCAL_POST_INSTALL_CMD + compatSymlinks []string - hostRequired []string + hostRequired []string + postInstallCommands []string } type sanitizedPrebuilt interface { @@ -224,10 +223,13 @@ func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries { func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { entries.SetString("LOCAL_MODULE_PATH", p.installDir.ToMakePath().String()) entries.SetString("LOCAL_MODULE_STEM", p.installFilename) - entries.SetPath("LOCAL_SOONG_INSTALLED_MODULE", p.installedFile) - entries.SetString("LOCAL_SOONG_INSTALL_PAIRS", p.outputApex.String()+":"+p.installedFile.String()) entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable()) entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.prebuiltCommonProperties.Overrides...) + postInstallCommands := append([]string{}, p.postInstallCommands...) + postInstallCommands = append(postInstallCommands, p.compatSymlinks...) + if len(postInstallCommands) > 0 { + entries.SetString("LOCAL_POST_INSTALL_CMD", strings.Join(postInstallCommands, " && ")) + } p.addRequiredModules(entries) }, }, @@ -257,9 +259,6 @@ func (p *prebuiltCommon) createEntriesForApexFile(fi apexFile, apexName string) ExtraEntries: []android.AndroidMkExtraEntriesFunc{ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { entries.SetString("LOCAL_MODULE_PATH", p.installDir.ToMakePath().String()) - entries.SetString("LOCAL_SOONG_INSTALLED_MODULE :=", filepath.Join(p.installDir.String(), fi.stem())) - entries.SetString("LOCAL_SOONG_INSTALL_PAIRS :=", - fi.builtFile.String()+":"+filepath.Join(p.installDir.String(), fi.stem())) // soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar Therefore // we need to remove the suffix from LOCAL_MODULE_STEM, otherwise @@ -472,10 +471,6 @@ type Prebuilt struct { inputApex android.Path } -func (p *Prebuilt) InstallBypassMake() bool { - return true -} - type ApexFileProperties struct { // the path to the prebuilt .apex file to import. // @@ -761,15 +756,15 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Save the files that need to be made available to Make. p.initApexFilesForAndroidMk(ctx) + if p.installable() { + ctx.InstallFile(p.installDir, p.installFilename, p.inputApex) + } + // in case that prebuilt_apex replaces source apex (using prefer: prop) - p.compatSymlinks = makeCompatSymlinks(p.BaseModuleName(), ctx, true) + p.compatSymlinks = makeCompatSymlinks(p.BaseModuleName(), ctx) // or that prebuilt_apex overrides other apexes (using overrides: prop) for _, overridden := range p.prebuiltCommonProperties.Overrides { - p.compatSymlinks = append(p.compatSymlinks, makeCompatSymlinks(overridden, ctx, true)...) - } - - if p.installable() { - p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks.Paths()...) + p.compatSymlinks = append(p.compatSymlinks, makeCompatSymlinks(overridden, ctx)...) } } @@ -969,10 +964,10 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { } // in case that apex_set replaces source apex (using prefer: prop) - a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx, true) + a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx) // or that apex_set overrides other apexes (using overrides: prop) for _, overridden := range a.prebuiltCommonProperties.Overrides { - a.compatSymlinks = append(a.compatSymlinks, makeCompatSymlinks(overridden, ctx, true)...) + a.compatSymlinks = append(a.compatSymlinks, makeCompatSymlinks(overridden, ctx)...) } } diff --git a/apex/vndk.go b/apex/vndk.go index cf525a874..75c0fb01b 100644 --- a/apex/vndk.go +++ b/apex/vndk.go @@ -15,6 +15,7 @@ package apex import ( + "path/filepath" "strings" "android/soong/android" @@ -95,14 +96,11 @@ func apexVndkDepsMutator(mctx android.BottomUpMutatorContext) { } // name is module.BaseModuleName() which is used as LOCAL_MODULE_NAME and also LOCAL_OVERRIDES_* -func makeCompatSymlinks(name string, ctx android.ModuleContext, primaryApex bool) (symlinks android.InstallPaths) { +func makeCompatSymlinks(name string, ctx android.ModuleContext) (symlinks []string) { // small helper to add symlink commands - addSymlink := func(target string, dir android.InstallPath, linkName string) { - if primaryApex { - symlinks = append(symlinks, ctx.InstallAbsoluteSymlink(dir, linkName, target)) - } else { - symlinks = append(symlinks, dir.Join(ctx, linkName)) - } + addSymlink := func(target, dir, linkName string) { + link := filepath.Join(dir, linkName) + symlinks = append(symlinks, "mkdir -p "+dir+" && rm -rf "+link+" && ln -sf "+target+" "+link) } // TODO(b/142911355): [VNDK APEX] Fix hard-coded references to /system/lib/vndk @@ -120,15 +118,14 @@ func makeCompatSymlinks(name string, ctx android.ModuleContext, primaryApex bool // the name of vndk apex is formatted "com.android.vndk.v" + version apexName := vndkApexNamePrefix + vndkVersion if ctx.Config().Android64() { - dir := android.PathForModuleInPartitionInstall(ctx, "system", "lib64") - addSymlink("/apex/"+apexName+"/lib64", dir, "vndk-sp-"+vndkVersion) - addSymlink("/apex/"+apexName+"/lib64", dir, "vndk-"+vndkVersion) + addSymlink("/apex/"+apexName+"/lib64", "$(TARGET_OUT)/lib64", "vndk-sp-"+vndkVersion) + addSymlink("/apex/"+apexName+"/lib64", "$(TARGET_OUT)/lib64", "vndk-"+vndkVersion) } if !ctx.Config().Android64() || ctx.DeviceConfig().DeviceSecondaryArch() != "" { - dir := android.PathForModuleInPartitionInstall(ctx, "system", "lib") - addSymlink("/apex/"+apexName+"/lib", dir, "vndk-sp-"+vndkVersion) - addSymlink("/apex/"+apexName+"/lib", dir, "vndk-"+vndkVersion) + addSymlink("/apex/"+apexName+"/lib", "$(TARGET_OUT)/lib", "vndk-sp-"+vndkVersion) + addSymlink("/apex/"+apexName+"/lib", "$(TARGET_OUT)/lib", "vndk-"+vndkVersion) } + return } // http://b/121248172 - create a link from /system/usr/icu to @@ -136,25 +133,19 @@ func makeCompatSymlinks(name string, ctx android.ModuleContext, primaryApex bool // A symlink can't overwrite a directory and the /system/usr/icu directory once // existed so the required structure must be created whatever we find. if name == "com.android.i18n" { - dir := android.PathForModuleInPartitionInstall(ctx, "system", "usr") - addSymlink("/apex/com.android.i18n/etc/icu", dir, "icu") + addSymlink("/apex/com.android.i18n/etc/icu", "$(TARGET_OUT)/usr", "icu") + return } // TODO(b/124106384): Clean up compat symlinks for ART binaries. - if name == "com.android.art" { - dir := android.PathForModuleInPartitionInstall(ctx, "system", "bin") - addSymlink("/apex/com.android.art/bin/dalvikvm", dir, "dalvikvm") + if name == "com.android.art" || strings.HasPrefix(name, "com.android.art.") { + addSymlink("/apex/com.android.art/bin/dalvikvm", "$(TARGET_OUT)/bin", "dalvikvm") dex2oat := "dex2oat32" if ctx.Config().Android64() { dex2oat = "dex2oat64" } - addSymlink("/apex/com.android.art/bin/"+dex2oat, dir, "dex2oat") - } else if name == "com.android.art" || strings.HasPrefix(name, "com.android.art.") { - dir := android.PathForModuleInPartitionInstall(ctx, "system", "bin") - symlinks = append(symlinks, - dir.Join(ctx, "dalvikvm"), - dir.Join(ctx, "dex2oat")) + addSymlink("/apex/com.android.art/bin/"+dex2oat, "$(TARGET_OUT)/bin", "dex2oat") + return } - - return symlinks + return } diff --git a/cc/sanitize.go b/cc/sanitize.go index c7e841122..93d4b4c54 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -88,7 +88,7 @@ const ( intOverflow scs Fuzzer - memtag_heap + Memtag_heap cfi // cfi is last to prevent it running before incompatible mutators ) @@ -99,7 +99,7 @@ var Sanitizers = []SanitizerType{ intOverflow, scs, Fuzzer, - memtag_heap, + Memtag_heap, cfi, // cfi is last to prevent it running before incompatible mutators } @@ -118,7 +118,7 @@ func (t SanitizerType) variationName() string { return "cfi" case scs: return "scs" - case memtag_heap: + case Memtag_heap: return "memtag_heap" case Fuzzer: return "fuzzer" @@ -134,7 +134,7 @@ func (t SanitizerType) name() string { return "address" case Hwasan: return "hwaddress" - case memtag_heap: + case Memtag_heap: return "memtag_heap" case tsan: return "thread" @@ -156,7 +156,7 @@ func (t SanitizerType) registerMutators(ctx android.RegisterMutatorsContext) { case Asan, Hwasan, Fuzzer, scs, tsan, cfi: ctx.TopDown(t.variationName()+"_deps", sanitizerDepsMutator(t)) ctx.BottomUp(t.variationName(), sanitizerMutator(t)) - case memtag_heap, intOverflow: + case Memtag_heap, intOverflow: // do nothing default: panic(fmt.Errorf("unknown SanitizerType %d", t)) @@ -179,6 +179,8 @@ func (*Module) SanitizerSupported(t SanitizerType) bool { return true case Fuzzer: return true + case Memtag_heap: + return true default: return false } @@ -467,7 +469,7 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { s.Scs = nil } - // memtag_heap is only implemented on AArch64. + // Memtag_heap is only implemented on AArch64. if ctx.Arch().ArchType != android.Arm64 { s.Memtag_heap = nil } @@ -813,7 +815,7 @@ func (sanitize *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool { return sanitize.Properties.Sanitize.Cfi case scs: return sanitize.Properties.Sanitize.Scs - case memtag_heap: + case Memtag_heap: return sanitize.Properties.Sanitize.Memtag_heap case Fuzzer: return sanitize.Properties.Sanitize.Fuzzer @@ -829,7 +831,7 @@ func (sanitize *sanitize) isUnsanitizedVariant() bool { !sanitize.isSanitizerEnabled(tsan) && !sanitize.isSanitizerEnabled(cfi) && !sanitize.isSanitizerEnabled(scs) && - !sanitize.isSanitizerEnabled(memtag_heap) && + !sanitize.isSanitizerEnabled(Memtag_heap) && !sanitize.isSanitizerEnabled(Fuzzer) } @@ -859,7 +861,7 @@ func (sanitize *sanitize) SetSanitizer(t SanitizerType, b bool) { sanitize.Properties.Sanitize.Cfi = bPtr case scs: sanitize.Properties.Sanitize.Scs = bPtr - case memtag_heap: + case Memtag_heap: sanitize.Properties.Sanitize.Memtag_heap = bPtr case Fuzzer: sanitize.Properties.Sanitize.Fuzzer = bPtr @@ -1148,7 +1150,7 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { if lib, ok := snapshot.StaticLibs[noteDep]; ok { noteDep = lib } - depTag := libraryDependencyTag{Kind: staticLibraryDependency, wholeStatic: true} + depTag := StaticDepTag(true) variations := append(mctx.Target().Variations(), blueprint.Variation{Mutator: "link", Variation: "static"}) if c.Device() { @@ -1318,6 +1320,10 @@ var _ PlatformSanitizeable = (*Module)(nil) func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) { return func(mctx android.BottomUpMutatorContext) { if c, ok := mctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() { + + // Make sure we're not setting CFI to any value if it's not supported. + cfiSupported := mctx.Module().(PlatformSanitizeable).SanitizerSupported(cfi) + if c.Binary() && c.IsSanitizerEnabled(t) { modules := mctx.CreateVariations(t.variationName()) modules[0].(PlatformSanitizeable).SetSanitizer(t, true) @@ -1338,7 +1344,6 @@ func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) { // is redirected to the sanitized variant of the dependent module. defaultVariation := t.variationName() // Not all PlatformSanitizeable modules support the CFI sanitizer - cfiSupported := mctx.Module().(PlatformSanitizeable).SanitizerSupported(cfi) mctx.SetDefaultDependencyVariation(&defaultVariation) modules := mctx.CreateVariations("", t.variationName()) @@ -1385,7 +1390,7 @@ func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) { modules[0].(PlatformSanitizeable).SetInSanitizerDir() } - if mctx.Device() && t.incompatibleWithCfi() { + if mctx.Device() && t.incompatibleWithCfi() && cfiSupported { // TODO: Make sure that cfi mutator runs "after" any of the sanitizers that // are incompatible with cfi modules[0].(PlatformSanitizeable).SetSanitizer(cfi, false) diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go index 183f19075..7ce183495 100644 --- a/mk2rbc/mk2rbc.go +++ b/mk2rbc/mk2rbc.go @@ -974,25 +974,16 @@ func (ctx *parseContext) processBranch(check *mkparser.Directive) { ctx.pushReceiver(&block) for ctx.hasNodes() { node := ctx.getNode() - if ctx.handleSimpleStatement(node) { - continue - } - switch d := node.(type) { - case *mkparser.Directive: + if d, ok := node.(*mkparser.Directive); ok { switch d.Name { case "else", "elifdef", "elifndef", "elifeq", "elifneq", "endif": ctx.popReceiver() ctx.receiver.newNode(&block) ctx.backNode() return - case "ifdef", "ifndef", "ifeq", "ifneq": - ctx.handleIfBlock(d) - default: - ctx.errorf(d, "unexpected directive %s", d.Name) } - default: - ctx.errorf(node, "unexpected statement") } + ctx.handleSimpleStatement(node) } ctx.fatalError = fmt.Errorf("no matching endif for %s", check.Dump()) ctx.popReceiver() @@ -1494,9 +1485,7 @@ func (ctx *parseContext) parseMakeString(node mkparser.Node, mk *mkparser.MakeSt // Handles the statements whose treatment is the same in all contexts: comment, // assignment, variable (which is a macro call in reality) and all constructs that // do not handle in any context ('define directive and any unrecognized stuff). -// Return true if we handled it. -func (ctx *parseContext) handleSimpleStatement(node mkparser.Node) bool { - handled := true +func (ctx *parseContext) handleSimpleStatement(node mkparser.Node) { switch x := node.(type) { case *mkparser.Comment: ctx.maybeHandleAnnotation(x) @@ -1511,13 +1500,14 @@ func (ctx *parseContext) handleSimpleStatement(node mkparser.Node) bool { ctx.handleDefine(x) case "include", "-include": ctx.handleInclude(node, ctx.parseMakeString(node, x.Args), x.Name[0] != '-') + case "ifeq", "ifneq", "ifdef", "ifndef": + ctx.handleIfBlock(x) default: - handled = false + ctx.errorf(x, "unexpected directive %s", x.Name) } default: ctx.errorf(x, "unsupported line %s", strings.ReplaceAll(x.Dump(), "\n", "\n#")) } - return handled } // Processes annotation. An annotation is a comment that starts with #RBC# and provides @@ -1691,21 +1681,7 @@ func Convert(req Request) (*StarlarkScript, error) { } ctx.pushReceiver(starScript) for ctx.hasNodes() && ctx.fatalError == nil { - node := ctx.getNode() - if ctx.handleSimpleStatement(node) { - continue - } - switch x := node.(type) { - case *mkparser.Directive: - switch x.Name { - case "ifeq", "ifneq", "ifdef", "ifndef": - ctx.handleIfBlock(x) - default: - ctx.errorf(x, "unexpected directive %s", x.Name) - } - default: - ctx.errorf(x, "unsupported line") - } + ctx.handleSimpleStatement(ctx.getNode()) } if ctx.fatalError != nil { return nil, ctx.fatalError diff --git a/rust/Android.bp b/rust/Android.bp index 0ee673de4..cda2dbc6a 100644 --- a/rust/Android.bp +++ b/rust/Android.bp @@ -54,6 +54,7 @@ bootstrap_go_package { "project_json_test.go", "protobuf_test.go", "rust_test.go", + "sanitize_test.go", "source_provider_test.go", "test_test.go", "vendor_snapshot_test.go", diff --git a/rust/androidmk.go b/rust/androidmk.go index 7eb5dbdbd..c9f648632 100644 --- a/rust/androidmk.go +++ b/rust/androidmk.go @@ -147,6 +147,7 @@ func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.An } }) } + func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) { ctx.SubAndroidMk(ret, procMacro.baseCompiler) diff --git a/rust/binary.go b/rust/binary.go index cba2f7232..db91ccb9a 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -34,6 +34,7 @@ type BinaryCompilerProperties struct { type binaryInterface interface { binary() bool staticallyLinked() bool + testBinary() bool } type binaryDecorator struct { @@ -172,3 +173,7 @@ func (binary *binaryDecorator) binary() bool { func (binary *binaryDecorator) staticallyLinked() bool { return Bool(binary.Properties.Static_executable) } + +func (binary *binaryDecorator) testBinary() bool { + return false +} diff --git a/rust/compiler.go b/rust/compiler.go index 293b17b50..3040e5d9e 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -363,9 +363,9 @@ func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps { if !Bool(compiler.Properties.No_stdlibs) { for _, stdlib := range config.Stdlibs { - // If we're building for the primary arch of the build host, use the compiler's stdlibs + // If we're building for the build host, use the prebuilt stdlibs if ctx.Target().Os == ctx.Config().BuildOS { - stdlib = stdlib + "_" + ctx.toolchain().RustTriple() + stdlib = "prebuilt_" + stdlib } deps.Stdlibs = append(deps.Stdlibs, stdlib) } diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go index 9b88b6d81..0d0b712c2 100644 --- a/rust/config/allowed_list.go +++ b/rust/config/allowed_list.go @@ -11,6 +11,7 @@ var ( "external/crosvm", "external/libchromeos-rs", "external/minijail", + "external/open-dice", "external/rust", "external/selinux/libselinux", "external/uwb", diff --git a/rust/fuzz.go b/rust/fuzz.go index c52f5f9e2..55921ba4b 100644 --- a/rust/fuzz.go +++ b/rust/fuzz.go @@ -36,7 +36,7 @@ type fuzzDecorator struct { fuzzPackagedModule fuzz.FuzzPackagedModule } -var _ compiler = (*binaryDecorator)(nil) +var _ compiler = (*fuzzDecorator)(nil) // rust_binary produces a binary that is runnable on a device. func RustFuzzFactory() android.Module { diff --git a/rust/prebuilt.go b/rust/prebuilt.go index 6099eec4d..6f17272f7 100644 --- a/rust/prebuilt.go +++ b/rust/prebuilt.go @@ -32,6 +32,8 @@ type PrebuiltProperties struct { } type prebuiltLibraryDecorator struct { + android.Prebuilt + *libraryDecorator Properties PrebuiltProperties } @@ -54,6 +56,13 @@ func PrebuiltRlibFactory() android.Module { return module.Init() } +func addSrcSupplier(module android.PrebuiltInterface, prebuilt *prebuiltLibraryDecorator) { + srcsSupplier := func(_ android.BaseModuleContext, _ android.Module) []string { + return prebuilt.prebuiltSrcs() + } + android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs") +} + func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *prebuiltLibraryDecorator) { module, library := NewRustLibrary(hod) library.BuildOnlyRust() @@ -62,6 +71,9 @@ func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *prebuiltLi libraryDecorator: library, } module.compiler = prebuilt + + addSrcSupplier(module, prebuilt) + return module, prebuilt } @@ -73,6 +85,9 @@ func NewPrebuiltDylib(hod android.HostOrDeviceSupported) (*Module, *prebuiltLibr libraryDecorator: library, } module.compiler = prebuilt + + addSrcSupplier(module, prebuilt) + return module, prebuilt } @@ -84,6 +99,9 @@ func NewPrebuiltRlib(hod android.HostOrDeviceSupported) (*Module, *prebuiltLibra libraryDecorator: library, } module.compiler = prebuilt + + addSrcSupplier(module, prebuilt) + return module, prebuilt } @@ -130,3 +148,7 @@ func (prebuilt *prebuiltLibraryDecorator) prebuiltSrcs() []string { return srcs } + +func (prebuilt *prebuiltLibraryDecorator) prebuilt() *android.Prebuilt { + return &prebuilt.Prebuilt +} diff --git a/rust/rust.go b/rust/rust.go index b3e543ee9..3cc786878 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -1019,6 +1019,13 @@ func (mod *Module) begin(ctx BaseModuleContext) { } } +func (mod *Module) Prebuilt() *android.Prebuilt { + if p, ok := mod.compiler.(*prebuiltLibraryDecorator); ok { + return p.prebuilt() + } + return nil +} + func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { var depPaths PathDeps diff --git a/rust/rust_test.go b/rust/rust_test.go index 9b518c8c5..b99b1e63b 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -442,3 +442,10 @@ func TestLibrarySizes(t *testing.T) { m.Output("unstripped/libwaldo.dylib.so.bloaty.csv") m.Output("libwaldo.dylib.so.bloaty.csv") } + +func assertString(t *testing.T, got, expected string) { + t.Helper() + if got != expected { + t.Errorf("expected %q got %q", expected, got) + } +} diff --git a/rust/sanitize.go b/rust/sanitize.go index baa383da6..fdb342d40 100644 --- a/rust/sanitize.go +++ b/rust/sanitize.go @@ -15,20 +15,39 @@ package rust import ( + "fmt" + "strings" + + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" + "android/soong/android" "android/soong/cc" "android/soong/rust/config" - "fmt" - "github.com/google/blueprint" ) +// TODO: When Rust has sanitizer-parity with CC, deduplicate this struct type SanitizeProperties struct { // enable AddressSanitizer, HWAddressSanitizer, and others. Sanitize struct { Address *bool `android:"arch_variant"` Hwaddress *bool `android:"arch_variant"` - Fuzzer *bool `android:"arch_variant"` - Never *bool `android:"arch_variant"` + + // Memory-tagging, only available on arm64 + // if diag.memtag unset or false, enables async memory tagging + Memtag_heap *bool `android:"arch_variant"` + Fuzzer *bool `android:"arch_variant"` + Never *bool `android:"arch_variant"` + + // Sanitizers to run in the diagnostic mode (as opposed to the release mode). + // Replaces abort() on error with a human-readable error message. + // Address and Thread sanitizers always run in diagnostic mode. + Diag struct { + // Memory-tagging, only available on arm64 + // requires sanitizer.memtag: true + // if set, enables sync memory tagging + Memtag_heap *bool `android:"arch_variant"` + } } SanitizerEnabled bool `blueprint:"mutated"` SanitizeDep bool `blueprint:"mutated"` @@ -59,9 +78,18 @@ var asanFlags = []string{ "-Z sanitizer=address", } +// See cc/sanitize.go's hwasanGlobalOptions for global hwasan options. var hwasanFlags = []string{ "-Z sanitizer=hwaddress", "-C target-feature=+tagged-globals", + + // Flags from cc/sanitize.go hwasanFlags + "-C llvm-args=--aarch64-enable-global-isel-at-O=-1", + "-C llvm-args=-fast-isel=false", + "-C llvm-args=-instcombine-lower-dbg-declare=0", + + // Additional flags for HWASAN-ified Rust/C interop + "-C llvm-args=--hwasan-with-ifunc", } func boolPtr(v bool) *bool { @@ -79,7 +107,85 @@ func (sanitize *sanitize) props() []interface{} { } func (sanitize *sanitize) begin(ctx BaseModuleContext) { - s := sanitize.Properties.Sanitize + s := &sanitize.Properties.Sanitize + + // Never always wins. + if Bool(s.Never) { + return + } + + // rust_test targets default to SYNC MemTag unless explicitly set to ASYNC (via diag: {Memtag_heap}). + if binary, ok := ctx.RustModule().compiler.(binaryInterface); ok && binary.testBinary() { + if s.Memtag_heap == nil { + s.Memtag_heap = proptools.BoolPtr(true) + } + if s.Diag.Memtag_heap == nil { + s.Diag.Memtag_heap = proptools.BoolPtr(true) + } + } + + var globalSanitizers []string + var globalSanitizersDiag []string + + if ctx.Host() { + if !ctx.Windows() { + globalSanitizers = ctx.Config().SanitizeHost() + } + } else { + arches := ctx.Config().SanitizeDeviceArch() + if len(arches) == 0 || android.InList(ctx.Arch().ArchType.Name, arches) { + globalSanitizers = ctx.Config().SanitizeDevice() + globalSanitizersDiag = ctx.Config().SanitizeDeviceDiag() + } + } + + if len(globalSanitizers) > 0 { + var found bool + + // Global Sanitizers + if found, globalSanitizers = android.RemoveFromList("hwaddress", globalSanitizers); found && s.Hwaddress == nil { + // TODO(b/180495975): HWASan for static Rust binaries isn't supported yet. + if !ctx.RustModule().StaticExecutable() { + s.Hwaddress = proptools.BoolPtr(true) + } + } + + if found, globalSanitizers = android.RemoveFromList("memtag_heap", globalSanitizers); found && s.Memtag_heap == nil { + if !ctx.Config().MemtagHeapDisabledForPath(ctx.ModuleDir()) { + s.Memtag_heap = proptools.BoolPtr(true) + } + } + + if found, globalSanitizers = android.RemoveFromList("address", globalSanitizers); found && s.Address == nil { + s.Address = proptools.BoolPtr(true) + } + + if found, globalSanitizers = android.RemoveFromList("fuzzer", globalSanitizers); found && s.Fuzzer == nil { + s.Fuzzer = proptools.BoolPtr(true) + } + + // Global Diag Sanitizers + if found, globalSanitizersDiag = android.RemoveFromList("memtag_heap", globalSanitizersDiag); found && + s.Diag.Memtag_heap == nil && Bool(s.Memtag_heap) { + s.Diag.Memtag_heap = proptools.BoolPtr(true) + } + } + + // Enable Memtag for all components in the include paths (for Aarch64 only) + if ctx.Arch().ArchType == android.Arm64 { + if ctx.Config().MemtagHeapSyncEnabledForPath(ctx.ModuleDir()) { + if s.Memtag_heap == nil { + s.Memtag_heap = proptools.BoolPtr(true) + } + if s.Diag.Memtag_heap == nil { + s.Diag.Memtag_heap = proptools.BoolPtr(true) + } + } else if ctx.Config().MemtagHeapAsyncEnabledForPath(ctx.ModuleDir()) { + if s.Memtag_heap == nil { + s.Memtag_heap = proptools.BoolPtr(true) + } + } + } // TODO:(b/178369775) // For now sanitizing is only supported on devices @@ -96,7 +202,22 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { s.Hwaddress = nil } - if ctx.Os() == android.Android && Bool(s.Hwaddress) { + // HWASan ramdisk (which is built from recovery) goes over some bootloader limit. + // Keep libc instrumented so that ramdisk / vendor_ramdisk / recovery can run hwasan-instrumented code if necessary. + if (ctx.RustModule().InRamdisk() || ctx.RustModule().InVendorRamdisk() || ctx.RustModule().InRecovery()) && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") { + s.Hwaddress = nil + } + + if Bool(s.Hwaddress) { + s.Address = nil + } + + // Memtag_heap is only implemented on AArch64. + if ctx.Arch().ArchType != android.Arm64 { + s.Memtag_heap = nil + } + + if ctx.Os() == android.Android && (Bool(s.Hwaddress) || Bool(s.Address) || Bool(s.Memtag_heap)) { sanitize.Properties.SanitizerEnabled = true } } @@ -136,6 +257,26 @@ func rustSanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { return } + if Bool(mod.sanitize.Properties.Sanitize.Memtag_heap) && mod.Binary() { + noteDep := "note_memtag_heap_async" + if Bool(mod.sanitize.Properties.Sanitize.Diag.Memtag_heap) { + noteDep = "note_memtag_heap_sync" + } + // If we're using snapshots, redirect to snapshot whenever possible + // TODO(b/178470649): clean manual snapshot redirections + snapshot := mctx.Provider(cc.SnapshotInfoProvider).(cc.SnapshotInfo) + if lib, ok := snapshot.StaticLibs[noteDep]; ok { + noteDep = lib + } + depTag := cc.StaticDepTag(true) + variations := append(mctx.Target().Variations(), + blueprint.Variation{Mutator: "link", Variation: "static"}) + if mod.Device() { + variations = append(variations, mod.ImageVariation()) + } + mctx.AddFarVariationDependencies(variations, depTag, noteDep) + } + variations := mctx.Target().Variations() var depTag blueprint.DependencyTag var deps []string @@ -149,26 +290,23 @@ func rustSanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { } else if mod.IsSanitizerEnabled(cc.Hwasan) || (mod.IsSanitizerEnabled(cc.Fuzzer) && mctx.Arch().ArchType == android.Arm64) { // TODO(b/180495975): HWASan for static Rust binaries isn't supported yet. - if binary, ok := mod.compiler.(*binaryDecorator); ok { - if Bool(binary.Properties.Static_executable) { + if binary, ok := mod.compiler.(binaryInterface); ok { + if binary.staticallyLinked() { mctx.ModuleErrorf("HWASan is not supported for static Rust executables yet.") } } - if mod.StaticallyLinked() { - variations = append(variations, - blueprint.Variation{Mutator: "link", Variation: "static"}) - depTag = cc.StaticDepTag(false) - deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan_static")} - } else { - variations = append(variations, - blueprint.Variation{Mutator: "link", Variation: "shared"}) - depTag = cc.SharedDepTag() - deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan")} - } + // Always link against the shared library -- static binaries will pull in the static + // library during final link if necessary + variations = append(variations, + blueprint.Variation{Mutator: "link", Variation: "shared"}) + depTag = cc.SharedDepTag() + deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan")} } - mctx.AddFarVariationDependencies(variations, depTag, deps...) + if len(deps) > 0 { + mctx.AddFarVariationDependencies(variations, depTag, deps...) + } } } @@ -184,6 +322,9 @@ func (sanitize *sanitize) SetSanitizer(t cc.SanitizerType, b bool) { case cc.Hwasan: sanitize.Properties.Sanitize.Hwaddress = boolPtr(b) sanitizerSet = true + case cc.Memtag_heap: + sanitize.Properties.Sanitize.Memtag_heap = boolPtr(b) + sanitizerSet = true default: panic(fmt.Errorf("setting unsupported sanitizerType %d", t)) } @@ -243,6 +384,8 @@ func (sanitize *sanitize) getSanitizerBoolPtr(t cc.SanitizerType) *bool { return sanitize.Properties.Sanitize.Address case cc.Hwasan: return sanitize.Properties.Sanitize.Hwaddress + case cc.Memtag_heap: + return sanitize.Properties.Sanitize.Memtag_heap default: return nil } @@ -268,6 +411,12 @@ func (mod *Module) SanitizerSupported(t cc.SanitizerType) bool { case cc.Asan: return true case cc.Hwasan: + // TODO(b/180495975): HWASan for static Rust binaries isn't supported yet. + if mod.StaticExecutable() { + return false + } + return true + case cc.Memtag_heap: return true default: return false diff --git a/rust/sanitize_test.go b/rust/sanitize_test.go new file mode 100644 index 000000000..d6a14b295 --- /dev/null +++ b/rust/sanitize_test.go @@ -0,0 +1,365 @@ +package rust + +import ( + "fmt" + "strings" + "testing" + + "android/soong/android" +) + +type MemtagNoteType int + +const ( + None MemtagNoteType = iota + 1 + Sync + Async +) + +func (t MemtagNoteType) str() string { + switch t { + case None: + return "none" + case Sync: + return "sync" + case Async: + return "async" + default: + panic("type_note_invalid") + } +} + +func checkHasMemtagNote(t *testing.T, m android.TestingModule, expected MemtagNoteType) { + t.Helper() + note_async := "note_memtag_heap_async" + note_sync := "note_memtag_heap_sync" + + found := None + implicits := m.Rule("rustc").Implicits + for _, lib := range implicits { + if strings.Contains(lib.Rel(), note_async) { + found = Async + break + } else if strings.Contains(lib.Rel(), note_sync) { + found = Sync + break + } + } + + if found != expected { + t.Errorf("Wrong Memtag note in target %q: found %q, expected %q", m.Module().(*Module).Name(), found.str(), expected.str()) + } +} + +var prepareForTestWithMemtagHeap = android.GroupFixturePreparers( + android.FixtureModifyMockFS(func(fs android.MockFS) { + templateBp := ` + rust_test { + name: "unset_test_%[1]s", + srcs: ["foo.rs"], + } + + rust_test { + name: "no_memtag_test_%[1]s", + srcs: ["foo.rs"], + sanitize: { memtag_heap: false }, + } + + rust_test { + name: "set_memtag_test_%[1]s", + srcs: ["foo.rs"], + sanitize: { memtag_heap: true }, + } + + rust_test { + name: "set_memtag_set_async_test_%[1]s", + srcs: ["foo.rs"], + sanitize: { memtag_heap: true, diag: { memtag_heap: false } }, + } + + rust_test { + name: "set_memtag_set_sync_test_%[1]s", + srcs: ["foo.rs"], + sanitize: { memtag_heap: true, diag: { memtag_heap: true } }, + } + + rust_test { + name: "unset_memtag_set_sync_test_%[1]s", + srcs: ["foo.rs"], + sanitize: { diag: { memtag_heap: true } }, + } + + rust_binary { + name: "unset_binary_%[1]s", + srcs: ["foo.rs"], + } + + rust_binary { + name: "no_memtag_binary_%[1]s", + srcs: ["foo.rs"], + sanitize: { memtag_heap: false }, + } + + rust_binary { + name: "set_memtag_binary_%[1]s", + srcs: ["foo.rs"], + sanitize: { memtag_heap: true }, + } + + rust_binary { + name: "set_memtag_set_async_binary_%[1]s", + srcs: ["foo.rs"], + sanitize: { memtag_heap: true, diag: { memtag_heap: false } }, + } + + rust_binary { + name: "set_memtag_set_sync_binary_%[1]s", + srcs: ["foo.rs"], + sanitize: { memtag_heap: true, diag: { memtag_heap: true } }, + } + + rust_binary { + name: "unset_memtag_set_sync_binary_%[1]s", + srcs: ["foo.rs"], + sanitize: { diag: { memtag_heap: true } }, + } + ` + subdirNoOverrideBp := fmt.Sprintf(templateBp, "no_override") + subdirOverrideDefaultDisableBp := fmt.Sprintf(templateBp, "override_default_disable") + subdirSyncBp := fmt.Sprintf(templateBp, "override_default_sync") + subdirAsyncBp := fmt.Sprintf(templateBp, "override_default_async") + + fs.Merge(android.MockFS{ + "subdir_no_override/Android.bp": []byte(subdirNoOverrideBp), + "subdir_override_default_disable/Android.bp": []byte(subdirOverrideDefaultDisableBp), + "subdir_sync/Android.bp": []byte(subdirSyncBp), + "subdir_async/Android.bp": []byte(subdirAsyncBp), + }) + }), + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.MemtagHeapExcludePaths = []string{"subdir_override_default_disable"} + // "subdir_override_default_disable" is covered by both include and override_default_disable paths. override_default_disable wins. + variables.MemtagHeapSyncIncludePaths = []string{"subdir_sync", "subdir_override_default_disable"} + variables.MemtagHeapAsyncIncludePaths = []string{"subdir_async", "subdir_override_default_disable"} + }), +) + +func TestSanitizeMemtagHeap(t *testing.T) { + variant := "android_arm64_armv8-a" + + result := android.GroupFixturePreparers( + prepareForRustTest, + prepareForTestWithMemtagHeap, + ).RunTest(t) + ctx := result.TestContext + + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_no_override", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_async", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_disable", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_sync", variant), None) + + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_no_override", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_async", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_disable", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_sync", variant), None) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_no_override", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_async", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_disable", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_no_override", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_async", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_disable", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_sync", variant), Async) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_no_override", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_async", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_disable", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_sync", variant), Async) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_no_override", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_disable", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_no_override", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_async", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_disable", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync) +} + +func TestSanitizeMemtagHeapWithSanitizeDevice(t *testing.T) { + variant := "android_arm64_armv8-a" + + result := android.GroupFixturePreparers( + prepareForRustTest, + prepareForTestWithMemtagHeap, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.SanitizeDevice = []string{"memtag_heap"} + }), + ).RunTest(t) + ctx := result.TestContext + + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_no_override", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_async", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_disable", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_sync", variant), None) + + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_no_override", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_async", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_disable", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_sync", variant), None) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_no_override", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_async", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_disable", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_no_override", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_async", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_disable", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_sync", variant), Async) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_no_override", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_async", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_disable", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_sync", variant), Async) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_sync", variant), Sync) + + // should sanitize: { diag: { memtag: true } } result in Sync instead of None here? + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_async", variant), Sync) + // should sanitize: { diag: { memtag: true } } result in Sync instead of None here? + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_disable", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_no_override", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_async", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_disable", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync) +} + +func TestSanitizeMemtagHeapWithSanitizeDeviceDiag(t *testing.T) { + variant := "android_arm64_armv8-a" + + result := android.GroupFixturePreparers( + prepareForRustTest, + prepareForTestWithMemtagHeap, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.SanitizeDevice = []string{"memtag_heap"} + variables.SanitizeDeviceDiag = []string{"memtag_heap"} + }), + ).RunTest(t) + ctx := result.TestContext + + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_no_override", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_async", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_disable", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_sync", variant), None) + + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_no_override", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_async", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_disable", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_sync", variant), None) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_no_override", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_async", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_disable", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_sync", variant), Async) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_no_override", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_async", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_disable", variant), Async) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_sync", variant), Async) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_async", variant), Sync) + // should sanitize: { diag: { memtag: true } } result in Sync instead of None here? + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_disable", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_disable", variant), None) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_sync", variant), Sync) + + checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_no_override", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_async", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync) + checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync) +} diff --git a/rust/test.go b/rust/test.go index 56da509b5..bb877a9a5 100644 --- a/rust/test.go +++ b/rust/test.go @@ -196,3 +196,7 @@ func (test *testDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { return deps } + +func (test *testDecorator) testBinary() bool { + return true +} diff --git a/rust/testing.go b/rust/testing.go index 94cdd9dcd..9f8ed54d9 100644 --- a/rust/testing.go +++ b/rust/testing.go @@ -53,74 +53,14 @@ var PrepareForTestWithRustIncludeVndk = android.GroupFixturePreparers( func GatherRequiredDepsForTest() string { bp := ` rust_prebuilt_library { - name: "libstd_x86_64-unknown-linux-gnu", - crate_name: "std", - rlib: { - srcs: ["libstd.rlib"], - }, - dylib: { - srcs: ["libstd.so"], - }, - host_supported: true, - sysroot: true, - } - rust_prebuilt_library { - name: "libtest_x86_64-unknown-linux-gnu", - crate_name: "test", - rlib: { - srcs: ["libtest.rlib"], - }, - dylib: { - srcs: ["libtest.so"], - }, - host_supported: true, - sysroot: true, - } - rust_prebuilt_library { - name: "libstd_i686-unknown-linux-gnu", - crate_name: "std", - rlib: { - srcs: ["libstd.rlib"], - }, - dylib: { - srcs: ["libstd.so"], - }, - host_supported: true, - sysroot: true, - } - rust_prebuilt_library { - name: "libtest_i686-unknown-linux-gnu", - crate_name: "test", - rlib: { - srcs: ["libtest.rlib"], - }, - dylib: { - srcs: ["libtest.so"], - }, - host_supported: true, - sysroot: true, - } - rust_prebuilt_library { - name: "libstd_x86_64-apple-darwin", - crate_name: "std", - rlib: { - srcs: ["libstd.rlib"], - }, - dylib: { - srcs: ["libstd.so"], - }, - host_supported: true, - sysroot: true, - } - rust_prebuilt_library { - name: "libtest_x86_64-apple-darwin", - crate_name: "test", - rlib: { - srcs: ["libtest.rlib"], - }, - dylib: { - srcs: ["libtest.so"], - }, + name: "libstd", + crate_name: "std", + rlib: { + srcs: ["libstd.rlib"], + }, + dylib: { + srcs: ["libstd.so"], + }, host_supported: true, sysroot: true, } @@ -151,7 +91,12 @@ func GatherRequiredDepsForTest() string { no_libcrt: true, nocrt: true, system_shared_libs: [], - export_include_dirs: ["libprotobuf-cpp-full-includes"], + } + cc_library { + name: "libclang_rt.hwasan_static-aarch64-android", + no_libcrt: true, + nocrt: true, + system_shared_libs: [], } rust_library { name: "libstd", @@ -246,5 +191,8 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) { ctx.BottomUp("rust_begin", BeginMutator).Parallel() }) ctx.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton) + ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { + ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel() + }) registerRustSnapshotModules(ctx) } diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go index 60ddb653f..bfa6f361a 100644 --- a/rust/vendor_snapshot_test.go +++ b/rust/vendor_snapshot_test.go @@ -562,6 +562,7 @@ func TestVendorSnapshotUse(t *testing.T) { "libvendor", "libvndk", "libclang_rt.builtins-aarch64-android", + "note_memtag_heap_sync", ], shared_libs: [ "libvendor_available", @@ -853,6 +854,20 @@ func TestVendorSnapshotUse(t *testing.T) { }, } + // Test sanitizers use the snapshot libraries + rust_binary { + name: "memtag_binary", + srcs: ["vendor/bin.rs"], + vendor: true, + compile_multilib: "64", + sanitize: { + memtag_heap: true, + diag: { + memtag_heap: true, + } + }, + } + // old snapshot module which has to be ignored vendor_snapshot_binary { name: "bin", @@ -880,11 +895,25 @@ func TestVendorSnapshotUse(t *testing.T) { }, }, } + + vendor_snapshot_static { + name: "note_memtag_heap_sync", + vendor: true, + target_arch: "arm64", + version: "30", + arch: { + arm64: { + src: "note_memtag_heap_sync.a", + }, + }, + } + ` mockFS := android.MockFS{ "framework/Android.bp": []byte(frameworkBp), "framework/bin.rs": nil, + "note_memtag_heap_sync.a": nil, "vendor/Android.bp": []byte(vendorProprietaryBp), "vendor/bin": nil, "vendor/bin32": nil, @@ -993,4 +1022,9 @@ func TestVendorSnapshotUse(t *testing.T) { if android.InList(binaryVariant, binVariants) { t.Errorf("bin must not have variant %#v, but it does", sharedVariant) } + + memtagStaticLibs := ctx.ModuleForTests("memtag_binary", "android_vendor.30_arm64_armv8-a").Module().(*Module).Properties.AndroidMkStaticLibs + if g, w := memtagStaticLibs, []string{"libclang_rt.builtins-aarch64-android.vendor", "note_memtag_heap_sync.vendor"}; !reflect.DeepEqual(g, w) { + t.Errorf("wanted memtag_binary AndroidMkStaticLibs %q, got %q", w, g) + } } diff --git a/scripts/Android.bp b/scripts/Android.bp index 635be10b3..730d7567e 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -1,5 +1,6 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], + default_visibility: ["//build/soong:__subpackages__"], } python_binary_host { @@ -8,14 +9,6 @@ python_binary_host { srcs: [ "check_boot_jars/check_boot_jars.py", ], - version: { - py2: { - enabled: true, - }, - py3: { - enabled: false, - }, - }, } python_binary_host { @@ -24,14 +17,6 @@ python_binary_host { srcs: [ "manifest_fixer.py", ], - version: { - py2: { - enabled: true, - }, - py3: { - enabled: false, - }, - }, libs: [ "manifest_utils", ], @@ -45,11 +30,8 @@ python_test_host { "manifest_fixer.py", ], version: { - py2: { - enabled: true, - }, py3: { - enabled: false, + embedded_launcher: true, }, }, libs: [ @@ -67,12 +49,14 @@ python_library_host { ], version: { py2: { + // TODO(b/203436762) Remove when system/apex/apexer/apexer.py is converted enabled: true, }, py3: { - enabled: false, + enabled: true, }, }, + visibility: ["//system/apex/apexer:__pkg__"], } python_binary_host { @@ -81,14 +65,6 @@ python_binary_host { srcs: [ "manifest_check.py", ], - version: { - py2: { - enabled: true, - }, - py3: { - enabled: false, - }, - }, libs: [ "manifest_utils", ], @@ -101,14 +77,6 @@ python_test_host { "manifest_check_test.py", "manifest_check.py", ], - version: { - py2: { - enabled: true, - }, - py3: { - enabled: false, - }, - }, libs: [ "manifest_utils", ], @@ -123,14 +91,6 @@ python_binary_host { srcs: [ "jsonmodify.py", ], - version: { - py2: { - enabled: true, - }, - py3: { - enabled: false, - }, - }, } python_binary_host { @@ -139,14 +99,6 @@ python_binary_host { srcs: [ "test_config_fixer.py", ], - version: { - py2: { - enabled: true, - }, - py3: { - enabled: false, - }, - }, libs: [ "manifest_utils", ], @@ -159,14 +111,6 @@ python_test_host { "test_config_fixer_test.py", "test_config_fixer.py", ], - version: { - py2: { - enabled: true, - }, - py3: { - enabled: false, - }, - }, libs: [ "manifest_utils", ], @@ -179,14 +123,6 @@ python_binary_host { srcs: [ "construct_context.py", ], - version: { - py2: { - enabled: true, - }, - py3: { - enabled: false, - }, - }, libs: [ "manifest_utils", ], @@ -199,14 +135,6 @@ python_test_host { "construct_context_test.py", "construct_context.py", ], - version: { - py2: { - enabled: true, - }, - py3: { - enabled: false, - }, - }, libs: [ "manifest_utils", ], @@ -253,11 +181,7 @@ python_binary_host { "conv_linker_config.py", ], version: { - py2: { - enabled: false, - }, py3: { - enabled: true, embedded_launcher: true, }, }, @@ -272,12 +196,4 @@ python_binary_host { srcs: [ "get_clang_version.py", ], - version: { - py2: { - enabled: false, - }, - py3: { - enabled: true, - }, - }, } diff --git a/scripts/manifest.py b/scripts/manifest.py index 04f7405df..81f9c61a8 100755 --- a/scripts/manifest.py +++ b/scripts/manifest.py @@ -123,4 +123,4 @@ def get_indent(element, default_level): def write_xml(f, doc): f.write('<?xml version="1.0" encoding="utf-8"?>\n') for node in doc.childNodes: - f.write(node.toxml(encoding='utf-8') + '\n') + f.write(node.toxml() + '\n') diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py index 8bed52a9f..c8d4f76c8 100755 --- a/scripts/manifest_check.py +++ b/scripts/manifest_check.py @@ -335,7 +335,7 @@ def main(): if is_apk: aapt = args.aapt if args.aapt is not None else 'aapt' manifest = subprocess.check_output( - [aapt, 'dump', 'badging', args.input]) + [aapt, 'dump', 'badging', args.input]).decode('utf-8') else: manifest = minidom.parse(args.input) @@ -381,7 +381,7 @@ def main(): if is_apk: raise RuntimeError('cannot save APK manifest as XML') - with open(args.output, 'wb') as f: + with open(args.output, 'w') as f: write_xml(f, manifest) # pylint: disable=broad-except diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py index 55d0fd158..d80a617a1 100755 --- a/scripts/manifest_fixer.py +++ b/scripts/manifest_fixer.py @@ -352,7 +352,7 @@ def main(): if args.extract_native_libs is not None: add_extract_native_libs(doc, args.extract_native_libs) - with open(args.output, 'wb') as f: + with open(args.output, 'w') as f: write_xml(f, doc) # pylint: disable=broad-except diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py index 3a0a25d1c..f6fcaafe5 100755 --- a/scripts/manifest_fixer_test.py +++ b/scripts/manifest_fixer_test.py @@ -16,16 +16,16 @@ # """Unit tests for manifest_fixer.py.""" -import StringIO +import io import sys import unittest from xml.dom import minidom +import xml.etree.ElementTree as ET import manifest_fixer sys.dont_write_bytecode = True - class CompareVersionGtTest(unittest.TestCase): """Unit tests for compare_version_gt function.""" @@ -59,7 +59,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): doc = minidom.parseString(input_manifest) manifest_fixer.raise_min_sdk_version(doc, min_sdk_version, target_sdk_version, library) - output = StringIO.StringIO() + output = io.StringIO() manifest_fixer.write_xml(output, doc) return output.getvalue() @@ -80,13 +80,16 @@ class RaiseMinSdkVersionTest(unittest.TestCase): attrs += ' ' + extra return ' <uses-sdk%s/>\n' % (attrs) + def assert_xml_equal(self, output, expected): + self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected)) + def test_no_uses_sdk(self): """Tests inserting a uses-sdk element into a manifest.""" manifest_input = self.manifest_tmpl % '' expected = self.manifest_tmpl % self.uses_sdk(min='28', target='28') output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_no_min(self): """Tests inserting a minSdkVersion attribute into a uses-sdk element.""" @@ -95,7 +98,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): expected = self.manifest_tmpl % self.uses_sdk(min='28', target='28', extra='extra="foo"') output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_raise_min(self): """Tests inserting a minSdkVersion attribute into a uses-sdk element.""" @@ -103,7 +106,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): manifest_input = self.manifest_tmpl % self.uses_sdk(min='27') expected = self.manifest_tmpl % self.uses_sdk(min='28', target='28') output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_raise(self): """Tests raising a minSdkVersion attribute.""" @@ -111,7 +114,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): manifest_input = self.manifest_tmpl % self.uses_sdk(min='27') expected = self.manifest_tmpl % self.uses_sdk(min='28', target='28') output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_no_raise_min(self): """Tests a minSdkVersion that doesn't need raising.""" @@ -119,7 +122,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): manifest_input = self.manifest_tmpl % self.uses_sdk(min='28') expected = self.manifest_tmpl % self.uses_sdk(min='28', target='27') output = self.raise_min_sdk_version_test(manifest_input, '27', '27', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_raise_codename(self): """Tests raising a minSdkVersion attribute to a codename.""" @@ -127,7 +130,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): manifest_input = self.manifest_tmpl % self.uses_sdk(min='28') expected = self.manifest_tmpl % self.uses_sdk(min='P', target='P') output = self.raise_min_sdk_version_test(manifest_input, 'P', 'P', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_no_raise_codename(self): """Tests a minSdkVersion codename that doesn't need raising.""" @@ -135,7 +138,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): manifest_input = self.manifest_tmpl % self.uses_sdk(min='P') expected = self.manifest_tmpl % self.uses_sdk(min='P', target='28') output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_target(self): """Tests an existing targetSdkVersion is preserved.""" @@ -143,7 +146,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): manifest_input = self.manifest_tmpl % self.uses_sdk(min='26', target='27') expected = self.manifest_tmpl % self.uses_sdk(min='28', target='27') output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_no_target(self): """Tests inserting targetSdkVersion when minSdkVersion exists.""" @@ -151,7 +154,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): manifest_input = self.manifest_tmpl % self.uses_sdk(min='27') expected = self.manifest_tmpl % self.uses_sdk(min='28', target='29') output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_target_no_min(self): """"Tests inserting targetSdkVersion when minSdkVersion exists.""" @@ -159,7 +162,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): manifest_input = self.manifest_tmpl % self.uses_sdk(target='27') expected = self.manifest_tmpl % self.uses_sdk(min='28', target='27') output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_no_target_no_min(self): """Tests inserting targetSdkVersion when minSdkVersion does not exist.""" @@ -167,7 +170,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): manifest_input = self.manifest_tmpl % '' expected = self.manifest_tmpl % self.uses_sdk(min='28', target='29') output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_library_no_target(self): """Tests inserting targetSdkVersion when minSdkVersion exists.""" @@ -175,7 +178,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): manifest_input = self.manifest_tmpl % self.uses_sdk(min='27') expected = self.manifest_tmpl % self.uses_sdk(min='28', target='16') output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_library_target_no_min(self): """Tests inserting targetSdkVersion when minSdkVersion exists.""" @@ -183,7 +186,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): manifest_input = self.manifest_tmpl % self.uses_sdk(target='27') expected = self.manifest_tmpl % self.uses_sdk(min='28', target='27') output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_library_no_target_no_min(self): """Tests inserting targetSdkVersion when minSdkVersion does not exist.""" @@ -191,7 +194,7 @@ class RaiseMinSdkVersionTest(unittest.TestCase): manifest_input = self.manifest_tmpl % '' expected = self.manifest_tmpl % self.uses_sdk(min='28', target='16') output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_extra(self): """Tests that extra attributes and elements are maintained.""" @@ -204,12 +207,12 @@ class RaiseMinSdkVersionTest(unittest.TestCase): # pylint: disable=line-too-long expected = self.manifest_tmpl % ( ' <!-- comment -->\n' - ' <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="29" extra="foo"/>\n' + ' <uses-sdk android:minSdkVersion="28" extra="foo" android:targetSdkVersion="29"/>\n' ' <application/>\n') output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_indent(self): """Tests that an inserted element copies the existing indentation.""" @@ -223,17 +226,20 @@ class RaiseMinSdkVersionTest(unittest.TestCase): output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) class AddLoggingParentTest(unittest.TestCase): """Unit tests for add_logging_parent function.""" + def assert_xml_equal(self, output, expected): + self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected)) + def add_logging_parent_test(self, input_manifest, logging_parent=None): doc = minidom.parseString(input_manifest) if logging_parent: manifest_fixer.add_logging_parent(doc, logging_parent) - output = StringIO.StringIO() + output = io.StringIO() manifest_fixer.write_xml(output, doc) return output.getvalue() @@ -257,23 +263,26 @@ class AddLoggingParentTest(unittest.TestCase): manifest_input = self.manifest_tmpl % '' expected = self.manifest_tmpl % self.uses_logging_parent() output = self.add_logging_parent_test(manifest_input) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_logging_parent(self): """Tests manifest_fixer with no logging_parent.""" manifest_input = self.manifest_tmpl % '' expected = self.manifest_tmpl % self.uses_logging_parent('FOO') output = self.add_logging_parent_test(manifest_input, 'FOO') - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) class AddUsesLibrariesTest(unittest.TestCase): """Unit tests for add_uses_libraries function.""" + def assert_xml_equal(self, output, expected): + self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected)) + def run_test(self, input_manifest, new_uses_libraries): doc = minidom.parseString(input_manifest) manifest_fixer.add_uses_libraries(doc, new_uses_libraries, True) - output = StringIO.StringIO() + output = io.StringIO() manifest_fixer.write_xml(output, doc) return output.getvalue() @@ -301,7 +310,7 @@ class AddUsesLibrariesTest(unittest.TestCase): ('bar', 'false')]) expected = manifest_input output = self.run_test(manifest_input, []) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_not_overwrite(self): """new_uses_libraries must not overwrite existing tags.""" @@ -310,7 +319,7 @@ class AddUsesLibrariesTest(unittest.TestCase): ('bar', 'false')]) expected = manifest_input output = self.run_test(manifest_input, ['foo', 'bar']) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_add(self): """New names are added with 'required:true'.""" @@ -323,7 +332,7 @@ class AddUsesLibrariesTest(unittest.TestCase): ('baz', 'true'), ('qux', 'true')]) output = self.run_test(manifest_input, ['bar', 'baz', 'qux']) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_no_application(self): """When there is no <application> tag, the tag is added.""" @@ -336,7 +345,7 @@ class AddUsesLibrariesTest(unittest.TestCase): ('foo', 'true'), ('bar', 'true')]) output = self.run_test(manifest_input, ['foo', 'bar']) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_empty_application(self): """Even when here is an empty <application/> tag, the libs are added.""" @@ -350,16 +359,19 @@ class AddUsesLibrariesTest(unittest.TestCase): ('foo', 'true'), ('bar', 'true')]) output = self.run_test(manifest_input, ['foo', 'bar']) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) class AddUsesNonSdkApiTest(unittest.TestCase): """Unit tests for add_uses_libraries function.""" + def assert_xml_equal(self, output, expected): + self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected)) + def run_test(self, input_manifest): doc = minidom.parseString(input_manifest) manifest_fixer.add_uses_non_sdk_api(doc) - output = StringIO.StringIO() + output = io.StringIO() manifest_fixer.write_xml(output, doc) return output.getvalue() @@ -377,23 +389,26 @@ class AddUsesNonSdkApiTest(unittest.TestCase): manifest_input = self.manifest_tmpl % self.uses_non_sdk_api(False) expected = self.manifest_tmpl % self.uses_non_sdk_api(True) output = self.run_test(manifest_input) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_already_set(self): """new_uses_libraries must not overwrite existing tags.""" manifest_input = self.manifest_tmpl % self.uses_non_sdk_api(True) expected = manifest_input output = self.run_test(manifest_input) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) class UseEmbeddedDexTest(unittest.TestCase): """Unit tests for add_use_embedded_dex function.""" + def assert_xml_equal(self, output, expected): + self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected)) + def run_test(self, input_manifest): doc = minidom.parseString(input_manifest) manifest_fixer.add_use_embedded_dex(doc) - output = StringIO.StringIO() + output = io.StringIO() manifest_fixer.write_xml(output, doc) return output.getvalue() @@ -410,13 +425,13 @@ class UseEmbeddedDexTest(unittest.TestCase): manifest_input = self.manifest_tmpl % '' expected = self.manifest_tmpl % self.use_embedded_dex('true') output = self.run_test(manifest_input) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_manifest_with_use_embedded_dex(self): manifest_input = self.manifest_tmpl % self.use_embedded_dex('true') expected = manifest_input output = self.run_test(manifest_input) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_manifest_with_not_use_embedded_dex(self): manifest_input = self.manifest_tmpl % self.use_embedded_dex('false') @@ -426,10 +441,13 @@ class UseEmbeddedDexTest(unittest.TestCase): class AddExtractNativeLibsTest(unittest.TestCase): """Unit tests for add_extract_native_libs function.""" + def assert_xml_equal(self, output, expected): + self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected)) + def run_test(self, input_manifest, value): doc = minidom.parseString(input_manifest) manifest_fixer.add_extract_native_libs(doc, value) - output = StringIO.StringIO() + output = io.StringIO() manifest_fixer.write_xml(output, doc) return output.getvalue() @@ -446,19 +464,19 @@ class AddExtractNativeLibsTest(unittest.TestCase): manifest_input = self.manifest_tmpl % '' expected = self.manifest_tmpl % self.extract_native_libs('true') output = self.run_test(manifest_input, True) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_set_false(self): manifest_input = self.manifest_tmpl % '' expected = self.manifest_tmpl % self.extract_native_libs('false') output = self.run_test(manifest_input, False) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_match(self): manifest_input = self.manifest_tmpl % self.extract_native_libs('true') expected = manifest_input output = self.run_test(manifest_input, True) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_conflict(self): manifest_input = self.manifest_tmpl % self.extract_native_libs('true') @@ -468,10 +486,13 @@ class AddExtractNativeLibsTest(unittest.TestCase): class AddNoCodeApplicationTest(unittest.TestCase): """Unit tests for set_has_code_to_false function.""" + def assert_xml_equal(self, output, expected): + self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected)) + def run_test(self, input_manifest): doc = minidom.parseString(input_manifest) manifest_fixer.set_has_code_to_false(doc) - output = StringIO.StringIO() + output = io.StringIO() manifest_fixer.write_xml(output, doc) return output.getvalue() @@ -485,26 +506,26 @@ class AddNoCodeApplicationTest(unittest.TestCase): manifest_input = self.manifest_tmpl % '' expected = self.manifest_tmpl % ' <application android:hasCode="false"/>\n' output = self.run_test(manifest_input) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_has_application_no_has_code(self): manifest_input = self.manifest_tmpl % ' <application/>\n' expected = self.manifest_tmpl % ' <application android:hasCode="false"/>\n' output = self.run_test(manifest_input) - self.assertEqual(output, expected) + self.assert_xml_equal(output, expected) def test_has_application_has_code_false(self): """ Do nothing if there's already an application elemeent. """ manifest_input = self.manifest_tmpl % ' <application android:hasCode="false"/>\n' output = self.run_test(manifest_input) - self.assertEqual(output, manifest_input) + self.assert_xml_equal(output, manifest_input) def test_has_application_has_code_true(self): """ Do nothing if there's already an application elemeent even if its hasCode attribute is true. """ manifest_input = self.manifest_tmpl % ' <application android:hasCode="true"/>\n' output = self.run_test(manifest_input) - self.assertEqual(output, manifest_input) + self.assert_xml_equal(output, manifest_input) if __name__ == '__main__': diff --git a/scripts/test_config_fixer.py b/scripts/test_config_fixer.py index 32d5b175e..c150e8cfd 100644 --- a/scripts/test_config_fixer.py +++ b/scripts/test_config_fixer.py @@ -86,7 +86,7 @@ def main(): if args.test_file_name: overwrite_test_file_name(doc, args.test_file_name) - with open(args.output, 'wb') as f: + with open(args.output, 'w') as f: write_xml(f, doc) # pylint: disable=broad-except diff --git a/scripts/test_config_fixer_test.py b/scripts/test_config_fixer_test.py index 1272c6b33..d00a59315 100644 --- a/scripts/test_config_fixer_test.py +++ b/scripts/test_config_fixer_test.py @@ -16,7 +16,7 @@ # """Unit tests for test_config_fixer.py.""" -import StringIO +import io import sys import unittest from xml.dom import minidom @@ -59,7 +59,7 @@ class OverwritePackageNameTest(unittest.TestCase): manifest = minidom.parseString(self.manifest) test_config_fixer.overwrite_package_name(doc, manifest, "com.soong.foo") - output = StringIO.StringIO() + output = io.StringIO() test_config_fixer.write_xml(output, doc) # Only the matching package name in a test node should be updated. @@ -86,7 +86,7 @@ class OverwriteTestFileNameTest(unittest.TestCase): doc = minidom.parseString(self.test_config % ("foo.apk")) test_config_fixer.overwrite_test_file_name(doc, "bar.apk") - output = StringIO.StringIO() + output = io.StringIO() test_config_fixer.write_xml(output, doc) # Only the matching package name in a test node should be updated. |