1#!/usr/bin/env python3 2# 3# Copyright 2015 The Chromium Authors 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6"""Generate or update an existing config (.options file) for libfuzzer test. 7 8Invoked by GN from fuzzer_test.gni. 9""" 10 11import argparse 12import os 13import sys 14 15if sys.version_info.major == 2: 16 from ConfigParser import ConfigParser 17else: 18 from configparser import ConfigParser 19 20 21def AddSectionOptions(config, section_name, options): 22 """Add |options| to the |section_name| section of |config|. 23 24 Throws an 25 assertion error if any option in |options| does not have exactly two 26 elements. 27 """ 28 if not options: 29 return 30 31 config.add_section(section_name) 32 for option_and_value in options: 33 assert len(option_and_value) == 2, ( 34 '%s is not an option, value pair' % option_and_value) 35 36 config.set(section_name, *option_and_value) 37 38 39def main(): 40 parser = argparse.ArgumentParser(description='Generate fuzzer config.') 41 parser.add_argument('--config', required=True) 42 parser.add_argument('--dict') 43 parser.add_argument('--libfuzzer_options', nargs='+', default=[]) 44 parser.add_argument('--centipede_options', nargs='+', default=[]) 45 parser.add_argument('--asan_options', nargs='+', default=[]) 46 parser.add_argument('--msan_options', nargs='+', default=[]) 47 parser.add_argument('--ubsan_options', nargs='+', default=[]) 48 parser.add_argument('--grammar_options', nargs='+', default=[]) 49 parser.add_argument( 50 '--environment_variables', 51 nargs='+', 52 default=[], 53 choices=['AFL_DRIVER_DONT_DEFER=1']) 54 args = parser.parse_args() 55 56 # Script shouldn't be invoked without any arguments, but just in case. 57 if not (args.dict or args.libfuzzer_options or args.environment_variables or 58 args.asan_options or args.msan_options or args.ubsan_options or 59 args.grammar_options): 60 return 61 62 config = ConfigParser() 63 libfuzzer_options = [] 64 if args.dict: 65 libfuzzer_options.append(('dict', os.path.basename(args.dict))) 66 libfuzzer_options.extend( 67 option.split('=') for option in args.libfuzzer_options) 68 69 AddSectionOptions(config, 'libfuzzer', libfuzzer_options) 70 71 centipede_options = [] 72 if args.dict: 73 centipede_options.append(('dictionary', os.path.basename(args.dict))) 74 centipede_options.extend( 75 option.split('=') for option in args.centipede_options) 76 AddSectionOptions(config, 'centipede', centipede_options) 77 78 AddSectionOptions(config, 'asan', 79 [option.split('=') for option in args.asan_options]) 80 81 AddSectionOptions(config, 'msan', 82 [option.split('=') for option in args.msan_options]) 83 84 AddSectionOptions(config, 'ubsan', 85 [option.split('=') for option in args.ubsan_options]) 86 87 AddSectionOptions(config, 'grammar', 88 [option.split('=') for option in args.grammar_options]) 89 90 AddSectionOptions( 91 config, 'env', 92 [option.split('=') for option in args.environment_variables]) 93 94 # Generate .options file. 95 config_path = args.config 96 with open(config_path, 'w') as options_file: 97 options_file.write( 98 '# This is an automatically generated config for ClusterFuzz.\n') 99 config.write(options_file) 100 101 102if __name__ == '__main__': 103 main() 104