From bb2cc698c1dd69ad57450bb48d64f2b8aaae7bb7 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Sun, 14 Jan 2007 17:03:32 +0000 Subject: [PATCH] Patch #1635058 by Mark Roberts: ensure that htonl and friends never accept or return negative numbers, per the underlying C implementation. --- Lib/test/test_socket.py | 14 ++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 +++ Modules/socketmodule.c | 28 ++++++++++++++++++++++++---- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 356b80199bb..1357d54d1e7 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -310,6 +310,20 @@ class GeneralModuleTests(unittest.TestCase): self.assertEqual(swapped & mask, mask) self.assertRaises(OverflowError, func, 1L<<34) + def testNtoHErrors(self): + good_values = [ 1, 2, 3, 1L, 2L, 3L ] + bad_values = [ -1, -2, -3, -1L, -2L, -3L ] + for k in good_values: + socket.ntohl(k) + socket.ntohs(k) + socket.htonl(k) + socket.htons(k) + for k in bad_values: + self.assertRaises(OverflowError, socket.ntohl, k) + self.assertRaises(OverflowError, socket.ntohs, k) + self.assertRaises(OverflowError, socket.htonl, k) + self.assertRaises(OverflowError, socket.htons, k) + def testGetServBy(self): eq = self.assertEqual # Find one service that exists, then check all the related interfaces. diff --git a/Misc/ACKS b/Misc/ACKS index b1981140b0a..7ea63cce752 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -521,6 +521,7 @@ Armin Rigo Nicholas Riley Jean-Claude Rimbault Anthony Roach +Mark Roberts Andy Robinson Jim Robinson Kevin Rodgers diff --git a/Misc/NEWS b/Misc/NEWS index 754ceae53f0..37a1ab668c6 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -301,6 +301,9 @@ Library Extension Modules ----------------- +- Patch #1635058: ensure that htonl and friends never accept or + return negative numbers, per the underlying C implementation. + - Patch #1544279: Improve thread-safety of the socket module by moving the sock_addr_t storage out of the socket object. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 8ec0ed73ca3..82461d4602e 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3468,7 +3468,12 @@ socket_ntohs(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "i:ntohs", &x1)) { return NULL; } - x2 = (int)ntohs((short)x1); + if (x1 < 0) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative number to unsigned long"); + return NULL; + } + x2 = (unsigned int)ntohs((unsigned short)x1); return PyInt_FromLong(x2); } @@ -3487,6 +3492,11 @@ socket_ntohl(PyObject *self, PyObject *arg) x = PyInt_AS_LONG(arg); if (x == (unsigned long) -1 && PyErr_Occurred()) return NULL; + if ((long)x < 0) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative number to unsigned long"); + return NULL; + } } else if (PyLong_Check(arg)) { x = PyLong_AsUnsignedLong(arg); @@ -3510,7 +3520,7 @@ socket_ntohl(PyObject *self, PyObject *arg) arg->ob_type->tp_name); if (x == (unsigned long) -1 && PyErr_Occurred()) return NULL; - return PyInt_FromLong(ntohl(x)); + return PyLong_FromUnsignedLong(ntohl(x)); } PyDoc_STRVAR(ntohl_doc, @@ -3527,7 +3537,12 @@ socket_htons(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "i:htons", &x1)) { return NULL; } - x2 = (int)htons((short)x1); + if (x1 < 0) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative number to unsigned long"); + return NULL; + } + x2 = (unsigned int)htons((unsigned short)x1); return PyInt_FromLong(x2); } @@ -3546,6 +3561,11 @@ socket_htonl(PyObject *self, PyObject *arg) x = PyInt_AS_LONG(arg); if (x == (unsigned long) -1 && PyErr_Occurred()) return NULL; + if ((long)x < 0) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative number to unsigned long"); + return NULL; + } } else if (PyLong_Check(arg)) { x = PyLong_AsUnsignedLong(arg); @@ -3567,7 +3587,7 @@ socket_htonl(PyObject *self, PyObject *arg) return PyErr_Format(PyExc_TypeError, "expected int/long, %s found", arg->ob_type->tp_name); - return PyInt_FromLong(htonl(x)); + return PyLong_FromUnsignedLong(htonl((unsigned long)x)); } PyDoc_STRVAR(htonl_doc,