Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 20f5e42

Browse files
committed
CVE-2023-40590 Hand Cherry-Picking pull/1636
Fix syntax error Switch to mock Fix print function Get TemporaryDirectory for Python2 We don't really care about the encoding of the file Its a script Use six to get assertRegex Create a nullcontext Fix unicode problem Just use the Python2 methods
1 parent 09ac0a1 commit 20f5e42

File tree

4 files changed

+64
-16
lines changed

4 files changed

+64
-16
lines changed

git/cmd.py

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# This module is part of GitPython and is released under
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66

7-
from contextlib import contextmanager
7+
import contextlib
88
import io
99
import logging
1010
import os
@@ -19,6 +19,7 @@
1919
import threading
2020
from collections import OrderedDict
2121
from textwrap import dedent
22+
import mock
2223

2324
from git.compat import (
2425
string_types,
@@ -59,6 +60,11 @@
5960
__all__ = ('Git',)
6061

6162

63+
@contextlib.contextmanager
64+
def nullcontext(enter_result=None):
65+
yield enter_result
66+
67+
6268
# ==============================================================================
6369
## @name Utilities
6470
# ------------------------------------------------------------------------------
@@ -705,11 +711,15 @@ def execute(self, command,
705711
cmd_not_found_exception = OSError
706712
if kill_after_timeout:
707713
raise GitCommandError(command, '"kill_after_timeout" feature is not supported on Windows.')
714+
715+
# Only search PATH, not CWD. This must be in the *caller* environment. The "1" can be any value.
716+
patch_caller_env = unittest.mock.patch.dict(os.environ, {"NoDefaultCurrentDirectoryInExePath": "1"})
708717
else:
709718
if sys.version_info[0] > 2:
710719
cmd_not_found_exception = FileNotFoundError # NOQA # exists, flake8 unknown @UndefinedVariable
711720
else:
712721
cmd_not_found_exception = OSError
722+
patch_caller_env = nullcontext()
713723
# end handle
714724

715725
stdout_sink = (PIPE
@@ -721,19 +731,21 @@ def execute(self, command,
721731
log.debug("Popen(%s, cwd=%s, universal_newlines=%s, shell=%s, istream=%s)",
722732
command, cwd, universal_newlines, shell, istream_ok)
723733
try:
724-
proc = Popen(command,
725-
env=env,
726-
cwd=cwd,
727-
bufsize=-1,
728-
stdin=istream,
729-
stderr=PIPE,
730-
stdout=stdout_sink,
731-
shell=shell is not None and shell or self.USE_SHELL,
732-
close_fds=is_posix, # unsupported on windows
733-
universal_newlines=universal_newlines,
734-
creationflags=PROC_CREATIONFLAGS,
735-
**subprocess_kwargs
736-
)
734+
with patch_caller_env:
735+
proc = Popen(
736+
command,
737+
env=env,
738+
cwd=cwd,
739+
bufsize=-1,
740+
stdin=istream,
741+
stderr=PIPE,
742+
stdout=stdout_sink,
743+
shell=shell is not None and shell or self.USE_SHELL,
744+
close_fds=is_posix, # unsupported on windows
745+
universal_newlines=universal_newlines,
746+
creationflags=PROC_CREATIONFLAGS,
747+
**subprocess_kwargs
748+
)
737749
except cmd_not_found_exception as err:
738750
raise GitCommandNotFound(command, err)
739751

@@ -862,7 +874,7 @@ def update_environment(self, **kwargs):
862874
del self._environment[key]
863875
return old_env
864876

865-
@contextmanager
877+
@contextlib.contextmanager
866878
def custom_environment(self, **kwargs):
867879
"""
868880
A context manager around the above ``update_environment`` method to restore the

git/test/test_git.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,16 @@
44
#
55
# This module is part of GitPython and is released under
66
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
7+
from __future__ import print_function
8+
9+
import contextlib
710
import os
11+
import shutil
812
import subprocess
913
import sys
1014
from tempfile import TemporaryFile
15+
from backports.tempfile import TemporaryDirectory
16+
import six
1117

1218
from git import (
1319
Git,
@@ -40,6 +46,16 @@
4046

4147
from git.compat import is_win
4248

49+
@contextlib.contextmanager
50+
def _chdir(new_dir):
51+
"""Context manager to temporarily change directory. Not reentrant."""
52+
old_dir = os.getcwd()
53+
os.chdir(new_dir)
54+
try:
55+
yield
56+
finally:
57+
os.chdir(old_dir)
58+
4359

4460
class TestGit(TestBase):
4561

@@ -100,6 +116,24 @@ def test_it_transforms_kwargs_into_git_command_arguments(self):
100116
def test_it_executes_git_to_shell_and_returns_result(self):
101117
assert_match(r'^git version [\d\.]{2}.*$', self.git.execute(["git", "version"]))
102118

119+
def test_it_executes_git_not_from_cwd(self):
120+
with TemporaryDirectory() as tmpdir:
121+
if is_win:
122+
# Copy an actual binary executable that is not git.
123+
other_exe_path = os.path.join(os.getenv("WINDIR"), "system32", "hostname.exe")
124+
impostor_path = os.path.join(tmpdir, "git.exe")
125+
shutil.copy(other_exe_path, impostor_path)
126+
else:
127+
# Create a shell script that doesn't do anything.
128+
impostor_path = os.path.join(tmpdir, "git")
129+
with open(impostor_path, mode="w") as file:
130+
print("#!/bin/sh", file=file)
131+
os.chmod(impostor_path, 0o755)
132+
133+
with _chdir(tmpdir):
134+
# six.assertRegex(self.git.execute(["git", "version"]).encode("UTF-8"), r"^git version\b")
135+
self.assertRegexpMatches(self.git.execute(["git", "version"]), r"^git version\b")
136+
103137
def test_it_accepts_stdin(self):
104138
filename = fixture_path("cat_file_blob")
105139
with open(filename, 'r') as fh:

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
gitdb2>=2,<3
2+
mock

test-requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ coverage
33
flake8
44
nose
55
tox
6-
mock; python_version=='2.7'
6+
backports.tempfile
7+
six

0 commit comments

Comments
 (0)