Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/fuzz/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 24 kB image not shown  

Quelle  fuzz_common.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// 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 fuzz

// This file contains the common code for compiling C/C++ and Rust fuzzers for Android.

import (
 "encoding/json"
 "fmt"
 "sort"
 "strings"

 "github.com/google/blueprint"
 "github.com/google/blueprint/proptools"

 "android/soong/android"
)

//go:generate go run ../../blueprint/gobtools/codegen

type Lang string

const (
 Cc   Lang = "cc"
 Rust Lang = "rust"
 Java Lang = "java"
)

type Framework string

const (
 AFL              Framework = "afl"
 LibFuzzer        Framework = "libfuzzer"
 Jazzer           Framework = "jazzer"
 UnknownFramework Framework = "unknownframework"
)

func (f Framework) Variant() string {
 switch f {
 case AFL:
  return "afl"
 case LibFuzzer:
  return "libfuzzer"
 case Jazzer:
  return "jazzer"
 default:
  panic(fmt.Errorf("unknown fuzzer %q when getting variant", f))
 }
}

func FrameworkFromVariant(v string) Framework {
 switch v {
 case "afl":
  return AFL
 case "libfuzzer":
  return LibFuzzer
 case "jazzer":
  return Jazzer
 default:
  panic(fmt.Errorf("unknown variant %q when getting fuzzer", v))
 }
}

var BoolDefault = proptools.BoolDefault

type FuzzModule struct {
 android.ModuleBase
 android.DefaultableModuleBase
 android.ApexModuleBase
}

type FuzzPackager struct {
 Packages                android.Paths
 FuzzTargets             map[string]bool
 SharedLibInstallStrings []string
}

type FileToZip struct {
 SourceFilePath        android.Path
 DestinationPathPrefix string
 DestinationPath       string
}

type ArchOs struct {
 HostOrTarget string
 Arch         string
 Dir          string
}

type Vector string

const (
 unknown_access_vector Vector = "unknown_access_vector"
 // The code being fuzzed is reachable from a remote source, or using data
 // provided by a remote source.  For example: media codecs process media files
 // from the internet, SMS processing handles remote message data.
 // See
 // https://source.android.com/docs/security/overview/updates-resources#local-vs-remote
 // for an explanation of what's considered "remote."
 remote = "remote"
 // The code being fuzzed can only be reached locally, such as from an
 // installed app.  As an example, if it's fuzzing a Binder interface, it's
 // assumed that you'd need a local app to make arbitrary Binder calls.
 // And the app that's calling the fuzzed code does not require any privileges;
 // any 3rd party app could make these calls.
 local_no_privileges_required = "local_no_privileges_required"
 // The code being fuzzed can only be called locally, and the calling process
 // requires additional permissions that prevent arbitrary 3rd party apps from
 // calling the code.  For instance: this requires a privileged or signature
 // permission to reach, or SELinux restrictions prevent the untrusted_app
 // domain from calling it.
 local_privileges_required = "local_privileges_required"
 // The code is only callable on a PC host, not on a production Android device.
 // For instance, this is fuzzing code used during the build process, or
 // tooling that does not exist on a user's actual Android device.
 host_access = "host_access"
 // The code being fuzzed is only reachable if the user has enabled Developer
 // Options, or has enabled a persistent Developer Options setting.
 local_with_developer_options = "local_with_developer_options"
)

func (vector Vector) isValidVector() bool {
 switch vector {
 case "",
  unknown_access_vector,
  remote,
  local_no_privileges_required,
  local_privileges_required,
  host_access,
  local_with_developer_options:
  return true
 }
 return false
}

type ServicePrivilege string

