Coverage for /pythoncovmergedfiles/medio/medio/src/pdfplumber/fuzz/fuzz_helpers.py: 63%
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#!/usr/bin/python3
2# Copyright 2023 Google LLC
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16################################################################################
17import contextlib
18import io
19import tempfile
20from enum import IntEnum
21from typing import Protocol, Type, TypeVar
23import atheris
26class HasMax(Protocol):
27 MAX: int
30T = TypeVar("T", bound=IntEnum)
33class EnhancedFuzzedDataProvider(atheris.FuzzedDataProvider):
34 def ConsumeRandomBytes(self) -> bytes:
35 return self.ConsumeBytes(self.ConsumeIntInRange(0, self.remaining_bytes()))
37 def ConsumeRandomString(self) -> str:
38 return self.ConsumeUnicodeNoSurrogates(
39 self.ConsumeIntInRange(0, self.remaining_bytes())
40 )
42 def ConsumeRemainingString(self) -> str:
43 return self.ConsumeUnicodeNoSurrogates(self.remaining_bytes())
45 def ConsumeRemainingBytes(self) -> bytes:
46 return self.ConsumeBytes(self.remaining_bytes())
48 @contextlib.contextmanager
49 def ConsumeMemoryFile(
50 self, all_data: bool = False, as_bytes: bool = True
51 ) -> io.BytesIO:
52 if all_data:
53 file_data = (
54 self.ConsumeRemainingBytes()
55 if as_bytes
56 else self.ConsumeRemainingString()
57 )
58 else:
59 file_data = (
60 self.ConsumeRandomBytes() if as_bytes else self.ConsumeRandomString()
61 )
63 file = io.BytesIO(file_data) if as_bytes else io.StringIO(file_data)
64 yield file
65 file.close()
67 @contextlib.contextmanager
68 def ConsumeTemporaryFile(
69 self, suffix: str, all_data: bool = False, as_bytes: bool = True
70 ) -> str:
71 if all_data:
72 file_data = (
73 self.ConsumeRemainingBytes()
74 if as_bytes
75 else self.ConsumeRemainingString()
76 )
77 else:
78 file_data = (
79 self.ConsumeRandomBytes() if as_bytes else self.ConsumeRandomString()
80 )
82 mode = "w+b" if as_bytes else "w+"
83 tfile = tempfile.NamedTemporaryFile(mode=mode, suffix=suffix)
84 tfile.write(file_data)
85 tfile.seek(0)
86 tfile.flush()
87 yield tfile.name
88 tfile.close()
90 def ConsumeEnum(self, enum_type: Type[T]) -> T:
91 return enum_type(self.ConsumeIntInRange(0, enum_type.MAX))