Coverage for /pythoncovmergedfiles/medio/medio/src/tomli/fuzzer/fuzz.py: 39%

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

62 statements  

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 

12import atheris 

13 

14with atheris.instrument_imports(): 

15 from math import isnan 

16 import sys 

17 import warnings 

18 

19 import tomli_w 

20 

21 import tomli 

22 

23# Disable any caching used so that the same lines of code run 

24# on a given input consistently. 

25tomli._re.cached_tz = tomli._re.cached_tz.__wrapped__ 

26 

27# Suppress all warnings. 

28warnings.simplefilter("ignore") 

29 

30 

31def test_one_input(input_bytes: bytes) -> None: 

32 # We need a Unicode string, not bytes 

33 fdp = atheris.FuzzedDataProvider(input_bytes) 

34 data = fdp.ConsumeUnicode(sys.maxsize) 

35 

36 try: 

37 toml_obj = tomli.loads(data) 

38 except (tomli.TOMLDecodeError, RecursionError): 

39 return 

40 except BaseException: 

41 print_err(data) 

42 raise 

43 

44 try: 

45 recovered_data = tomli_w.dumps(toml_obj) 

46 except RecursionError: 

47 return 

48 except BaseException: 

49 print_err(data) 

50 raise 

51 

52 roundtripped_obj = tomli.loads(recovered_data) 

53 normalize_toml_obj(roundtripped_obj) 

54 normalize_toml_obj(toml_obj) 

55 if roundtripped_obj != toml_obj: 

56 sys.stderr.write( 

57 f"Original dict:\n{toml_obj}\nRoundtripped dict:\n{roundtripped_obj}\n" 

58 ) 

59 sys.stderr.flush() 

60 print_err(data) 

61 raise Exception("Dicts not equal after roundtrip") 

62 

63 

64def print_err(data): 

65 codepoints = [hex(ord(x)) for x in data] 

66 sys.stderr.write(f"Input was {type(data)}:\n{data}\nCodepoints:\n{codepoints}\n") 

67 sys.stderr.flush() 

68 

69 

70def normalize_toml_obj(toml_obj: dict) -> None: 

71 """Make NaNs equal when compared (without using recursion).""" 

72 to_process = [toml_obj] 

73 while to_process: 

74 cont = to_process.pop() 

75 for k, v in cont.items() if isinstance(cont, dict) else enumerate(cont): 

76 if isinstance(v, float) and isnan(v): 

77 cont[k] = "nan" 

78 elif isinstance(v, (dict, list)): 

79 to_process.append(v) 

80 

81 

82def main(): 

83 # For possible options, see https://llvm.org/docs/LibFuzzer.html#options 

84 fuzzer_options = sys.argv 

85 atheris.Setup(fuzzer_options, test_one_input) 

86 atheris.Fuzz() 

87 

88 

89if __name__ == "__main__": 

90 main()