xref: /aosp_15_r20/external/cronet/testing/libfuzzer/fuzzers/generate_v8_inspector_fuzzer_corpus.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1#!/usr/bin/env python3
2# Copyright 2020 The Chromium Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import os
7import re
8import shutil
9import sys
10
11
12load_regexp = re.compile(r'^\s*utils\.load\([\'"]([^\'"]+)[\'"]\);\s*$')
13load_root = None
14
15def resolve_loads(output_file, input_lines, loaded_files):
16  for line in input_lines:
17    load_match = load_regexp.match(line)
18    if not load_match:
19      output_file.write(line)
20      continue
21    load_file(output_file, load_match.group(1), loaded_files)
22
23
24def load_file(output_file, input_file, loaded_files):
25  if input_file in loaded_files:
26    sys.exit('Recursive load of \'{}\''.format(input_file))
27  loaded_files.add(input_file)
28  output_file.write('\n// Loaded from \'{}\':\n'.format(input_file))
29  with open(os.path.join(load_root, input_file)) as file:
30    resolve_loads(output_file, file.readlines(), loaded_files)
31
32
33def generate_content(output_file, input_file):
34  # The fuzzer does not provide the same methods on 'utils' as the
35  # inspector-test executable. Thus mock out non-existing ones via a proxy.
36  output_file.write("""
37utils = new Proxy(utils, {
38    get: function(target, prop) {
39      if (prop in target) return target[prop];
40      return i=>i;
41    }
42  });
43""".lstrip())
44
45  # Always prepend the 'protocol-test.js' file, which is always loaded first
46  # by the test runner for inspector tests.
47  protocol_test_file = os.path.join('test', 'inspector', 'protocol-test.js')
48  load_file(output_file, protocol_test_file, set())
49
50  # Then load the actual input file, inlining all recursively loaded files.
51  load_file(output_file, input_file, set())
52
53
54def main():
55  if len(sys.argv) != 3:
56    print(
57      'Usage: {} <path to input directory> <path to output directory>'.format(
58        sys.argv[0]))
59    sys.exit(1)
60
61  input_root = sys.argv[1]
62  output_root = sys.argv[2]
63  # Start with a clean output directory.
64  if os.path.exists(output_root):
65    shutil.rmtree(output_root)
66  os.makedirs(output_root)
67
68  # Loaded files are relative to the v8 root, which is two levels above the
69  # inspector test directory.
70  global load_root
71  load_root = os.path.dirname(os.path.dirname(os.path.normpath(input_root)))
72
73  for parent, _, files in os.walk(input_root):
74    for filename in files:
75      if filename.endswith('.js'):
76        output_file = os.path.join(output_root, filename)
77        output_dir = os.path.dirname(output_file)
78        if not os.path.exists(output_dir):
79          os.makedirs(os.path.dirname(output_file))
80        with open(output_file, 'w') as output_file:
81          abs_input_file = os.path.join(parent, filename)
82          rel_input_file = os.path.relpath(abs_input_file, load_root)
83          generate_content(output_file, rel_input_file)
84
85  # Done.
86  sys.exit(0)
87
88
89if __name__ == '__main__':
90  main()
91