1# 2# Copyright (C) 2017 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16 17import os 18 19from vts.utils.python.os import path_utils 20 21from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test_config as config 22 23 24class LibFuzzerTestCase(object): 25 """Represents libfuzzer test case. 26 27 Attributes: 28 _bin_host_path: string, path to binary on host. 29 _bin_name: string, name of the binary. 30 _test_name: string, name of the test case. 31 _libfuzzer_params: dict, libfuzzer-specific parameters. 32 _additional_params: dict, additional parameters. 33 """ 34 35 def __init__(self, bin_host_path, libfuzzer_params, additional_params): 36 self._bin_host_path = bin_host_path 37 self._libfuzzer_params = libfuzzer_params 38 self._additional_params = additional_params 39 self._binary_name = os.path.basename(bin_host_path) 40 self._test_name = self._binary_name 41 42 def _GetCorpusDir(self): 43 """Returns corpus directory name on target.""" 44 corpus_dir = path_utils.JoinTargetPath(config.FUZZER_TEST_DIR, 45 '%s_corpus' % self._test_name) 46 return corpus_dir 47 48 def GetCorpusOutDir(self): 49 """Returns corpus output directory name on target.""" 50 return self._GetCorpusDir() + '_out' 51 52 def GetCorpusSeedDir(self): 53 """Returns corpus seed directory name on target.""" 54 return self._GetCorpusDir() + '_seed' 55 56 def GetCorpusTriggerDir(self): 57 """Returns basename of corpus trigger directory.""" 58 return '%s_corpus_trigger' % self._test_name 59 60 def CreateFuzzerFlags(self): 61 """Creates flags for the fuzzer executable. 62 63 Returns: 64 string, of form '-<flag0>=<val0> -<flag1>=<val1> ... ' 65 """ 66 # Used to separate additional and libfuzzer flags. 67 DELIMITER = '--' 68 additional_flags = ' '.join( 69 ['--%s=%s' % (k, v) for k, v in self._additional_params.items()]) 70 libfuzzer_flags = ' '.join( 71 ['-%s=%s' % (k, v) for k, v in self._libfuzzer_params.items()]) 72 if not additional_flags: 73 flags = libfuzzer_flags 74 else: 75 flags = '%s %s %s' % (additional_flags, DELIMITER, libfuzzer_flags) 76 return flags 77 78 def GetRunCommand(self, debug_mode=False): 79 """Returns target shell command to run the fuzzer binary.""" 80 test_flags = self.CreateFuzzerFlags() 81 corpus_out = '' if debug_mode else self.GetCorpusOutDir() 82 corpus_seed = '' if debug_mode else self.GetCorpusSeedDir() 83 84 cd_cmd = 'cd %s' % config.FUZZER_TEST_DIR 85 chmod_cmd = 'chmod 777 %s' % self._binary_name 86 ld_path = 'LD_LIBRARY_PATH=/data/local/tmp/64:/data/local/tmp/32:$LD_LIBRARY_PATH' 87 test_cmd = '%s ./%s %s %s %s' % (ld_path, self._binary_name, 88 corpus_out, corpus_seed, test_flags) 89 if not debug_mode: 90 test_cmd += ' > /dev/null' 91 return ' && '.join([cd_cmd, chmod_cmd, test_cmd]) 92 93 @property 94 def test_name(self): 95 """Name of this test case.""" 96 return str(self._test_name) 97 98 @test_name.setter 99 def test_name(self, name): 100 """Set name of this test case.""" 101 self._test_name = name 102 103 @property 104 def bin_host_path(self): 105 """Host path to binary for this test case.""" 106 return self._bin_host_path 107