const (
 unknown_service_privilege ServicePrivilege = "unknown_service_privilege"
 // The code being fuzzed runs on a Secure Element.  This has access to some
 // of the most privileged data on the device, such as authentication keys.
 // Not all devices have a Secure Element.
 secure_element = "secure_element"
 // The code being fuzzed runs in the TEE.  The TEE is designed to be resistant
 // to a compromised kernel, and stores sensitive data.
 trusted_execution = "trusted_execution"
 // The code being fuzzed has privileges beyond what arbitrary 3rd party apps
 // have.  For instance, it's running as the System UID, or it's in an SELinux
 // domain that's able to perform calls that can't be made by 3rd party apps.
 privileged = "privileged"
 // The code being fuzzed is equivalent to a 3rd party app.  It runs in the
 // untrusted_app SELinux domain, or it only has privileges that are equivalent
 // to what a 3rd party app could have.
 unprivileged = "unprivileged"
 // The code being fuzzed is significantly constrained, and even if it's
 // compromised, it has significant restrictions that prevent it from
 // performing most actions.  This is significantly more restricted than
 // UNPRIVILEGED.  An example is the isolatedProcess=true setting in a 3rd
 // party app.  Or a process that's very restricted by SELinux, such as
 // anything in the mediacodec SELinux domain.
 constrained = "constrained"
 // The code being fuzzed always has Negligible Security Impact.  Even
 // arbitrary out of bounds writes and full code execution would not be
 // considered a security vulnerability.  This typically only makes sense if
 // FuzzedCodeUsage is set to FUTURE_VERSION or EXPERIMENTAL, and if
 // AutomaticallyRouteTo is set to ALWAYS_NSI.
 nsi = "nsi"
 // The code being fuzzed only runs on a PC host, not on a production Android
 // device.  For instance, the fuzzer is fuzzing code used during the build
 // process, or tooling that does not exist on a user's actual Android device.
 host_only = "host_only"
)

func (service_privilege ServicePrivilege) isValidServicePrivilege() bool {
 switch service_privilege {
 case "",
  unknown_service_privilege,
  secure_element,
  trusted_execution,
  privileged,
  unprivileged,
  constrained,
  nsi,
  host_only:
  return true
 }
 return false
}

type UsePlatformLibs string

const (
 unknown_use_platform_libs UsePlatformLibs = "unknown_use_platform_libs"
 // Use the native libraries on the device, typically in /system directory
 use_platform_libs = "use_platform_libs"
 // Do not use any native libraries (ART will not be initialized)
 use_none = "use_none"
)

func (use_platform_libs UsePlatformLibs) isValidUsePlatformLibs() bool {
 switch use_platform_libs {
 case "",
  unknown_use_platform_libs,
  use_platform_libs,
  use_none:
  return true
 }
 return false
}

type UserData string

const (
 unknown_user_data UserData = "unknown_user_data"
 // The process being fuzzed only handles data from a single user, or from a
 // single process or app.  It's possible the process shuts down before
 // handling data from another user/process/app, or it's possible the process
 // only ever handles one user's/process's/app's data.  As an example, some
 // print spooler processes are started for a single document and terminate
 // when done, so each instance only handles data from a single user/app.
 single_user = "single_user"
 // The process handles data from multiple users, or from multiple other apps
 // or processes.  Media processes, for instance, can handle media requests
 // from multiple different apps without restarting.  Wi-Fi and network
 // processes handle data from multiple users, and processes, and apps.
 multi_user = "multi_user"
)

func (user_data UserData) isValidUserData() bool {
 switch user_data {
 case "",
  unknown_user_data,
  single_user,
  multi_user:
  return true
 }
 return false
}

type FuzzedCodeUsage string

const (
 undefined FuzzedCodeUsage = "undefined"
 unknown                   = "unknown"
 // The code being fuzzed exists in a shipped version of Android and runs on
 // devices in production.
 shipped = "shipped"
 // The code being fuzzed is not yet in a shipping version of Android, but it
 // will be at some point in the future.
 future_version = "future_version"
 // The code being fuzzed is not in a shipping version of Android, and there
 // are no plans to ship it in the future.
 experimental = "experimental"
)

func (fuzzed_code_usage FuzzedCodeUsage) isValidFuzzedCodeUsage() bool {
 switch fuzzed_code_usage {
 case "",
  undefined,
  unknown,
  shipped,
  future_version,
  experimental:
  return true
 }
 return false
}

type AutomaticallyRouteTo string

const (
 undefined_routing AutomaticallyRouteTo = "undefined_routing"
 // Automatically route this to the Android Automotive security team for
 // assessment.
 android_automotive = "android_automotive"
 // This should not be used in fuzzer configurations.  It is used internally
 // by Severity Assigner to flag memory leak reports.
 memory_leak = "memory_leak"
 // Route this vulnerability to our Ittiam vendor team for assessment.
 ittiam = "ittiam"
 // Reports from this fuzzer are always NSI (see the NSI ServicePrivilegeEnum
 // value for additional context).  It is not possible for this code to ever
 // have a security vulnerability.
 always_nsi = "always_nsi"
 // Route this vulnerability to AIDL team for assessment.
 aidl = "aidl"
)

