Extended socket.htonl and ntohl to accept longs.

Fixes SF bug #568322.

The code should raise an OverflowError if the long is > 32 bits, even
on platforms where sizeof(long) > 4.
This commit is contained in:
Jeremy Hylton 2002-07-25 16:01:12 +00:00
parent b8a690d42a
commit c075e197d6
2 changed files with 64 additions and 15 deletions

View File

@ -247,6 +247,17 @@ class GeneralModuleTests(unittest.TestCase):
except socket.error:
pass
def testNtoH(self):
def twice(f):
def g(x):
return f(f(x))
return g
for i in (0, 1, 0xffff0000, 2L, (2**32L) - 1):
self.assertEqual(i, twice(socket.htonl)(i))
self.assertEqual(i, twice(socket.ntohl)(i))
self.assertRaises(OverflowError, socket.htonl, 2L**34)
self.assertRaises(OverflowError, socket.ntohl, 2L**34)
def testGetServByName(self):
"""Testing getservbyname()."""
if hasattr(socket, 'getservbyname'):

View File

@ -2469,15 +2469,34 @@ Convert a 16-bit integer from network to host byte order.");
static PyObject *
socket_ntohl(PyObject *self, PyObject *args)
socket_ntohl(PyObject *self, PyObject *arg)
{
int x1, x2;
unsigned long x;
if (!PyArg_ParseTuple(args, "i:ntohl", &x1)) {
return NULL;
if (PyInt_Check(arg)) {
x = PyInt_AS_LONG(arg);
}
x2 = ntohl(x1);
return PyInt_FromLong(x2);
else if (PyLong_Check(arg)) {
x = PyLong_AsUnsignedLong(arg);
#if SIZEOF_LONG > 4
{
unsigned long y;
/* only want the trailing 32 bits */
y = x & 0xFFFFFFFFUL;
if (y ^ x)
return PyErr_Format(PyExc_OverflowError,
"long int larger than 32 bits");
x = y;
}
#endif
}
else
return PyErr_Format(PyExc_TypeError,
"expected int/long, %s found",
arg->ob_type->tp_name);
if (x == (unsigned long) -1 && PyErr_Occurred())
return NULL;
return PyInt_FromLong(ntohl(x));
}
PyDoc_STRVAR(ntohl_doc,
@ -2489,7 +2508,7 @@ Convert a 32-bit integer from network to host byte order.");
static PyObject *
socket_htons(PyObject *self, PyObject *args)
{
int x1, x2;
unsigned long x1, x2;
if (!PyArg_ParseTuple(args, "i:htons", &x1)) {
return NULL;
@ -2505,15 +2524,34 @@ Convert a 16-bit integer from host to network byte order.");
static PyObject *
socket_htonl(PyObject *self, PyObject *args)
socket_htonl(PyObject *self, PyObject *arg)
{
int x1, x2;
unsigned long x;
if (!PyArg_ParseTuple(args, "i:htonl", &x1)) {
return NULL;
if (PyInt_Check(arg)) {
x = PyInt_AS_LONG(arg);
}
x2 = htonl(x1);
return PyInt_FromLong(x2);
else if (PyLong_Check(arg)) {
x = PyLong_AsUnsignedLong(arg);
#if SIZEOF_LONG > 4
{
unsigned long y;
/* only want the trailing 32 bits */
y = x & 0xFFFFFFFFUL;
if (y ^ x)
return PyErr_Format(PyExc_OverflowError,
"long int larger than 32 bits");
x = y;
}
#endif
}
else
return PyErr_Format(PyExc_TypeError,
"expected int/long, %s found",
arg->ob_type->tp_name);
if (x == (unsigned long) -1 && PyErr_Occurred())
return NULL;
return PyInt_FromLong(htonl(x));
}
PyDoc_STRVAR(htonl_doc,
@ -2812,11 +2850,11 @@ static PyMethodDef socket_methods[] = {
{"ntohs", socket_ntohs,
METH_VARARGS, ntohs_doc},
{"ntohl", socket_ntohl,
METH_VARARGS, ntohl_doc},
METH_O, ntohl_doc},
{"htons", socket_htons,
METH_VARARGS, htons_doc},
{"htonl", socket_htonl,
METH_VARARGS, htonl_doc},
METH_O, htonl_doc},
{"inet_aton", socket_inet_aton,
METH_VARARGS, inet_aton_doc},
{"inet_ntoa", socket_inet_ntoa,