[pypy-commit] pypy default: Fix the out-of-range cases of socket.ntohl() & co., as an
arigo
pypy.commits at gmail.com
Mon Jan 2 10:20:55 EST 2017
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r89300:f934a882b7ba
Date: 2017-01-02 16:20 +0100
http://bitbucket.org/pypy/pypy/changeset/f934a882b7ba/
Log: Fix the out-of-range cases of socket.ntohl() & co., as an attempt to
pass the stricter tests of py3.5
diff --git a/pypy/module/_socket/interp_func.py b/pypy/module/_socket/interp_func.py
--- a/pypy/module/_socket/interp_func.py
+++ b/pypy/module/_socket/interp_func.py
@@ -1,6 +1,6 @@
from rpython.rlib import rsocket
from rpython.rlib.rsocket import SocketError, INVALID_SOCKET
-from rpython.rlib.rarithmetic import intmask
+from rpython.rlib.rarithmetic import intmask, r_longlong, r_uint32
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
@@ -164,40 +164,58 @@
space.wrap(W_Socket(space, sock2))
])
-# The following 4 functions refuse all negative numbers, like CPython 2.6.
-# They could also check that the argument is not too large, but CPython 2.6
-# is not doing that consistently.
- at unwrap_spec(x="c_uint")
+# The following 4 functions refuse all negative numbers.
+# They also check that the argument is not too large, but note that
+# CPython 2.7 is not doing that consistently (CPython 3.x does).
+LONGLONG_UINT32_MAX = r_longlong(2**32-1)
+
+ at unwrap_spec(x="c_int")
def ntohs(space, x):
"""ntohs(integer) -> integer
Convert a 16-bit integer from network to host byte order.
"""
+ if x < 0:
+ raise oefmt(space.w_OverflowError,
+ "can't convert negative number to unsigned long")
return space.wrap(rsocket.ntohs(intmask(x)))
- at unwrap_spec(x="c_uint")
+ at unwrap_spec(x=r_longlong)
def ntohl(space, x):
"""ntohl(integer) -> integer
Convert a 32-bit integer from network to host byte order.
"""
- return space.wrap(rsocket.ntohl(x))
+ if x < r_longlong(0):
+ raise oefmt(space.w_OverflowError,
+ "can't convert negative number to unsigned long")
+ if x > LONGLONG_UINT32_MAX:
+ raise oefmt(space.w_OverflowError, "long int larger than 32 bits")
+ return space.wrap(rsocket.ntohl(r_uint32(x)))
- at unwrap_spec(x="c_uint")
+ at unwrap_spec(x="c_int")
def htons(space, x):
"""htons(integer) -> integer
Convert a 16-bit integer from host to network byte order.
"""
- return space.wrap(rsocket.htons(intmask(x)))
+ if x < 0:
+ raise oefmt(space.w_OverflowError,
+ "can't convert negative number to unsigned long")
+ return space.wrap(rsocket.htons(x))
- at unwrap_spec(x="c_uint")
+ at unwrap_spec(x=r_longlong)
def htonl(space, x):
"""htonl(integer) -> integer
Convert a 32-bit integer from host to network byte order.
"""
- return space.wrap(rsocket.htonl(x))
+ if x < r_longlong(0):
+ raise oefmt(space.w_OverflowError,
+ "can't convert negative number to unsigned long")
+ if x > LONGLONG_UINT32_MAX:
+ raise oefmt(space.w_OverflowError, "long int larger than 32 bits")
+ return space.wrap(rsocket.htonl(r_uint32(x)))
@unwrap_spec(ip=str)
def inet_aton(space, ip):
diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
--- a/pypy/module/_socket/test/test_sock_app.py
+++ b/pypy/module/_socket/test/test_sock_app.py
@@ -320,9 +320,10 @@
assert _socket.socket.__name__ == 'socket'
assert _socket.socket.__module__ == '_socket'
- def test_getservbyport(self):
+ def test_overflow_errors(self):
import _socket
raises(OverflowError, _socket.getservbyport, -1)
+ raises(OverflowError, _socket.getservbyport, 65536)
def test_ntoa_exception(self):
import _socket
@@ -518,44 +519,25 @@
def test_NtoH(self):
import sys
import _socket as socket
- # This just checks that htons etc. are their own inverse,
- # when looking at the lower 16 or 32 bits.
+ # This checks that htons etc. are their own inverse,
+ # when looking at the lower 16 or 32 bits. It also
+ # checks that we get OverflowErrors when calling with -1,
+ # or (for XtoXl()) with too large values. For XtoXs()
+ # large values are silently truncated instead, like CPython.
sizes = {socket.htonl: 32, socket.ntohl: 32,
socket.htons: 16, socket.ntohs: 16}
for func, size in sizes.items():
mask = (1 << size) - 1
- for i in (0, 1, 0xffff, ~0xffff, 2, 0x01234567, 0x76543210):
+ for i in (0, 1, 0xffff, 0xffff0000, 2, 0x01234567, 0x76543210):
assert i & mask == func(func(i&mask)) & mask
swapped = func(mask)
assert swapped & mask == mask
- try:
- func(-1)
- except (OverflowError, ValueError):
- pass
- else:
- assert False
- try:
- func(sys.maxint*2+2)
- except OverflowError:
- pass
- else:
- assert False
-
- def test_NtoH_overflow(self):
- skip("we are not checking for overflowing values yet")
- import _socket as socket
- # Checks that we cannot give too large values to htons etc.
- # Skipped for now; CPython 2.6 is also not consistent.
- sizes = {socket.htonl: 32, socket.ntohl: 32,
- socket.htons: 16, socket.ntohs: 16}
- for func, size in sizes.items():
- try:
- func(1 << size)
- except OverflowError:
- pass
- else:
- assert False
+ raises(OverflowError, func, -1)
+ raises(OverflowError, func, -1L)
+ if size > 16: # else, values too large are ignored
+ raises(OverflowError, func, 2 ** size)
+ raises(OverflowError, func, 2L ** size)
def test_newsocket(self):
import socket
More information about the pypy-commit
mailing list