diff -r a13310c045b0 Lib/test/test_socket.py --- a/Lib/test/test_socket.py Mon May 02 13:36:18 2011 +0200 +++ b/Lib/test/test_socket.py Tue May 03 12:41:31 2011 +0300 @@ -274,6 +274,45 @@ self.assertRaises(socket.error, raise_gaierror, "Error raising socket exception.") + def testSendtoErrors(self): + # Testing that sendto doens't masks failures. See #10169. + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.addCleanup(s.close) + s.bind(('', 0)) + sockname = s.getsockname() + # 2 args + with self.assertRaises(UnicodeEncodeError): + s.sendto(u'\u2620', sockname) + with self.assertRaises(TypeError) as cm: + s.sendto(5j, sockname) + self.assertIn('not complex', str(cm.exception)) + with self.assertRaises(TypeError) as cm: + s.sendto('foo', None) + self.assertIn('not NoneType', str(cm.exception)) + # 3 args + with self.assertRaises(UnicodeEncodeError): + s.sendto(u'\u2620', 0, sockname) + with self.assertRaises(TypeError) as cm: + s.sendto(5j, 0, sockname) + self.assertIn('not complex', str(cm.exception)) + with self.assertRaises(TypeError) as cm: + s.sendto('foo', 0, None) + self.assertIn('not NoneType', str(cm.exception)) + with self.assertRaises(TypeError) as cm: + s.sendto('foo', 'bar', sockname) + self.assertIn('an integer is required', str(cm.exception)) + with self.assertRaises(TypeError) as cm: + s.sendto('foo', None, None) + self.assertIn('an integer is required', str(cm.exception)) + # wrong number of args + with self.assertRaises(TypeError) as cm: + s.sendto('foo') + self.assertIn('(1 given)', str(cm.exception)) + with self.assertRaises(TypeError) as cm: + s.sendto('foo', 0, sockname, 4) + self.assertIn('(4 given)', str(cm.exception)) + + def testCrucialConstants(self): # Testing for mission critical constants socket.AF_INET diff -r a13310c045b0 Modules/socketmodule.c --- a/Modules/socketmodule.c Mon May 02 13:36:18 2011 +0200 +++ b/Modules/socketmodule.c Tue May 03 12:41:31 2011 +0300 @@ -2821,18 +2821,25 @@ sock_sendto(PySocketSockObject *s, PyObject *args) { Py_buffer pbuf; - PyObject *addro; + PyObject *addro, *tmp = NULL; char *buf; Py_ssize_t len; sock_addr_t addrbuf; int addrlen, n = -1, flags, timeout; flags = 0; - if (!PyArg_ParseTuple(args, "s*O:sendto", &pbuf, &addro)) { - PyErr_Clear(); - if (!PyArg_ParseTuple(args, "s*iO:sendto", - &pbuf, &flags, &addro)) + /* sendto accepts an optional second arg 'flags' */ + if (!PyArg_ParseTuple(args, "s*O|O:sendto", &pbuf, &addro, &tmp)) + return NULL; + /* if tmp is set, 3 arguments have been passed, so convert the second + (flags) to int, and copy the third one to addro */ + if (tmp != NULL) { + flags = PyInt_AsLong(addro); + if ((flags == -1) && PyErr_Occurred()) { + PyBuffer_Release(&pbuf); return NULL; + } + addro = tmp; } buf = pbuf.buf; len = pbuf.len;