| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Mutational ClusterFuzz fuzzer. A pre-built corpus of ipcdump files has | 6 """Mutational ClusterFuzz fuzzer. A pre-built corpus of ipcdump files has |
| 7 to be uploaded to ClusterFuzz along with this script. As chrome is being | 7 to be uploaded to ClusterFuzz along with this script. As chrome is being |
| 8 developed, the corpus will become out-of-date and needs to be updated. | 8 developed, the corpus will become out-of-date and needs to be updated. |
| 9 | 9 |
| 10 This fuzzer will pick some ipcdumps from the corpus, concatenate them with | 10 This fuzzer will pick some ipcdumps from the corpus, concatenate them with |
| 11 ipc_message_util and mutate the result with ipc_fuzzer_mutate. | 11 ipc_message_util and mutate the result with ipc_fuzzer_mutate. |
| 12 """ | 12 """ |
| 13 | 13 |
| 14 import os | 14 import os |
| 15 import random | 15 import random |
| 16 import subprocess | 16 import subprocess |
| 17 import sys | 17 import sys |
| 18 import utils | 18 import utils |
| 19 | 19 |
| 20 FUZZER_NAME_OPTION = '--fuzzer-name=mutate' |
| 20 IPC_MESSAGE_UTIL_APPLICATION = 'ipc_message_util' | 21 IPC_MESSAGE_UTIL_APPLICATION = 'ipc_message_util' |
| 21 IPC_MUTATE_APPLICATION = 'ipc_fuzzer_mutate' | |
| 22 IPC_REPLAY_APPLICATION = 'ipc_fuzzer_replay' | |
| 23 IPCDUMP_MERGE_LIMIT = 50 | 22 IPCDUMP_MERGE_LIMIT = 50 |
| 24 | 23 |
| 25 class MutationalFuzzer: | 24 class MutationalFuzzer: |
| 26 def parse_arguments(self): | 25 def parse_arguments(self): |
| 27 self.args = utils.parse_arguments() | 26 self.args = utils.parse_arguments() |
| 28 | 27 |
| 29 def set_application_paths(self): | 28 def set_application_paths(self): |
| 30 chrome_application_path = utils.get_application_path() | 29 chrome_application_path = utils.get_application_path() |
| 31 chrome_application_directory = os.path.dirname(chrome_application_path) | 30 chrome_application_directory = os.path.dirname(chrome_application_path) |
| 32 | 31 |
| 33 self.ipc_message_util_binary = utils.application_name_for_platform( | 32 self.ipc_message_util_binary = utils.application_name_for_platform( |
| 34 IPC_MESSAGE_UTIL_APPLICATION) | 33 IPC_MESSAGE_UTIL_APPLICATION) |
| 35 self.ipc_mutate_binary = utils.application_name_for_platform( | 34 self.ipc_fuzzer_binary = utils.get_fuzzer_application_name() |
| 36 IPC_MUTATE_APPLICATION) | 35 self.ipc_replay_binary = utils.get_replay_application_name() |
| 37 self.ipc_replay_binary = utils.application_name_for_platform( | |
| 38 IPC_REPLAY_APPLICATION) | |
| 39 self.ipc_message_util_binary_path = os.path.join( | 36 self.ipc_message_util_binary_path = os.path.join( |
| 40 chrome_application_directory, self.ipc_message_util_binary) | 37 chrome_application_directory, self.ipc_message_util_binary) |
| 41 self.ipc_mutate_binary_path = os.path.join( | 38 self.ipc_fuzzer_binary_path = os.path.join( |
| 42 chrome_application_directory, self.ipc_mutate_binary) | 39 chrome_application_directory, self.ipc_fuzzer_binary) |
| 43 self.ipc_replay_binary_path = os.path.join( | 40 self.ipc_replay_binary_path = os.path.join( |
| 44 chrome_application_directory, self.ipc_replay_binary) | 41 chrome_application_directory, self.ipc_replay_binary) |
| 45 | 42 |
| 46 def set_corpus(self): | 43 def set_corpus(self): |
| 47 input_directory = self.args.input_dir | 44 input_directory = self.args.input_dir |
| 48 entries = os.listdir(input_directory) | 45 entries = os.listdir(input_directory) |
| 49 entries = [i for i in entries if i.endswith(utils.IPCDUMP_EXTENSION)] | 46 entries = [i for i in entries if i.endswith(utils.IPCDUMP_EXTENSION)] |
| 50 self.corpus = [os.path.join(input_directory, entry) for entry in entries] | 47 self.corpus = [os.path.join(input_directory, entry) for entry in entries] |
| 51 | 48 |
| 52 def create_mutated_ipcdump_testcase(self): | 49 def create_mutated_ipcdump_testcase(self): |
| 53 ipcdumps = ','.join(random.sample(self.corpus, IPCDUMP_MERGE_LIMIT)) | 50 ipcdumps = ','.join(random.sample(self.corpus, IPCDUMP_MERGE_LIMIT)) |
| 54 tmp_ipcdump_testcase = utils.create_temp_file() | 51 tmp_ipcdump_testcase = utils.create_temp_file() |
| 55 mutated_ipcdump_testcase = ( | 52 mutated_ipcdump_testcase = ( |
| 56 utils.random_ipcdump_testcase_path(self.args.output_dir)) | 53 utils.random_ipcdump_testcase_path(self.args.output_dir)) |
| 57 | 54 |
| 58 # Concatenate ipcdumps -> tmp_ipcdump. | 55 # Concatenate ipcdumps -> tmp_ipcdump. |
| 59 cmd = [ | 56 cmd = [ |
| 60 self.ipc_message_util_binary_path, | 57 self.ipc_message_util_binary_path, |
| 61 ipcdumps, | 58 ipcdumps, |
| 62 tmp_ipcdump_testcase, | 59 tmp_ipcdump_testcase, |
| 63 ] | 60 ] |
| 64 if subprocess.call(cmd): | 61 if subprocess.call(cmd): |
| 65 sys.exit('%s failed.' % self.ipc_message_util_binary) | 62 sys.exit('%s failed.' % self.ipc_message_util_binary) |
| 66 | 63 |
| 67 # Mutate tmp_ipcdump -> mutated_ipcdump. | 64 # Mutate tmp_ipcdump -> mutated_ipcdump. |
| 68 cmd = [ | 65 cmd = [ |
| 69 self.ipc_mutate_binary_path, | 66 self.ipc_fuzzer_binary_path, |
| 67 FUZZER_NAME_OPTION, |
| 70 tmp_ipcdump_testcase, | 68 tmp_ipcdump_testcase, |
| 71 mutated_ipcdump_testcase, | 69 mutated_ipcdump_testcase, |
| 72 ] | 70 ] |
| 73 if subprocess.call(cmd): | 71 if subprocess.call(cmd): |
| 74 sys.exit('%s failed.' % self.ipc_mutate_binary) | 72 sys.exit('%s failed.' % self.ipc_fuzzer_binary) |
| 75 | 73 |
| 76 utils.create_flags_file( | 74 utils.create_flags_file( |
| 77 mutated_ipcdump_testcase, self.ipc_replay_binary_path) | 75 mutated_ipcdump_testcase, self.ipc_replay_binary_path) |
| 78 os.remove(tmp_ipcdump_testcase) | 76 os.remove(tmp_ipcdump_testcase) |
| 79 | 77 |
| 80 def main(self): | 78 def main(self): |
| 81 self.parse_arguments() | 79 self.parse_arguments() |
| 82 self.set_application_paths() | 80 self.set_application_paths() |
| 83 self.set_corpus() | 81 self.set_corpus() |
| 84 for _ in xrange(self.args.no_of_files): | 82 for _ in xrange(self.args.no_of_files): |
| 85 self.create_mutated_ipcdump_testcase() | 83 self.create_mutated_ipcdump_testcase() |
| 86 | 84 |
| 87 return 0 | 85 return 0 |
| 88 | 86 |
| 89 if __name__ == "__main__": | 87 if __name__ == "__main__": |
| 90 fuzzer = MutationalFuzzer() | 88 fuzzer = MutationalFuzzer() |
| 91 sys.exit(fuzzer.main()) | 89 sys.exit(fuzzer.main()) |
| OLD | NEW |