diff -r 51ac5f06dd04 Lib/test/test_genericpath.py --- a/Lib/test/test_genericpath.py Tue Jul 24 03:45:39 2012 -0700 +++ b/Lib/test/test_genericpath.py Thu Jul 26 09:37:59 2012 +0900 @@ -311,6 +311,8 @@ @unittest.skipIf(sys.platform == 'darwin', "Mac OS X denies the creation of a directory with an invalid utf8 name") + @unittest.skipIf(sys.platform == 'win32', + "Win32 can fail cwd() with invalid utf8 name") def test_nonascii_abspath(self): # Test non-ASCII, non-UTF8 bytes in the path. with warnings.catch_warnings(): diff -r 51ac5f06dd04 Lib/test/test_os.py --- a/Lib/test/test_os.py Tue Jul 24 03:45:39 2012 -0700 +++ b/Lib/test/test_os.py Thu Jul 26 09:37:59 2012 +0900 @@ -28,7 +28,7 @@ import threading except ImportError: threading = None -from test.script_helper import assert_python_ok +from test.script_helper import assert_python_ok, make_script, temp_dir with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) @@ -1061,6 +1061,45 @@ def test_chmod(self): self.assertRaises(WindowsError, os.chmod, support.TESTFN, 0) + def test_chdir_invalid_filename(self): + # In code pages such as cp932(Japanese ShiftJIS), decoding + # ANSI file name in can be failed with UnicodeDecodeError. + # If such errors happens while building exception object, + # the UnicodeDecodeError should not hide original exception. + + batfile = """ +chcp 932 +{exe} {scriptname} +chcp {codepage} +""" + + pyscript = r""" +import os, sys +with open(r"{outputfilename}", "w") as f: + try: + os.chdir(b'\xe7w\xf0') + except WindowsError: + f.write("ok") + except Exception as e: + f.write(repr(e)) +""" + + with temp_dir() as script_dir: + outputfilename=os.path.join(script_dir, 'result') + scriptname = make_script(script_dir, 'test', + pyscript.format(outputfilename=outputfilename)) + + batname = os.path.join(script_dir, "test.bat") + with open(batname, "w") as f: + codepage = locale.getpreferredencoding()[2:] + f.write( + batfile.format(exe=sys.executable, + scriptname=scriptname, codepage=codepage)) + + subprocess.call(batname, shell=True) + with open(outputfilename) as f: + self.assertEqual("ok", f.read()) + class TestInvalidFD(unittest.TestCase): singles = ["fchdir", "dup", "fdopen", "fdatasync", "fstat", "fstatvfs", "fsync", "tcgetpgrp", "ttyname"] diff -r 51ac5f06dd04 Python/errors.c --- a/Python/errors.c Tue Jul 24 03:45:39 2012 -0700 +++ b/Python/errors.c Thu Jul 26 09:37:59 2012 +0900 @@ -595,10 +595,24 @@ int ierr, const char *filename) { - PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; - PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( - PyExc_WindowsError, - ierr, name); + PyObject *name=NULL, *result=NULL; + if (filename) { + name = PyUnicode_DecodeFSDefault(filename); + if (!name) { + /* display byte object if failed to convert to Unicode */ + PyObject *bytename = PyBytes_FromString(filename); + if (bytename) { + name = PyObject_Repr(bytename); + Py_XDECREF(bytename); + } + } + /* Clear exception raised while constructing file name */ + PyErr_Clear(); + } + + result = PyErr_SetExcFromWindowsErrWithFilenameObject( + PyExc_WindowsError, + ierr, name); Py_XDECREF(name); return result; }