blob: 42fd228863c2455affeecf3b89b99bc6f14f23b9 [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
Colin Cross597bad62024-10-08 15:10:55 -070047func (f Framework) Variant() string {
48 switch f {
49 case AFL:
50 return "afl"
51 case LibFuzzer:
52 return "libfuzzer"
53 case Jazzer:
54 return "jazzer"
55 default:
56 panic(fmt.Errorf("unknown fuzzer %q when getting variant", f))
57 }
58}
59
60func FrameworkFromVariant(v string) Framework {
61 switch v {
62 case "afl":
63 return AFL
64 case "libfuzzer":
65 return LibFuzzer
66 case "jazzer":
67 return Jazzer
68 default:
69 panic(fmt.Errorf("unknown variant %q when getting fuzzer", v))
70 }
71}
72
hamzehc0a671f2021-07-22 12:05:08 -070073var BoolDefault = proptools.BoolDefault
74
hamzeh41ad8812021-07-07 14:00:07 -070075type FuzzModule struct {
76 android.ModuleBase
77 android.DefaultableModuleBase
78 android.ApexModuleBase
79}
80
81type FuzzPackager struct {
Ivan Lozano39b0bf02021-10-14 12:22:09 -040082 Packages android.Paths
83 FuzzTargets map[string]bool
84 SharedLibInstallStrings []string
hamzeh41ad8812021-07-07 14:00:07 -070085}
86
87type FileToZip struct {
88 SourceFilePath android.Path
89 DestinationPathPrefix string
Colin Cross80462dc2023-05-08 15:09:31 -070090 DestinationPath string
hamzeh41ad8812021-07-07 14:00:07 -070091}
92
93type ArchOs struct {
94 HostOrTarget string
95 Arch string
96 Dir string
97}
98
hamzeheea256b2023-02-09 13:22:09 -080099type Vector string
hamzehe8a1bfa2022-06-21 12:22:06 -0700100
101const (
hamzeheea256b2023-02-09 13:22:09 -0800102 unknown_access_vector Vector = "unknown_access_vector"
103 // The code being fuzzed is reachable from a remote source, or using data
104 // provided by a remote source. For example: media codecs process media files
105 // from the internet, SMS processing handles remote message data.
106 // See
107 // https://source.android.com/docs/security/overview/updates-resources#local-vs-remote
108 // for an explanation of what's considered "remote."
109 remote = "remote"
110 // The code being fuzzed can only be reached locally, such as from an
111 // installed app. As an example, if it's fuzzing a Binder interface, it's
112 // assumed that you'd need a local app to make arbitrary Binder calls.
113 // And the app that's calling the fuzzed code does not require any privileges;
114 // any 3rd party app could make these calls.
115 local_no_privileges_required = "local_no_privileges_required"
116 // The code being fuzzed can only be called locally, and the calling process
117 // requires additional permissions that prevent arbitrary 3rd party apps from
118 // calling the code. For instance: this requires a privileged or signature
119 // permission to reach, or SELinux restrictions prevent the untrusted_app
120 // domain from calling it.
121 local_privileges_required = "local_privileges_required"
122 // The code is only callable on a PC host, not on a production Android device.
123 // For instance, this is fuzzing code used during the build process, or
124 // tooling that does not exist on a user's actual Android device.
125 host_access = "host_access"
126 // The code being fuzzed is only reachable if the user has enabled Developer
127 // Options, or has enabled a persistent Developer Options setting.
128 local_with_developer_options = "local_with_developer_options"
hamzehe8a1bfa2022-06-21 12:22:06 -0700129)
130
hamzeheea256b2023-02-09 13:22:09 -0800131func (vector Vector) isValidVector() bool {
132 switch vector {
133 case "",
134 unknown_access_vector,
135 remote,
136 local_no_privileges_required,
137 local_privileges_required,
138 host_access,
139 local_with_developer_options:
140 return true
141 }
142 return false
143}
144
145type ServicePrivilege string
146
147const (
148 unknown_service_privilege ServicePrivilege = "unknown_service_privilege"
149 // The code being fuzzed runs on a Secure Element. This has access to some
150 // of the most privileged data on the device, such as authentication keys.
151 // Not all devices have a Secure Element.
152 secure_element = "secure_element"
153 // The code being fuzzed runs in the TEE. The TEE is designed to be resistant
154 // to a compromised kernel, and stores sensitive data.
155 trusted_execution = "trusted_execution"
156 // The code being fuzzed has privileges beyond what arbitrary 3rd party apps
157 // have. For instance, it's running as the System UID, or it's in an SELinux
158 // domain that's able to perform calls that can't be made by 3rd party apps.
159 privileged = "privileged"
160 // The code being fuzzed is equivalent to a 3rd party app. It runs in the
161 // untrusted_app SELinux domain, or it only has privileges that are equivalent
162 // to what a 3rd party app could have.
163 unprivileged = "unprivileged"
164 // The code being fuzzed is significantly constrained, and even if it's
165 // compromised, it has significant restrictions that prevent it from
166 // performing most actions. This is significantly more restricted than
167 // UNPRIVILEGED. An example is the isolatedProcess=true setting in a 3rd
168 // party app. Or a process that's very restricted by SELinux, such as
169 // anything in the mediacodec SELinux domain.
170 constrained = "constrained"
171 // The code being fuzzed always has Negligible Security Impact. Even
172 // arbitrary out of bounds writes and full code execution would not be
173 // considered a security vulnerability. This typically only makes sense if
174 // FuzzedCodeUsage is set to FUTURE_VERSION or EXPERIMENTAL, and if
175 // AutomaticallyRouteTo is set to ALWAYS_NSI.
176 nsi = "nsi"
177 // The code being fuzzed only runs on a PC host, not on a production Android
178 // device. For instance, the fuzzer is fuzzing code used during the build
179 // process, or tooling that does not exist on a user's actual Android device.
180 host_only = "host_only"
181)
182
183func (service_privilege ServicePrivilege) isValidServicePrivilege() bool {
184 switch service_privilege {
185 case "",
186 unknown_service_privilege,
187 secure_element,
188 trusted_execution,
189 privileged,
190 unprivileged,
191 constrained,
192 nsi,
193 host_only:
194 return true
195 }
196 return false
197}
198
Markf736b922023-05-08 22:11:44 +0000199type UsePlatformLibs string
200
201const (
202 unknown_use_platform_libs UsePlatformLibs = "unknown_use_platform_libs"
203 // Use the native libraries on the device, typically in /system directory
204 use_platform_libs = "use_platform_libs"
205 // Do not use any native libraries (ART will not be initialized)
206 use_none = "use_none"
207)
208
209func (use_platform_libs UsePlatformLibs) isValidUsePlatformLibs() bool {
210 switch use_platform_libs {
211 case "",
212 unknown_use_platform_libs,
213 use_platform_libs,
214 use_none:
215 return true
216 }
217 return false
218}
219
hamzeheea256b2023-02-09 13:22:09 -0800220type UserData string
221
222const (
223 unknown_user_data UserData = "unknown_user_data"
224 // The process being fuzzed only handles data from a single user, or from a
225 // single process or app. It's possible the process shuts down before
226 // handling data from another user/process/app, or it's possible the process
227 // only ever handles one user's/process's/app's data. As an example, some
228 // print spooler processes are started for a single document and terminate
229 // when done, so each instance only handles data from a single user/app.
230 single_user = "single_user"
231 // The process handles data from multiple users, or from multiple other apps
232 // or processes. Media processes, for instance, can handle media requests
233 // from multiple different apps without restarting. Wi-Fi and network
234 // processes handle data from multiple users, and processes, and apps.
235 multi_user = "multi_user"
236)
237
238func (user_data UserData) isValidUserData() bool {
239 switch user_data {
240 case "",
241 unknown_user_data,
242 single_user,
243 multi_user:
244 return true
245 }
246 return false
247}
248
249type FuzzedCodeUsage string
250
251const (
252 undefined FuzzedCodeUsage = "undefined"
253 unknown = "unknown"
254 // The code being fuzzed exists in a shipped version of Android and runs on
255 // devices in production.
256 shipped = "shipped"
257 // The code being fuzzed is not yet in a shipping version of Android, but it
258 // will be at some point in the future.
259 future_version = "future_version"
260 // The code being fuzzed is not in a shipping version of Android, and there
261 // are no plans to ship it in the future.
262 experimental = "experimental"
263)
264
265func (fuzzed_code_usage FuzzedCodeUsage) isValidFuzzedCodeUsage() bool {
266 switch fuzzed_code_usage {
267 case "",
268 undefined,
269 unknown,
270 shipped,
271 future_version,
272 experimental:
273 return true
274 }
275 return false
276}
277
278type AutomaticallyRouteTo string
279
280const (
281 undefined_routing AutomaticallyRouteTo = "undefined_routing"
282 // Automatically route this to the Android Automotive security team for
283 // assessment.
284 android_automotive = "android_automotive"
285 // This should not be used in fuzzer configurations. It is used internally
286 // by Severity Assigner to flag memory leak reports.
287 memory_leak = "memory_leak"
288 // Route this vulnerability to our Ittiam vendor team for assessment.
289 ittiam = "ittiam"
290 // Reports from this fuzzer are always NSI (see the NSI ServicePrivilegeEnum
291 // value for additional context). It is not possible for this code to ever
292 // have a security vulnerability.
293 always_nsi = "always_nsi"
294 // Route this vulnerability to AIDL team for assessment.
295 aidl = "aidl"
296)
297
298func (automatically_route_to AutomaticallyRouteTo) isValidAutomaticallyRouteTo() bool {
299 switch automatically_route_to {
300 case "",
301 undefined_routing,
302 android_automotive,
303 memory_leak,
304 ittiam,
305 always_nsi,
306 aidl:
307 return true
308 }
309 return false
310}
311
hamzehe8a1bfa2022-06-21 12:22:06 -0700312func IsValidConfig(fuzzModule FuzzPackagedModule, moduleName string) bool {
313 var config = fuzzModule.FuzzProperties.Fuzz_config
314 if config != nil {
hamzeheea256b2023-02-09 13:22:09 -0800315 if !config.Vector.isValidVector() {
316 panic(fmt.Errorf("Invalid vector in fuzz config in %s", moduleName))
hamzehe8a1bfa2022-06-21 12:22:06 -0700317 }
hamzeheea256b2023-02-09 13:22:09 -0800318
319 if !config.Service_privilege.isValidServicePrivilege() {
320 panic(fmt.Errorf("Invalid service_privilege in fuzz config in %s", moduleName))
321 }
322
323 if !config.Users.isValidUserData() {
324 panic(fmt.Errorf("Invalid users (user_data) in fuzz config in %s", moduleName))
325 }
326
327 if !config.Fuzzed_code_usage.isValidFuzzedCodeUsage() {
328 panic(fmt.Errorf("Invalid fuzzed_code_usage in fuzz config in %s", moduleName))
329 }
330
331 if !config.Automatically_route_to.isValidAutomaticallyRouteTo() {
332 panic(fmt.Errorf("Invalid automatically_route_to in fuzz config in %s", moduleName))
333 }
Markf736b922023-05-08 22:11:44 +0000334
335 if !config.Use_platform_libs.isValidUsePlatformLibs() {
336 panic(fmt.Errorf("Invalid use_platform_libs in fuzz config in %s", moduleName))
337 }
hamzehe8a1bfa2022-06-21 12:22:06 -0700338 }
hamzeheea256b2023-02-09 13:22:09 -0800339 return true
hamzehe8a1bfa2022-06-21 12:22:06 -0700340}
341
hamzehc0a671f2021-07-22 12:05:08 -0700342type FuzzConfig struct {
343 // Email address of people to CC on bugs or contact about this fuzz target.
344 Cc []string `json:"cc,omitempty"`
hamzehe8a1bfa2022-06-21 12:22:06 -0700345 // A brief description of what the fuzzed code does.
346 Description string `json:"description,omitempty"`
hamzeheea256b2023-02-09 13:22:09 -0800347 // Whether the code being fuzzed is remotely accessible or requires privileges
348 // to access locally.
349 Vector Vector `json:"vector,omitempty"`
350 // How privileged the service being fuzzed is.
351 Service_privilege ServicePrivilege `json:"service_privilege,omitempty"`
352 // Whether the service being fuzzed handles data from multiple users or only
353 // a single one.
354 Users UserData `json:"users,omitempty"`
355 // Specifies the use state of the code being fuzzed. This state factors into
356 // how an issue is handled.
357 Fuzzed_code_usage FuzzedCodeUsage `json:"fuzzed_code_usage,omitempty"`
358 // Comment describing how we came to these settings for this fuzzer.
359 Config_comment string
360 // Which team to route this to, if it should be routed automatically.
361 Automatically_route_to AutomaticallyRouteTo `json:"automatically_route_to,omitempty"`
hamzehe8a1bfa2022-06-21 12:22:06 -0700362 // Can third party/untrusted apps supply data to fuzzed code.
hamzeh3c983d22022-07-26 14:19:22 -0700363 Untrusted_data *bool `json:"untrusted_data,omitempty"`
Jon Bottarinia0b44cb2022-10-19 03:13:14 +0000364 // When code was released or will be released.
hamzehe8a1bfa2022-06-21 12:22:06 -0700365 Production_date string `json:"production_date,omitempty"`
366 // Prevents critical service functionality like phone calls, bluetooth, etc.
hamzeh3c983d22022-07-26 14:19:22 -0700367 Critical *bool `json:"critical,omitempty"`
hamzehc0a671f2021-07-22 12:05:08 -0700368 // Specify whether to enable continuous fuzzing on devices. Defaults to true.
369 Fuzz_on_haiku_device *bool `json:"fuzz_on_haiku_device,omitempty"`
370 // Specify whether to enable continuous fuzzing on host. Defaults to true.
371 Fuzz_on_haiku_host *bool `json:"fuzz_on_haiku_host,omitempty"`
372 // Component in Google's bug tracking system that bugs should be filed to.
373 Componentid *int64 `json:"componentid,omitempty"`
Jon Bottarinia0b44cb2022-10-19 03:13:14 +0000374 // Hotlist(s) in Google's bug tracking system that bugs should be marked with.
hamzehc0a671f2021-07-22 12:05:08 -0700375 Hotlists []string `json:"hotlists,omitempty"`
376 // Specify whether this fuzz target was submitted by a researcher. Defaults
377 // to false.
378 Researcher_submitted *bool `json:"researcher_submitted,omitempty"`
379 // Specify who should be acknowledged for CVEs in the Android Security
380 // Bulletin.
381 Acknowledgement []string `json:"acknowledgement,omitempty"`
382 // Additional options to be passed to libfuzzer when run in Haiku.
383 Libfuzzer_options []string `json:"libfuzzer_options,omitempty"`
384 // Additional options to be passed to HWASAN when running on-device in Haiku.
385 Hwasan_options []string `json:"hwasan_options,omitempty"`
386 // Additional options to be passed to HWASAN when running on host in Haiku.
387 Asan_options []string `json:"asan_options,omitempty"`
Muhammad Haseeb Ahmad7e744052022-03-25 22:50:53 +0000388 // If there's a Java fuzzer with JNI, a different version of Jazzer would
389 // need to be added to the fuzzer package than one without JNI
390 IsJni *bool `json:"is_jni,omitempty"`
Mark74c0ad22022-09-30 21:13:01 +0000391 // List of modules for monitoring coverage drops in directories (e.g. "libicu")
392 Target_modules []string `json:"target_modules,omitempty"`
David Fuaf4e33b2023-04-07 12:24:35 -0700393 // Specifies a bug assignee to replace default ISE assignment
David Fu44fc9a82023-04-26 20:25:30 +0000394 Triage_assignee string `json:"triage_assignee,omitempty"`
Markf736b922023-05-08 22:11:44 +0000395 // Specifies libs used to initialize ART (java only, 'use_none' for no initialization)
396 Use_platform_libs UsePlatformLibs `json:"use_platform_libs,omitempty"`
David Fu4ad9bba2023-06-28 21:49:31 +0000397 // Specifies whether fuzz target should check presubmitted code changes for crashes.
398 // Defaults to false.
399 Use_for_presubmit *bool `json:"use_for_presubmit,omitempty"`
Cory Barker24907572023-07-18 21:19:53 +0000400 // Specify which paths to exclude from fuzzing coverage reports
401 Exclude_paths_from_reports []string `json:"exclude_paths_from_reports,omitempty"`
hamzehc0a671f2021-07-22 12:05:08 -0700402}
403
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000404type FuzzFrameworks struct {
405 Afl *bool
406 Libfuzzer *bool
407 Jazzer *bool
408}
409
hamzehc0a671f2021-07-22 12:05:08 -0700410type FuzzProperties struct {
411 // Optional list of seed files to be installed to the fuzz target's output
412 // directory.
413 Corpus []string `android:"path"`
414 // Optional list of data files to be installed to the fuzz target's output
415 // directory. Directory structure relative to the module is preserved.
416 Data []string `android:"path"`
417 // Optional dictionary to be installed to the fuzz target's output directory.
418 Dictionary *string `android:"path"`
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000419 // Define the fuzzing frameworks this fuzz target can be built for. If
420 // empty then the fuzz target will be available to be built for all fuzz
421 // frameworks available
422 Fuzzing_frameworks *FuzzFrameworks
hamzehc0a671f2021-07-22 12:05:08 -0700423 // Config for running the target on fuzzing infrastructure.
424 Fuzz_config *FuzzConfig
425}
426
hamzeh41ad8812021-07-07 14:00:07 -0700427type FuzzPackagedModule struct {
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800428 FuzzProperties FuzzProperties
429 Dictionary android.Path
430 Corpus android.Paths
431 Config android.Path
432 Data android.Paths
hamzeh41ad8812021-07-07 14:00:07 -0700433}
434
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000435func GetFramework(ctx android.LoadHookContext, lang Lang) Framework {
436 framework := ctx.Config().Getenv("FUZZ_FRAMEWORK")
437
438 if lang == Cc {
439 switch strings.ToLower(framework) {
440 case "":
441 return LibFuzzer
442 case "libfuzzer":
443 return LibFuzzer
444 case "afl":
445 return AFL
446 }
447 } else if lang == Rust {
448 return LibFuzzer
449 } else if lang == Java {
450 return Jazzer
451 }
452
453 ctx.ModuleErrorf(fmt.Sprintf("%s is not a valid fuzzing framework for %s", framework, lang))
454 return UnknownFramework
455}
456
457func IsValidFrameworkForModule(targetFramework Framework, lang Lang, moduleFrameworks *FuzzFrameworks) bool {
458 if targetFramework == UnknownFramework {
459 return false
460 }
461
462 if moduleFrameworks == nil {
463 return true
464 }
465
466 switch targetFramework {
467 case LibFuzzer:
468 return proptools.BoolDefault(moduleFrameworks.Libfuzzer, true)
469 case AFL:
470 return proptools.BoolDefault(moduleFrameworks.Afl, true)
471 case Jazzer:
472 return proptools.BoolDefault(moduleFrameworks.Jazzer, true)
473 default:
474 panic("%s is not supported as a fuzz framework")
475 }
476}
477
Cole Fauste8a87832024-09-11 11:35:46 -0700478func IsValid(ctx android.ConfigurableEvaluatorContext, fuzzModule FuzzModule) bool {
hamzeh41ad8812021-07-07 14:00:07 -0700479 // Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of
480 // fuzz targets we're going to package anyway.
Cole Fausta963b942024-04-11 17:43:00 -0700481 if !fuzzModule.Enabled(ctx) || fuzzModule.InRamdisk() || fuzzModule.InVendorRamdisk() || fuzzModule.InRecovery() {
hamzeh41ad8812021-07-07 14:00:07 -0700482 return false
483 }
484
485 // Discard modules that are in an unavailable namespace.
486 if !fuzzModule.ExportedToMake() {
487 return false
488 }
489
490 return true
491}
492
493func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.Module, fuzzModule FuzzPackagedModule, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip {
494 // Package the corpora into a zipfile.
495 var files []FileToZip
496 if fuzzModule.Corpus != nil {
497 corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
498 command := builder.Command().BuiltTool("soong_zip").
499 Flag("-j").
500 FlagWithOutput("-o ", corpusZip)
501 rspFile := corpusZip.ReplaceExtension(ctx, "rsp")
502 command.FlagWithRspFileInputList("-r ", rspFile, fuzzModule.Corpus)
Colin Cross80462dc2023-05-08 15:09:31 -0700503 files = append(files, FileToZip{SourceFilePath: corpusZip})
hamzeh41ad8812021-07-07 14:00:07 -0700504 }
505
506 // Package the data into a zipfile.
507 if fuzzModule.Data != nil {
508 dataZip := archDir.Join(ctx, module.Name()+"_data.zip")
509 command := builder.Command().BuiltTool("soong_zip").
510 FlagWithOutput("-o ", dataZip)
511 for _, f := range fuzzModule.Data {
512 intermediateDir := strings.TrimSuffix(f.String(), f.Rel())
513 command.FlagWithArg("-C ", intermediateDir)
514 command.FlagWithInput("-f ", f)
515 }
Colin Cross80462dc2023-05-08 15:09:31 -0700516 files = append(files, FileToZip{SourceFilePath: dataZip})
hamzeh41ad8812021-07-07 14:00:07 -0700517 }
518
519 // The dictionary.
520 if fuzzModule.Dictionary != nil {
Colin Cross80462dc2023-05-08 15:09:31 -0700521 files = append(files, FileToZip{SourceFilePath: fuzzModule.Dictionary})
hamzeh41ad8812021-07-07 14:00:07 -0700522 }
523
524 // Additional fuzz config.
hamzehe8a1bfa2022-06-21 12:22:06 -0700525 if fuzzModule.Config != nil && IsValidConfig(fuzzModule, module.Name()) {
Colin Cross80462dc2023-05-08 15:09:31 -0700526 files = append(files, FileToZip{SourceFilePath: fuzzModule.Config})
hamzeh41ad8812021-07-07 14:00:07 -0700527 }
528
529 return files
530}
531
532func (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) {
533 fuzzZip := archDir.Join(ctx, module.Name()+".zip")
534
535 command := builder.Command().BuiltTool("soong_zip").
536 Flag("-j").
537 FlagWithOutput("-o ", fuzzZip)
538
539 for _, file := range files {
540 if file.DestinationPathPrefix != "" {
541 command.FlagWithArg("-P ", file.DestinationPathPrefix)
542 } else {
543 command.Flag("-P ''")
544 }
Colin Cross80462dc2023-05-08 15:09:31 -0700545 if file.DestinationPath != "" {
546 command.FlagWithArg("-e ", file.DestinationPath)
547 }
hamzeh41ad8812021-07-07 14:00:07 -0700548 command.FlagWithInput("-f ", file.SourceFilePath)
549 }
550
551 builder.Build("create-"+fuzzZip.String(),
552 "Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
553
hamzeh41ad8812021-07-07 14:00:07 -0700554 if config := fuzzModule.FuzzProperties.Fuzz_config; config != nil {
555 if strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_host, true) {
556 return archDirs[archOs], false
hamzeh65dd2c32023-12-27 15:27:12 -0800557 } else if !strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_device, true) {
hamzeh41ad8812021-07-07 14:00:07 -0700558 return archDirs[archOs], false
559 }
560 }
561
562 s.FuzzTargets[module.Name()] = true
Colin Cross80462dc2023-05-08 15:09:31 -0700563 archDirs[archOs] = append(archDirs[archOs], FileToZip{SourceFilePath: fuzzZip})
hamzeh41ad8812021-07-07 14:00:07 -0700564
565 return archDirs[archOs], true
566}
567
hamzehc0a671f2021-07-22 12:05:08 -0700568func (f *FuzzConfig) String() string {
569 b, err := json.Marshal(f)
570 if err != nil {
571 panic(err)
572 }
573
574 return string(b)
575}
576
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000577func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, fuzzType Lang, pctx android.PackageContext) {
hamzeh41ad8812021-07-07 14:00:07 -0700578 var archOsList []ArchOs
579 for archOs := range archDirs {
580 archOsList = append(archOsList, archOs)
581 }
582 sort.Slice(archOsList, func(i, j int) bool { return archOsList[i].Dir < archOsList[j].Dir })
583
584 for _, archOs := range archOsList {
585 filesToZip := archDirs[archOs]
586 arch := archOs.Arch
587 hostOrTarget := archOs.HostOrTarget
588 builder := android.NewRuleBuilder(pctx, ctx)
589 zipFileName := "fuzz-" + hostOrTarget + "-" + arch + ".zip"
Cory Barkera1da26f2022-06-07 20:12:06 +0000590 if fuzzType == Rust {
hamzeh41ad8812021-07-07 14:00:07 -0700591 zipFileName = "fuzz-rust-" + hostOrTarget + "-" + arch + ".zip"
592 }
Cory Barkera1da26f2022-06-07 20:12:06 +0000593 if fuzzType == Java {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000594 zipFileName = "fuzz-java-" + hostOrTarget + "-" + arch + ".zip"
595 }
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000596
hamzeh41ad8812021-07-07 14:00:07 -0700597 outputFile := android.PathForOutput(ctx, zipFileName)
598
599 s.Packages = append(s.Packages, outputFile)
600
601 command := builder.Command().BuiltTool("soong_zip").
602 Flag("-j").
603 FlagWithOutput("-o ", outputFile).
604 Flag("-L 0") // No need to try and re-compress the zipfiles.
605
606 for _, fileToZip := range filesToZip {
hamzeh41ad8812021-07-07 14:00:07 -0700607 if fileToZip.DestinationPathPrefix != "" {
608 command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
609 } else {
610 command.Flag("-P ''")
611 }
612 command.FlagWithInput("-f ", fileToZip.SourceFilePath)
613
614 }
615 builder.Build("create-fuzz-package-"+arch+"-"+hostOrTarget,
616 "Create fuzz target packages for "+arch+"-"+hostOrTarget)
617 }
618}
619
620func (s *FuzzPackager) PreallocateSlice(ctx android.MakeVarsContext, targets string) {
621 fuzzTargets := make([]string, 0, len(s.FuzzTargets))
622 for target, _ := range s.FuzzTargets {
623 fuzzTargets = append(fuzzTargets, target)
624 }
Cory Barkera1da26f2022-06-07 20:12:06 +0000625
hamzeh41ad8812021-07-07 14:00:07 -0700626 sort.Strings(fuzzTargets)
627 ctx.Strict(targets, strings.Join(fuzzTargets, " "))
628}