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