func (automatically_route_to AutomaticallyRouteTo) isValidAutomaticallyRouteTo() bool {
 switch automatically_route_to {
 case "",
  undefined_routing,
  android_automotive,
  memory_leak,
  ittiam,
  always_nsi,
  aidl:
  return true
 }
 return false
}

func IsValidConfig(fuzzModule *FuzzPackagedModuleInfo, moduleName string) bool {
 var config = fuzzModule.FuzzConfig
 if config != nil {
  if !config.Vector.isValidVector() {
   panic(fmt.Errorf("Invalid vector in fuzz config in %s", moduleName))
  }

  if !config.ServicePrivilege.isValidServicePrivilege() {
   panic(fmt.Errorf("Invalid service_privilege in fuzz config in %s", moduleName))
  }

  if !config.Users.isValidUserData() {
   panic(fmt.Errorf("Invalid users (user_data) in fuzz config in %s", moduleName))
  }

  if !config.FuzzedCodeUsage.isValidFuzzedCodeUsage() {
   panic(fmt.Errorf("Invalid fuzzed_code_usage in fuzz config in %s", moduleName))
  }

  if !config.AutomaticallyRouteTo.isValidAutomaticallyRouteTo() {
   panic(fmt.Errorf("Invalid automatically_route_to in fuzz config in %s", moduleName))
  }

  if !config.UsePlatformLibs.isValidUsePlatformLibs() {
   panic(fmt.Errorf("Invalid use_platform_libs in fuzz config in %s", moduleName))
  }
 }
 return true
}

type FuzzConfig struct {
 // Email address of people to CC on bugs or contact about this fuzz target.
 Cc []string `json:"cc,omitempty"`
 // A brief description of what the fuzzed code does.
 Description string `json:"description,omitempty"`
 // Whether the code being fuzzed is remotely accessible or requires privileges
 // to access locally.
 Vector Vector `json:"vector,omitempty"`
 // How privileged the service being fuzzed is.
 Service_privilege ServicePrivilege `json:"service_privilege,omitempty"`
 // Whether the service being fuzzed handles data from multiple users or only
 // a single one.
 Users UserData `json:"users,omitempty"`
 // Specifies the use state of the code being fuzzed. This state factors into
 // how an issue is handled.
 Fuzzed_code_usage FuzzedCodeUsage `json:"fuzzed_code_usage,omitempty"`
 // Comment describing how we came to these settings for this fuzzer.
 Config_comment string
 // Which team to route this to, if it should be routed automatically.
 Automatically_route_to AutomaticallyRouteTo `json:"automatically_route_to,omitempty"`
 // Can third party/untrusted apps supply data to fuzzed code.
 Untrusted_data *bool `json:"untrusted_data,omitempty"`
 // When code was released or will be released.
 Production_date string `json:"production_date,omitempty"`
 // Prevents critical service functionality like phone calls, bluetooth, etc.
 Critical *bool `json:"critical,omitempty"`
 // Specify whether to enable continuous fuzzing on devices. Defaults to true.
 Fuzz_on_haiku_device *bool `json:"fuzz_on_haiku_device,omitempty"`
 // Specify whether to enable continuous fuzzing on host. Defaults to true.
 Fuzz_on_haiku_host *bool `json:"fuzz_on_haiku_host,omitempty"`
 // Component in Google's bug tracking system that bugs should be filed to.
 Componentid *int64 `json:"componentid,omitempty"`
 // Hotlist(s) in Google's bug tracking system that bugs should be marked with.
 Hotlists []string `json:"hotlists,omitempty"`
 // Specify whether this fuzz target was submitted by a researcher. Defaults
 // to false.
 Researcher_submitted *bool `json:"researcher_submitted,omitempty"`
 // Specify who should be acknowledged for CVEs in the Android Security
 // Bulletin.
 Acknowledgement []string `json:"acknowledgement,omitempty"`
 // Additional options to be passed to libfuzzer when run in Haiku.
 Libfuzzer_options []string `json:"libfuzzer_options,omitempty"`
 // Additional options to be passed to HWASAN when running on-device in Haiku.
 Hwasan_options []string `json:"hwasan_options,omitempty"`
 // Additional options to be passed to HWASAN when running on host in Haiku.
 Asan_options []string `json:"asan_options,omitempty"`
 // If there's a Java fuzzer with JNI, a different version of Jazzer would
 // need to be added to the fuzzer package than one without JNI
 IsJni *bool `json:"is_jni,omitempty"`
 // List of modules for monitoring coverage drops in directories (e.g. "libicu")
 Target_modules []string `json:"target_modules,omitempty"`
 // Specifies a bug assignee to replace default ISE assignment
 Triage_assignee string `json:"triage_assignee,omitempty"`
 // Specifies libs used to initialize ART (java only, 'use_none' for no initialization)
 Use_platform_libs UsePlatformLibs `json:"use_platform_libs,omitempty"`
 // Specifies whether fuzz target should check presubmitted code changes for crashes.
 // Defaults to false.
 Use_for_presubmit *bool `json:"use_for_presubmit,omitempty"`
 // Specify which paths to exclude from fuzzing coverage reports
 Exclude_paths_from_reports []string `json:"exclude_paths_from_reports,omitempty"`
}

