mirror of
https://github.com/python/cpython.git
synced 2026-06-27 19:36:07 +00:00
[3.15] gh-80198: Improve test_pwd and test_grp (GH-150380) (GH-150398)
Fix tests for non-existing names and ids when getpwall()/getgrall()
don't return all users/groups.
Add tests for out-of-range uids, integer float ids, bytes names,
null-terminated names, names with surrogates, empty names, excessive
arguments.
(cherry picked from commit 46e8f7a9e7)
This commit is contained in:
parent
e2362aac34
commit
4bdff2cc89
2 changed files with 90 additions and 98 deletions
|
|
@ -1,5 +1,7 @@
|
|||
"""Test script for the grp module."""
|
||||
|
||||
import random
|
||||
import string
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
|
||||
|
|
@ -50,61 +52,51 @@ def test_values_extended(self):
|
|||
def test_errors(self):
|
||||
self.assertRaises(TypeError, grp.getgrgid)
|
||||
self.assertRaises(TypeError, grp.getgrgid, 3.14)
|
||||
self.assertRaises(TypeError, grp.getgrgid, 0.0)
|
||||
self.assertRaises(TypeError, grp.getgrgid, 0, 0)
|
||||
# should be out of gid_t range
|
||||
self.assertRaises(OverflowError, grp.getgrgid, 2**128)
|
||||
self.assertRaises(OverflowError, grp.getgrgid, -2**128)
|
||||
self.assertRaises(TypeError, grp.getgrnam)
|
||||
self.assertRaises(TypeError, grp.getgrnam, 42)
|
||||
self.assertRaises(TypeError, grp.getgrall, 42)
|
||||
self.assertRaises(TypeError, grp.getgrnam, b'root')
|
||||
self.assertRaises(TypeError, grp.getgrnam, 'root', 0)
|
||||
# embedded null character
|
||||
self.assertRaisesRegex(ValueError, 'null', grp.getgrnam, 'a\x00b')
|
||||
self.assertRaisesRegex(ValueError, 'null', grp.getgrnam, 'root\x00')
|
||||
self.assertRaises(UnicodeEncodeError, grp.getgrnam, 'roo\udc74')
|
||||
self.assertRaises(KeyError, grp.getgrnam, '')
|
||||
self.assertRaises(TypeError, grp.getgrall, 42)
|
||||
|
||||
# try to get some errors
|
||||
bynames = {}
|
||||
bygids = {}
|
||||
for (n, p, g, mem) in grp.getgrall():
|
||||
if not n or n == '+':
|
||||
continue # skip NIS entries etc.
|
||||
bynames[n] = g
|
||||
bygids[g] = n
|
||||
# Find a non-existent group name.
|
||||
# getgrall() will not necessarily report all existing groups
|
||||
# (typical for LDAP based directories in big organizations).
|
||||
for _ in range(30):
|
||||
fakename = ''.join(random.choices(string.ascii_lowercase, k=6))
|
||||
try:
|
||||
grp.getgrnam(fakename)
|
||||
except KeyError:
|
||||
break
|
||||
else:
|
||||
self.fail('Cannot find non-existent group name')
|
||||
|
||||
allnames = list(bynames.keys())
|
||||
namei = 0
|
||||
fakename = allnames[namei]
|
||||
while fakename in bynames:
|
||||
chars = list(fakename)
|
||||
for i in range(len(chars)):
|
||||
if chars[i] == 'z':
|
||||
chars[i] = 'A'
|
||||
break
|
||||
elif chars[i] == 'Z':
|
||||
continue
|
||||
# Find a non-existent gid.
|
||||
maxgid = 2**31
|
||||
for _ in range(30):
|
||||
fakegid = random.randrange(maxgid)
|
||||
try:
|
||||
grp.getgrgid(fakegid)
|
||||
except KeyError:
|
||||
break
|
||||
except OverflowError:
|
||||
if maxgid == 2**31:
|
||||
maxgid = 2**16-1
|
||||
elif maxgid == 2**16-1:
|
||||
maxgid = 2**15
|
||||
else:
|
||||
chars[i] = chr(ord(chars[i]) + 1)
|
||||
break
|
||||
else:
|
||||
namei = namei + 1
|
||||
try:
|
||||
fakename = allnames[namei]
|
||||
except IndexError:
|
||||
# should never happen... if so, just forget it
|
||||
break
|
||||
fakename = ''.join(chars)
|
||||
|
||||
self.assertRaises(KeyError, grp.getgrnam, fakename)
|
||||
|
||||
# Choose a non-existent gid.
|
||||
fakegid = 4127
|
||||
while fakegid in bygids:
|
||||
fakegid = (fakegid * 3) % 0x10000
|
||||
|
||||
self.assertRaises(KeyError, grp.getgrgid, fakegid)
|
||||
|
||||
def test_noninteger_gid(self):
|
||||
entries = grp.getgrall()
|
||||
if not entries:
|
||||
self.skipTest('no groups')
|
||||
# Choose an existent gid.
|
||||
gid = entries[0][2]
|
||||
self.assertRaises(TypeError, grp.getgrgid, float(gid))
|
||||
self.assertRaises(TypeError, grp.getgrgid, str(gid))
|
||||
raise
|
||||
else:
|
||||
self.fail('Cannot find non-existent gid')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import random
|
||||
import string
|
||||
import sys
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
|
|
@ -56,59 +58,57 @@ def test_values_extended(self):
|
|||
def test_errors(self):
|
||||
self.assertRaises(TypeError, pwd.getpwuid)
|
||||
self.assertRaises(TypeError, pwd.getpwuid, 3.14)
|
||||
self.assertRaises(TypeError, pwd.getpwnam)
|
||||
self.assertRaises(TypeError, pwd.getpwnam, 42)
|
||||
self.assertRaises(TypeError, pwd.getpwall, 42)
|
||||
# embedded null character
|
||||
self.assertRaisesRegex(ValueError, 'null', pwd.getpwnam, 'a\x00b')
|
||||
|
||||
# try to get some errors
|
||||
bynames = {}
|
||||
byuids = {}
|
||||
for (n, p, u, g, gecos, d, s) in pwd.getpwall():
|
||||
bynames[n] = u
|
||||
byuids[u] = n
|
||||
|
||||
allnames = list(bynames.keys())
|
||||
namei = 0
|
||||
fakename = allnames[namei] if allnames else "invaliduser"
|
||||
while fakename in bynames:
|
||||
chars = list(fakename)
|
||||
for i in range(len(chars)):
|
||||
if chars[i] == 'z':
|
||||
chars[i] = 'A'
|
||||
break
|
||||
elif chars[i] == 'Z':
|
||||
continue
|
||||
else:
|
||||
chars[i] = chr(ord(chars[i]) + 1)
|
||||
break
|
||||
else:
|
||||
namei = namei + 1
|
||||
try:
|
||||
fakename = allnames[namei]
|
||||
except IndexError:
|
||||
# should never happen... if so, just forget it
|
||||
break
|
||||
fakename = ''.join(chars)
|
||||
|
||||
self.assertRaises(KeyError, pwd.getpwnam, fakename)
|
||||
|
||||
# In some cases, byuids isn't a complete list of all users in the
|
||||
# system, so if we try to pick a value not in byuids (via a perturbing
|
||||
# loop, say), pwd.getpwuid() might still be able to find data for that
|
||||
# uid. Using sys.maxint may provoke the same problems, but hopefully
|
||||
# it will be a more repeatable failure.
|
||||
fakeuid = sys.maxsize
|
||||
self.assertNotIn(fakeuid, byuids)
|
||||
self.assertRaises(KeyError, pwd.getpwuid, fakeuid)
|
||||
|
||||
# -1 shouldn't be a valid uid because it has a special meaning in many
|
||||
# uid-related functions
|
||||
self.assertRaises(KeyError, pwd.getpwuid, -1)
|
||||
self.assertRaises(TypeError, pwd.getpwuid, 0.0)
|
||||
self.assertRaises(TypeError, pwd.getpwuid, 0, 0)
|
||||
# should be out of uid_t range
|
||||
self.assertRaises(KeyError, pwd.getpwuid, 2**128)
|
||||
self.assertRaises(KeyError, pwd.getpwuid, -2**128)
|
||||
self.assertRaises(TypeError, pwd.getpwnam)
|
||||
self.assertRaises(TypeError, pwd.getpwnam, 42)
|
||||
self.assertRaises(TypeError, pwd.getpwnam, b'root')
|
||||
self.assertRaises(TypeError, pwd.getpwnam, 'root', 0)
|
||||
# embedded null character
|
||||
self.assertRaisesRegex(ValueError, 'null', pwd.getpwnam, 'a\x00b')
|
||||
self.assertRaisesRegex(ValueError, 'null', pwd.getpwnam, 'root\x00')
|
||||
self.assertRaises(UnicodeEncodeError, pwd.getpwnam, 'roo\udc74')
|
||||
self.assertRaises(KeyError, pwd.getpwnam, '')
|
||||
self.assertRaises(TypeError, pwd.getpwall, 42)
|
||||
|
||||
# Find a non-existent user name.
|
||||
# getpwall() will not necessarily report all existing users
|
||||
# (typical for LDAP based directories in big organizations).
|
||||
for _ in range(30):
|
||||
fakename = ''.join(random.choices(string.ascii_lowercase, k=6))
|
||||
try:
|
||||
pwd.getpwnam(fakename)
|
||||
except KeyError:
|
||||
break
|
||||
else:
|
||||
self.fail('Cannot find non-existent user name')
|
||||
|
||||
# Find a non-existent uid.
|
||||
maxuid = max(e.pw_uid for e in pwd.getpwall())
|
||||
if maxuid < 2**15:
|
||||
maxuid = 2**15
|
||||
elif maxuid < 2**16:
|
||||
maxuid = 2**16-1
|
||||
else:
|
||||
maxuid = 2**31
|
||||
for _ in range(30):
|
||||
fakeuid = random.randrange(maxuid)
|
||||
try:
|
||||
pwd.getpwuid(fakeuid)
|
||||
except KeyError:
|
||||
break
|
||||
else:
|
||||
self.fail('Cannot find non-existent uid')
|
||||
|
||||
# On Cygwin, getpwuid(-1) returns 'Unknown+User' user
|
||||
if sys.platform != 'cygwin':
|
||||
# -1 shouldn't be a valid uid because it has a special meaning in many
|
||||
# uid-related functions
|
||||
self.assertRaises(KeyError, pwd.getpwuid, -1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue