Skip to content

Commit

Permalink
Fix IndexError in GitConfigParser when config value ends in new line
Browse files Browse the repository at this point in the history
Improve the guarding `if` check in `GitConfigParser`'s `string_decode`
function to safely handle empty strings and prevent `IndexError`s when
accessing string elements.

This resolves an IndexError in the `GitConfigParser`'s `.read()`
method when the config file contains a quoted value containing a
trailing new line.

Fixes:
#1887
  • Loading branch information
DaveLak committed Apr 22, 2024
1 parent bc7bd22 commit f6174e7
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 6 deletions.
6 changes: 1 addition & 5 deletions fuzzing/fuzz-targets/fuzz_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ def TestOneInput(data):
except (MissingSectionHeaderError, ParsingError, UnicodeDecodeError):
return -1 # Reject inputs raising expected exceptions
except (IndexError, ValueError) as e:
if isinstance(e, IndexError) and "string index out of range" in str(e):
# Known possibility that might be patched
# See: https://github.com/gitpython-developers/GitPython/issues/1887
pass
elif isinstance(e, ValueError) and "embedded null byte" in str(e):
if isinstance(e, ValueError) and "embedded null byte" in str(e):
# The `os.path.expanduser` function, which does not accept strings
# containing null bytes might raise this.
return -1
Expand Down
2 changes: 1 addition & 1 deletion git/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ def _read(self, fp: Union[BufferedReader, IO[bytes]], fpname: str) -> None:
e = None # None, or an exception.

def string_decode(v: str) -> str:
if v[-1] == "\\":
if v and v[-1] == "\\":
v = v[:-1]
# END cut trailing escapes to prevent decode error

Expand Down
8 changes: 8 additions & 0 deletions test/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ def test_multi_line_config(self):
)
self.assertEqual(len(config.sections()), 23)

def test_config_value_with_trailing_new_line(self):
config_content = b'[section-header]\nkey:"value\n"'
config_file = io.BytesIO(config_content)
config_file.name = "multiline_value.config"

git_config = GitConfigParser(config_file)
git_config.read() # This should not throw an exception

def test_base(self):
path_repo = fixture_path("git_config")
path_global = fixture_path("git_config_global")
Expand Down

0 comments on commit f6174e7

Please sign in to comment.