diff -up Python-2.7.3/Include/modsupport.h.uid-gid-overflows Python-2.7.3/Include/modsupport.h --- Python-2.7.3/Include/modsupport.h.uid-gid-overflows 2012-04-09 19:07:29.000000000 -0400 +++ Python-2.7.3/Include/modsupport.h 2012-06-26 14:52:03.739471150 -0400 @@ -8,6 +8,7 @@ extern "C" { /* Module support interface */ #include +#include /* If PY_SSIZE_T_CLEAN is defined, each functions treats #-specifier to mean Py_ssize_t */ @@ -128,6 +129,17 @@ PyAPI_FUNC(PyObject *) Py_InitModule4(co PyAPI_DATA(char *) _Py_PackageContext; +/* + 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-2.7.3/Lib/test/test_grp.py.uid-gid-overflows Python-2.7.3/Lib/test/test_grp.py --- Python-2.7.3/Lib/test/test_grp.py.uid-gid-overflows 2012-04-09 19:07:31.000000000 -0400 +++ Python-2.7.3/Lib/test/test_grp.py 2012-06-26 14:51:36.000817929 -0400 @@ -16,7 +16,7 @@ class GroupDatabaseTestCase(unittest.Tes self.assertEqual(value[1], value.gr_passwd) self.assertIsInstance(value.gr_passwd, basestring) self.assertEqual(value[2], value.gr_gid) - self.assertIsInstance(value.gr_gid, int) + self.assertIsInstance(value.gr_gid, (int, long)) self.assertEqual(value[3], value.gr_mem) self.assertIsInstance(value.gr_mem, list) diff -up Python-2.7.3/Lib/test/test_os.py.uid-gid-overflows Python-2.7.3/Lib/test/test_os.py --- Python-2.7.3/Lib/test/test_os.py.uid-gid-overflows 2012-04-09 19:07:32.000000000 -0400 +++ Python-2.7.3/Lib/test/test_os.py 2012-06-26 14:51:36.000817929 -0400 @@ -677,30 +677,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) @@ -715,6 +721,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-2.7.3/Lib/test/test_posix.py.uid-gid-overflows Python-2.7.3/Lib/test/test_posix.py --- Python-2.7.3/Lib/test/test_posix.py.uid-gid-overflows 2012-04-09 19:07:32.000000000 -0400 +++ Python-2.7.3/Lib/test/test_posix.py 2012-06-26 14:51:36.001817916 -0400 @@ -217,7 +217,7 @@ class PosixTester(unittest.TestCase): if hasattr(posix, 'stat'): self.assertTrue(posix.stat(test_support.TESTFN)) - 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: @@ -237,6 +237,13 @@ class PosixTester(unittest.TestCase): # 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): @@ -246,7 +253,7 @@ class PosixTester(unittest.TestCase): # re-create the file open(test_support.TESTFN, 'w').close() - self._test_all_chown_common(posix.chown, test_support.TESTFN) + self._test_all_chown_common(posix.chown, posix.stat, test_support.TESTFN) @unittest.skipUnless(hasattr(posix, 'fchown'), "test needs os.fchown()") def test_fchown(self): @@ -256,7 +263,7 @@ class PosixTester(unittest.TestCase): test_file = open(test_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() @@ -265,7 +272,7 @@ class PosixTester(unittest.TestCase): os.unlink(test_support.TESTFN) # create a symlink os.symlink(_DUMMY_SYMLINK, test_support.TESTFN) - self._test_all_chown_common(posix.lchown, test_support.TESTFN) + self._test_all_chown_common(posix.lchown, posix.lstat, test_support.TESTFN) def test_chdir(self): if hasattr(posix, 'chdir'): diff -up Python-2.7.3/Lib/test/test_pwd.py.uid-gid-overflows Python-2.7.3/Lib/test/test_pwd.py --- Python-2.7.3/Lib/test/test_pwd.py.uid-gid-overflows 2012-04-09 19:07:32.000000000 -0400 +++ Python-2.7.3/Lib/test/test_pwd.py 2012-06-26 14:51:36.001817916 -0400 @@ -18,9 +18,9 @@ class PwdTest(unittest.TestCase): self.assertEqual(e[1], e.pw_passwd) self.assertIsInstance(e.pw_passwd, basestring) self.assertEqual(e[2], e.pw_uid) - self.assertIsInstance(e.pw_uid, int) + self.assertIsInstance(e.pw_uid, (int, long)) self.assertEqual(e[3], e.pw_gid) - self.assertIsInstance(e.pw_gid, int) + self.assertIsInstance(e.pw_gid, (int, long)) self.assertEqual(e[4], e.pw_gecos) self.assertIsInstance(e.pw_gecos, basestring) self.assertEqual(e[5], e.pw_dir) @@ -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.maxint + fakeuid = 2**32 - 2 self.assertNotIn(fakeuid, byuids) self.assertRaises(KeyError, pwd.getpwuid, fakeuid) diff -up Python-2.7.3/Modules/grpmodule.c.uid-gid-overflows Python-2.7.3/Modules/grpmodule.c --- Python-2.7.3/Modules/grpmodule.c.uid-gid-overflows 2012-04-09 19:07:34.000000000 -0400 +++ Python-2.7.3/Modules/grpmodule.c 2012-06-26 14:51:36.002817904 -0400 @@ -70,7 +70,7 @@ mkgrent(struct group *p) Py_INCREF(Py_None); } #endif - SET(setIndex++, PyInt_FromLong((long) p->gr_gid)); + SET(setIndex++, _PyObject_FromGid(p->gr_gid)); SET(setIndex++, w); #undef SET @@ -85,18 +85,15 @@ 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_Int(pyo_id); - if (!py_int_id) - return NULL; - gid = PyInt_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-2.7.3/Modules/posixmodule.c.uid-gid-overflows Python-2.7.3/Modules/posixmodule.c --- Python-2.7.3/Modules/posixmodule.c.uid-gid-overflows 2012-06-26 14:51:35.864819629 -0400 +++ Python-2.7.3/Modules/posixmodule.c 2012-06-26 14:51:36.005817868 -0400 @@ -1305,8 +1305,8 @@ _pystat_fromstructstat(STRUCT_STAT *st) PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long)st->st_dev)); #endif PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long)st->st_nlink)); - PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long)st->st_uid)); - PyStructSequence_SET_ITEM(v, 5, PyInt_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)); @@ -1883,14 +1883,16 @@ static PyObject * posix_chown(PyObject *self, PyObject *args) { char *path = NULL; - long uid, gid; + uid_t uid; + gid_t gid; int res; - if (!PyArg_ParseTuple(args, "etll:chown", + if (!PyArg_ParseTuple(args, "etO&O&:chown", Py_FileSystemDefaultEncoding, &path, - &uid, &gid)) + _PyArg_ParseUid, &uid, + _PyArg_ParseGid, &gid)) return NULL; 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(path); @@ -1910,12 +1912,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:chown", &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(); @@ -1933,14 +1938,16 @@ static PyObject * posix_lchown(PyObject *self, PyObject *args) { char *path = NULL; - long uid, gid; + uid_t uid; + gid_t gid; int res; - if (!PyArg_ParseTuple(args, "etll:lchown", + if (!PyArg_ParseTuple(args, "etO&O&:lchown", Py_FileSystemDefaultEncoding, &path, - &uid, &gid)) + _PyArg_ParseUid, &uid, + _PyArg_ParseGid, &gid)) return NULL; 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(path); @@ -3841,7 +3848,7 @@ Return the current process's effective g static PyObject * posix_getegid(PyObject *self, PyObject *noargs) { - return PyInt_FromLong((long)getegid()); + return _PyObject_FromGid(getegid()); } #endif @@ -3854,7 +3861,7 @@ Return the current process's effective u static PyObject * posix_geteuid(PyObject *self, PyObject *noargs) { - return PyInt_FromLong((long)geteuid()); + return _PyObject_FromUid(geteuid()); } #endif @@ -3867,7 +3874,7 @@ Return the current process's group id.") static PyObject * posix_getgid(PyObject *self, PyObject *noargs) { - return PyInt_FromLong((long)getgid()); + return _PyObject_FromGid(getgid()); } #endif @@ -3942,7 +3949,7 @@ posix_getgroups(PyObject *self, PyObject if (result != NULL) { int i; for (i = 0; i < n; ++i) { - PyObject *o = PyInt_FromLong((long)alt_grouplist[i]); + PyObject *o = _PyObject_FromGid(alt_grouplist[i]); if (o == NULL) { Py_DECREF(result); result = NULL; @@ -3971,12 +3978,13 @@ static PyObject * posix_initgroups(PyObject *self, PyObject *args) { char *username; - long gid; + gid_t gid; - if (!PyArg_ParseTuple(args, "sl:initgroups", &username, &gid)) + if (!PyArg_ParseTuple(args, "sO&:initgroups", &username, + _PyArg_ParseGid, &gid)) return NULL; - if (initgroups(username, (gid_t) gid) == -1) + if (initgroups(username, gid) == -1) return PyErr_SetFromErrno(PyExc_OSError); Py_INCREF(Py_None); @@ -4090,7 +4098,7 @@ Return the current process's user id."); static PyObject * posix_getuid(PyObject *self, PyObject *noargs) { - return PyInt_FromLong((long)getuid()); + return _PyObject_FromUid(getuid()); } #endif @@ -5736,15 +5744,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)) + if (!PyArg_ParseTuple(args, "O&:setuid", _PyArg_ParseUid, &uid)) return NULL; - uid = uid_arg; - if (uid != uid_arg) { - PyErr_SetString(PyExc_OverflowError, "user id too big"); - return NULL; - } if (setuid(uid) < 0) return posix_error(); Py_INCREF(Py_None); @@ -5761,15 +5763,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)) + if (!PyArg_ParseTuple(args, "O&:seteuid", _PyArg_ParseUid, &euid)) return NULL; - euid = euid_arg; - if (euid != euid_arg) { - PyErr_SetString(PyExc_OverflowError, "user id too big"); - return NULL; - } if (seteuid(euid) < 0) { return posix_error(); } else { @@ -5787,15 +5783,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)) + if (!PyArg_ParseTuple(args, "O&:setegid", _PyArg_ParseGid, &egid)) return NULL; - egid = egid_arg; - if (egid != egid_arg) { - PyErr_SetString(PyExc_OverflowError, "group id too big"); - return NULL; - } if (setegid(egid) < 0) { return posix_error(); } else { @@ -5813,23 +5803,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)) + if (!PyArg_ParseTuple(args, "O&O&", + _PyArg_ParseUid, &ruid, + _PyArg_ParseUid, &euid)) 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"); - return NULL; - } if (setreuid(ruid, euid) < 0) { return posix_error(); } else { @@ -5847,23 +5825,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)) + if (!PyArg_ParseTuple(args, "O&O&", + _PyArg_ParseGid, &rgid, + _PyArg_ParseGid, &egid)) 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"); - return NULL; - } if (setregid(rgid, egid) < 0) { return posix_error(); } else { @@ -5881,15 +5847,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)) - return NULL; - gid = gid_arg; - if (gid != gid_arg) { - PyErr_SetString(PyExc_OverflowError, "group id too big"); + if (!PyArg_ParseTuple(args, "O&:setgid", _PyArg_ParseGid, &gid)) return NULL; - } if (setgid(gid) < 0) return posix_error(); Py_INCREF(Py_None); @@ -5922,39 +5882,10 @@ posix_setgroups(PyObject *self, PyObject elem = PySequence_GetItem(groups, i); if (!elem) return NULL; - if (!PyInt_Check(elem)) { - if (!PyLong_Check(elem)) { - PyErr_SetString(PyExc_TypeError, - "groups must be integers"); - 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 to see if it fits in gid_t */ - if (grouplist[i] != x) { - PyErr_SetString(PyExc_TypeError, - "group id too big"); - Py_DECREF(elem); - return NULL; - } - } - } else { - long x = PyInt_AsLong(elem); - grouplist[i] = x; - if (grouplist[i] != x) { - PyErr_SetString(PyExc_TypeError, - "group id too big"); - Py_DECREF(elem); - return NULL; - } - } + if (!_PyArg_ParseGid(elem, &grouplist[i])) { + Py_DECREF(elem); + return NULL; + } Py_DECREF(elem); } @@ -8576,9 +8507,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(); @@ -8594,9 +8527,12 @@ 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(); @@ -8613,14 +8549,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 @@ -8632,15 +8567,14 @@ Get tuple of the current process's real, static PyObject* posix_getresgid (PyObject *self, PyObject *noargs) { - uid_t rgid, egid, sgid; - long l_rgid, l_egid, l_sgid; + gid_t rgid, egid, 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-2.7.3/Modules/pwdmodule.c.uid-gid-overflows Python-2.7.3/Modules/pwdmodule.c --- Python-2.7.3/Modules/pwdmodule.c.uid-gid-overflows 2012-04-09 19:07:34.000000000 -0400 +++ Python-2.7.3/Modules/pwdmodule.c 2012-06-26 14:51:36.006817855 -0400 @@ -73,8 +73,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 @@ -103,13 +103,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-2.7.3/Python/getargs.c.uid-gid-overflows Python-2.7.3/Python/getargs.c --- Python-2.7.3/Python/getargs.c.uid-gid-overflows 2012-04-09 19:07:35.000000000 -0400 +++ Python-2.7.3/Python/getargs.c 2012-06-26 14:51:36.007817842 -0400 @@ -4,6 +4,7 @@ #include "Python.h" #include +#include #ifdef __cplusplus @@ -1902,6 +1903,110 @@ _PyArg_NoKeywords(const char *funcname, funcname); return 0; } + +PyObject * +_PyObject_FromUid(uid_t uid) +{ + if (uid <= (uid_t)LONG_MAX) { + return PyInt_FromLong((uid_t)uid); + } else { + return PyLong_FromUnsignedLong((uid_t)uid); + } +} + +PyObject * +_PyObject_FromGid(gid_t gid) +{ + if (gid <= (gid_t)LONG_MAX) { + return PyInt_FromLong((gid_t)gid); + } else { + 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