blob: aa393a2d56eeb1c6baa71bb6b80946bedbf479c7 [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"`
Cole Faust65cb40a2024-10-21 15:41:42 -0700414
415 // Same as corpus, but adds dependencies on module references using the device's os variant
416 // and the common arch variant.
417 Device_common_corpus []string `android:"path_device_common"`
418
hamzehc0a671f2021-07-22 12:05:08 -0700419 // Optional list of data files to be installed to the fuzz target's output
420 // directory. Directory structure relative to the module is preserved.
421 Data []string `android:"path"`
422 // Optional dictionary to be installed to the fuzz target's output directory.
423 Dictionary *string `android:"path"`
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000424 // Define the fuzzing frameworks this fuzz target can be built for. If
425 // empty then the fuzz target will be available to be built for all fuzz
426 // frameworks available
427 Fuzzing_frameworks *FuzzFrameworks
hamzehc0a671f2021-07-22 12:05:08 -0700428 // Config for running the target on fuzzing infrastructure.
429 Fuzz_config *FuzzConfig
430}
431
hamzeh41ad8812021-07-07 14:00:07 -0700432type FuzzPackagedModule struct {
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800433 FuzzProperties FuzzProperties
434 Dictionary android.Path
435 Corpus android.Paths
436 Config android.Path
437 Data android.Paths
hamzeh41ad8812021-07-07 14:00:07 -0700438}
439
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000440func GetFramework(ctx android.LoadHookContext, lang Lang) Framework {
441 framework := ctx.Config().Getenv("FUZZ_FRAMEWORK")
442
443 if lang == Cc {
444 switch strings.ToLower(framework) {
445 case "":
446 return LibFuzzer
447 case "libfuzzer":
448 return LibFuzzer
449 case "afl":
450 return AFL
451 }
452 } else if lang == Rust {
453 return LibFuzzer
454 } else if lang == Java {
455 return Jazzer
456 }
457
458 ctx.ModuleErrorf(fmt.Sprintf("%s is not a valid fuzzing framework for %s", framework, lang))
459 return UnknownFramework
460}
461
462func IsValidFrameworkForModule(targetFramework Framework, lang Lang, moduleFrameworks *FuzzFrameworks) bool {
463 if targetFramework == UnknownFramework {
464 return false
465 }
466
467 if moduleFrameworks == nil {
468 return true
469 }
470
471 switch targetFramework {
472 case LibFuzzer:
473 return proptools.BoolDefault(moduleFrameworks.Libfuzzer, true)
474 case AFL:
475 return proptools.BoolDefault(moduleFrameworks.Afl, true)
476 case Jazzer:
477 return proptools.BoolDefault(moduleFrameworks.Jazzer, true)
478 default:
479 panic("%s is not supported as a fuzz framework")
480 }
481}
482
Cole Fauste8a87832024-09-11 11:35:46 -0700483func IsValid(ctx android.ConfigurableEvaluatorContext, fuzzModule FuzzModule) bool {
hamzeh41ad8812021-07-07 14:00:07 -0700484 // Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of
485 // fuzz targets we're going to package anyway.
Cole Fausta963b942024-04-11 17:43:00 -0700486 if !fuzzModule.Enabled(ctx) || fuzzModule.InRamdisk() || fuzzModule.InVendorRamdisk() || fuzzModule.InRecovery() {
hamzeh41ad8812021-07-07 14:00:07 -0700487 return false
488 }
489
490 // Discard modules that are in an unavailable namespace.
491 if !fuzzModule.ExportedToMake() {
492 return false
493 }
494
495 return true
496}
497
498func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.Module, fuzzModule FuzzPackagedModule, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip {
499 // Package the corpora into a zipfile.
500 var files []FileToZip
501 if fuzzModule.Corpus != nil {
502 corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
503 command := builder.Command().BuiltTool("soong_zip").
504 Flag("-j").
505 FlagWithOutput("-o ", corpusZip)
506 rspFile := corpusZip.ReplaceExtension(ctx, "rsp")
507 command.FlagWithRspFileInputList("-r ", rspFile, fuzzModule.Corpus)
Colin Cross80462dc2023-05-08 15:09:31 -0700508 files = append(files, FileToZip{SourceFilePath: corpusZip})
hamzeh41ad8812021-07-07 14:00:07 -0700509 }
510
511 // Package the data into a zipfile.
512 if fuzzModule.Data != nil {
513 dataZip := archDir.Join(ctx, module.Name()+"_data.zip")
514 command := builder.Command().BuiltTool("soong_zip").
515 FlagWithOutput("-o ", dataZip)
516 for _, f := range fuzzModule.Data {
517 intermediateDir := strings.TrimSuffix(f.String(), f.Rel())
518 command.FlagWithArg("-C ", intermediateDir)
519 command.FlagWithInput("-f ", f)
520 }
Colin Cross80462dc2023-05-08 15:09:31 -0700521 files = append(files, FileToZip{SourceFilePath: dataZip})
hamzeh41ad8812021-07-07 14:00:07 -0700522 }
523
524 // The dictionary.
525 if fuzzModule.Dictionary != nil {
Colin Cross80462dc2023-05-08 15:09:31 -0700526 files = append(files, FileToZip{SourceFilePath: fuzzModule.Dictionary})
hamzeh41ad8812021-07-07 14:00:07 -0700527 }
528
529 // Additional fuzz config.
hamzehe8a1bfa2022-06-21 12:22:06 -0700530 if fuzzModule.Config != nil && IsValidConfig(fuzzModule, module.Name()) {
Colin Cross80462dc2023-05-08 15:09:31 -0700531 files = append(files, FileToZip{SourceFilePath: fuzzModule.Config})
hamzeh41ad8812021-07-07 14:00:07 -0700532 }
533
534 return files
535}
536
537func (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) {
538 fuzzZip := archDir.Join(ctx, module.Name()+".zip")
539
540 command := builder.Command().BuiltTool("soong_zip").
541 Flag("-j").
542 FlagWithOutput("-o ", fuzzZip)
543
544 for _, file := range files {
545 if file.DestinationPathPrefix != "" {
546 command.FlagWithArg("-P ", file.DestinationPathPrefix)
547 } else {
548 command.Flag("-P ''")
549 }
Colin Cross80462dc2023-05-08 15:09:31 -0700550 if file.DestinationPath != "" {
551 command.FlagWithArg("-e ", file.DestinationPath)
552 }
hamzeh41ad8812021-07-07 14:00:07 -0700553 command.FlagWithInput("-f ", file.SourceFilePath)
554 }
555
556 builder.Build("create-"+fuzzZip.String(),
557 "Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
558
hamzeh41ad8812021-07-07 14:00:07 -0700559 if config := fuzzModule.FuzzProperties.Fuzz_config; config != nil {
560 if strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_host, true) {
561 return archDirs[archOs], false
hamzeh65dd2c32023-12-27 15:27:12 -0800562 } else if !strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_device, true) {
hamzeh41ad8812021-07-07 14:00:07 -0700563 return archDirs[archOs], false
564 }
565 }
566
567 s.FuzzTargets[module.Name()] = true
Colin Cross80462dc2023-05-08 15:09:31 -0700568 archDirs[archOs] = append(archDirs[archOs], FileToZip{SourceFilePath: fuzzZip})
hamzeh41ad8812021-07-07 14:00:07 -0700569
570 return archDirs[archOs], true
571}
572
hamzehc0a671f2021-07-22 12:05:08 -0700573func (f *FuzzConfig) String() string {
574 b, err := json.Marshal(f)
575 if err != nil {
576 panic(err)
577 }
578
579 return string(b)
580}
581
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000582func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, fuzzType Lang, pctx android.PackageContext) {
hamzeh41ad8812021-07-07 14:00:07 -0700583 var archOsList []ArchOs
584 for archOs := range archDirs {
585 archOsList = append(archOsList, archOs)
586 }
587 sort.Slice(archOsList, func(i, j int) bool { return archOsList[i].Dir < archOsList[j].Dir })
588
589 for _, archOs := range archOsList {
590 filesToZip := archDirs[archOs]
591 arch := archOs.Arch
592 hostOrTarget := archOs.HostOrTarget
593 builder := android.NewRuleBuilder(pctx, ctx)
594 zipFileName := "fuzz-" + hostOrTarget + "-" + arch + ".zip"
Cory Barkera1da26f2022-06-07 20:12:06 +0000595 if fuzzType == Rust {
hamzeh41ad8812021-07-07 14:00:07 -0700596 zipFileName = "fuzz-rust-" + hostOrTarget + "-" + arch + ".zip"
597 }
Cory Barkera1da26f2022-06-07 20:12:06 +0000598 if fuzzType == Java {
Muhammad Haseeb Ahmade3803102022-01-10 21:37:07 +0000599 zipFileName = "fuzz-java-" + hostOrTarget + "-" + arch + ".zip"
600 }
Cory Barker9cfcf6d2022-07-22 17:22:02 +0000601
hamzeh41ad8812021-07-07 14:00:07 -0700602 outputFile := android.PathForOutput(ctx, zipFileName)
603
604 s.Packages = append(s.Packages, outputFile)
605
606 command := builder.Command().BuiltTool("soong_zip").
607 Flag("-j").
608 FlagWithOutput("-o ", outputFile).
609 Flag("-L 0") // No need to try and re-compress the zipfiles.
610
611 for _, fileToZip := range filesToZip {
hamzeh41ad8812021-07-07 14:00:07 -0700612 if fileToZip.DestinationPathPrefix != "" {
613 command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
614 } else {
615 command.Flag("-P ''")
616 }
617 command.FlagWithInput("-f ", fileToZip.SourceFilePath)
618
619 }
620 builder.Build("create-fuzz-package-"+arch+"-"+hostOrTarget,
621 "Create fuzz target packages for "+arch+"-"+hostOrTarget)
622 }
623}
624
625func (s *FuzzPackager) PreallocateSlice(ctx android.MakeVarsContext, targets string) {
626 fuzzTargets := make([]string, 0, len(s.FuzzTargets))
627 for target, _ := range s.FuzzTargets {
628 fuzzTargets = append(fuzzTargets, target)
629 }
Cory Barkera1da26f2022-06-07 20:12:06 +0000630
hamzeh41ad8812021-07-07 14:00:07 -0700631 sort.Strings(fuzzTargets)
632 ctx.Strict(targets, strings.Join(fuzzTargets, " "))
633}