Index: Lib/test/test_os.py =================================================================== --- Lib/test/test_os.py (revision 61521) +++ Lib/test/test_os.py (working copy) @@ -509,6 +509,10 @@ def test_chmod(self): self.assertRaises(WindowsError, os.utime, test_support.TESTFN, 0) +class MiscTests(unittest.TestCase): + def test_strerror(self): + self.assertTrue(isinstance(os.strerror(0), str)) + if sys.platform != 'win32': class Win32ErrorTests(unittest.TestCase): pass @@ -523,7 +527,8 @@ MakedirTests, DevNullTests, URandomTests, - Win32ErrorTests + Win32ErrorTests, + MiscTests, ) if __name__ == "__main__": Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 61521) +++ Modules/posixmodule.c (working copy) @@ -6710,7 +6710,6 @@ } #endif /* unsetenv */ -#ifdef HAVE_STRERROR PyDoc_STRVAR(posix_strerror__doc__, "strerror(code) -> string\n\n\ Translate an error code to a message string."); @@ -6718,19 +6717,27 @@ static PyObject * posix_strerror(PyObject *self, PyObject *args) { - int code; + int code, old_errno; char *message; if (!PyArg_ParseTuple(args, "i:strerror", &code)) return NULL; + old_errno = errno; + errno = 0; message = strerror(code); - if (message == NULL) { + /* ISO C/POSIX do not allow NULL returns from strerror */ + assert(message); + if (errno == EINVAL) { PyErr_SetString(PyExc_ValueError, "strerror() argument out of range"); return NULL; } + else if (errno != 0) + /* Should not happen on ISO C/POSIX compliant platforms */ + return posix_error(); + errno = old_errno; + return PyString_FromString(message); } -#endif /* strerror */ #ifdef HAVE_SYS_WAIT_H @@ -8510,9 +8517,7 @@ #ifdef HAVE_UNSETENV {"unsetenv", posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__}, #endif -#ifdef HAVE_STRERROR {"strerror", posix_strerror, METH_VARARGS, posix_strerror__doc__}, -#endif #ifdef HAVE_FCHDIR {"fchdir", posix_fchdir, METH_O, posix_fchdir__doc__}, #endif