File size: 3,405 Bytes
aef804e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
"""
Fuzzy Test Helpers for Atom Testing Framework

Provides common utilities and helpers for writing fuzz tests using Atheris.
"""

import sys
import os
from typing import Callable, Any

# Add backend to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../'))

try:
    import atheris
    ATHERIS_AVAILABLE = True
except ImportError:
    ATHERIS_AVAILABLE = False
    print("Warning: Atheris not available. Fuzz tests will be skipped.")


def setup_fuzzer(test_func: Callable[[bytes], None], argv: list = None):
    """
    Set up Atheris fuzzer with the given test function.

    Args:
        test_func: Function that takes bytes and tests the code
        argv: Command-line arguments (defaults to sys.argv)
    """
    if not ATHERIS_AVAILABLE:
        print("Atheris not available. Skipping fuzzer setup.")
        return

    if argv is None:
        argv = sys.argv

    atheris.Setup(argv, test_func)


def run_fuzz():
    """Run the fuzzer (must be called after setup_fuzzer)."""
    if not ATHERIS_AVAILABLE:
        print("Atheris not available. Skipping fuzzing.")
        return

    atheris.Fuzz()


def with_expected_exceptions(*exceptions):
    """
    Decorator that catches expected exceptions during fuzzing.

    Usage:
        @with_expected_exceptions(ValueError, TypeError)
        def test_fuzz(data):
            ...
    """
    def decorator(func):
        def wrapper(data):
            try:
                func(data)
            except exceptions:
                pass  # Expected exceptions are OK
            except Exception as e:
                # Unexpected exceptions should crash
                raise
        return wrapper
    return decorator


def sanitize_bytes(data: bytes) -> str:
    """
    Safely convert bytes to string, ignoring errors.

    Args:
        data: Input bytes

    Returns:
        String representation (with invalid UTF-8 replaced)
    """
    return data.decode('utf-8', errors='ignore')


def truncate_string(s: str, max_length: int = 1000) -> str:
    """
    Truncate string to max length for safety.

    Args:
        s: Input string
        max_length: Maximum length

    Returns:
        Truncated string
    """
    return s[:max_length] if len(s) > max_length else s


class FuzzTestCase:
    """Base class for fuzz test cases."""

    def __init__(self, name: str):
        self.name = name
        self.crashes = 0
        self.executions = 0

    def run(self, data: bytes):
        """
        Run the fuzz test case.

        Args:
            data: Fuzz input data
        """
        self.executions += 1
        try:
            self.test_func(data)
        except Exception as e:
            self.crashes += 1
            print(f"Crash in {self.name}: {e}")
            raise

    def test_func(self, data: bytes):
        """Override this method in subclasses."""
        raise NotImplementedError

    def stats(self) -> dict:
        """Return test statistics."""
        return {
            'name': self.name,
            'executions': self.executions,
            'crashes': self.crashes,
            'crash_rate': self.crashes / self.executions if self.executions > 0 else 0
        }


if __name__ == "__main__":
    if ATHERIS_AVAILABLE:
        print("Atheris fuzzing helpers loaded successfully.")
    else:
        print("Warning: Atheris not available. Install with: pip install atheris")