Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/icalendar/tests/fuzzed/__init__.py: 94%

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

31 statements  

1"""This is a collection of test files that are generated from the fuzzer. 

2 

3The fuzzer finds the cases in which the icalendar module breaks. 

4These test cases reproduce the failure. 

5Some more tests can be added to make sure that the behavior works properly. 

6""" 

7 

8import inspect 

9 

10_value_error_matches = [ 

11 "component", 

12 "parse", 

13 "Expected", 

14 "Wrong date format", 

15 "END encountered", 

16 "vDDD", 

17 "recurrence", 

18 "Offset must", 

19 "Invalid iCalendar", 

20 "alue MUST", 

21 "Key name", 

22 "Invalid content line", 

23 "Content line could not be parsed", 

24 "does not exist", 

25 "base 64", 

26 "must use datetime", 

27 "Unknown date type", 

28 "Wrong", 

29 "Start time", 

30 "iCalendar", 

31 "recurrence", 

32 "float, float", 

33 "utc offset", 

34 "parent", 

35 "MUST be a datetime", 

36 "Invalid month:", 

37 "must have exactly", # vCard field count validation (ADR, N) 

38 "must have at least", # vCard ORG minimum field validation 

39 "not enough values to unpack", # dateutil rejects a malformed VTIMEZONE content line 

40 "Content line can not contain unescaped new line characters.", # Contentline after #1559 

41] 

42 

43 

44def format_fuzz_log( 

45 from_ical, multiple: bool, should_walk: bool, calendar_string: str | bytes 

46) -> str: 

47 """Format the log entry for fuzzed test case extraction. 

48 

49 Outputs entrypoint name, parameter values, and base64-encoded calendar content. 

50 """ 

51 import base64 

52 

53 try: 

54 # print the ICS file for the test case extraction 

55 # see https://stackoverflow.com/a/27367173/1320237 

56 encoded = base64.b64encode( 

57 calendar_string.encode("UTF-8", "surrogateescape") 

58 if isinstance(calendar_string, str) 

59 else calendar_string 

60 ).decode("ASCII") 

61 except UnicodeEncodeError as e: 

62 encoded = str(e) 

63 return ( 

64 f"{_get_name_of_caller()} {from_ical.__qualname__} multiple={multiple} " 

65 f"should_walk={should_walk} {encoded}" 

66 ) 

67 

68 

69def _get_name_of_caller(skip: int = 0) -> str: 

70 stack = inspect.stack() 

71 relevant_index = skip + 2 # ignore own and caller frame 

72 if relevant_index < len(stack) and (frame := stack[relevant_index]): 

73 return frame.function 

74 return "<unknown source>" 

75 

76 

77def fuzz_v1_calendar( 

78 from_ical, calendar_string: str, multiple: bool, should_walk: bool 

79): 

80 """Take a from_ical function and reproduce the error. 

81 

82 The calendar_string is a fuzzed input. 

83 """ 

84 print(format_fuzz_log(from_ical, multiple, should_walk, calendar_string)) 

85 try: 

86 cal = from_ical(calendar_string, multiple=multiple) 

87 

88 if not multiple: 

89 cal = [cal] 

90 for c in cal: 

91 if should_walk: 

92 for event in c.walk("VEVENT"): 

93 event.to_ical() 

94 else: 

95 c.to_ical() 

96 except (ValueError, TypeError) as e: 

97 if any(m in str(e) for m in _value_error_matches): 

98 return -1 

99 raise