Skip to content

Commit 17d0c05

Browse files
authored
bpo-10496: distutils check_environ() handles getpwuid() error (GH-10931)
check_environ() of distutils.utils now catchs KeyError on calling pwd.getpwuid(): don't create the HOME environment variable in this case.
1 parent e6b247c commit 17d0c05

File tree

3 files changed

+35
-11
lines changed

3 files changed

+35
-11
lines changed

‎Lib/distutils/tests/test_util.py‎

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import unittest
55
from copy import copy
66
from test.support import run_unittest
7+
from unittest import mock
78

89
from distutils.errors import DistutilsPlatformError, DistutilsByteCompileError
910
from distutils.util import (get_platform, convert_path, change_root,
@@ -234,20 +235,35 @@ def _join(*path):
234235

235236
def test_check_environ(self):
236237
util._environ_checked = 0
237-
if 'HOME' in os.environ:
238-
del os.environ['HOME']
238+
os.environ.pop('HOME', None)
239239

240-
# posix without HOME
241-
if os.name == 'posix': # this test won't run on windows
242-
check_environ()
243-
import pwd
244-
self.assertEqual(os.environ['HOME'], pwd.getpwuid(os.getuid())[5])
245-
else:
246-
check_environ()
240+
check_environ()
247241

248242
self.assertEqual(os.environ['PLAT'], get_platform())
249243
self.assertEqual(util._environ_checked, 1)
250244

245+
@unittest.skipUnless(os.name == 'posix', 'specific to posix')
246+
def test_check_environ_getpwuid(self):
247+
util._environ_checked = 0
248+
os.environ.pop('HOME', None)
249+
250+
import pwd
251+
252+
# only set pw_dir field, other fields are not used
253+
result = pwd.struct_passwd((None, None, None, None, None,
254+
'/home/distutils', None))
255+
with mock.patch.object(pwd, 'getpwuid', return_value=result):
256+
check_environ()
257+
self.assertEqual(os.environ['HOME'], '/home/distutils')
258+
259+
util._environ_checked = 0
260+
os.environ.pop('HOME', None)
261+
262+
# bpo-10496: Catch pwd.getpwuid() error
263+
with mock.patch.object(pwd, 'getpwuid', side_effect=KeyError):
264+
check_environ()
265+
self.assertNotIn('HOME', os.environ)
266+
251267
def test_split_quoted(self):
252268
self.assertEqual(split_quoted('""one"" "two" \'three\' \\four'),
253269
['one', 'two', 'three', 'four'])

‎Lib/distutils/util.py‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,13 @@ def check_environ ():
157157
return
158158

159159
if os.name == 'posix' and 'HOME' not in os.environ:
160-
import pwd
161-
os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
160+
try:
161+
import pwd
162+
os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
163+
except (ImportError, KeyError):
164+
# bpo-10496: if the current user identifier doesn't exist in the
165+
# password database, do nothing
166+
pass
162167

163168
if 'PLAT' not in os.environ:
164169
os.environ['PLAT'] = get_platform()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:func:`~distutils.utils.check_environ` of :mod:`distutils.utils` now catchs
2+
:exc:`KeyError` on calling :func:`pwd.getpwuid`: don't create the ``HOME``
3+
environment variable in this case.

0 commit comments

Comments
 (0)