Coverage for /pythoncovmergedfiles/medio/medio/src/hypothesis_structured_fuzzer.py: 17%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1###### Coverage stub
2import atexit
3import coverage
4cov = coverage.coverage(data_file='.coverage', cover_pylib=True)
5cov.start()
6# Register an exist handler that will print coverage
7def exit_handler():
8 cov.stop()
9 cov.save()
10atexit.register(exit_handler)
11####### End of coverage stub
12#!/usr/bin/python3
14# Copyright 2021 Zac Hatfield-Dodds
15#
16# Licensed under the Apache License, Version 2.0 (the "License");
17# you may not use this file except in compliance with the License.
18# You may obtain a copy of the License at
19#
20# http://www.apache.org/licenses/LICENSE-2.0
21#
22# Unless required by applicable law or agreed to in writing, software
23# distributed under the License is distributed on an "AS IS" BASIS,
24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25# See the License for the specific language governing permissions and
26# limitations under the License.
28"""This fuzzer is an example harness using Hypothesis for structured inputs.
30It would be possible, though more difficult, to write this test in terms
31of Atheris' `FuzzedDataProvider` instead of Hypothesis strategies.
33As well as defining structured inputs however, the call to
34`test_ujson_roundtrip()` will replay, deduplicate, and minimize any known
35failing examples from previous runs - which is great when debugging.
36Hypothesis uses a separate cache to Atheris/LibFuzzer seeds, so this is
37strictly complementary to your traditional fuzzing workflow.
39For more details on Hypothesis, see:
40https://hypothesis.readthedocs.io/en/latest/data.html
41https://hypothesis.readthedocs.io/en/latest/details.html#use-with-external-fuzzers
42"""
44import sys
45import atheris
46import ujson
47from hypothesis import given, strategies as st
49# We could define all these inline within the call to @given(),
50# but it's a bit easier to read if we name them here instead.
51JSON_ATOMS = st.one_of(
52 st.none(),
53 st.booleans(),
54 st.integers(min_value=-(2 ** 63), max_value=2 ** 63 - 1),
55 st.floats(allow_nan=False, allow_infinity=False),
56 st.text(),
57)
58JSON_OBJECTS = st.recursive(
59 base=JSON_ATOMS,
60 extend=lambda inner: st.lists(inner) | st.dictionaries(st.text(), inner),
61)
62UJSON_ENCODE_KWARGS = {
63 "ensure_ascii": st.booleans(),
64 "encode_html_chars": st.booleans(),
65 "escape_forward_slashes": st.booleans(),
66 "sort_keys": st.booleans(),
67 "indent": st.integers(0, 20),
68}
71@given(obj=JSON_OBJECTS, kwargs=st.fixed_dictionaries(UJSON_ENCODE_KWARGS))
72@atheris.instrument_func
73def test_ujson_roundtrip(obj, kwargs):
74 """Check that all JSON objects round-trip regardless of other options."""
75 assert obj == ujson.decode(ujson.encode(obj, **kwargs))
78if __name__ == "__main__":
79 # Running `pytest hypothesis_structured_fuzzer.py` will replay, deduplicate,
80 # and minimize any failures discovered by earlier runs or by OSS-Fuzz, or
81 # briefly search for new failures if none are known.
82 # Or, when running via OSS-Fuzz, we'll execute it via the fuzzing hook:
83 atheris.Setup(sys.argv, atheris.instrument_func(test_ujson_roundtrip.hypothesis.fuzz_one_input))
84 atheris.Fuzz()