1#!/usr/bin/python3 2 3# Copyright 2020 Google LLC 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16"""This fuzzer is an example of native extension fuzzing with coverage. 17 18This requires that the fuzzer be built with coverage: 19see build_install_ujson.sh. 20The fuzzer should then be executed under ASAN. 21 22As an example, this is the run command under the author's machine: 23 LD_PRELOAD="/usr/lib/llvm-9/lib/clang/9.0.1/lib/linux/libclang_rt.asan-x86_64.so 24 $(python3 -c "import atheris; print(atheris.path())")" python3 25 ./ujson_fuzzer.py -detect_leaks=0 26 27This fuzzer is provided mainly as an example for how to deal with native 28coverage. 29""" 30 31import sys 32import atheris 33import ujson 34 35 36def TestOneInput(input_bytes): 37 fdp = atheris.FuzzedDataProvider(input_bytes) 38 original = fdp.ConsumeUnicode(sys.maxsize) 39 40 try: 41 ujson_data = ujson.loads(original) 42 except ValueError: 43 return 44 45 # We make sure there's no error in encoding, but we don't actually compare 46 # (encoded == original) because it's not entirely preserving. For example, 47 # it does not preserve whitespace. 48 encoded = ujson.dumps(ujson_data) 49 del encoded 50 51 52def main(): 53 # Since everything interesting in this fuzzer is in native code, we can 54 # disable Python coverage to improve performance and reduce coverage noise. 55 atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=False) 56 atheris.Fuzz() 57 58 59if __name__ == "__main__": 60 main() 61