]> granicus.if.org Git - python/commitdiff
bpo-10496: distutils check_environ() handles getpwuid() error (GH-10931)
authorVictor Stinner <vstinner@redhat.com>
Tue, 18 Dec 2018 15:17:56 +0000 (16:17 +0100)
committerGitHub <noreply@github.com>
Tue, 18 Dec 2018 15:17:56 +0000 (16:17 +0100)
check_environ() of distutils.utils now catchs KeyError on calling
pwd.getpwuid(): don't create the HOME environment variable in this
case.

Lib/distutils/tests/test_util.py
Lib/distutils/util.py
Misc/NEWS.d/next/Library/2018-12-05-17-42-49.bpo-10496.laV_IE.rst [new file with mode: 0644]

index e2fc3809587faa329f096846188a7df85edde48c..bf0d4333f9aeaad97720a44ca4e058501930b9dc 100644 (file)
@@ -4,6 +4,7 @@ import sys
 import unittest
 from copy import copy
 from test.support import run_unittest
+from unittest import mock
 
 from distutils.errors import DistutilsPlatformError, DistutilsByteCompileError
 from distutils.util import (get_platform, convert_path, change_root,
@@ -234,20 +235,35 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
 
     def test_check_environ(self):
         util._environ_checked = 0
-        if 'HOME' in os.environ:
-            del os.environ['HOME']
+        os.environ.pop('HOME', None)
 
-        # posix without HOME
-        if os.name == 'posix':  # this test won't run on windows
-            check_environ()
-            import pwd
-            self.assertEqual(os.environ['HOME'], pwd.getpwuid(os.getuid())[5])
-        else:
-            check_environ()
+        check_environ()
 
         self.assertEqual(os.environ['PLAT'], get_platform())
         self.assertEqual(util._environ_checked, 1)
 
+    @unittest.skipUnless(os.name == 'posix', 'specific to posix')
+    def test_check_environ_getpwuid(self):
+        util._environ_checked = 0
+        os.environ.pop('HOME', None)
+
+        import pwd
+
+        # only set pw_dir field, other fields are not used
+        result = pwd.struct_passwd((None, None, None, None, None,
+                                    '/home/distutils', None))
+        with mock.patch.object(pwd, 'getpwuid', return_value=result):
+            check_environ()
+            self.assertEqual(os.environ['HOME'], '/home/distutils')
+
+        util._environ_checked = 0
+        os.environ.pop('HOME', None)
+
+        # bpo-10496: Catch pwd.getpwuid() error
+        with mock.patch.object(pwd, 'getpwuid', side_effect=KeyError):
+            check_environ()
+            self.assertNotIn('HOME', os.environ)
+
     def test_split_quoted(self):
         self.assertEqual(split_quoted('""one"" "two" \'three\' \\four'),
                          ['one', 'two', 'three', 'four'])
index 83682628ba680cfc261c0aeb81d9bf0043c8554d..30a21e4afa1f74f6c7d99ef1fd3ea1c26bece00f 100644 (file)
@@ -157,8 +157,13 @@ def check_environ ():
         return
 
     if os.name == 'posix' and 'HOME' not in os.environ:
-        import pwd
-        os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
+        try:
+            import pwd
+            os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]
+        except (ImportError, KeyError):
+            # bpo-10496: if the current user identifier doesn't exist in the
+            # password database, do nothing
+            pass
 
     if 'PLAT' not in os.environ:
         os.environ['PLAT'] = get_platform()
diff --git a/Misc/NEWS.d/next/Library/2018-12-05-17-42-49.bpo-10496.laV_IE.rst b/Misc/NEWS.d/next/Library/2018-12-05-17-42-49.bpo-10496.laV_IE.rst
new file mode 100644 (file)
index 0000000..cbfe5eb
--- /dev/null
@@ -0,0 +1,3 @@
+:func:`~distutils.utils.check_environ` of :mod:`distutils.utils` now catchs
+:exc:`KeyError` on calling :func:`pwd.getpwuid`: don't create the ``HOME``
+environment variable in this case.