Index: Lib/test/test_syslog.py =================================================================== --- Lib/test/test_syslog.py (revision 87118) +++ Lib/test/test_syslog.py (working copy) @@ -11,6 +11,8 @@ def test_openlog(self): syslog.openlog('python') + # Issue #6697. + self.assertRaises(UnicodeEncodeError, syslog.openlog, '\uD800') def test_syslog(self): syslog.openlog('python') Index: Lib/test/datetimetester.py =================================================================== --- Lib/test/datetimetester.py (revision 87118) +++ Lib/test/datetimetester.py (working copy) @@ -2508,11 +2508,18 @@ # Check that an invalid tzname result raises an exception. class Badtzname(tzinfo): - def tzname(self, dt): return 42 + tz = 42 + def tzname(self, dt): return self.tz t = time(2, 3, 4, tzinfo=Badtzname()) self.assertEqual(t.strftime("%H:%M:%S"), "02:03:04") self.assertRaises(TypeError, t.strftime, "%Z") + # Issue #6697: + if '_Fast' in str(type(self)): + Badtzname.tz = '\ud800' + self.assertRaises(ValueError, t.strftime, "%Z") + + def test_hash_edge_cases(self): # Offsets that overflow a basic time. t1 = self.theclass(0, 1, 2, 3, tzinfo=FixedOffset(1439, "")) Index: Lib/test/test_socket.py =================================================================== --- Lib/test/test_socket.py (revision 87118) +++ Lib/test/test_socket.py (working copy) @@ -667,7 +667,10 @@ type=socket.SOCK_STREAM, proto=0, flags=socket.AI_PASSIVE) self.assertEqual(a, b) + # Issue #6697. + self.assertRaises(UnicodeEncodeError, socket.getaddrinfo, 'localhost', '\uD800') + def test_getnameinfo(self): # only IP addresses are allowed self.assertRaises(socket.error, socket.getnameinfo, ('mail.python.org',0), 0) Index: Lib/test/test_xml_etree_c.py =================================================================== --- Lib/test/test_xml_etree_c.py (revision 87118) +++ Lib/test/test_xml_etree_c.py (working copy) @@ -8,10 +8,26 @@ # cElementTree specific tests def sanity(): - """ + r""" Import sanity. >>> from xml.etree import cElementTree + + Issue #6697. + + >>> e = cElementTree.Element('a') + >>> getattr(e, '\uD800') # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + UnicodeEncodeError: ... + + >>> p = cElementTree.XMLParser() + >>> p.version.split()[0] + 'Expat' + >>> getattr(p, '\uD800') + Traceback (most recent call last): + ... + AttributeError: 'XMLParser' object has no attribute '\ud800' """ Index: Modules/_datetimemodule.c =================================================================== --- Modules/_datetimemodule.c (revision 87118) +++ Modules/_datetimemodule.c (working copy) @@ -1257,7 +1257,8 @@ assert(PyUnicode_Check(Zreplacement)); ptoappend = _PyUnicode_AsStringAndSize(Zreplacement, &ntoappend); - ntoappend = Py_SIZE(Zreplacement); + if (ptoappend == NULL) + goto Done; } else if (ch == 'f') { /* format microseconds */ Index: Modules/socketmodule.c =================================================================== --- Modules/socketmodule.c (revision 87118) +++ Modules/socketmodule.c (working copy) @@ -4022,8 +4022,10 @@ pptr = pbuf; } else if (PyUnicode_Check(pobj)) { pptr = _PyUnicode_AsString(pobj); + if (pptr == NULL) + goto err; } else if (PyBytes_Check(pobj)) { - pptr = PyBytes_AsString(pobj); + pptr = PyBytes_AS_STRING(pobj); } else if (pobj == Py_None) { pptr = (char *)NULL; } else { Index: Modules/_lsprof.c =================================================================== --- Modules/_lsprof.c (revision 87118) +++ Modules/_lsprof.c (working copy) @@ -178,7 +178,14 @@ PyObject *mod = fn->m_module; const char *modname; if (mod && PyUnicode_Check(mod)) { + /* XXX: The following will truncate module names with embedded + * null-characters. It is unlikely that this can happen in + * practice and the concequences are not serious enough to + * introduce extra checks here. + */ modname = _PyUnicode_AsString(mod); + if (modname == NULL) + modname = ""; } else if (mod && PyModule_Check(mod)) { modname = PyModule_GetName(mod); Index: Modules/syslogmodule.c =================================================================== --- Modules/syslogmodule.c (revision 87118) +++ Modules/syslogmodule.c (working copy) @@ -68,9 +68,9 @@ * is optional. */ - Py_ssize_t argv_len; + Py_ssize_t argv_len, scriptlen; PyObject *scriptobj; - char *atslash; + Py_UNICODE *atslash, *atstart; PyObject *argv = PySys_GetObject("argv"); if (argv == NULL) { @@ -90,13 +90,16 @@ if (!PyUnicode_Check(scriptobj)) { return(NULL); } - if (PyUnicode_GET_SIZE(scriptobj) == 0) { + scriptlen = PyUnicode_GET_SIZE(scriptobj); + if (scriptlen == 0) { return(NULL); } - atslash = strrchr(_PyUnicode_AsString(scriptobj), SEP); + atstart = PyUnicode_AS_UNICODE(scriptobj); + atslash = Py_UNICODE_strrchr(atstart, SEP); if (atslash) { - return(PyUnicode_FromString(atslash + 1)); + return(PyUnicode_FromUnicode(atslash + 1, + scriptlen - (atslash - atstart) - 1)); } else { Py_INCREF(scriptobj); return(scriptobj); @@ -113,6 +116,7 @@ long facility = LOG_USER; PyObject *new_S_ident_o = NULL; static char *keywords[] = {"ident", "logoption", "facility", 0}; + char *S_ident_o_str; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Ull:openlog", keywords, &new_S_ident_o, &logopt, &facility)) @@ -130,12 +134,19 @@ Py_XDECREF(S_ident_o); S_ident_o = new_S_ident_o; + if (S_ident_o) { + S_ident_o_str = _PyUnicode_AsString(S_ident_o); + if (S_ident_o_str == NULL) + return NULL; + } else + S_ident_o_str = NULL; + /* At this point, S_ident_o should be INCREF()ed. openlog(3) does not * make a copy, and syslog(3) later uses it. We can't garbagecollect it * If NULL, just let openlog figure it out (probably using C argv[0]). */ - openlog(S_ident_o ? _PyUnicode_AsString(S_ident_o) : NULL, logopt, facility); + openlog(S_ident_o_str, logopt, facility); S_log_open = 1; Py_INCREF(Py_None); Index: Modules/pyexpat.c =================================================================== --- Modules/pyexpat.c (revision 87118) +++ Modules/pyexpat.c (working copy) @@ -1243,6 +1243,9 @@ if (PyUnicode_Check(nameobj)) name = _PyUnicode_AsString(nameobj); + if (name == NULL) + name = ""; + handlernum = handlername2int(name); if (handlernum != -1) { Index: Modules/parsermodule.c =================================================================== --- Modules/parsermodule.c (revision 87118) +++ Modules/parsermodule.c (working copy) @@ -792,6 +792,11 @@ } } temp_str = _PyUnicode_AsStringAndSize(temp, &len); + if (temp_str == NULL) { + Py_DECREF(temp); + Py_XDECREF(elem); + return 0; + } strn = (char *)PyObject_MALLOC(len + 1); if (strn != NULL) (void) memcpy(strn, temp_str, len + 1); @@ -870,6 +875,8 @@ encoding = PySequence_GetItem(tuple, 2); /* tuple isn't borrowed anymore here, need to DECREF */ tuple = PySequence_GetSlice(tuple, 0, 2); + if (tuple == NULL) + return NULL; } res = PyNode_New(num); if (res != NULL) { @@ -881,6 +888,12 @@ Py_ssize_t len; const char *temp; temp = _PyUnicode_AsStringAndSize(encoding, &len); + if (temp == NULL) { + Py_DECREF(res); + Py_DECREF(encoding); + Py_DECREF(tuple); + return NULL; + } res->n_str = (char *)PyObject_MALLOC(len + 1); if (res->n_str != NULL && temp != NULL) (void) memcpy(res->n_str, temp, len + 1); Index: Modules/_elementtree.c =================================================================== --- Modules/_elementtree.c (revision 87118) +++ Modules/_elementtree.c (working copy) @@ -1483,6 +1483,9 @@ if (PyUnicode_Check(nameobj)) name = _PyUnicode_AsString(nameobj); + + if (name == NULL) + return NULL; /* handle common attributes first */ if (strcmp(name, "tag") == 0) { @@ -2194,8 +2197,8 @@ Py_XDECREF(res); } else if (!PyErr_Occurred()) { /* Report the first error, not the last */ - char message[128]; - sprintf(message, "undefined entity &%.100s;", _PyUnicode_AsString(key)); + char message[128] = "undefined entity "; + strncat(message, data_in, data_len < 100?data_len:100); expat_set_error( message, EXPAT(GetErrorLineNumber)(self->parser), @@ -2796,29 +2799,26 @@ static PyObject* xmlparser_getattro(XMLParserObject* self, PyObject* nameobj) { - PyObject* res; - char *name = ""; - - if (PyUnicode_Check(nameobj)) - name = _PyUnicode_AsString(nameobj); - - PyErr_Clear(); - - if (strcmp(name, "entity") == 0) - res = self->entity; - else if (strcmp(name, "target") == 0) - res = self->target; - else if (strcmp(name, "version") == 0) { - char buffer[100]; - sprintf(buffer, "Expat %d.%d.%d", XML_MAJOR_VERSION, + if (PyUnicode_Check(nameobj)) { + PyObject* res; +#define CMP PyUnicode_CompareWithASCIIString + if (CMP(nameobj, "entity") == 0) + res = self->entity; + else if (CMP(nameobj, "target") == 0) + res = self->target; + else if (CMP(nameobj, "version") == 0) { + return PyUnicode_FromFormat( + "Expat %d.%d.%d", XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION); - return PyUnicode_DecodeUTF8(buffer, strlen(buffer), "strict"); - } else { - return PyObject_GenericGetAttr((PyObject*) self, nameobj); + } + else + goto generic; +#undef CMP + Py_INCREF(res); + return res; } - - Py_INCREF(res); - return res; + generic: + return PyObject_GenericGetAttr((PyObject*) self, nameobj); } static PyTypeObject XMLParser_Type = { Index: Modules/_testcapimodule.c =================================================================== --- Modules/_testcapimodule.c (revision 87118) +++ Modules/_testcapimodule.c (working copy) @@ -1741,15 +1741,16 @@ { PyObject *result; char *msg; + Py_UNICODE one[] = {'1', 0}; -#define CHECK_1_FORMAT(FORMAT, TYPE) \ - result = PyUnicode_FromFormat(FORMAT, (TYPE)1); \ - if (result == NULL) \ - return NULL; \ - if (strcmp(_PyUnicode_AsString(result), "1")) { \ - msg = FORMAT " failed at 1"; \ - goto Fail; \ - } \ +#define CHECK_1_FORMAT(FORMAT, TYPE) \ + result = PyUnicode_FromFormat(FORMAT, (TYPE)1); \ + if (result == NULL) \ + return NULL; \ + if (Py_UNICODE_strcmp(PyUnicode_AS_UNICODE(result), one)) { \ + msg = FORMAT " failed at 1"; \ + goto Fail; \ + } \ Py_DECREF(result) CHECK_1_FORMAT("%d", int);