type FuzzFrameworks struct {
 Afl       *bool
 Libfuzzer *bool
 Jazzer    *bool
}

type FuzzProperties struct {
 // Optional list of seed files to be installed to the fuzz target's output
 // directory.
 Corpus []string `android:"path"`

 // Same as corpus, but adds dependencies on module references using the device's os variant
 // and the common arch variant.
 Device_common_corpus []string `android:"path_device_common"`

 // Optional list of data files to be installed to the fuzz target's output
 // directory. Directory structure relative to the module is preserved.
 Data []string `android:"path"`
 // Same as data, but adds dependencies on modules using the device's os variant, and common
 // architecture's variant. Can be useful to add device-built apps to the data of a host
 // test.
 Device_common_data []string `android:"path_device_common"`
 // Same as data, but adds dependencies on modules using the device's os variant, and the
 // device's first architecture's variant. Can be useful to add device-built apps to the data
 // of a host test.
 Device_first_data []string `android:"path_device_first"`

 // Same as data, but will add dependencies on modules using the host's os variation and
 // the common arch variation. Useful for a device test that wants to depend on a host
 // module, for example to include a custom Tradefed test runner.
 Host_common_data []string `android:"path_host_common"`

 // Optional dictionary to be installed to the fuzz target's output directory.
 Dictionary *string `android:"path"`
 // Define the fuzzing frameworks this fuzz target can be built for. If
 // empty then the fuzz target will be available to be  built for all fuzz
 // frameworks available
 Fuzzing_frameworks *FuzzFrameworks
 // Config for running the target on fuzzing infrastructure.
 Fuzz_config *FuzzConfig
}

type FuzzPackagedModule struct {
 FuzzProperties FuzzProperties
 Dictionary     android.Path
 Corpus         android.Paths
 Config         android.Path
 Data           android.Paths
}

// @auto-generate: gob
type FuzzConfigInfo struct {
 Vector Vector
 // How privileged the service being fuzzed is.
 ServicePrivilege ServicePrivilege
 // Whether the service being fuzzed handles data from multiple users or only
 // a single one.
 Users UserData
 // Specifies the use state of the code being fuzzed. This state factors into
 // how an issue is handled.
 FuzzedCodeUsage FuzzedCodeUsage
 // Which team to route this to, if it should be routed automatically.
 AutomaticallyRouteTo AutomaticallyRouteTo
 // Specifies libs used to initialize ART (java only, 'use_none' for no initialization)
 UsePlatformLibs UsePlatformLibs
 // Specify whether to enable continuous fuzzing on devices. Defaults to true.
 FuzzOnHaikuDevice bool
 // Specify whether to enable continuous fuzzing on host. Defaults to true.
 FuzzOnHaikuHost bool
 // Specifies whether fuzz target should check presubmitted code changes for crashes.
 // Defaults to false.
 UseForPresubmit bool
}

// @auto-generate: gob
type FuzzPackagedModuleInfo struct {
 FuzzConfig *FuzzConfigInfo
 Dictionary android.Path
 Corpus     android.Paths
 Config     android.Path
 Data       android.Paths
}

var FuzzPackagedModuleInfoProvider = blueprint.NewProvider[FuzzPackagedModuleInfo]()

