Issue #23001: Few functions in modules mmap, ossaudiodev, socket, ssl, and
codecs, that accepted only read-only bytes-like object now accept writable bytes-like object too.
This commit is contained in:
parent
0eac13052c
commit
8490f5acfe
|
@ -174,6 +174,9 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
|
||||||
Optional arguments *start* and *end* are interpreted as in slice notation.
|
Optional arguments *start* and *end* are interpreted as in slice notation.
|
||||||
Returns ``-1`` on failure.
|
Returns ``-1`` on failure.
|
||||||
|
|
||||||
|
.. versionchanged: 3.5
|
||||||
|
Writable :term:`bytes-like object` is now accepted.
|
||||||
|
|
||||||
|
|
||||||
.. method:: flush([offset[, size]])
|
.. method:: flush([offset[, size]])
|
||||||
|
|
||||||
|
@ -234,6 +237,9 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
|
||||||
Optional arguments *start* and *end* are interpreted as in slice notation.
|
Optional arguments *start* and *end* are interpreted as in slice notation.
|
||||||
Returns ``-1`` on failure.
|
Returns ``-1`` on failure.
|
||||||
|
|
||||||
|
.. versionchanged: 3.5
|
||||||
|
Writable :term:`bytes-like object` is now accepted.
|
||||||
|
|
||||||
|
|
||||||
.. method:: seek(pos[, whence])
|
.. method:: seek(pos[, whence])
|
||||||
|
|
||||||
|
@ -261,6 +267,9 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
|
||||||
were written. If the mmap was created with :const:`ACCESS_READ`, then
|
were written. If the mmap was created with :const:`ACCESS_READ`, then
|
||||||
writing to it will raise a :exc:`TypeError` exception.
|
writing to it will raise a :exc:`TypeError` exception.
|
||||||
|
|
||||||
|
.. versionchanged: 3.5
|
||||||
|
Writable :term:`bytes-like object` is now accepted.
|
||||||
|
|
||||||
|
|
||||||
.. method:: write_byte(byte)
|
.. method:: write_byte(byte)
|
||||||
|
|
||||||
|
|
|
@ -148,21 +148,30 @@ and (read-only) attributes:
|
||||||
|
|
||||||
.. method:: oss_audio_device.write(data)
|
.. method:: oss_audio_device.write(data)
|
||||||
|
|
||||||
Write the Python string *data* to the audio device and return the number of
|
Write a :term:`bytes-like object` *data* to the audio device and return the
|
||||||
bytes written. If the audio device is in blocking mode (the default), the
|
number of bytes written. If the audio device is in blocking mode (the
|
||||||
entire string is always written (again, this is different from usual Unix device
|
default), the entire data is always written (again, this is different from
|
||||||
semantics). If the device is in non-blocking mode, some data may not be written
|
usual Unix device semantics). If the device is in non-blocking mode, some
|
||||||
|
data may not be written
|
||||||
---see :meth:`writeall`.
|
---see :meth:`writeall`.
|
||||||
|
|
||||||
|
.. versionchanged: 3.5
|
||||||
|
Writable :term:`bytes-like object` is now accepted.
|
||||||
|
|
||||||
|
|
||||||
.. method:: oss_audio_device.writeall(data)
|
.. method:: oss_audio_device.writeall(data)
|
||||||
|
|
||||||
Write the entire Python string *data* to the audio device: waits until the audio
|
Write a :term:`bytes-like object` *data* to the audio device: waits until
|
||||||
device is able to accept data, writes as much data as it will accept, and
|
the audio device is able to accept data, writes as much data as it will
|
||||||
repeats until *data* has been completely written. If the device is in blocking
|
accept, and repeats until *data* has been completely written. If the device
|
||||||
mode (the default), this has the same effect as :meth:`write`; :meth:`writeall`
|
is in blocking mode (the default), this has the same effect as
|
||||||
is only useful in non-blocking mode. Has no return value, since the amount of
|
:meth:`write`; :meth:`writeall` is only useful in non-blocking mode. Has
|
||||||
data written is always equal to the amount of data supplied.
|
no return value, since the amount of data written is always equal to the
|
||||||
|
amount of data supplied.
|
||||||
|
|
||||||
|
.. versionchanged: 3.5
|
||||||
|
Writable :term:`bytes-like object` is now accepted.
|
||||||
|
|
||||||
|
|
||||||
.. versionchanged:: 3.2
|
.. versionchanged:: 3.2
|
||||||
Audio device objects also support the context management protocol, i.e. they can
|
Audio device objects also support the context management protocol, i.e. they can
|
||||||
|
|
|
@ -46,17 +46,20 @@ created. Socket addresses are represented as follows:
|
||||||
- The address of an :const:`AF_UNIX` socket bound to a file system node
|
- The address of an :const:`AF_UNIX` socket bound to a file system node
|
||||||
is represented as a string, using the file system encoding and the
|
is represented as a string, using the file system encoding and the
|
||||||
``'surrogateescape'`` error handler (see :pep:`383`). An address in
|
``'surrogateescape'`` error handler (see :pep:`383`). An address in
|
||||||
Linux's abstract namespace is returned as a :class:`bytes` object with
|
Linux's abstract namespace is returned as a :term:`bytes-like object` with
|
||||||
an initial null byte; note that sockets in this namespace can
|
an initial null byte; note that sockets in this namespace can
|
||||||
communicate with normal file system sockets, so programs intended to
|
communicate with normal file system sockets, so programs intended to
|
||||||
run on Linux may need to deal with both types of address. A string or
|
run on Linux may need to deal with both types of address. A string or
|
||||||
:class:`bytes` object can be used for either type of address when
|
bytes-like object can be used for either type of address when
|
||||||
passing it as an argument.
|
passing it as an argument.
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
Previously, :const:`AF_UNIX` socket paths were assumed to use UTF-8
|
Previously, :const:`AF_UNIX` socket paths were assumed to use UTF-8
|
||||||
encoding.
|
encoding.
|
||||||
|
|
||||||
|
.. versionchanged: 3.5
|
||||||
|
Writable :term:`bytes-like object` is now accepted.
|
||||||
|
|
||||||
- A pair ``(host, port)`` is used for the :const:`AF_INET` address family,
|
- A pair ``(host, port)`` is used for the :const:`AF_INET` address family,
|
||||||
where *host* is a string representing either a hostname in Internet domain
|
where *host* is a string representing either a hostname in Internet domain
|
||||||
notation like ``'daring.cwi.nl'`` or an IPv4 address like ``'100.50.200.5'``,
|
notation like ``'daring.cwi.nl'`` or an IPv4 address like ``'100.50.200.5'``,
|
||||||
|
@ -609,8 +612,8 @@ The :mod:`socket` module also offers various network-related services:
|
||||||
|
|
||||||
.. function:: inet_ntoa(packed_ip)
|
.. function:: inet_ntoa(packed_ip)
|
||||||
|
|
||||||
Convert a 32-bit packed IPv4 address (a bytes object four characters in
|
Convert a 32-bit packed IPv4 address (a :term:`bytes-like object` four
|
||||||
length) to its standard dotted-quad string representation (for example,
|
bytes in length) to its standard dotted-quad string representation (for example,
|
||||||
'123.45.67.89'). This is useful when conversing with a program that uses the
|
'123.45.67.89'). This is useful when conversing with a program that uses the
|
||||||
standard C library and needs objects of type :c:type:`struct in_addr`, which
|
standard C library and needs objects of type :c:type:`struct in_addr`, which
|
||||||
is the C type for the 32-bit packed binary data this function takes as an
|
is the C type for the 32-bit packed binary data this function takes as an
|
||||||
|
@ -621,6 +624,9 @@ The :mod:`socket` module also offers various network-related services:
|
||||||
support IPv6, and :func:`inet_ntop` should be used instead for IPv4/v6 dual
|
support IPv6, and :func:`inet_ntop` should be used instead for IPv4/v6 dual
|
||||||
stack support.
|
stack support.
|
||||||
|
|
||||||
|
.. versionchanged: 3.5
|
||||||
|
Writable :term:`bytes-like object` is now accepted.
|
||||||
|
|
||||||
|
|
||||||
.. function:: inet_pton(address_family, ip_string)
|
.. function:: inet_pton(address_family, ip_string)
|
||||||
|
|
||||||
|
@ -643,22 +649,26 @@ The :mod:`socket` module also offers various network-related services:
|
||||||
|
|
||||||
.. function:: inet_ntop(address_family, packed_ip)
|
.. function:: inet_ntop(address_family, packed_ip)
|
||||||
|
|
||||||
Convert a packed IP address (a bytes object of some number of characters) to its
|
Convert a packed IP address (a :term:`bytes-like object` of some number of
|
||||||
standard, family-specific string representation (for example, ``'7.10.0.5'`` or
|
bytes) to its standard, family-specific string representation (for
|
||||||
``'5aef:2b::8'``). :func:`inet_ntop` is useful when a library or network protocol
|
example, ``'7.10.0.5'`` or ``'5aef:2b::8'``).
|
||||||
returns an object of type :c:type:`struct in_addr` (similar to :func:`inet_ntoa`)
|
:func:`inet_ntop` is useful when a library or network protocol returns an
|
||||||
or :c:type:`struct in6_addr`.
|
object of type :c:type:`struct in_addr` (similar to :func:`inet_ntoa`) or
|
||||||
|
:c:type:`struct in6_addr`.
|
||||||
|
|
||||||
Supported values for *address_family* are currently :const:`AF_INET` and
|
Supported values for *address_family* are currently :const:`AF_INET` and
|
||||||
:const:`AF_INET6`. If the string *packed_ip* is not the correct length for the
|
:const:`AF_INET6`. If the bytes object *packed_ip* is not the correct
|
||||||
specified address family, :exc:`ValueError` will be raised. A
|
length for the specified address family, :exc:`ValueError` will be raised.
|
||||||
:exc:`OSError` is raised for errors from the call to :func:`inet_ntop`.
|
A :exc:`OSError` is raised for errors from the call to :func:`inet_ntop`.
|
||||||
|
|
||||||
Availability: Unix (maybe not all platforms), Windows.
|
Availability: Unix (maybe not all platforms), Windows.
|
||||||
|
|
||||||
.. versionchanged:: 3.4
|
.. versionchanged:: 3.4
|
||||||
Windows support added
|
Windows support added
|
||||||
|
|
||||||
|
.. versionchanged: 3.5
|
||||||
|
Writable :term:`bytes-like object` is now accepted.
|
||||||
|
|
||||||
|
|
||||||
..
|
..
|
||||||
XXX: Are sendmsg(), recvmsg() and CMSG_*() available on any
|
XXX: Are sendmsg(), recvmsg() and CMSG_*() available on any
|
||||||
|
@ -1207,11 +1217,15 @@ to sockets.
|
||||||
|
|
||||||
Set the value of the given socket option (see the Unix manual page
|
Set the value of the given socket option (see the Unix manual page
|
||||||
:manpage:`setsockopt(2)`). The needed symbolic constants are defined in the
|
:manpage:`setsockopt(2)`). The needed symbolic constants are defined in the
|
||||||
:mod:`socket` module (:const:`SO_\*` etc.). The value can be an integer or a
|
:mod:`socket` module (:const:`SO_\*` etc.). The value can be an integer or
|
||||||
bytes object representing a buffer. In the latter case it is up to the caller to
|
a :term:`bytes-like object` representing a buffer. In the latter case it is
|
||||||
|
up to the caller to
|
||||||
ensure that the bytestring contains the proper bits (see the optional built-in
|
ensure that the bytestring contains the proper bits (see the optional built-in
|
||||||
module :mod:`struct` for a way to encode C structures as bytestrings).
|
module :mod:`struct` for a way to encode C structures as bytestrings).
|
||||||
|
|
||||||
|
.. versionchanged: 3.5
|
||||||
|
Writable :term:`bytes-like object` is now accepted.
|
||||||
|
|
||||||
|
|
||||||
.. method:: socket.shutdown(how)
|
.. method:: socket.shutdown(how)
|
||||||
|
|
||||||
|
|
|
@ -340,6 +340,9 @@ Random generation
|
||||||
string (so you can always use :const:`0.0`). See :rfc:`1750` for more
|
string (so you can always use :const:`0.0`). See :rfc:`1750` for more
|
||||||
information on sources of entropy.
|
information on sources of entropy.
|
||||||
|
|
||||||
|
.. versionchanged: 3.5
|
||||||
|
Writable :term:`bytes-like object` is now accepted.
|
||||||
|
|
||||||
Certificate handling
|
Certificate handling
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -1086,6 +1086,7 @@ class UTF8SigTest(UTF8Test, unittest.TestCase):
|
||||||
class EscapeDecodeTest(unittest.TestCase):
|
class EscapeDecodeTest(unittest.TestCase):
|
||||||
def test_empty(self):
|
def test_empty(self):
|
||||||
self.assertEqual(codecs.escape_decode(b""), (b"", 0))
|
self.assertEqual(codecs.escape_decode(b""), (b"", 0))
|
||||||
|
self.assertEqual(codecs.escape_decode(bytearray()), (b"", 0))
|
||||||
|
|
||||||
def test_raw(self):
|
def test_raw(self):
|
||||||
decode = codecs.escape_decode
|
decode = codecs.escape_decode
|
||||||
|
|
|
@ -282,6 +282,7 @@ class MmapTests(unittest.TestCase):
|
||||||
self.assertEqual(m.find(b'one', 1), 8)
|
self.assertEqual(m.find(b'one', 1), 8)
|
||||||
self.assertEqual(m.find(b'one', 1, -1), 8)
|
self.assertEqual(m.find(b'one', 1, -1), 8)
|
||||||
self.assertEqual(m.find(b'one', 1, -2), -1)
|
self.assertEqual(m.find(b'one', 1, -2), -1)
|
||||||
|
self.assertEqual(m.find(bytearray(b'one')), 0)
|
||||||
|
|
||||||
|
|
||||||
def test_rfind(self):
|
def test_rfind(self):
|
||||||
|
@ -300,6 +301,7 @@ class MmapTests(unittest.TestCase):
|
||||||
self.assertEqual(m.rfind(b'one', 0, -2), 0)
|
self.assertEqual(m.rfind(b'one', 0, -2), 0)
|
||||||
self.assertEqual(m.rfind(b'one', 1, -1), 8)
|
self.assertEqual(m.rfind(b'one', 1, -1), 8)
|
||||||
self.assertEqual(m.rfind(b'one', 1, -2), -1)
|
self.assertEqual(m.rfind(b'one', 1, -2), -1)
|
||||||
|
self.assertEqual(m.rfind(bytearray(b'one')), 8)
|
||||||
|
|
||||||
|
|
||||||
def test_double_close(self):
|
def test_double_close(self):
|
||||||
|
@ -601,8 +603,10 @@ class MmapTests(unittest.TestCase):
|
||||||
m.write(b"bar")
|
m.write(b"bar")
|
||||||
self.assertEqual(m.tell(), 6)
|
self.assertEqual(m.tell(), 6)
|
||||||
self.assertEqual(m[:], b"012bar6789")
|
self.assertEqual(m[:], b"012bar6789")
|
||||||
m.seek(8)
|
m.write(bytearray(b"baz"))
|
||||||
self.assertRaises(ValueError, m.write, b"bar")
|
self.assertEqual(m.tell(), 9)
|
||||||
|
self.assertEqual(m[:], b"012barbaz9")
|
||||||
|
self.assertRaises(ValueError, m.write, b"ba")
|
||||||
|
|
||||||
def test_non_ascii_byte(self):
|
def test_non_ascii_byte(self):
|
||||||
for b in (129, 200, 255): # > 128
|
for b in (129, 200, 255): # > 128
|
||||||
|
|
|
@ -1074,6 +1074,7 @@ class GeneralModuleTests(unittest.TestCase):
|
||||||
assertInvalid(f, b'\x00' * 3)
|
assertInvalid(f, b'\x00' * 3)
|
||||||
assertInvalid(f, b'\x00' * 5)
|
assertInvalid(f, b'\x00' * 5)
|
||||||
assertInvalid(f, b'\x00' * 16)
|
assertInvalid(f, b'\x00' * 16)
|
||||||
|
self.assertEqual('170.85.170.85', f(bytearray(b'\xaa\x55\xaa\x55')))
|
||||||
|
|
||||||
self.assertEqual('1.0.1.0', g(b'\x01\x00\x01\x00'))
|
self.assertEqual('1.0.1.0', g(b'\x01\x00\x01\x00'))
|
||||||
self.assertEqual('170.85.170.85', g(b'\xaa\x55\xaa\x55'))
|
self.assertEqual('170.85.170.85', g(b'\xaa\x55\xaa\x55'))
|
||||||
|
@ -1081,6 +1082,7 @@ class GeneralModuleTests(unittest.TestCase):
|
||||||
assertInvalid(g, b'\x00' * 3)
|
assertInvalid(g, b'\x00' * 3)
|
||||||
assertInvalid(g, b'\x00' * 5)
|
assertInvalid(g, b'\x00' * 5)
|
||||||
assertInvalid(g, b'\x00' * 16)
|
assertInvalid(g, b'\x00' * 16)
|
||||||
|
self.assertEqual('170.85.170.85', g(bytearray(b'\xaa\x55\xaa\x55')))
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(socket, 'inet_ntop'),
|
@unittest.skipUnless(hasattr(socket, 'inet_ntop'),
|
||||||
'test needs socket.inet_ntop()')
|
'test needs socket.inet_ntop()')
|
||||||
|
@ -1110,6 +1112,7 @@ class GeneralModuleTests(unittest.TestCase):
|
||||||
'aef:b01:506:1001:ffff:9997:55:170',
|
'aef:b01:506:1001:ffff:9997:55:170',
|
||||||
f(b'\x0a\xef\x0b\x01\x05\x06\x10\x01\xff\xff\x99\x97\x00\x55\x01\x70')
|
f(b'\x0a\xef\x0b\x01\x05\x06\x10\x01\xff\xff\x99\x97\x00\x55\x01\x70')
|
||||||
)
|
)
|
||||||
|
self.assertEqual('::1', f(bytearray(b'\x00' * 15 + b'\x01')))
|
||||||
|
|
||||||
assertInvalid(b'\x12' * 15)
|
assertInvalid(b'\x12' * 15)
|
||||||
assertInvalid(b'\x12' * 17)
|
assertInvalid(b'\x12' * 17)
|
||||||
|
@ -1497,6 +1500,7 @@ class BasicCANTest(unittest.TestCase):
|
||||||
s.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, can_filter)
|
s.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, can_filter)
|
||||||
self.assertEqual(can_filter,
|
self.assertEqual(can_filter,
|
||||||
s.getsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, 8))
|
s.getsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, 8))
|
||||||
|
s.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, bytearray(can_filter))
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.')
|
@unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.')
|
||||||
|
@ -4508,6 +4512,12 @@ class TestLinuxAbstractNamespace(unittest.TestCase):
|
||||||
finally:
|
finally:
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
def testBytearrayName(self):
|
||||||
|
# Check that an abstract name can be passed as a bytearray.
|
||||||
|
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s:
|
||||||
|
s.bind(bytearray(b"\x00python\x00test\x00"))
|
||||||
|
self.assertEqual(s.getsockname(), b"\x00python\x00test\x00")
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'test needs socket.AF_UNIX')
|
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'test needs socket.AF_UNIX')
|
||||||
class TestUnixDomain(unittest.TestCase):
|
class TestUnixDomain(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -171,6 +171,8 @@ class BasicSocketTests(unittest.TestCase):
|
||||||
self.assertRaises(TypeError, ssl.RAND_egd, 1)
|
self.assertRaises(TypeError, ssl.RAND_egd, 1)
|
||||||
self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
|
self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
|
||||||
ssl.RAND_add("this is a random string", 75.0)
|
ssl.RAND_add("this is a random string", 75.0)
|
||||||
|
ssl.RAND_add(b"this is a random bytes object", 75.0)
|
||||||
|
ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
|
||||||
|
|
||||||
@unittest.skipUnless(os.name == 'posix', 'requires posix')
|
@unittest.skipUnless(os.name == 'posix', 'requires posix')
|
||||||
def test_random_fork(self):
|
def test_random_fork(self):
|
||||||
|
|
|
@ -21,6 +21,10 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #23001: Few functions in modules mmap, ossaudiodev, socket, ssl, and
|
||||||
|
codecs, that accepted only read-only bytes-like object now accept writable
|
||||||
|
bytes-like object too.
|
||||||
|
|
||||||
- Issue #23646: If time.sleep() is interrupted by a signal, the sleep is now
|
- Issue #23646: If time.sleep() is interrupted by a signal, the sleep is now
|
||||||
retried with the recomputed delay, except if the signal handler raises an
|
retried with the recomputed delay, except if the signal handler raises an
|
||||||
exception (PEP 475).
|
exception (PEP 475).
|
||||||
|
|
|
@ -208,15 +208,18 @@ static PyObject *
|
||||||
escape_decode(PyObject *self,
|
escape_decode(PyObject *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
|
Py_buffer pbuf;
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
const char *data;
|
PyObject *result;
|
||||||
Py_ssize_t size;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s#|z:escape_decode",
|
if (!PyArg_ParseTuple(args, "s*|z:escape_decode",
|
||||||
&data, &size, &errors))
|
&pbuf, &errors))
|
||||||
return NULL;
|
return NULL;
|
||||||
return codec_tuple(PyBytes_DecodeEscape(data, size, errors, 0, NULL),
|
result = codec_tuple(
|
||||||
size);
|
PyBytes_DecodeEscape(pbuf.buf, pbuf.len, errors, 0, NULL),
|
||||||
|
pbuf.len);
|
||||||
|
PyBuffer_Release(&pbuf);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
|
|
@ -3672,18 +3672,22 @@ static PyTypeObject PySSLMemoryBIO_Type = {
|
||||||
static PyObject *
|
static PyObject *
|
||||||
PySSL_RAND_add(PyObject *self, PyObject *args)
|
PySSL_RAND_add(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
char *buf;
|
Py_buffer view;
|
||||||
|
const char *buf;
|
||||||
Py_ssize_t len, written;
|
Py_ssize_t len, written;
|
||||||
double entropy;
|
double entropy;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s#d:RAND_add", &buf, &len, &entropy))
|
if (!PyArg_ParseTuple(args, "s*d:RAND_add", &view, &entropy))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
buf = (const char *)view.buf;
|
||||||
|
len = view.len;
|
||||||
do {
|
do {
|
||||||
written = Py_MIN(len, INT_MAX);
|
written = Py_MIN(len, INT_MAX);
|
||||||
RAND_add(buf, (int)written, entropy);
|
RAND_add(buf, (int)written, entropy);
|
||||||
buf += written;
|
buf += written;
|
||||||
len -= written;
|
len -= written;
|
||||||
} while (len);
|
} while (len);
|
||||||
|
PyBuffer_Release(&view);
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,16 +301,17 @@ mmap_gfind(mmap_object *self,
|
||||||
{
|
{
|
||||||
Py_ssize_t start = self->pos;
|
Py_ssize_t start = self->pos;
|
||||||
Py_ssize_t end = self->size;
|
Py_ssize_t end = self->size;
|
||||||
const char *needle;
|
Py_buffer view;
|
||||||
Py_ssize_t len;
|
|
||||||
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
if (!PyArg_ParseTuple(args, reverse ? "y#|nn:rfind" : "y#|nn:find",
|
if (!PyArg_ParseTuple(args, reverse ? "y*|nn:rfind" : "y*|nn:find",
|
||||||
&needle, &len, &start, &end)) {
|
&view, &start, &end)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
const char *p, *start_p, *end_p;
|
const char *p, *start_p, *end_p;
|
||||||
int sign = reverse ? -1 : 1;
|
int sign = reverse ? -1 : 1;
|
||||||
|
const char *needle = view.buf;
|
||||||
|
Py_ssize_t len = view.len;
|
||||||
|
|
||||||
if (start < 0)
|
if (start < 0)
|
||||||
start += self->size;
|
start += self->size;
|
||||||
|
@ -335,9 +336,11 @@ mmap_gfind(mmap_object *self,
|
||||||
for (i = 0; i < len && needle[i] == p[i]; ++i)
|
for (i = 0; i < len && needle[i] == p[i]; ++i)
|
||||||
/* nothing */;
|
/* nothing */;
|
||||||
if (i == len) {
|
if (i == len) {
|
||||||
|
PyBuffer_Release(&view);
|
||||||
return PyLong_FromSsize_t(p - self->data);
|
return PyLong_FromSsize_t(p - self->data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PyBuffer_Release(&view);
|
||||||
return PyLong_FromLong(-1);
|
return PyLong_FromLong(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,22 +388,25 @@ static PyObject *
|
||||||
mmap_write_method(mmap_object *self,
|
mmap_write_method(mmap_object *self,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
Py_ssize_t length;
|
Py_buffer data;
|
||||||
char *data;
|
|
||||||
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
if (!PyArg_ParseTuple(args, "y#:write", &data, &length))
|
if (!PyArg_ParseTuple(args, "y*:write", &data))
|
||||||
return(NULL);
|
return(NULL);
|
||||||
|
|
||||||
if (!is_writable(self))
|
if (!is_writable(self)) {
|
||||||
return NULL;
|
PyBuffer_Release(&data);
|
||||||
|
|
||||||
if ((self->pos + length) > self->size) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "data out of range");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memcpy(self->data+self->pos, data, length);
|
|
||||||
self->pos = self->pos+length;
|
if ((self->pos + data.len) > self->size) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "data out of range");
|
||||||
|
PyBuffer_Release(&data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(self->data + self->pos, data.buf, data.len);
|
||||||
|
self->pos = self->pos + data.len;
|
||||||
|
PyBuffer_Release(&data);
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -426,17 +426,18 @@ oss_read(oss_audio_t *self, PyObject *args)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
oss_write(oss_audio_t *self, PyObject *args)
|
oss_write(oss_audio_t *self, PyObject *args)
|
||||||
{
|
{
|
||||||
char *cp;
|
Py_buffer data;
|
||||||
int rv, size;
|
int rv;
|
||||||
|
|
||||||
if (!_is_fd_valid(self->fd))
|
if (!_is_fd_valid(self->fd))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "y#:write", &cp, &size)) {
|
if (!PyArg_ParseTuple(args, "y*:write", &data)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = _Py_write(self->fd, cp, size);
|
rv = _Py_write(self->fd, data.buf, data.len);
|
||||||
|
PyBuffer_Release(&data);
|
||||||
if (rv == -1)
|
if (rv == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -447,8 +448,10 @@ oss_write(oss_audio_t *self, PyObject *args)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
oss_writeall(oss_audio_t *self, PyObject *args)
|
oss_writeall(oss_audio_t *self, PyObject *args)
|
||||||
{
|
{
|
||||||
char *cp;
|
Py_buffer data;
|
||||||
int rv, size;
|
const char *cp;
|
||||||
|
Py_ssize_t size;
|
||||||
|
int rv;
|
||||||
fd_set write_set_fds;
|
fd_set write_set_fds;
|
||||||
int select_rv;
|
int select_rv;
|
||||||
|
|
||||||
|
@ -462,17 +465,20 @@ oss_writeall(oss_audio_t *self, PyObject *args)
|
||||||
if (!_is_fd_valid(self->fd))
|
if (!_is_fd_valid(self->fd))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "y#:write", &cp, &size))
|
if (!PyArg_ParseTuple(args, "y*:writeall", &data))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!_PyIsSelectable_fd(self->fd)) {
|
if (!_PyIsSelectable_fd(self->fd)) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"file descriptor out of range for select");
|
"file descriptor out of range for select");
|
||||||
|
PyBuffer_Release(&data);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* use select to wait for audio device to be available */
|
/* use select to wait for audio device to be available */
|
||||||
FD_ZERO(&write_set_fds);
|
FD_ZERO(&write_set_fds);
|
||||||
FD_SET(self->fd, &write_set_fds);
|
FD_SET(self->fd, &write_set_fds);
|
||||||
|
cp = (const char *)data.buf;
|
||||||
|
size = data.len;
|
||||||
|
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
@ -480,10 +486,12 @@ oss_writeall(oss_audio_t *self, PyObject *args)
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
assert(select_rv != 0); /* no timeout, can't expire */
|
assert(select_rv != 0); /* no timeout, can't expire */
|
||||||
if (select_rv == -1)
|
if (select_rv == -1) {
|
||||||
|
PyBuffer_Release(&data);
|
||||||
return PyErr_SetFromErrno(PyExc_IOError);
|
return PyErr_SetFromErrno(PyExc_IOError);
|
||||||
|
}
|
||||||
|
|
||||||
rv = _Py_write(self->fd, cp, size);
|
rv = _Py_write(self->fd, , cp, Py_MIN(size, INT_MAX));
|
||||||
if (rv == -1) {
|
if (rv == -1) {
|
||||||
/* buffer is full, try again */
|
/* buffer is full, try again */
|
||||||
if (errno == EAGAIN) {
|
if (errno == EAGAIN) {
|
||||||
|
@ -491,6 +499,7 @@ oss_writeall(oss_audio_t *self, PyObject *args)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* it's a real error */
|
/* it's a real error */
|
||||||
|
PyBuffer_Release(&data);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,6 +508,7 @@ oss_writeall(oss_audio_t *self, PyObject *args)
|
||||||
size -= rv;
|
size -= rv;
|
||||||
cp += rv;
|
cp += rv;
|
||||||
}
|
}
|
||||||
|
PyBuffer_Release(&data);
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1299,8 +1299,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
||||||
case AF_UNIX:
|
case AF_UNIX:
|
||||||
{
|
{
|
||||||
struct sockaddr_un* addr;
|
struct sockaddr_un* addr;
|
||||||
char *path;
|
Py_buffer path;
|
||||||
int len;
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
/* PEP 383. Not using PyUnicode_FSConverter since we need to
|
/* PEP 383. Not using PyUnicode_FSConverter since we need to
|
||||||
|
@ -1311,15 +1310,17 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Py_INCREF(args);
|
Py_INCREF(args);
|
||||||
if (!PyArg_Parse(args, "y#", &path, &len))
|
if (!PyArg_Parse(args, "y*", &path)) {
|
||||||
goto unix_out;
|
Py_DECREF(args);
|
||||||
assert(len >= 0);
|
return retval;
|
||||||
|
}
|
||||||
|
assert(path.len >= 0);
|
||||||
|
|
||||||
addr = (struct sockaddr_un*)addr_ret;
|
addr = (struct sockaddr_un*)addr_ret;
|
||||||
#ifdef linux
|
#ifdef linux
|
||||||
if (len > 0 && path[0] == 0) {
|
if (path.len > 0 && *(const char *)path.buf == 0) {
|
||||||
/* Linux abstract namespace extension */
|
/* Linux abstract namespace extension */
|
||||||
if ((size_t)len > sizeof addr->sun_path) {
|
if ((size_t)path.len > sizeof addr->sun_path) {
|
||||||
PyErr_SetString(PyExc_OSError,
|
PyErr_SetString(PyExc_OSError,
|
||||||
"AF_UNIX path too long");
|
"AF_UNIX path too long");
|
||||||
goto unix_out;
|
goto unix_out;
|
||||||
|
@ -1329,18 +1330,19 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
||||||
#endif /* linux */
|
#endif /* linux */
|
||||||
{
|
{
|
||||||
/* regular NULL-terminated string */
|
/* regular NULL-terminated string */
|
||||||
if ((size_t)len >= sizeof addr->sun_path) {
|
if ((size_t)path.len >= sizeof addr->sun_path) {
|
||||||
PyErr_SetString(PyExc_OSError,
|
PyErr_SetString(PyExc_OSError,
|
||||||
"AF_UNIX path too long");
|
"AF_UNIX path too long");
|
||||||
goto unix_out;
|
goto unix_out;
|
||||||
}
|
}
|
||||||
addr->sun_path[len] = 0;
|
addr->sun_path[path.len] = 0;
|
||||||
}
|
}
|
||||||
addr->sun_family = s->sock_family;
|
addr->sun_family = s->sock_family;
|
||||||
memcpy(addr->sun_path, path, len);
|
memcpy(addr->sun_path, path.buf, path.len);
|
||||||
*len_ret = len + offsetof(struct sockaddr_un, sun_path);
|
*len_ret = path.len + offsetof(struct sockaddr_un, sun_path);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
unix_out:
|
unix_out:
|
||||||
|
PyBuffer_Release(&path);
|
||||||
Py_DECREF(args);
|
Py_DECREF(args);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1562,8 +1564,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
||||||
int protoNumber;
|
int protoNumber;
|
||||||
int hatype = 0;
|
int hatype = 0;
|
||||||
int pkttype = 0;
|
int pkttype = 0;
|
||||||
char *haddr = NULL;
|
Py_buffer haddr = {NULL, NULL};
|
||||||
unsigned int halen = 0;
|
|
||||||
|
|
||||||
if (!PyTuple_Check(args)) {
|
if (!PyTuple_Check(args)) {
|
||||||
PyErr_Format(
|
PyErr_Format(
|
||||||
|
@ -1573,25 +1574,28 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
||||||
Py_TYPE(args)->tp_name);
|
Py_TYPE(args)->tp_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!PyArg_ParseTuple(args, "si|iiy#", &interfaceName,
|
if (!PyArg_ParseTuple(args, "si|iiy*", &interfaceName,
|
||||||
&protoNumber, &pkttype, &hatype,
|
&protoNumber, &pkttype, &hatype,
|
||||||
&haddr, &halen))
|
&haddr))
|
||||||
return 0;
|
return 0;
|
||||||
strncpy(ifr.ifr_name, interfaceName, sizeof(ifr.ifr_name));
|
strncpy(ifr.ifr_name, interfaceName, sizeof(ifr.ifr_name));
|
||||||
ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0';
|
ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0';
|
||||||
if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr) < 0) {
|
if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr) < 0) {
|
||||||
s->errorhandler();
|
s->errorhandler();
|
||||||
|
PyBuffer_Release(&haddr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (halen > 8) {
|
if (haddr.buf && haddr.len > 8) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"Hardware address must be 8 bytes or less");
|
"Hardware address must be 8 bytes or less");
|
||||||
return 0;
|
PyBuffer_Release(&haddr);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
if (protoNumber < 0 || protoNumber > 0xffff) {
|
if (protoNumber < 0 || protoNumber > 0xffff) {
|
||||||
PyErr_SetString(
|
PyErr_SetString(
|
||||||
PyExc_OverflowError,
|
PyExc_OverflowError,
|
||||||
"getsockaddrarg: protoNumber must be 0-65535.");
|
"getsockaddrarg: protoNumber must be 0-65535.");
|
||||||
|
PyBuffer_Release(&haddr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
addr = (struct sockaddr_ll*)addr_ret;
|
addr = (struct sockaddr_ll*)addr_ret;
|
||||||
|
@ -1600,11 +1604,14 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
||||||
addr->sll_ifindex = ifr.ifr_ifindex;
|
addr->sll_ifindex = ifr.ifr_ifindex;
|
||||||
addr->sll_pkttype = pkttype;
|
addr->sll_pkttype = pkttype;
|
||||||
addr->sll_hatype = hatype;
|
addr->sll_hatype = hatype;
|
||||||
if (halen != 0) {
|
if (haddr.buf) {
|
||||||
memcpy(&addr->sll_addr, haddr, halen);
|
memcpy(&addr->sll_addr, haddr.buf, haddr.len);
|
||||||
|
addr->sll_halen = haddr.len;
|
||||||
}
|
}
|
||||||
addr->sll_halen = halen;
|
else
|
||||||
|
addr->sll_halen = 0;
|
||||||
*len_ret = sizeof *addr;
|
*len_ret = sizeof *addr;
|
||||||
|
PyBuffer_Release(&haddr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2230,22 +2237,21 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)
|
||||||
int level;
|
int level;
|
||||||
int optname;
|
int optname;
|
||||||
int res;
|
int res;
|
||||||
char *buf;
|
Py_buffer optval;
|
||||||
int buflen;
|
|
||||||
int flag;
|
int flag;
|
||||||
|
|
||||||
if (PyArg_ParseTuple(args, "iii:setsockopt",
|
if (PyArg_ParseTuple(args, "iii:setsockopt",
|
||||||
&level, &optname, &flag)) {
|
&level, &optname, &flag)) {
|
||||||
buf = (char *) &flag;
|
res = setsockopt(s->sock_fd, level, optname, &flag, sizeof flag);
|
||||||
buflen = sizeof flag;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
if (!PyArg_ParseTuple(args, "iiy#:setsockopt",
|
if (!PyArg_ParseTuple(args, "iiy*:setsockopt",
|
||||||
&level, &optname, &buf, &buflen))
|
&level, &optname, &optval))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
res = setsockopt(s->sock_fd, level, optname, optval.buf, optval.len);
|
||||||
|
PyBuffer_Release(&optval);
|
||||||
}
|
}
|
||||||
res = setsockopt(s->sock_fd, level, optname, (void *)buf, buflen);
|
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return s->errorhandler();
|
return s->errorhandler();
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
|
@ -5037,21 +5043,22 @@ Convert an IP address from 32-bit packed binary format to string format");
|
||||||
static PyObject*
|
static PyObject*
|
||||||
socket_inet_ntoa(PyObject *self, PyObject *args)
|
socket_inet_ntoa(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
char *packed_str;
|
Py_buffer packed_ip;
|
||||||
int addr_len;
|
|
||||||
struct in_addr packed_addr;
|
struct in_addr packed_addr;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "y#:inet_ntoa", &packed_str, &addr_len)) {
|
if (!PyArg_ParseTuple(args, "y*:inet_ntoa", &packed_ip)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr_len != sizeof(packed_addr)) {
|
if (packed_ip.len != sizeof(packed_addr)) {
|
||||||
PyErr_SetString(PyExc_OSError,
|
PyErr_SetString(PyExc_OSError,
|
||||||
"packed IP wrong length for inet_ntoa");
|
"packed IP wrong length for inet_ntoa");
|
||||||
|
PyBuffer_Release(&packed_ip);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&packed_addr, packed_str, addr_len);
|
memcpy(&packed_addr, packed_ip.buf, packed_ip.len);
|
||||||
|
PyBuffer_Release(&packed_ip);
|
||||||
|
|
||||||
return PyUnicode_FromString(inet_ntoa(packed_addr));
|
return PyUnicode_FromString(inet_ntoa(packed_addr));
|
||||||
}
|
}
|
||||||
|
@ -5162,8 +5169,7 @@ static PyObject *
|
||||||
socket_inet_ntop(PyObject *self, PyObject *args)
|
socket_inet_ntop(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
int af;
|
int af;
|
||||||
char* packed;
|
Py_buffer packed_ip;
|
||||||
int len;
|
|
||||||
const char* retval;
|
const char* retval;
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1];
|
char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1];
|
||||||
|
@ -5174,31 +5180,35 @@ socket_inet_ntop(PyObject *self, PyObject *args)
|
||||||
/* Guarantee NUL-termination for PyUnicode_FromString() below */
|
/* Guarantee NUL-termination for PyUnicode_FromString() below */
|
||||||
memset((void *) &ip[0], '\0', sizeof(ip));
|
memset((void *) &ip[0], '\0', sizeof(ip));
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "iy#:inet_ntop", &af, &packed, &len)) {
|
if (!PyArg_ParseTuple(args, "iy*:inet_ntop", &af, &packed_ip)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (af == AF_INET) {
|
if (af == AF_INET) {
|
||||||
if (len != sizeof(struct in_addr)) {
|
if (packed_ip.len != sizeof(struct in_addr)) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"invalid length of packed IP address string");
|
"invalid length of packed IP address string");
|
||||||
|
PyBuffer_Release(&packed_ip);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
} else if (af == AF_INET6) {
|
} else if (af == AF_INET6) {
|
||||||
if (len != sizeof(struct in6_addr)) {
|
if (packed_ip.len != sizeof(struct in6_addr)) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"invalid length of packed IP address string");
|
"invalid length of packed IP address string");
|
||||||
|
PyBuffer_Release(&packed_ip);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"unknown address family %d", af);
|
"unknown address family %d", af);
|
||||||
|
PyBuffer_Release(&packed_ip);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = inet_ntop(af, packed, ip, sizeof(ip));
|
retval = inet_ntop(af, packed_ip.buf, ip, sizeof(ip));
|
||||||
|
PyBuffer_Release(&packed_ip);
|
||||||
if (!retval) {
|
if (!retval) {
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -5217,8 +5227,7 @@ static PyObject *
|
||||||
socket_inet_ntop(PyObject *self, PyObject *args)
|
socket_inet_ntop(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
int af;
|
int af;
|
||||||
char* packed;
|
Py_buffer packed_ip;
|
||||||
int len;
|
|
||||||
struct sockaddr_in6 addr;
|
struct sockaddr_in6 addr;
|
||||||
DWORD addrlen, ret, retlen;
|
DWORD addrlen, ret, retlen;
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
|
@ -5230,38 +5239,42 @@ socket_inet_ntop(PyObject *self, PyObject *args)
|
||||||
/* Guarantee NUL-termination for PyUnicode_FromString() below */
|
/* Guarantee NUL-termination for PyUnicode_FromString() below */
|
||||||
memset((void *) &ip[0], '\0', sizeof(ip));
|
memset((void *) &ip[0], '\0', sizeof(ip));
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "iy#:inet_ntop", &af, &packed, &len)) {
|
if (!PyArg_ParseTuple(args, "iy*:inet_ntop", &af, &packed_ip)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (af == AF_INET) {
|
if (af == AF_INET) {
|
||||||
struct sockaddr_in * addr4 = (struct sockaddr_in *)&addr;
|
struct sockaddr_in * addr4 = (struct sockaddr_in *)&addr;
|
||||||
|
|
||||||
if (len != sizeof(struct in_addr)) {
|
if (packed_ip.len != sizeof(struct in_addr)) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"invalid length of packed IP address string");
|
"invalid length of packed IP address string");
|
||||||
|
PyBuffer_Release(&packed_ip);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(addr4, 0, sizeof(struct sockaddr_in));
|
memset(addr4, 0, sizeof(struct sockaddr_in));
|
||||||
addr4->sin_family = AF_INET;
|
addr4->sin_family = AF_INET;
|
||||||
memcpy(&(addr4->sin_addr), packed, sizeof(addr4->sin_addr));
|
memcpy(&(addr4->sin_addr), packed_ip.buf, sizeof(addr4->sin_addr));
|
||||||
addrlen = sizeof(struct sockaddr_in);
|
addrlen = sizeof(struct sockaddr_in);
|
||||||
} else if (af == AF_INET6) {
|
} else if (af == AF_INET6) {
|
||||||
if (len != sizeof(struct in6_addr)) {
|
if (packed_ip.len != sizeof(struct in6_addr)) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"invalid length of packed IP address string");
|
"invalid length of packed IP address string");
|
||||||
|
PyBuffer_Release(&packed_ip);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.sin6_family = AF_INET6;
|
addr.sin6_family = AF_INET6;
|
||||||
memcpy(&(addr.sin6_addr), packed, sizeof(addr.sin6_addr));
|
memcpy(&(addr.sin6_addr), packed_ip.buf, sizeof(addr.sin6_addr));
|
||||||
addrlen = sizeof(addr);
|
addrlen = sizeof(addr);
|
||||||
} else {
|
} else {
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"unknown address family %d", af);
|
"unknown address family %d", af);
|
||||||
|
PyBuffer_Release(&packed_ip);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
PyBuffer_Release(&packed_ip);
|
||||||
|
|
||||||
retlen = sizeof(ip);
|
retlen = sizeof(ip);
|
||||||
ret = WSAAddressToStringA((struct sockaddr*)&addr, addrlen, NULL,
|
ret = WSAAddressToStringA((struct sockaddr*)&addr, addrlen, NULL,
|
||||||
|
|
Loading…
Reference in New Issue