blob: 306d65e29a24ed1b0fff3719baa6ad153908c14f [file] [log] [blame]
hamzeh41ad8812021-07-07 14:00:07 -07001// Copyright 2021 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
hamzehc0a671f2021-07-22 12:05:08 -070015package fuzz
hamzeh41ad8812021-07-07 14:00:07 -070016
17// This file contains the common code for compiling C/C++ and Rust fuzzers for Android.
18
19import (
hamzehc0a671f2021-07-22 12:05:08 -070020 "encoding/json"
hamzehe8a1bfa2022-06-21 12:22:06 -070021 "fmt"
hamzeh41ad8812021-07-07 14:00:07 -070022 "sort"
23 "strings"
24
hamzehc0a671f2021-07-22 12:05:08 -070025 "github.com/google/blueprint/proptools"
26
hamzeh41ad8812021-07-07 14:00:07 -070027 "android/soong/android"
28)
29
Cory Barker9cfcf6d2022-07-22 17:22:02 +000030type Lang string
hamzeh41ad8812021-07-07 14:00:07 -070031
32const (
Cory Barker9cfcf6d2022-07-22 17:22:02 +000033 Cc Lang = "cc"
34 Rust Lang = "rust"
35 Java Lang = "java"
36)
37
38type Framework string
39
40const (
41 AFL Framework = "afl"
42 LibFuzzer Framework = "libfuzzer"
43 Jazzer Framework = "jazzer"
44 UnknownFramework Framework = "unknownframework"
hamzeh41ad8812021-07-07 14:00:07 -070045)
46
hamzehc0a671f2021-07-22 12:05:08 -070047var BoolDefault = proptools.BoolDefault
48
hamzeh41ad8812021-07-07 14:00:07 -070049type FuzzModule struct {
50 android.ModuleBase
51 android.DefaultableModuleBase
52 android.ApexModuleBase
53}
54
55type FuzzPackager struct {
Ivan Lozano39b0bf02021-10-14 12:22:09 -040056 Packages android.Paths
57 FuzzTargets map[string]bool
58 SharedLibInstallStrings []string
hamzeh41ad8812021-07-07 14:00:07 -070059}
60
61type FileToZip struct {
62 SourceFilePath android.Path
63 DestinationPathPrefix string
Colin Cross80462dc2023-05-08 15:09:31 -070064 DestinationPath string
hamzeh41ad8812021-07-07 14:00:07 -070065}
66
67type ArchOs struct {
68 HostOrTarget string
69 Arch string
70 Dir string
71}
72
hamzeheea256b2023-02-09 13:22:09 -080073type Vector string
hamzehe8a1bfa2022-06-21 12:22:06 -070074
75const (
hamzeheea256b2023-02-09 13:22:09 -080076 unknown_access_vector Vector = "unknown_access_vector"
77 // The code being fuzzed is reachable from a remote source, or using data
78 // provided by a remote source. For example: media codecs process media files
79 // from the internet, SMS processing handles remote message data.
80 // See
81 // https://source.android.com/docs/security/overview/updates-resources#local-vs-remote
82 // for an explanation of what's considered "remote."
83 remote = "remote"
84 // The code being fuzzed can only be reached locally, such as from an
85 // installed app. As an example, if it's fuzzing a Binder interface, it's
86 // assumed that you'd need a local app to make arbitrary Binder calls.
87 // And the app that's calling the fuzzed code does not require any privileges;
88 // any 3rd party app could make these calls.
89 local_no_privileges_required = "local_no_privileges_required"
90 // The code being fuzzed can only be called locally, and the calling process
91 // requires additional permissions that prevent arbitrary 3rd party apps from
92 // calling the code. For instance: this requires a privileged or signature
93 // permission to reach, or SELinux restrictions prevent the untrusted_app
94 // domain from calling it.
95 local_privileges_required = "local_privileges_required"
96 // The code is only callable on a PC host, not on a production Android device.
97 // For instance, this is fuzzing code used during the build process, or
98 // tooling that does not exist on a user's actual Android device.
99 host_access = "host_access"
100 // The code being fuzzed is only reachable if the user has enabled Developer
101 // Options, or has enabled a persistent Developer Options setting.
102 local_with_developer_options = "local_with_developer_options"
hamzehe8a1bfa2022-06-21 12:22:06 -0700103)
104
hamzeheea256b2023-02-09 13:22:09 -0800105func (vector Vector) isValidVector() bool {
106 switch vector {
107 case "",
108 unknown_access_vector,
109 remote,
110 local_no_privileges_required,
111 local_privileges_required,
112 host_access,
113 local_with_developer_options:
114 return true
115 }
116 return false
117}
118
119type ServicePrivilege string
120
121const (
122 unknown_service_privilege ServicePrivilege = "unknown_service_privilege"
123 // The code being fuzzed runs on a Secure Element. This has access to some
124 // of the most privileged data on the device, such as authentication keys.
125 // Not all devices have a Secure Element.
126 secure_element = "secure_element"
127 // The code being fuzzed runs in the TEE. The TEE is designed to be resistant
128 // to a compromised kernel, and stores sensitive data.
129 trusted_execution = "trusted_execution"
130 // The code being fuzzed has privileges beyond what arbitrary 3rd party apps
131 // have. For instance, it's running as the System UID, or it's in an SELinux
132 // domain that's able to perform calls that can't be made by 3rd party apps.
133 privileged = "privileged"
134 // The code being fuzzed is equivalent to a 3rd party app. It runs in the
135 // untrusted_app SELinux domain, or it only has privileges that are equivalent
136 // to what a 3rd party app could have.
137 unprivileged = "unprivileged"
138 // The code being fuzzed is significantly constrained, and even if it's
139 // compromised, it has significant restrictions that prevent it from
140 // performing most actions. This is significantly more restricted than
141 // UNPRIVILEGED. An example is the isolatedProcess=true setting in a 3rd
142 // party app. Or a process that's very restricted by SELinux, such as
143 // anything in the mediacodec SELinux domain.
144 constrained = "constrained"
145 // The code being fuzzed always has Negligible Security Impact. Even
146 // arbitrary out of bounds writes and full code execution would not be
147 // considered a security vulnerability. This typically only makes sense if
148 // FuzzedCodeUsage is set to FUTURE_VERSION or EXPERIMENTAL, and if
149 // AutomaticallyRouteTo is set to ALWAYS_NSI.
150 nsi = "nsi"
151 // The code being fuzzed only runs on a PC host, not on a production Android
152 // device. For instance, the fuzzer is fuzzing code used during the build
153 // process, or tooling that does not exist on a user's actual Android device.
154 host_only = "host_only"
155)
156
157func (service_privilege ServicePrivilege) isValidServicePrivilege() bool {
158 switch service_privilege {
159 case "",
160 unknown_service_privilege,
161 secure_element,
162 trusted_execution,
163 privileged,
164 unprivileged,
165 constrained,
166 nsi,
167 host_only:
168 return true
169 }
170 return false
171}
172
Markf736b922023-05-08 22:11:44 +0000173type UsePlatformLibs string
174
175const (
176 unknown_use_platform_libs UsePlatformLibs = "unknown_use_platform_libs"
177 // Use the native libraries on the device, typically in /system directory
178 use_platform_libs = "use_platform_libs"
179 // Do not use any native libraries (ART will not be initialized)
180 use_none = "use_none"
181)
182
183func (use_platform_libs UsePlatformLibs) isValidUsePlatformLibs() bool {
184 switch use_platform_libs {
185 case "",
186 unknown_use_platform_libs,
187 use_platform_libs,
188 use_none:
189 return true
190 }
191 return false
192}
193
hamzeheea256b2023-02-09 13:22:09 -0800194type UserData string
195
196const (
197 unknown_user_data UserData = "unknown_user_data"
198 // The process being fuzzed only handles data from a single user, or from a
199 // single process or app. It's possible the process shuts down before
200 // handling data from another user/process/app, or it's possible the process
201 // only ever handles one user's/process's/app's data. As an example, some
202 // print spooler processes are started for a single document and terminate
203 // when done, so each instance only handles data from a single user/app.
204 single_user = "single_user"
205 // The process handles data from multiple users, or from multiple other apps
206 // or processes. Media processes, for instance, can handle media requests
207 // from multiple different apps without restarting. Wi-Fi and network
208 // processes handle data from multiple users, and processes, and apps.
209 multi_user = "multi_user"
210)
211
212func (user_data UserData) isValidUserData() bool {
213 switch user_data {
214 case "",
215 unknown_user_data,
216 single_user,
217 multi_user:
218 return true
219 }
220 return false
221}
222
223type FuzzedCodeUsage string
224
225const (
226 undefined FuzzedCodeUsage = "undefined"
227 unknown = "unknown"
228 // The code being fuzzed exists in a shipped version of Android and runs on
229 // devices in production.
230 shipped = "shipped"
231 // The code being fuzzed is not yet in a shipping version of Android, but it
232 // will be at some point in the future.
233 future_version = "future_version"
234 // The code being fuzzed is not in a shipping version of Android, and there
235 // are no plans to ship it in the future.
236 experimental = "experimental"
237)
238
239func (fuzzed_code_usage FuzzedCodeUsage) isValidFuzzedCodeUsage() bool {
240 switch fuzzed_code_usage {
241 case "",
242 undefined,
243 unknown,
244 shipped,
245 future_version,
246 experimental:
247 return true
248 }
249 return false
250}
251
252type AutomaticallyRouteTo string
253
254const (
255 undefined_routing AutomaticallyRouteTo = "undefined_routing"
256 // Automatically route this to the Android Automotive security team for
257 // assessment.
258 android_automotive = "android_automotive"
259 // This should not be used in fuzzer configurations. It is used internally
260 // by Severity Assigner to flag memory leak reports.
261 memory_leak = "memory_leak"
262 // Route this vulnerability to our Ittiam vendor team for assessment.
263 ittiam = "ittiam"
264 // Reports from this fuzzer are always NSI (see the NSI ServicePrivilegeEnum
265 // value for additional context). It is not possible for this code to ever
266 // have a security vulnerability.
267 always_nsi = "always_nsi"
268 // Route this vulnerability to AIDL team for assessment.
269 aidl = "aidl"
270)
271
272func (automatically_route_to AutomaticallyRouteTo) isValidAutomaticallyRouteTo() bool {
273 switch automatically_route_to {
274 case "",
275 undefined_routing,
276 android_automotive,
277 memory_leak,
278 ittiam,
279 always_nsi,
280 aidl:
281 return true
282 }
283 return false
284}
285
hamzehe8a1bfa2022-06-21 12:22:06 -0700286func IsValidConfig(fuzzModule FuzzPackagedModule, moduleName string) bool {
287 var config = fuzzModule.FuzzProperties.Fuzz_config
288 if config != nil {
hamzeheea256b2023-02-09 13:22:09 -0800289 if !config.Vector.isValidVector() {
290 panic(fmt.Errorf("Invalid vector in fuzz config in %s", moduleName))
hamzehe8a1bfa2022-06-21 12:22:06 -0700291 }
hamzeheea256b2023-02-09 13:22:09 -0800292
293 if !config.Service_privilege.isValidServicePrivilege() {
294 panic(fmt.Errorf("Invalid service_privilege in fuzz config in %s", moduleName))
295 }
296
297 if !config.Users.isValidUserData() {
298 panic(fmt.Errorf("Invalid users (user_data) in fuzz config in %s", moduleName))
299 }
300
301 if !config.Fuzzed_code_usage.isValidFuzzedCodeUsage() {
302 panic(fmt.Errorf("Invalid fuzzed_code_usage in fuzz config in %s", moduleName))
303 }
304
305 if !config.Automatically_route_to.isValidAutomaticallyRouteTo() {
306 panic(fmt.Errorf("Invalid automatically_route_to in fuzz config in %s", moduleName))
307 }
Markf736b922023-05-08 22:11:44 +0000308
309 if !config.Use_platform_libs.isValidUsePlatformLibs() {
310 panic(fmt.Errorf("Invalid use_platform_libs in fuzz config in %s", moduleName))
311 }
hamzehe8a1bfa2022-06-21 12:22:06 -0700312 }
hamzeheea256b2023-02-09 13:22:09 -0800313 return true
hamzehe8a1bfa2022-06-21 12:22:06 -0700314}
315
hamzehc0a671f2021-07-22 12:05:08 -0700316type FuzzConfig struct {
317 // Email address of people to CC on bugs or contact about this fuzz target.
318 Cc []string `json:"cc,omitempty"`
hamzehe8a1bfa2022-06-21 12:22:06 -0700319 // A brief description of what the fuzzed code does.
320 Description string `json:"description,omitempty"`
hamzeheea256b2023-02-09 13:22:09 -0800321 // Whether the code being fuzzed is remotely accessible or requires privileges
322 // to access locally.
323 Vector Vector `json:"vector,omitempty"`
324 // How privileged the service being fuzzed is.
325 Service_privilege ServicePrivilege `json:"service_privilege,omitempty"`
326 // Whether the service being fuzzed handles data from multiple users or only
327 // a single one.
328 Users UserData `json:"users,omitempty"`
329 // Specifies the use state of the code being fuzzed. This state factors into
330 // how an issue is handled.
331 Fuzzed_code_usage FuzzedCodeUsage `json:"fuzzed_code_usage,omitempty"`
332 // Comment describing how we came to these settings for this fuzzer.
333 Config_comment string
334 // Which team to route this to, if it should be routed automatically.
335 Automatically_route_to AutomaticallyRouteTo `json:"automatically_route_to,omitempty"`
hamzehe8a1bfa2022-06-21 12:22:06 -0700336 // Can third party/untrusted apps supply data to fuzzed code.
hamzeh3c983d22022-07-26 14:19:22 -0700337 Untrusted_data *bool `json:"untrusted_data,omitempty"`
Jon Bottarinia0b44cb2022-10-19 03:13:14 +0000338 // When code was released or will be released.
hamzehe8a1bfa2022-06-21 12:22:06 -0700339 Production_date string `json:"production_date,omitempty"`
340 // Prevents critical service functionality like phone calls, bluetooth, etc.
hamzeh3c983d22022-07-26 14:19:22 -0700341 Critical *bool `json:"critical,omitempty"`
hamzehc0a671f2021-07-22 12:05:08 -0700342 // Specify whether to enable continuous fuzzing on devices. Defaults to true.
343 Fuzz_on_haiku_device *bool `json:"fuzz_on_haiku_device,omitempty"`
344 // Specify whether to enable continuous fuzzing on host. Defaults to true.
345 Fuzz_on_haiku_host *bool `json:"fuzz_on_haiku_host,omitempty"`
346 // Component in Google's bug tracking system that bugs should be filed to.
347 Componentid *int64 `json:"componentid,omitempty"`
Jon Bottarinia0b44cb2022-10-19 03:13:14 +0000348 // Hotlist(s) in Google's bug tracking system that bugs should be marked with.
hamzehc0a671f2021-07-22 12:05:08 -0700349 Hotlists []string `json:"hotlists,omitempty"`
350 // Specify whether this fuzz target was submitted by a researcher. Defaults
351 // to false.
352 Researcher_submitted *bool `json:"researcher_submitted,omitempty"`
353 // Specify who should be acknowledged for CVEs in the Android Security
354 // Bulletin.
355 Acknowledgement []string `json:"acknowledgement,omitempty"`
356 // Additional options to be passed to libfuzzer when run in Haiku.
357 Libfuzzer_options []string `json:"libfuzzer_options,omitempty"`
358 // Additional options to be passed to HWASAN when running on-device in Haiku.
359 Hwasan_options []string `json:"hwasan_options,omitempty"`
360 // Additional options to be passed to HWASAN when running on host in Haiku.
361 Asan_options []string `json:"asan_options,omitempty"`
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000362 // If there's a Java fuzzer with JNI, a different version of Jazzer would
363 // need to be added to the fuzzer package than one without JNI
364 IsJni *bool `json:"is_jni,omitempty"`
Mark74c0ad22022-09-30 21:13:01 +0000365 // List of modules for monitoring coverage drops in directories (e.g. "libicu")
366 Target_modules []string `json:"target_modules,omitempty"`
David Fuaf4e33b2023-04-07 12:24:35 -0700367 // Specifies a bug assignee to replace default ISE assignment
David Fu44fc9a82023-04-26 20:25:30 +0000368 Triage_assignee string `json:"triage_assignee,omitempty"`
Markf736b922023-05-08 22:11:44 +0000369 // Specifies libs used to initialize ART (java only, 'use_none' for no initialization)
370 Use_platform_libs UsePlatformLibs `json:"use_platform_libs,omitempty"`
David Fu4ad9bba2023-06-28 21:49:31 +0000371 // Specifies whether fuzz target should check presubmitted code changes for crashes.
372 // Defaults to false.
373 Use_for_presubmit *bool `json:"use_for_presubmit,omitempty"`
Cory Barker24907572023-07-18 21:19:53 +0000374 // Specify which paths to exclude from fuzzing coverage reports
375 Exclude_paths_from_reports []string `json:"exclude_paths_from_reports,omitempty"`
hamzehc0a671f2021-07-22 12:05:08 -0700376}
377
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000378type FuzzFrameworks struct {
379 Afl *bool
380 Libfuzzer *bool
381 Jazzer *bool
382}
383
hamzehc0a671f2021-07-22 12:05:08 -0700384type FuzzProperties struct {
385 // Optional list of seed files to be installed to the fuzz target's output
386 // directory.
387 Corpus []string `android:"path"`
388 // Optional list of data files to be installed to the fuzz target's output
389 // directory. Directory structure relative to the module is preserved.
390 Data []string `android:"path"`
391 // Optional dictionary to be installed to the fuzz target's output directory.
392 Dictionary *string `android:"path"`
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000393 // Define the fuzzing frameworks this fuzz target can be built for. If
394 // empty then the fuzz target will be available to be built for all fuzz
395 // frameworks available
396 Fuzzing_frameworks *FuzzFrameworks
hamzehc0a671f2021-07-22 12:05:08 -0700397 // Config for running the target on fuzzing infrastructure.
398 Fuzz_config *FuzzConfig
399}
400
hamzeh41ad8812021-07-07 14:00:07 -0700401type FuzzPackagedModule struct {
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800402 FuzzProperties FuzzProperties
403 Dictionary android.Path
404 Corpus android.Paths
405 Config android.Path
406 Data android.Paths
hamzeh41ad8812021-07-07 14:00:07 -0700407}
408
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000409func GetFramework(ctx android.LoadHookContext, lang Lang) Framework {
410 framework := ctx.Config().Getenv("FUZZ_FRAMEWORK")
411
412 if lang == Cc {
413 switch strings.ToLower(framework) {
414 case "":
415 return LibFuzzer
416 case "libfuzzer":
417 return LibFuzzer
418 case "afl":
419 return AFL
420 }
421 } else if lang == Rust {
422 return LibFuzzer
423 } else if lang == Java {
424 return Jazzer
425 }
426
427 ctx.ModuleErrorf(fmt.Sprintf("%s is not a valid fuzzing framework for %s", framework, lang))
428 return UnknownFramework
429}
430
431func IsValidFrameworkForModule(targetFramework Framework, lang Lang, moduleFrameworks *FuzzFrameworks) bool {
432 if targetFramework == UnknownFramework {
433 return false
434 }
435
436 if moduleFrameworks == nil {
437 return true
438 }
439
440 switch targetFramework {
441 case LibFuzzer:
442 return proptools.BoolDefault(moduleFrameworks.Libfuzzer, true)
443 case AFL:
444 return proptools.BoolDefault(moduleFrameworks.Afl, true)
445 case Jazzer:
446 return proptools.BoolDefault(moduleFrameworks.Jazzer, true)
447 default:
448 panic("%s is not supported as a fuzz framework")
449 }
450}
451
Cole Faust021bf3d2024-05-01 16:59:00 -0700452func IsValid(ctx android.ConfigAndErrorContext, fuzzModule FuzzModule) bool {
hamzeh41ad8812021-07-07 14:00:07 -0700453 // Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of
454 // fuzz targets we're going to package anyway.
Cole Faust021bf3d2024-05-01 16:59:00 -0700455 if !fuzzModule.Enabled(ctx) || fuzzModule.InRamdisk() || fuzzModule.InVendorRamdisk() || fuzzModule.InRecovery() {
hamzeh41ad8812021-07-07 14:00:07 -0700456 return false
457 }
458
459 // Discard modules that are in an unavailable namespace.
460 if !fuzzModule.ExportedToMake() {
461 return false
462 }
463
464 return true
465}
466
467func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.Module, fuzzModule FuzzPackagedModule, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip {
468 // Package the corpora into a zipfile.
469 var files []FileToZip
470 if fuzzModule.Corpus != nil {
471 corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
472 command := builder.Command().BuiltTool("soong_zip").
473 Flag("-j").
474 FlagWithOutput("-o ", corpusZip)
475 rspFile := corpusZip.ReplaceExtension(ctx, "rsp")
476 command.FlagWithRspFileInputList("-r ", rspFile, fuzzModule.Corpus)
Colin Cross80462dc2023-05-08 15:09:31 -0700477 files = append(files, FileToZip{SourceFilePath: corpusZip})
hamzeh41ad8812021-07-07 14:00:07 -0700478 }
479
480 // Package the data into a zipfile.
481 if fuzzModule.Data != nil {
482 dataZip := archDir.Join(ctx, module.Name()+"_data.zip")
483 command := builder.Command().BuiltTool("soong_zip").
484 FlagWithOutput("-o ", dataZip)
485 for _, f := range fuzzModule.Data {
486 intermediateDir := strings.TrimSuffix(f.String(), f.Rel())
487 command.FlagWithArg("-C ", intermediateDir)
488 command.FlagWithInput("-f ", f)
489 }
Colin Cross80462dc2023-05-08 15:09:31 -0700490 files = append(files, FileToZip{SourceFilePath: dataZip})
hamzeh41ad8812021-07-07 14:00:07 -0700491 }
492
493 // The dictionary.
494 if fuzzModule.Dictionary != nil {
Colin Cross80462dc2023-05-08 15:09:31 -0700495 files = append(files, FileToZip{SourceFilePath: fuzzModule.Dictionary})
hamzeh41ad8812021-07-07 14:00:07 -0700496 }
497
498 // Additional fuzz config.
hamzehe8a1bfa2022-06-21 12:22:06 -0700499 if fuzzModule.Config != nil && IsValidConfig(fuzzModule, module.Name()) {
Colin Cross80462dc2023-05-08 15:09:31 -0700500 files = append(files, FileToZip{SourceFilePath: fuzzModule.Config})
hamzeh41ad8812021-07-07 14:00:07 -0700501 }
502
503 return files
504}
505
506func (s *FuzzPackager) BuildZipFile(ctx android.SingletonContext, module android.Module, fuzzModule FuzzPackagedModule, files []FileToZip, builder *android.RuleBuilder, archDir android.OutputPath, archString string, hostOrTargetString string, archOs ArchOs, archDirs map[ArchOs][]FileToZip) ([]FileToZip, bool) {
507 fuzzZip := archDir.Join(ctx, module.Name()+".zip")
508
509 command := builder.Command().BuiltTool("soong_zip").
510 Flag("-j").
511 FlagWithOutput("-o ", fuzzZip)
512
513 for _, file := range files {
514 if file.DestinationPathPrefix != "" {
515 command.FlagWithArg("-P ", file.DestinationPathPrefix)
516 } else {
517 command.Flag("-P ''")
518 }
Colin Cross80462dc2023-05-08 15:09:31 -0700519 if file.DestinationPath != "" {
520 command.FlagWithArg("-e ", file.DestinationPath)
521 }
hamzeh41ad8812021-07-07 14:00:07 -0700522 command.FlagWithInput("-f ", file.SourceFilePath)
523 }
524
525 builder.Build("create-"+fuzzZip.String(),
526 "Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
527
hamzeh41ad8812021-07-07 14:00:07 -0700528 if config := fuzzModule.FuzzProperties.Fuzz_config; config != nil {
529 if strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_host, true) {
530 return archDirs[archOs], false
hamzeh65dd2c32023-12-27 15:27:12 -0800531 } else if !strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_device, true) {
hamzeh41ad8812021-07-07 14:00:07 -0700532 return archDirs[archOs], false
533 }
534 }
535
536 s.FuzzTargets[module.Name()] = true
Colin Cross80462dc2023-05-08 15:09:31 -0700537 archDirs[archOs] = append(archDirs[archOs], FileToZip{SourceFilePath: fuzzZip})
hamzeh41ad8812021-07-07 14:00:07 -0700538
539 return archDirs[archOs], true
540}
541
hamzehc0a671f2021-07-22 12:05:08 -0700542func (f *FuzzConfig) String() string {
543 b, err := json.Marshal(f)
544 if err != nil {
545 panic(err)
546 }
547
548 return string(b)
549}
550
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000551func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, fuzzType Lang, pctx android.PackageContext) {
hamzeh41ad8812021-07-07 14:00:07 -0700552 var archOsList []ArchOs
553 for archOs := range archDirs {
554 archOsList = append(archOsList, archOs)
555 }
556 sort.Slice(archOsList, func(i, j int) bool { return archOsList[i].Dir < archOsList[j].Dir })
557
558 for _, archOs := range archOsList {
559 filesToZip := archDirs[archOs]
560 arch := archOs.Arch
561 hostOrTarget := archOs.HostOrTarget
562 builder := android.NewRuleBuilder(pctx, ctx)
563 zipFileName := "fuzz-" + hostOrTarget + "-" + arch + ".zip"
Cory Barkera1da26f2022-06-07 20:12:06 +0000564 if fuzzType == Rust {
hamzeh41ad8812021-07-07 14:00:07 -0700565 zipFileName = "fuzz-rust-" + hostOrTarget + "-" + arch + ".zip"
566 }
Cory Barkera1da26f2022-06-07 20:12:06 +0000567 if fuzzType == Java {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000568 zipFileName = "fuzz-java-" + hostOrTarget + "-" + arch + ".zip"
569 }
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000570
hamzeh41ad8812021-07-07 14:00:07 -0700571 outputFile := android.PathForOutput(ctx, zipFileName)
572
573 s.Packages = append(s.Packages, outputFile)
574
575 command := builder.Command().BuiltTool("soong_zip").
576 Flag("-j").
577 FlagWithOutput("-o ", outputFile).
578 Flag("-L 0") // No need to try and re-compress the zipfiles.
579
580 for _, fileToZip := range filesToZip {
hamzeh41ad8812021-07-07 14:00:07 -0700581 if fileToZip.DestinationPathPrefix != "" {
582 command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
583 } else {
584 command.Flag("-P ''")
585 }
586 command.FlagWithInput("-f ", fileToZip.SourceFilePath)
587
588 }
589 builder.Build("create-fuzz-package-"+arch+"-"+hostOrTarget,
590 "Create fuzz target packages for "+arch+"-"+hostOrTarget)
591 }
592}
593
594func (s *FuzzPackager) PreallocateSlice(ctx android.MakeVarsContext, targets string) {
595 fuzzTargets := make([]string, 0, len(s.FuzzTargets))
596 for target, _ := range s.FuzzTargets {
597 fuzzTargets = append(fuzzTargets, target)
598 }
Cory Barkera1da26f2022-06-07 20:12:06 +0000599
hamzeh41ad8812021-07-07 14:00:07 -0700600 sort.Strings(fuzzTargets)
601 ctx.Strict(targets, strings.Join(fuzzTargets, " "))
602}