func SetFuzzPackagedModuleInfo(ctx android.ModuleContext, fm *FuzzPackagedModule) {
 info := FuzzPackagedModuleInfo{
  Dictionary: fm.Dictionary,
  Config:     fm.Config,
  Corpus:     fm.Corpus,
  Data:       fm.Data,
 }
 if fm.FuzzProperties.Fuzz_config != nil {
  info.FuzzConfig = &FuzzConfigInfo{
   Vector:               fm.FuzzProperties.Fuzz_config.Vector,
   ServicePrivilege:     fm.FuzzProperties.Fuzz_config.Service_privilege,
   Users:                fm.FuzzProperties.Fuzz_config.Users,
   FuzzedCodeUsage:      fm.FuzzProperties.Fuzz_config.Fuzzed_code_usage,
   AutomaticallyRouteTo: fm.FuzzProperties.Fuzz_config.Automatically_route_to,
   FuzzOnHaikuDevice:    BoolDefault(fm.FuzzProperties.Fuzz_config.Fuzz_on_haiku_device, true),
   FuzzOnHaikuHost:      BoolDefault(fm.FuzzProperties.Fuzz_config.Fuzz_on_haiku_host, true),
   UsePlatformLibs:      fm.FuzzProperties.Fuzz_config.Use_platform_libs,
   UseForPresubmit:      BoolDefault(fm.FuzzProperties.Fuzz_config.Use_for_presubmit, false),
  }
 }

 android.SetProvider(ctx, FuzzPackagedModuleInfoProvider, info)
}

func GetFramework(ctx android.LoadHookContext, lang Lang) Framework {
 framework := ctx.Config().Getenv("FUZZ_FRAMEWORK")

 if lang == Cc {
  switch strings.ToLower(framework) {
  case "":
   return LibFuzzer
  case "libfuzzer":
   return LibFuzzer
  case "afl":
   return AFL
  }
 } else if lang == Rust {
  return LibFuzzer
 } else if lang == Java {
  return Jazzer
 }

 ctx.ModuleErrorf(fmt.Sprintf("%s is not a valid fuzzing framework for %s", framework, lang))
 return UnknownFramework
}

func IsValidFrameworkForModule(targetFramework Framework, lang Lang, moduleFrameworks *FuzzFrameworks) bool {
 if targetFramework == UnknownFramework {
  return false
 }

 if moduleFrameworks == nil {
  return true
 }

 switch targetFramework {
 case LibFuzzer:
  return proptools.BoolDefault(moduleFrameworks.Libfuzzer, true)
 case AFL:
  return proptools.BoolDefault(moduleFrameworks.Afl, true)
 case Jazzer:
  return proptools.BoolDefault(moduleFrameworks.Jazzer, true)
 default:
  panic("%s is not supported as a fuzz framework")
 }
}

func IsValid(ctx android.ConfigurableEvaluatorContext, fuzzModule FuzzModule) bool {
 // Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of
 // fuzz targets we're going to package anyway.
 if !fuzzModule.Enabled(ctx) || fuzzModule.InRamdisk() || fuzzModule.InVendorRamdisk() || fuzzModule.InRecovery() {
  return false
 }

 // Discard modules that are in an unavailable namespace.
 if !fuzzModule.ExportedToMake() {
  return false
 }

 return true
}

// TODO(b/397766191): Change the signature to take ModuleProxy
// Please only access the module's internal data through providers.
func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.ModuleProxy, fuzzModule *FuzzPackagedModuleInfo, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip {
 // Package the corpora into a zipfile.
 var files []FileToZip
 if len(fuzzModule.Corpus) > 0 {
  corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
  command := builder.Command().BuiltTool("soong_zip").
   Flag("-j").
   FlagWithOutput("-o ", corpusZip)
  rspFile := corpusZip.ReplaceExtension(ctx, "rsp")
  command.FlagWithRspFileInputList("-r ", rspFile, fuzzModule.Corpus)
  files = append(files, FileToZip{SourceFilePath: corpusZip})
 }

 // Package the data into a zipfile.
 if len(fuzzModule.Data) > 0 {
  dataZip := archDir.Join(ctx, module.Name()+"_data.zip")
  command := builder.Command().BuiltTool("soong_zip").
   FlagWithOutput("-o ", dataZip)
  for _, f := range fuzzModule.Data {
   intermediateDir := strings.TrimSuffix(f.String(), f.Rel())
   command.FlagWithArg("-C ", intermediateDir)
   command.FlagWithInput("-f ", f)
  }
  files = append(files, FileToZip{SourceFilePath: dataZip})
 }

 // The dictionary.
 if fuzzModule.Dictionary != nil {
  files = append(files, FileToZip{SourceFilePath: fuzzModule.Dictionary})
 }

 // Additional fuzz config.
 if fuzzModule.Config != nil && IsValidConfig(fuzzModule, module.Name()) {
  files = append(files, FileToZip{SourceFilePath: fuzzModule.Config})
 }

 return files
}

