1#!/usr/bin/env python 2# Copyright 2018 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""Script for generating new binary protobuf seeds for fuzzers. 7 8Currently supports creating a single seed binary protobuf of the form 9zucchini.fuzzer.FilePair. 10""" 11 12import argparse 13import hashlib 14import logging 15import os 16import platform 17import subprocess 18import sys 19 20ABS_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__))) 21ABS_TESTDATA_PATH = os.path.join(ABS_PATH, 'testdata') 22 23def parse_args(): 24 """Parses arguments from command-line.""" 25 parser = argparse.ArgumentParser() 26 parser.add_argument('--raw', help='Whether to use Raw Zucchini.', 27 action='store_true') 28 parser.add_argument('old_file', help='Old file to generate/apply patch.') 29 parser.add_argument('new_file', help='New file to generate patch from.') 30 parser.add_argument('patch_file', help='Patch filename to use.') 31 parser.add_argument('output_file', help='File to write binary protobuf to.') 32 return parser.parse_args() 33 34 35def gen(old_file, new_file, patch_file, output_file, is_raw, is_win): 36 """Generates a new patch and binary encodes a protobuf pair.""" 37 # Create output directory if missing. 38 output_dir = os.path.dirname(output_file) 39 if not os.path.exists(output_dir): 40 os.makedirs(output_dir) 41 42 # Handle Windows executable names. 43 zucchini = 'zucchini' 44 protoc = 'protoc' 45 if is_win: 46 zucchini += '.exe' 47 protoc += '.exe' 48 49 zuc_cmd = [os.path.abspath(zucchini), '-gen'] 50 if is_raw: 51 zuc_cmd.append('-raw') 52 # Generate a new patch. 53 ret = subprocess.call(zuc_cmd + [old_file, new_file, patch_file], 54 stdout=subprocess.PIPE, 55 stderr=subprocess.PIPE) 56 if ret: 57 logging.error('Patch generation failed for ({}, {})'.format(old_file, 58 new_file)) 59 return ret 60 # Binary encode the protobuf pair. 61 ret = subprocess.call([sys.executable, 62 os.path.join(ABS_PATH, 'create_seed_file_pair.py'), 63 os.path.abspath(protoc), old_file, patch_file, 64 output_file]) 65 os.remove(patch_file) 66 return ret 67 68 69def main(): 70 args = parse_args() 71 return gen(os.path.join(ABS_TESTDATA_PATH, args.old_file), 72 os.path.join(ABS_TESTDATA_PATH, args.new_file), 73 os.path.abspath(args.patch_file), 74 os.path.abspath(args.output_file), 75 args.raw, 76 platform.system() == 'Windows') 77 78 79if __name__ == '__main__': 80 sys.exit(main()) 81 82