diff -r 76713f4d9f0f Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py Sun Feb 09 06:07:47 2014 -0800 +++ b/Lib/test/test_tcl.py Sun Feb 09 22:27:16 2014 +0200 @@ -341,7 +341,12 @@ self.assertEqual(passValue(True), True if self.wantobjects else '1') self.assertEqual(passValue(False), False if self.wantobjects else '0') self.assertEqual(passValue('string'), 'string') + self.assertEqual(passValue('string\xbd'), 'string\xbd') self.assertEqual(passValue('string\u20ac'), 'string\u20ac') + self.assertEqual(passValue(b'string'), 'string') + self.assertEqual(passValue(b'string\xe2\x82\xac'), 'string\u20ac') + self.assertEqual(passValue('string\ud801'), 'string\ud801') + self.assertEqual(passValue('string\ud801\udca2'), 'string\ud801\udca2') self.assertEqual(passValue('str\x00ing'), 'str\x00ing') self.assertEqual(passValue('str\x00ing\xbd'), 'str\x00ing\xbd') self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac') @@ -397,6 +402,12 @@ check('string\u20ac', 'string\u20ac') check(b'string', 'string') check(b'string\xe2\x82\xac', 'string\u20ac') + check('string\udca2', 'string\udced\udcb2\udca2') + check('string\ud801\udca2', + 'string\udced\udca0\udc81\udced\udcb2\udca2') + check(b'string\xed\xa0\x81', 'string\udced\udca0\udc81') + check(b'string\xed\xa0\x81\xed\xb2\xa2', + 'string\udced\udca0\udc81\udced\udcb2\udca2') check('str\x00ing', 'str\x00ing') check('str\x00ing\xbd', 'str\x00ing\xbd') check('str\x00ing\u20ac', 'str\x00ing\u20ac') diff -r 76713f4d9f0f Modules/_tkinter.c --- a/Modules/_tkinter.c Sun Feb 09 06:07:47 2014 -0800 +++ b/Modules/_tkinter.c Sun Feb 09 22:27:16 2014 +0200 @@ -329,16 +329,16 @@ static PyObject * -unicodeFromTclStringAndSize(const char *s, Py_ssize_t size) +unicodeFromTclStringAndSize(const char *s, Py_ssize_t size, const char *errors) { PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL); if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { + char *buf = NULL; + PyErr_Clear(); /* Tcl encodes null character as \xc0\x80 */ if (memchr(s, '\xc0', size)) { - char *buf, *q; const char *e = s + size; - PyErr_Clear(); - q = buf = (char *)PyMem_Malloc(size); + char *q = buf = (char *)PyMem_Malloc(size); if (buf == NULL) return NULL; while (s != e) { @@ -351,9 +351,10 @@ } s = buf; size = q - s; - r = PyUnicode_DecodeUTF8(s, size, NULL); + } + r = PyUnicode_DecodeUTF8(s, size, errors); + if (buf != NULL) PyMem_Free(buf); - } } return r; } @@ -361,7 +362,7 @@ static PyObject * unicodeFromTclString(const char *s) { - return unicodeFromTclStringAndSize(s, strlen(s)); + return unicodeFromTclStringAndSize(s, strlen(s), NULL); } static PyObject * @@ -369,7 +370,7 @@ { int len; char *s = Tcl_GetStringFromObj(value, &len); - return unicodeFromTclStringAndSize(s, len); + return unicodeFromTclStringAndSize(s, len, NULL); } @@ -970,7 +971,7 @@ TkappObject *app = (TkappObject*)tkapp; if (value->typePtr == NULL) { - return unicodeFromTclStringAndSize(value->bytes, value->length); + return unicodeFromTclStringAndSize(value->bytes, value->length, NULL); } if (value->typePtr == app->BooleanType) { @@ -1946,7 +1947,9 @@ return PythonCmd_Error(interp); for (i = 0; i < (argc - 1); i++) { - PyObject *s = unicodeFromTclString(argv[i + 1]); + PyObject *s = unicodeFromTclStringAndSize(argv[i + 1], + strlen(argv[i + 1]), + "surrogateescape"); if (!s || PyTuple_SetItem(arg, i, s)) { Py_DECREF(arg); return PythonCmd_Error(interp);