Skip to content

Commit 1637e23

Browse files
committed
ok
1 parent b357a52 commit 1637e23

1 file changed

Lines changed: 33 additions & 55 deletions

File tree

fuzz/collect_fuzz_python.py

Lines changed: 33 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,8 @@ def generate_test_template(target_name: str, repo_path: str):
212212
class Test{target_name.capitalize()}(unittest.TestCase):
213213
def test_generated(self):
214214
\"\"\"Test generated from fuzzing input\"\"\"
215-
input_data = b"" # FUZZ_PLACEHOLDER
215+
input_data = b""
216216
result = TestClass(input_data)
217-
self.assertIsNotNone(result)
218217
219218
if __name__ == '__main__':
220219
unittest.main()
@@ -313,6 +312,7 @@ def substitute_one_repo(
313312
):
314313
"""
315314
Process a single repository, replace fuzzing inputs into test templates
315+
and generate {target_name}.inputs.py files.
316316
"""
317317
template_dir = pjoin(repo, "tests-gen")
318318
input_dir = pjoin(repo, "fuzz_inputs")
@@ -324,21 +324,13 @@ def substitute_one_repo(
324324
f.write("")
325325

326326
for target_name in targets:
327-
template_path = pjoin(template_dir, f"{target_name}.py")
328327
input_path = pjoin(input_dir, target_name)
329328

330329
try:
331-
if not os.path.exists(template_path):
332-
logging.warning(f"Template file not found: {template_path}")
333-
continue
334-
335330
if not os.path.exists(input_path):
336331
logging.warning(f"Input file not found: {input_path}")
337332
continue
338333

339-
with open(template_path) as f_template:
340-
template = f_template.read()
341-
342334
with open(input_path, "r") as f_input:
343335
all_inputs = [line.strip() for line in f_input if line.strip()]
344336

@@ -363,62 +355,47 @@ def substitute_one_repo(
363355
else:
364356
inputs = all_inputs[:n_fuzz]
365357

366-
# Extract structure from template
367-
match = re.search(r"(class\s+Test\w+\(unittest\.TestCase\):)", template)
368-
if not match:
369-
logging.error(f"Class definition not found in template: {template_path}")
370-
continue
358+
# Header
359+
file_header = f"""import sys
360+
import os
361+
import unittest
371362
372-
class_def_index = match.start()
373-
before_class = template[:class_def_index]
374-
class_and_after = template[class_def_index:]
363+
# 将项目目录加入 Python 路径,确保能导入上层模块
364+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
375365
376-
method_match = re.search(r"def\s+test_generated\(self\):", class_and_after)
377-
if not method_match:
378-
logging.error(f"test_generated method not found in template: {template_path}")
379-
continue
366+
try:
367+
from {target_name} import TestOneInput as TestClass
368+
except ImportError:
369+
from {target_name} import TestInput as TestClass
370+
371+
372+
class Test{target_name.capitalize()}(unittest.TestCase):"""
380373

381-
method_start = method_match.end()
382-
class_header = class_and_after[:method_start]
383-
method_indent_block = class_and_after[method_start:]
384-
385-
method_lines = method_indent_block.splitlines()
386-
method_body = []
387-
footer_lines = []
388-
for line in method_lines:
389-
if line.strip() == "":
390-
continue
391-
if not line.startswith(" "): # outside method block
392-
footer_lines.append(line)
393-
elif not footer_lines: # still inside method
394-
method_body.append(line)
395-
396-
method_body_str = "\n".join(method_body)
397-
footer_str = "\n".join(footer_lines)
398-
399-
# Build all test methods
374+
# Method body template
375+
method_body_template = [
376+
'"""Test generated from fuzzing input"""',
377+
'input_data = b""',
378+
'result = TestClass(input_data)',
379+
]
380+
381+
# Generate test methods
400382
test_methods = []
401383
for i, input_data in enumerate(inputs):
402384
escaped_input = escape_special_chars(input_data)
403385
test_func = f" def test_{i}(self):\n"
404-
test_func += "\n".join(
405-
" " + line.lstrip().replace('input_data = b""', f"input_data = {escaped_input}")
406-
for line in method_body if line.strip()
407-
)
386+
for line in method_body_template:
387+
replaced_line = line.replace('input_data = b""', f"input_data = {escaped_input}")
388+
test_func += f" {replaced_line}\n"
408389
test_methods.append(test_func)
409390

410391
if not test_methods:
411-
# Fallback: generate dummy method to avoid syntax error
412392
test_methods = [" def test_placeholder(self):\n self.assertTrue(True)"]
413393

414-
final_code = before_class.rstrip() + "\n" + class_header.rstrip() + "\n\n"
415-
final_code += "\n\n".join(test_methods).rstrip() + "\n"
416-
417-
if footer_str.strip():
418-
final_code += "\n\n" + footer_str.strip() + "\n"
394+
# Combine full file
395+
final_code = file_header + "\n\n" + "\n\n".join(test_methods)
396+
final_code += "\n\nif __name__ == '__main__':\n unittest.main()\n"
419397

420-
421-
# Write to output
398+
# Write output file
422399
generated_path = pjoin(template_dir, f"{target_name}.inputs.py")
423400
with open(generated_path, "w") as f:
424401
f.write(final_code)
@@ -432,6 +409,7 @@ def substitute_one_repo(
432409
except Exception as e:
433410
logging.error(f"Error processing {target_name}: {e}")
434411

412+
435413
def testgen_repos(
436414
repos: list[str],
437415
jobs: int,
@@ -471,10 +449,10 @@ def testgen_repos(
471449
))
472450

473451
def main(
474-
repo_id: str = "data/valid_projects3.txt",
452+
repo_id: str = "data/valid_projects.txt",
475453
repo_root: str = "fuzz/oss-fuzz/projects/",
476454
timeout: int = 60,
477-
jobs: int = 8,
455+
jobs: int = 4,
478456
pipeline: str = "all",
479457
n_fuzz: int = 100,
480458
strategy: str = "shuffle",

0 commit comments

Comments
 (0)