3.2.3-7: update uid/gid handling (patch 157; rhbz#697470)

* Tue May 15 2012 David Malcolm <dmalcolm@redhat.com> - 3.2.3-7
- update uid/gid handling to avoid int overflows seen with uid/gid
values >= 2^31 on 32-bit architectures (patch 157; rhbz#697470)
This commit is contained in:
David Malcolm 2012-05-18 14:57:53 -04:00
parent bbb50840b1
commit 7989368053
2 changed files with 707 additions and 1 deletions

View File

@ -0,0 +1,685 @@
diff -up Python-3.2.3/Include/modsupport.h.uid-gid-overflows Python-3.2.3/Include/modsupport.h
--- Python-3.2.3/Include/modsupport.h.uid-gid-overflows 2012-05-16 11:56:26.947069274 -0400
+++ Python-3.2.3/Include/modsupport.h 2012-05-16 11:56:26.545066073 -0400
@@ -122,6 +122,17 @@ PyAPI_FUNC(PyObject *) PyModule_Create2(
PyAPI_DATA(char *) _Py_PackageContext;
#endif
+/*
+ Non-standard extension: support for dealing with uid_t and gid_t without
+ integer overflow
+ */
+
+PyAPI_FUNC(PyObject *) _PyObject_FromUid(uid_t uid);
+PyAPI_FUNC(PyObject *) _PyObject_FromGid(gid_t gid);
+
+PyAPI_FUNC(int) _PyArg_ParseUid(PyObject *in_obj, uid_t *out_uid);
+PyAPI_FUNC(int) _PyArg_ParseGid(PyObject *in_obj, gid_t *out_gid);
+
#ifdef __cplusplus
}
#endif
diff -up Python-3.2.3/Lib/test/test_grp.py.uid-gid-overflows Python-3.2.3/Lib/test/test_grp.py
diff -up Python-3.2.3/Lib/test/test_os.py.uid-gid-overflows Python-3.2.3/Lib/test/test_os.py
--- Python-3.2.3/Lib/test/test_os.py.uid-gid-overflows 2012-05-16 11:56:50.427256400 -0400
+++ Python-3.2.3/Lib/test/test_os.py 2012-05-16 11:56:49.848251767 -0400
@@ -885,30 +885,36 @@ if sys.platform != 'win32':
def test_setuid(self):
if os.getuid() != 0:
self.assertRaises(os.error, os.setuid, 0)
+ self.assertRaises(TypeError, os.setuid, 'not an int')
self.assertRaises(OverflowError, os.setuid, 1<<32)
if hasattr(os, 'setgid'):
def test_setgid(self):
if os.getuid() != 0:
self.assertRaises(os.error, os.setgid, 0)
+ self.assertRaises(TypeError, os.setgid, 'not an int')
self.assertRaises(OverflowError, os.setgid, 1<<32)
if hasattr(os, 'seteuid'):
def test_seteuid(self):
if os.getuid() != 0:
self.assertRaises(os.error, os.seteuid, 0)
+ self.assertRaises(TypeError, os.seteuid, 'not an int')
self.assertRaises(OverflowError, os.seteuid, 1<<32)
if hasattr(os, 'setegid'):
def test_setegid(self):
if os.getuid() != 0:
self.assertRaises(os.error, os.setegid, 0)
+ self.assertRaises(TypeError, os.setegid, 'not an int')
self.assertRaises(OverflowError, os.setegid, 1<<32)
if hasattr(os, 'setreuid'):
def test_setreuid(self):
if os.getuid() != 0:
self.assertRaises(os.error, os.setreuid, 0, 0)
+ self.assertRaises(TypeError, os.setreuid, 'not an int', 0)
+ self.assertRaises(TypeError, os.setreuid, 0, 'not an int')
self.assertRaises(OverflowError, os.setreuid, 1<<32, 0)
self.assertRaises(OverflowError, os.setreuid, 0, 1<<32)
@@ -923,6 +929,8 @@ if sys.platform != 'win32':
def test_setregid(self):
if os.getuid() != 0:
self.assertRaises(os.error, os.setregid, 0, 0)
+ self.assertRaises(TypeError, os.setregid, 'not an int', 0)
+ self.assertRaises(TypeError, os.setregid, 0, 'not an int')
self.assertRaises(OverflowError, os.setregid, 1<<32, 0)
self.assertRaises(OverflowError, os.setregid, 0, 1<<32)
diff -up Python-3.2.3/Lib/test/test_posix.py.uid-gid-overflows Python-3.2.3/Lib/test/test_posix.py
--- Python-3.2.3/Lib/test/test_posix.py.uid-gid-overflows 2012-05-16 11:56:51.579265577 -0400
+++ Python-3.2.3/Lib/test/test_posix.py 2012-05-16 11:56:47.142230218 -0400
@@ -227,7 +227,7 @@ class PosixTester(unittest.TestCase):
else:
self.assertTrue(stat.S_ISFIFO(posix.stat(support.TESTFN).st_mode))
- def _test_all_chown_common(self, chown_func, first_param):
+ def _test_all_chown_common(self, chown_func, stat_func, first_param):
"""Common code for chown, fchown and lchown tests."""
if os.getuid() == 0:
try:
@@ -246,6 +246,13 @@ class PosixTester(unittest.TestCase):
first_param, 0, 0)
# test a successful chown call
chown_func(first_param, os.getuid(), os.getgid())
+ self.assertEqual(stat_func(first_param).st_uid, os.getuid())
+ self.assertEqual(stat_func(first_param).st_gid, os.getgid())
+
+ # verify that -1 works as a "do-nothing" option:
+ chown_func(first_param, -1, -1)
+ self.assertEqual(stat_func(first_param).st_uid, os.getuid())
+ self.assertEqual(stat_func(first_param).st_gid, os.getgid())
@unittest.skipUnless(hasattr(posix, 'chown'), "test needs os.chown()")
def test_chown(self):
@@ -255,7 +262,7 @@ class PosixTester(unittest.TestCase):
# re-create the file
open(support.TESTFN, 'w').close()
- self._test_all_chown_common(posix.chown, support.TESTFN)
+ self._test_all_chown_common(posix.chown, posix.stat, support.TESTFN)
@unittest.skipUnless(hasattr(posix, 'fchown'), "test needs os.fchown()")
def test_fchown(self):
@@ -265,7 +272,7 @@ class PosixTester(unittest.TestCase):
test_file = open(support.TESTFN, 'w')
try:
fd = test_file.fileno()
- self._test_all_chown_common(posix.fchown, fd)
+ self._test_all_chown_common(posix.fchown, posix.fstat, fd)
finally:
test_file.close()
@@ -274,7 +281,7 @@ class PosixTester(unittest.TestCase):
os.unlink(support.TESTFN)
# create a symlink
os.symlink(_DUMMY_SYMLINK, support.TESTFN)
- self._test_all_chown_common(posix.lchown, support.TESTFN)
+ self._test_all_chown_common(posix.lchown, posix.lstat, support.TESTFN)
def test_chdir(self):
if hasattr(posix, 'chdir'):
diff -up Python-3.2.3/Lib/test/test_pwd.py.uid-gid-overflows Python-3.2.3/Lib/test/test_pwd.py
--- Python-3.2.3/Lib/test/test_pwd.py.uid-gid-overflows 2012-05-16 11:56:47.171230447 -0400
+++ Python-3.2.3/Lib/test/test_pwd.py 2012-05-17 14:52:07.425548111 -0400
@@ -87,9 +87,9 @@ class PwdTest(unittest.TestCase):
# 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
+ # uid. Using 2**32 - 2 may provoke the same problems, but hopefully
# it will be a more repeatable failure.
- fakeuid = sys.maxsize
+ fakeuid = 2**32 - 2
self.assertNotIn(fakeuid, byuids)
self.assertRaises(KeyError, pwd.getpwuid, fakeuid)
diff -up Python-3.2.3/Modules/grpmodule.c.uid-gid-overflows Python-3.2.3/Modules/grpmodule.c
--- Python-3.2.3/Modules/grpmodule.c.uid-gid-overflows 2012-05-16 11:56:20.025014112 -0400
+++ Python-3.2.3/Modules/grpmodule.c 2012-05-16 11:56:19.682011408 -0400
@@ -69,7 +69,7 @@ mkgrent(struct group *p)
Py_INCREF(Py_None);
}
#endif
- SET(setIndex++, PyLong_FromLong((long) p->gr_gid));
+ SET(setIndex++, _PyObject_FromGid(p->gr_gid));
SET(setIndex++, w);
#undef SET
@@ -84,18 +84,16 @@ mkgrent(struct group *p)
static PyObject *
grp_getgrgid(PyObject *self, PyObject *pyo_id)
{
- PyObject *py_int_id;
- unsigned int gid;
+ gid_t gid;
struct group *p;
- py_int_id = PyNumber_Long(pyo_id);
- if (!py_int_id)
- return NULL;
- gid = PyLong_AS_LONG(py_int_id);
- Py_DECREF(py_int_id);
+ if (!_PyArg_ParseGid(pyo_id, &gid)) {
+ return NULL;
+ }
if ((p = getgrgid(gid)) == NULL) {
- PyErr_Format(PyExc_KeyError, "getgrgid(): gid not found: %d", gid);
+ PyErr_Format(PyExc_KeyError,
+ "getgrgid(): gid not found: %lu", (unsigned long)gid);
return NULL;
}
return mkgrent(p);
diff -up Python-3.2.3/Modules/posixmodule.c.uid-gid-overflows Python-3.2.3/Modules/posixmodule.c
--- Python-3.2.3/Modules/posixmodule.c.uid-gid-overflows 2012-05-16 11:56:23.722043536 -0400
+++ Python-3.2.3/Modules/posixmodule.c 2012-05-16 11:56:23.836044488 -0400
@@ -1642,8 +1642,8 @@ _pystat_fromstructstat(STRUCT_STAT *st)
PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long)st->st_dev));
#endif
PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
- PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long)st->st_uid));
- PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long)st->st_gid));
+ PyStructSequence_SET_ITEM(v, 4, _PyObject_FromUid(st->st_uid));
+ PyStructSequence_SET_ITEM(v, 5, _PyObject_FromGid(st->st_gid));
#ifdef HAVE_LARGEFILE_SUPPORT
PyStructSequence_SET_ITEM(v, 6,
PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
@@ -2172,15 +2172,17 @@ posix_chown(PyObject *self, PyObject *ar
{
PyObject *opath;
char *path;
- long uid, gid;
+ uid_t uid;
+ gid_t gid;
int res;
- if (!PyArg_ParseTuple(args, "O&ll:chown",
+ if (!PyArg_ParseTuple(args, "O&O&O&:chown",
PyUnicode_FSConverter, &opath,
- &uid, &gid))
+ _PyArg_ParseUid, &uid,
+ _PyArg_ParseGid, &gid))
return NULL;
path = PyBytes_AsString(opath);
Py_BEGIN_ALLOW_THREADS
- res = chown(path, (uid_t) uid, (gid_t) gid);
+ res = chown(path, uid, gid);
Py_END_ALLOW_THREADS
if (res < 0)
return posix_error_with_allocated_filename(opath);
@@ -2200,12 +2202,15 @@ static PyObject *
posix_fchown(PyObject *self, PyObject *args)
{
int fd;
- long uid, gid;
+ uid_t uid;
+ gid_t gid;
int res;
- if (!PyArg_ParseTuple(args, "ill:fchown", &fd, &uid, &gid))
+ if (!PyArg_ParseTuple(args, "iO&O&:chown", &fd,
+ _PyArg_ParseUid, &uid,
+ _PyArg_ParseGid, &gid))
return NULL;
Py_BEGIN_ALLOW_THREADS
- res = fchown(fd, (uid_t) uid, (gid_t) gid);
+ res = fchown(fd, uid, gid);
Py_END_ALLOW_THREADS
if (res < 0)
return posix_error();
@@ -2224,15 +2229,17 @@ posix_lchown(PyObject *self, PyObject *a
{
PyObject *opath;
char *path;
- long uid, gid;
+ uid_t uid;
+ gid_t gid;
int res;
- if (!PyArg_ParseTuple(args, "O&ll:lchown",
+ if (!PyArg_ParseTuple(args, "O&O&O&:lchown",
PyUnicode_FSConverter, &opath,
- &uid, &gid))
+ _PyArg_ParseUid, &uid,
+ _PyArg_ParseGid, &gid))
return NULL;
path = PyBytes_AsString(opath);
Py_BEGIN_ALLOW_THREADS
- res = lchown(path, (uid_t) uid, (gid_t) gid);
+ res = lchown(path, uid, gid);
Py_END_ALLOW_THREADS
if (res < 0)
return posix_error_with_allocated_filename(opath);
@@ -4287,7 +4294,7 @@ Return the current process's effective g
static PyObject *
posix_getegid(PyObject *self, PyObject *noargs)
{
- return PyLong_FromLong((long)getegid());
+ return _PyObject_FromGid(getegid());
}
#endif
@@ -4300,7 +4307,7 @@ Return the current process's effective u
static PyObject *
posix_geteuid(PyObject *self, PyObject *noargs)
{
- return PyLong_FromLong((long)geteuid());
+ return _PyObject_FromUid(geteuid());
}
#endif
@@ -4313,7 +4320,7 @@ Return the current process's group id.")
static PyObject *
posix_getgid(PyObject *self, PyObject *noargs)
{
- return PyLong_FromLong((long)getgid());
+ return _PyObject_FromGid(getgid());
}
#endif
@@ -4388,7 +4395,7 @@ posix_getgroups(PyObject *self, PyObject
if (result != NULL) {
int i;
for (i = 0; i < n; ++i) {
- PyObject *o = PyLong_FromLong((long)alt_grouplist[i]);
+ PyObject *o = _PyObject_FromGid(alt_grouplist[i]);
if (o == NULL) {
Py_DECREF(result);
result = NULL;
@@ -4419,14 +4426,15 @@ posix_initgroups(PyObject *self, PyObjec
PyObject *oname;
char *username;
int res;
- long gid;
+ gid_t gid;
- if (!PyArg_ParseTuple(args, "O&l:initgroups",
- PyUnicode_FSConverter, &oname, &gid))
+ if (!PyArg_ParseTuple(args, "O&O&:initgroups",
+ PyUnicode_FSConverter, &oname,
+ _PyArg_ParseGid, &gid))
return NULL;
username = PyBytes_AS_STRING(oname);
- res = initgroups(username, (gid_t) gid);
+ res = initgroups(username, gid);
Py_DECREF(oname);
if (res == -1)
return PyErr_SetFromErrno(PyExc_OSError);
@@ -4601,7 +4609,7 @@ Return the current process's user id.");
static PyObject *
posix_getuid(PyObject *self, PyObject *noargs)
{
- return PyLong_FromLong((long)getuid());
+ return _PyObject_FromUid(getuid());
}
#endif
@@ -4741,15 +4749,9 @@ Set the current process's user id.");
static PyObject *
posix_setuid(PyObject *self, PyObject *args)
{
- long uid_arg;
uid_t uid;
- if (!PyArg_ParseTuple(args, "l:setuid", &uid_arg))
- return NULL;
- uid = uid_arg;
- if (uid != uid_arg) {
- PyErr_SetString(PyExc_OverflowError, "user id too big");
+ if (!PyArg_ParseTuple(args, "O&:setuid", _PyArg_ParseUid, &uid))
return NULL;
- }
if (setuid(uid) < 0)
return posix_error();
Py_INCREF(Py_None);
@@ -4766,15 +4768,9 @@ Set the current process's effective user
static PyObject *
posix_seteuid (PyObject *self, PyObject *args)
{
- long euid_arg;
uid_t euid;
- if (!PyArg_ParseTuple(args, "l", &euid_arg))
- return NULL;
- euid = euid_arg;
- if (euid != euid_arg) {
- PyErr_SetString(PyExc_OverflowError, "user id too big");
+ if (!PyArg_ParseTuple(args, "O&:seteuid", _PyArg_ParseUid, &euid))
return NULL;
- }
if (seteuid(euid) < 0) {
return posix_error();
} else {
@@ -4792,15 +4788,9 @@ Set the current process's effective grou
static PyObject *
posix_setegid (PyObject *self, PyObject *args)
{
- long egid_arg;
gid_t egid;
- if (!PyArg_ParseTuple(args, "l", &egid_arg))
- return NULL;
- egid = egid_arg;
- if (egid != egid_arg) {
- PyErr_SetString(PyExc_OverflowError, "group id too big");
+ if (!PyArg_ParseTuple(args, "O&:setegid", _PyArg_ParseGid, &egid))
return NULL;
- }
if (setegid(egid) < 0) {
return posix_error();
} else {
@@ -4818,23 +4808,11 @@ Set the current process's real and effec
static PyObject *
posix_setreuid (PyObject *self, PyObject *args)
{
- long ruid_arg, euid_arg;
uid_t ruid, euid;
- if (!PyArg_ParseTuple(args, "ll", &ruid_arg, &euid_arg))
- return NULL;
- if (ruid_arg == -1)
- ruid = (uid_t)-1; /* let the compiler choose how -1 fits */
- else
- ruid = ruid_arg; /* otherwise, assign from our long */
- if (euid_arg == -1)
- euid = (uid_t)-1;
- else
- euid = euid_arg;
- if ((euid_arg != -1 && euid != euid_arg) ||
- (ruid_arg != -1 && ruid != ruid_arg)) {
- PyErr_SetString(PyExc_OverflowError, "user id too big");
+ if (!PyArg_ParseTuple(args, "O&O&",
+ _PyArg_ParseUid, &ruid,
+ _PyArg_ParseUid, &euid))
return NULL;
- }
if (setreuid(ruid, euid) < 0) {
return posix_error();
} else {
@@ -4852,23 +4830,11 @@ Set the current process's real and effec
static PyObject *
posix_setregid (PyObject *self, PyObject *args)
{
- long rgid_arg, egid_arg;
gid_t rgid, egid;
- if (!PyArg_ParseTuple(args, "ll", &rgid_arg, &egid_arg))
- return NULL;
- if (rgid_arg == -1)
- rgid = (gid_t)-1; /* let the compiler choose how -1 fits */
- else
- rgid = rgid_arg; /* otherwise, assign from our long */
- if (egid_arg == -1)
- egid = (gid_t)-1;
- else
- egid = egid_arg;
- if ((egid_arg != -1 && egid != egid_arg) ||
- (rgid_arg != -1 && rgid != rgid_arg)) {
- PyErr_SetString(PyExc_OverflowError, "group id too big");
+ if (!PyArg_ParseTuple(args, "O&O&",
+ _PyArg_ParseGid, &rgid,
+ _PyArg_ParseGid, &egid))
return NULL;
- }
if (setregid(rgid, egid) < 0) {
return posix_error();
} else {
@@ -4886,15 +4852,9 @@ Set the current process's group id.");
static PyObject *
posix_setgid(PyObject *self, PyObject *args)
{
- long gid_arg;
gid_t gid;
- if (!PyArg_ParseTuple(args, "l:setgid", &gid_arg))
+ if (!PyArg_ParseTuple(args, "O&:setgid", _PyArg_ParseGid, &gid))
return NULL;
- gid = gid_arg;
- if (gid != gid_arg) {
- PyErr_SetString(PyExc_OverflowError, "group id too big");
- return NULL;
- }
if (setgid(gid) < 0)
return posix_error();
Py_INCREF(Py_None);
@@ -4927,27 +4887,9 @@ posix_setgroups(PyObject *self, PyObject
elem = PySequence_GetItem(groups, i);
if (!elem)
return NULL;
- if (!PyLong_Check(elem)) {
- PyErr_SetString(PyExc_TypeError,
- "groups must be integers");
+ if (!_PyArg_ParseGid(elem, &grouplist[i])) {
Py_DECREF(elem);
return NULL;
- } else {
- unsigned long x = PyLong_AsUnsignedLong(elem);
- if (PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError,
- "group id too big");
- Py_DECREF(elem);
- return NULL;
- }
- grouplist[i] = x;
- /* read back the value to see if it fitted in gid_t */
- if (grouplist[i] != x) {
- PyErr_SetString(PyExc_TypeError,
- "group id too big");
- Py_DECREF(elem);
- return NULL;
- }
}
Py_DECREF(elem);
}
@@ -7689,9 +7631,11 @@ Set the current process's real, effectiv
static PyObject*
posix_setresuid (PyObject *self, PyObject *args)
{
- /* We assume uid_t is no larger than a long. */
- long ruid, euid, suid;
- if (!PyArg_ParseTuple(args, "lll", &ruid, &euid, &suid))
+ uid_t ruid, euid, suid;
+ if (!PyArg_ParseTuple(args, "O&O&O&",
+ _PyArg_ParseUid, &ruid,
+ _PyArg_ParseUid, &euid,
+ _PyArg_ParseUid, &suid))
return NULL;
if (setresuid(ruid, euid, suid) < 0)
return posix_error();
@@ -7707,9 +7651,11 @@ Set the current process's real, effectiv
static PyObject*
posix_setresgid (PyObject *self, PyObject *args)
{
- /* We assume uid_t is no larger than a long. */
- long rgid, egid, sgid;
- if (!PyArg_ParseTuple(args, "lll", &rgid, &egid, &sgid))
+ gid_t rgid, egid, sgid;
+ if (!PyArg_ParseTuple(args, "O&O&O&",
+ _PyArg_ParseGid, &rgid,
+ _PyArg_ParseGid, &egid,
+ _PyArg_ParseGid, &sgid))
return NULL;
if (setresgid(rgid, egid, sgid) < 0)
return posix_error();
@@ -7726,14 +7672,13 @@ static PyObject*
posix_getresuid (PyObject *self, PyObject *noargs)
{
uid_t ruid, euid, suid;
- long l_ruid, l_euid, l_suid;
+ PyObject *obj_ruid, *obj_euid, *obj_suid;
if (getresuid(&ruid, &euid, &suid) < 0)
return posix_error();
- /* Force the values into long's as we don't know the size of uid_t. */
- l_ruid = ruid;
- l_euid = euid;
- l_suid = suid;
- return Py_BuildValue("(lll)", l_ruid, l_euid, l_suid);
+ obj_ruid = _PyObject_FromUid(ruid);
+ obj_euid = _PyObject_FromUid(euid);
+ obj_suid = _PyObject_FromUid(suid);
+ return Py_BuildValue("(NNN)", obj_ruid, obj_euid, obj_suid);
}
#endif
@@ -7746,14 +7691,13 @@ static PyObject*
posix_getresgid (PyObject *self, PyObject *noargs)
{
uid_t rgid, egid, sgid;
- long l_rgid, l_egid, l_sgid;
+ PyObject *obj_rgid, *obj_egid, *obj_sgid;
if (getresgid(&rgid, &egid, &sgid) < 0)
return posix_error();
- /* Force the values into long's as we don't know the size of uid_t. */
- l_rgid = rgid;
- l_egid = egid;
- l_sgid = sgid;
- return Py_BuildValue("(lll)", l_rgid, l_egid, l_sgid);
+ obj_rgid = _PyObject_FromGid(rgid);
+ obj_egid = _PyObject_FromGid(egid);
+ obj_sgid = _PyObject_FromGid(sgid);
+ return Py_BuildValue("(NNN)", obj_rgid, obj_egid, obj_sgid);
}
#endif
diff -up Python-3.2.3/Modules/pwdmodule.c.uid-gid-overflows Python-3.2.3/Modules/pwdmodule.c
--- Python-3.2.3/Modules/pwdmodule.c.uid-gid-overflows 2012-05-16 11:56:21.353024696 -0400
+++ Python-3.2.3/Modules/pwdmodule.c 2012-05-17 14:47:37.465332677 -0400
@@ -74,8 +74,8 @@ mkpwent(struct passwd *p)
#else
SETS(setIndex++, p->pw_passwd);
#endif
- SETI(setIndex++, p->pw_uid);
- SETI(setIndex++, p->pw_gid);
+ PyStructSequence_SET_ITEM(v, setIndex++, _PyObject_FromUid(p->pw_uid));
+ PyStructSequence_SET_ITEM(v, setIndex++, _PyObject_FromGid(p->pw_gid));
#ifdef __VMS
SETS(setIndex++, "");
#else
@@ -104,13 +104,14 @@ See help(pwd) for more on password datab
static PyObject *
pwd_getpwuid(PyObject *self, PyObject *args)
{
- unsigned int uid;
+ uid_t uid;
struct passwd *p;
- if (!PyArg_ParseTuple(args, "I:getpwuid", &uid))
+ if (!PyArg_ParseTuple(args, "O&:getpwuid",
+ _PyArg_ParseUid, &uid))
return NULL;
if ((p = getpwuid(uid)) == NULL) {
PyErr_Format(PyExc_KeyError,
- "getpwuid(): uid not found: %d", uid);
+ "getpwuid(): uid not found: %lu", (unsigned long)uid);
return NULL;
}
return mkpwent(p);
diff -up Python-3.2.3/Python/getargs.c.uid-gid-overflows Python-3.2.3/Python/getargs.c
--- Python-3.2.3/Python/getargs.c.uid-gid-overflows 2012-05-16 11:56:34.572130014 -0400
+++ Python-3.2.3/Python/getargs.c 2012-05-16 11:56:34.042125832 -0400
@@ -4,6 +4,7 @@
#include "Python.h"
#include <ctype.h>
+#include <limits.h>
#ifdef __cplusplus
@@ -1789,6 +1790,102 @@ _PyArg_NoKeywords(const char *funcname,
funcname);
return 0;
}
+
+PyObject *
+_PyObject_FromUid(uid_t uid)
+{
+ return PyLong_FromUnsignedLong((uid_t)uid);
+}
+
+PyObject *
+_PyObject_FromGid(gid_t gid)
+{
+ return PyLong_FromUnsignedLong((gid_t)gid);
+}
+
+int
+_PyArg_ParseUid(PyObject *in_obj, uid_t *out_uid)
+{
+ PyObject *index, *number = NULL;
+ long sl;
+ unsigned long ul;
+
+ assert(out_uid);
+
+ index = PyNumber_Index(in_obj);
+ if (index != NULL) {
+ number = PyNumber_Long(index);
+ Py_DECREF(index);
+ }
+ if (number == NULL) {
+ PyErr_SetString(PyExc_TypeError, "user id must be integer");
+ return 0;
+ }
+
+ /* Special case: support -1 (e.g. for use by chown) */
+ sl = PyLong_AsLong(number);
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ } else if (sl == -1) {
+ Py_DECREF(number);
+ *out_uid = (uid_t)-1;
+ return 1;
+ }
+
+ /* Otherwise, it must be >= 0 */
+ ul = PyLong_AsUnsignedLong(number);
+ Py_DECREF(number);
+ *out_uid = ul;
+ /* read back the value to see if it fitted in uid_t */
+ if (PyErr_Occurred() || *out_uid != ul) {
+ PyErr_SetString(PyExc_OverflowError,
+ "user id is not in range(-1, 2^32-1)");
+ return 0;
+ }
+ return 1;
+}
+
+int
+_PyArg_ParseGid(PyObject *in_obj, gid_t *out_gid)
+{
+ PyObject *index, *number = NULL;
+ long sl;
+ unsigned long ul;
+
+ assert(out_gid);
+
+ index = PyNumber_Index(in_obj);
+ if (index != NULL) {
+ number = PyNumber_Long(index);
+ Py_DECREF(index);
+ }
+ if (number == NULL) {
+ PyErr_SetString(PyExc_TypeError, "group id must be integer");
+ return 0;
+ }
+
+ /* Special case: support -1 (e.g. for use by chown) */
+ sl = PyLong_AsLong(number);
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ } else if (sl == -1) {
+ Py_DECREF(number);
+ *out_gid = (gid_t)-1;
+ return 1;
+ }
+
+ ul = PyLong_AsUnsignedLong(number);
+ Py_DECREF(number);
+ *out_gid = ul;
+ /* read back the value to see if it fitted in gid_t */
+ if (PyErr_Occurred() || *out_gid != ul) {
+ PyErr_SetString(PyExc_OverflowError,
+ "group id is not in range(-1, 2^32-1)");
+ return 0;
+ }
+ return 1;
+}
+
#ifdef __cplusplus
};
#endif

View File

@ -122,7 +122,7 @@
Summary: Version 3 of the Python programming language aka Python 3000
Name: python3
Version: %{pybasever}.3
Release: 6%{?dist}
Release: 7%{?dist}
License: Python
Group: Development/Languages
@ -440,6 +440,22 @@ Patch155: 00155-avoid-ctypes-thunks.patch
# Not yet sent upstream
Patch156: 00156-gdb-autoload-safepath.patch
# 00157 #
# Update uid/gid handling throughout the standard library: uid_t and gid_t are
# unsigned 32-bit values, but existing code often passed them through C long
# values, which are signed 32-bit values on 32-bit architectures, leading to
# negative int objects for uid/gid values >= 2^31 on 32-bit architectures.
#
# Introduce _PyObject_FromUid/Gid to convert uid_t/gid_t values to python
# objects, using int objects where the value will fit (long objects otherwise),
# and _PyArg_ParseUid/Gid to convert int/long to uid_t/gid_t, with -1 allowed
# as a special case (since this is given special meaning by the chown syscall)
#
# Update standard library to use this throughout for uid/gid values, so that
# very large uid/gid values are round-trippable, and -1 remains usable.
# (rhbz#697470)
Patch157: 00157-uid-gid-overflows.patch
# (New patches go here ^^^)
#
# When adding new patches to "python" and "python3" in Fedora 17 onwards,
@ -667,6 +683,7 @@ done
# 00154: not for this branch
%patch155 -p1
%patch156 -p1
%patch157 -p1
# Currently (2010-01-15), http://docs.python.org/library is for 2.6, and there
# are many differences between 2.6 and the Python 3 library.
@ -1489,6 +1506,10 @@ rm -fr %{buildroot}
# ======================================================
%changelog
* Tue May 15 2012 David Malcolm <dmalcolm@redhat.com> - 3.2.3-7
- update uid/gid handling to avoid int overflows seen with uid/gid
values >= 2^31 on 32-bit architectures (patch 157; rhbz#697470)
* Fri May 4 2012 David Malcolm <dmalcolm@redhat.com> - 3.2.3-6
- renumber autotools patch from 300 to 5000
- specfile cleanups