Skip to content

Commit 8502efe

Browse files
authored
Merge pull request #1922 from DaveLak/fix-fuzz-submodule-expected-exceptions-handling
Add graceful handling of expected exceptions in fuzz_submodule.py
2 parents 2345c1a + 2b64dee commit 8502efe

File tree

2 files changed

+44
-11
lines changed

2 files changed

+44
-11
lines changed

fuzzing/fuzz-targets/fuzz_submodule.py

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,23 @@
33
import os
44
import tempfile
55
from configparser import ParsingError
6-
from utils import is_expected_exception_message
6+
from utils import is_expected_exception_message, get_max_filename_length
7+
from git import Repo, GitCommandError, InvalidGitRepositoryError
78

8-
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
9+
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"): # pragma: no cover
910
path_to_bundled_git_binary = os.path.abspath(os.path.join(os.path.dirname(__file__), "git"))
1011
os.environ["GIT_PYTHON_GIT_EXECUTABLE"] = path_to_bundled_git_binary
1112

12-
with atheris.instrument_imports():
13-
from git import Repo, GitCommandError, InvalidGitRepositoryError
13+
if not sys.warnoptions: # pragma: no cover
14+
# The warnings filter below can be overridden by passing the -W option
15+
# to the Python interpreter command line or setting the `PYTHONWARNINGS` environment variable.
16+
import warnings
17+
import logging
18+
19+
# Fuzzing data causes some modules to generate a large number of warnings
20+
# which are not usually interesting and make the test output hard to read, so we ignore them.
21+
warnings.simplefilter("ignore")
22+
logging.getLogger().setLevel(logging.ERROR)
1423

1524

1625
def TestOneInput(data):
@@ -42,12 +51,12 @@ def TestOneInput(data):
4251
writer.release()
4352

4453
submodule.update(init=fdp.ConsumeBool(), dry_run=fdp.ConsumeBool(), force=fdp.ConsumeBool())
45-
4654
submodule_repo = submodule.module()
47-
new_file_path = os.path.join(
48-
submodule_repo.working_tree_dir,
49-
f"new_file_{fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(1, 512))}",
55+
56+
new_file_name = fdp.ConsumeUnicodeNoSurrogates(
57+
fdp.ConsumeIntInRange(1, max(1, get_max_filename_length(submodule_repo.working_tree_dir)))
5058
)
59+
new_file_path = os.path.join(submodule_repo.working_tree_dir, new_file_name)
5160
with open(new_file_path, "wb") as new_file:
5261
new_file.write(fdp.ConsumeBytes(fdp.ConsumeIntInRange(1, 512)))
5362
submodule_repo.index.add([new_file_path])
@@ -67,16 +76,24 @@ def TestOneInput(data):
6776
)
6877
repo.index.commit(f"Removed submodule {submodule_name}")
6978

70-
except (ParsingError, GitCommandError, InvalidGitRepositoryError, FileNotFoundError, BrokenPipeError):
79+
except (
80+
ParsingError,
81+
GitCommandError,
82+
InvalidGitRepositoryError,
83+
FileNotFoundError,
84+
FileExistsError,
85+
IsADirectoryError,
86+
NotADirectoryError,
87+
BrokenPipeError,
88+
):
7189
return -1
72-
except (ValueError, OSError) as e:
90+
except ValueError as e:
7391
expected_messages = [
7492
"SHA is empty",
7593
"Reference at",
7694
"embedded null byte",
7795
"This submodule instance does not exist anymore",
7896
"cmd stdin was empty",
79-
"File name too long",
8097
]
8198
if is_expected_exception_message(e, expected_messages):
8299
return -1
@@ -85,6 +102,7 @@ def TestOneInput(data):
85102

86103

87104
def main():
105+
atheris.instrument_all()
88106
atheris.Setup(sys.argv, TestOneInput)
89107
atheris.Fuzz()
90108

fuzzing/fuzz-targets/utils.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import atheris # pragma: no cover
2+
import os # pragma: no cover
23
from typing import List # pragma: no cover
34

45

@@ -20,3 +21,17 @@ def is_expected_exception_message(exception: Exception, error_message_list: List
2021
if error.lower() in exception_message:
2122
return True
2223
return False
24+
25+
26+
@atheris.instrument_func
27+
def get_max_filename_length(path: str) -> int: # pragma: no cover
28+
"""
29+
Get the maximum filename length for the filesystem containing the given path.
30+
31+
Args:
32+
path (str): The path to check the filesystem for.
33+
34+
Returns:
35+
int: The maximum filename length.
36+
"""
37+
return os.pathconf(path, "PC_NAME_MAX")

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy