160 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			160 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 39a1aa65fb4163d917131b4814d4c2dd2bf19677 Mon Sep 17 00:00:00 2001
 | 
						|
From: Lumir Balhar <lbalhar@redhat.com>
 | 
						|
Date: Wed, 24 Jul 2024 12:43:20 +0200
 | 
						|
Subject: [PATCH] CVE-2024-6345
 | 
						|
 | 
						|
---
 | 
						|
 setuptools/package_index.py           | 23 +++++++++-------------
 | 
						|
 setuptools/tests/test_packageindex.py | 28 +++++++++++++--------------
 | 
						|
 2 files changed, 23 insertions(+), 28 deletions(-)
 | 
						|
 | 
						|
diff --git a/setuptools/package_index.py b/setuptools/package_index.py
 | 
						|
index 123e9582b..07cc8924b 100644
 | 
						|
--- a/setuptools/package_index.py
 | 
						|
+++ b/setuptools/package_index.py
 | 
						|
@@ -1,4 +1,5 @@
 | 
						|
 """PyPI and direct package downloading"""
 | 
						|
+import subprocess
 | 
						|
 import sys
 | 
						|
 import os
 | 
						|
 import re
 | 
						|
@@ -860,7 +861,7 @@ class PackageIndex(Environment):
 | 
						|
     def _download_svn(self, url, filename):
 | 
						|
         warnings.warn("SVN download support is deprecated", UserWarning)
 | 
						|
         url = url.split('#', 1)[0]  # remove any fragment for svn's sake
 | 
						|
-        creds = ''
 | 
						|
+        creds = []
 | 
						|
         if url.lower().startswith('svn:') and '@' in url:
 | 
						|
             scheme, netloc, path, p, q, f = urllib.parse.urlparse(url)
 | 
						|
             if not netloc and path.startswith('//') and '/' in path[2:]:
 | 
						|
@@ -869,14 +870,14 @@ class PackageIndex(Environment):
 | 
						|
                 if auth:
 | 
						|
                     if ':' in auth:
 | 
						|
                         user, pw = auth.split(':', 1)
 | 
						|
-                        creds = " --username=%s --password=%s" % (user, pw)
 | 
						|
+                        creds = [f"--username={user}", f"--password={pw}"]
 | 
						|
                     else:
 | 
						|
-                        creds = " --username=" + auth
 | 
						|
+                        creds = [f"--username={auth}"]
 | 
						|
                     netloc = host
 | 
						|
                     parts = scheme, netloc, url, p, q, f
 | 
						|
                     url = urllib.parse.urlunparse(parts)
 | 
						|
         self.info("Doing subversion checkout from %s to %s", url, filename)
 | 
						|
-        os.system("svn checkout%s -q %s %s" % (creds, url, filename))
 | 
						|
+        subprocess.check_call(["svn", "checkout"] + creds + ["-q", url, filename])
 | 
						|
         return filename
 | 
						|
 
 | 
						|
     @staticmethod
 | 
						|
@@ -902,14 +903,11 @@ class PackageIndex(Environment):
 | 
						|
         url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True)
 | 
						|
 
 | 
						|
         self.info("Doing git clone from %s to %s", url, filename)
 | 
						|
-        os.system("git clone --quiet %s %s" % (url, filename))
 | 
						|
+        subprocess.check_call(["git", "clone", "--quiet", url, filename])
 | 
						|
 
 | 
						|
         if rev is not None:
 | 
						|
             self.info("Checking out %s", rev)
 | 
						|
-            os.system("git -C %s checkout --quiet %s" % (
 | 
						|
-                filename,
 | 
						|
-                rev,
 | 
						|
-            ))
 | 
						|
+            subprocess.check_call(["git", "-C", filename, "checkout", "--quiet", rev])
 | 
						|
 
 | 
						|
         return filename
 | 
						|
 
 | 
						|
@@ -918,14 +916,11 @@ class PackageIndex(Environment):
 | 
						|
         url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True)
 | 
						|
 
 | 
						|
         self.info("Doing hg clone from %s to %s", url, filename)
 | 
						|
-        os.system("hg clone --quiet %s %s" % (url, filename))
 | 
						|
+        subprocess.check_call(["hg", "clone", "--quiet", url, filename])
 | 
						|
 
 | 
						|
         if rev is not None:
 | 
						|
             self.info("Updating to %s", rev)
 | 
						|
-            os.system("hg --cwd %s up -C -r %s -q" % (
 | 
						|
-                filename,
 | 
						|
-                rev,
 | 
						|
-            ))
 | 
						|
+            subprocess.check_call(["hg", "--cwd", filename, "up", "-C", "-r", rev, "-q"])
 | 
						|
 
 | 
						|
         return filename
 | 
						|
 
 | 
						|
diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py
 | 
						|
index 8e9435efe..9289b9032 100644
 | 
						|
--- a/setuptools/tests/test_packageindex.py
 | 
						|
+++ b/setuptools/tests/test_packageindex.py
 | 
						|
@@ -197,56 +197,56 @@ class TestPackageIndex:
 | 
						|
         url = 'git+https://github.example/group/project@master#egg=foo'
 | 
						|
         index = setuptools.package_index.PackageIndex()
 | 
						|
 
 | 
						|
-        with mock.patch("os.system") as os_system_mock:
 | 
						|
+        with mock.patch("subprocess.check_call") as subprocess_check_call_mock:
 | 
						|
             result = index.download(url, str(tmpdir))
 | 
						|
 
 | 
						|
-        os_system_mock.assert_called()
 | 
						|
+        subprocess_check_call_mock.assert_called()
 | 
						|
 
 | 
						|
         expected_dir = str(tmpdir / 'project@master')
 | 
						|
         expected = (
 | 
						|
             'git clone --quiet '
 | 
						|
             'https://github.example/group/project {expected_dir}'
 | 
						|
-        ).format(**locals())
 | 
						|
-        first_call_args = os_system_mock.call_args_list[0][0]
 | 
						|
+        ).format(**locals()).split()
 | 
						|
+        first_call_args = subprocess_check_call_mock.call_args_list[0][0]
 | 
						|
         assert first_call_args == (expected,)
 | 
						|
 
 | 
						|
         tmpl = 'git -C {expected_dir} checkout --quiet master'
 | 
						|
-        expected = tmpl.format(**locals())
 | 
						|
-        assert os_system_mock.call_args_list[1][0] == (expected,)
 | 
						|
+        expected = tmpl.format(**locals()).split()
 | 
						|
+        assert subprocess_check_call_mock.call_args_list[1][0] == (expected,)
 | 
						|
         assert result == expected_dir
 | 
						|
 
 | 
						|
     def test_download_git_no_rev(self, tmpdir):
 | 
						|
         url = 'git+https://github.example/group/project#egg=foo'
 | 
						|
         index = setuptools.package_index.PackageIndex()
 | 
						|
 
 | 
						|
-        with mock.patch("os.system") as os_system_mock:
 | 
						|
+        with mock.patch("subprocess.check_call") as subprocess_check_call_mock:
 | 
						|
             result = index.download(url, str(tmpdir))
 | 
						|
 
 | 
						|
-        os_system_mock.assert_called()
 | 
						|
+        subprocess_check_call_mock.assert_called()
 | 
						|
 
 | 
						|
         expected_dir = str(tmpdir / 'project')
 | 
						|
         expected = (
 | 
						|
             'git clone --quiet '
 | 
						|
             'https://github.example/group/project {expected_dir}'
 | 
						|
-        ).format(**locals())
 | 
						|
-        os_system_mock.assert_called_once_with(expected)
 | 
						|
+        ).format(**locals()).split()
 | 
						|
+        subprocess_check_call_mock.assert_called_once_with(expected)
 | 
						|
 
 | 
						|
     def test_download_svn(self, tmpdir):
 | 
						|
         url = 'svn+https://svn.example/project#egg=foo'
 | 
						|
         index = setuptools.package_index.PackageIndex()
 | 
						|
 
 | 
						|
         with pytest.warns(UserWarning):
 | 
						|
-            with mock.patch("os.system") as os_system_mock:
 | 
						|
+            with mock.patch("subprocess.check_call") as subprocess_check_call_mock:
 | 
						|
                 result = index.download(url, str(tmpdir))
 | 
						|
 
 | 
						|
-        os_system_mock.assert_called()
 | 
						|
+        subprocess_check_call_mock.assert_called()
 | 
						|
 
 | 
						|
         expected_dir = str(tmpdir / 'project')
 | 
						|
         expected = (
 | 
						|
             'svn checkout -q '
 | 
						|
             'svn+https://svn.example/project {expected_dir}'
 | 
						|
-        ).format(**locals())
 | 
						|
-        os_system_mock.assert_called_once_with(expected)
 | 
						|
+        ).format(**locals()).split()
 | 
						|
+        subprocess_check_call_mock.assert_called_once_with(expected)
 | 
						|
 
 | 
						|
 
 | 
						|
 class TestContentCheckers:
 | 
						|
-- 
 | 
						|
2.45.2
 | 
						|
 |