func (s *FuzzPackager) BuildZipFile(ctx android.SingletonContext, module android.ModuleProxy, fuzzModule *FuzzPackagedModuleInfo, files []FileToZip, builder *android.RuleBuilder, archDir android.OutputPath, archString string, hostOrTargetString string, archOs ArchOs, archDirs map[ArchOs][]FileToZip) ([]FileToZip, bool) {
 fuzzZip := archDir.Join(ctx, ctx.ModuleDir(module), module.Name()+".zip")

 command := builder.Command().BuiltTool("soong_zip").
  Flag("-j").
  FlagWithOutput("-o ", fuzzZip)

 for _, file := range files {
  if file.DestinationPathPrefix != "" {
   command.FlagWithArg("-P ", file.DestinationPathPrefix)
  } else {
   command.Flag("-P ''")
  }
  if file.DestinationPath != "" {
   command.FlagWithArg("-e ", file.DestinationPath)
  }
  command.FlagWithInput("-f ", file.SourceFilePath)
 }

 builder.Build("create-"+fuzzZip.String(),
  "Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)

 if config := fuzzModule.FuzzConfig; config != nil {
  if strings.Contains(hostOrTargetString, "host") && !config.FuzzOnHaikuHost {
   return archDirs[archOs], false
  } else if !strings.Contains(hostOrTargetString, "host") && !config.FuzzOnHaikuDevice {
   return archDirs[archOs], false
  }
 }

 s.FuzzTargets[module.Name()] = true
 archDirs[archOs] = append(archDirs[archOs], FileToZip{SourceFilePath: fuzzZip})

 return archDirs[archOs], true
}

func (f *FuzzConfig) String() string {
 b, err := json.Marshal(f)
 if err != nil {
  panic(err)
 }

 return string(b)
}

func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, fuzzType Lang, pctx android.PackageContext) {
 var archOsList []ArchOs
 for archOs := range archDirs {
  archOsList = append(archOsList, archOs)
 }
 sort.Slice(archOsList, func(i, j int) bool { return archOsList[i].Dir < archOsList[j].Dir })

 for _, archOs := range archOsList {
  filesToZip := archDirs[archOs]
  arch := archOs.Arch
  hostOrTarget := archOs.HostOrTarget
  builder := android.NewRuleBuilder(pctx, ctx).SandboxDisabled()
  zipFileName := "fuzz-" + hostOrTarget + "-" + arch + ".zip"
  if fuzzType == Rust {
   zipFileName = "fuzz-rust-" + hostOrTarget + "-" + arch + ".zip"
  }
  if fuzzType == Java {
   zipFileName = "fuzz-java-" + hostOrTarget + "-" + arch + ".zip"
  }

  outputFile := android.PathForOutput(ctx, zipFileName)

  s.Packages = append(s.Packages, outputFile)

  command := builder.Command().BuiltTool("soong_zip").
   Flag("-j").
   FlagWithOutput("-o ", outputFile).
   Flag("-L 0") // No need to try and re-compress the zipfiles.

  for _, fileToZip := range filesToZip {
   if fileToZip.DestinationPathPrefix != "" {
    command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
   } else {
    command.Flag("-P ''")
   }
   command.FlagWithInput("-f ", fileToZip.SourceFilePath)

  }
  builder.Build("create-fuzz-package-"+arch+"-"+hostOrTarget,
   "Create fuzz target packages for "+arch+"-"+hostOrTarget)
 }
}

func (s *FuzzPackager) PreallocateSlice(ctx android.MakeVarsContext, targets string) {
 fuzzTargets := make([]string, 0, len(s.FuzzTargets))
 for target, _ := range s.FuzzTargets {
  fuzzTargets = append(fuzzTargets, target)
 }

 sort.Strings(fuzzTargets)
 ctx.Strict(targets, strings.Join(fuzzTargets, " "))
}

[Dauer der Verarbeitung: 0.23 Sekunden, vorverarbeitet 2026-06-28]