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.
|
||||
Returns ``-1`` on failure.
|
||||
|
||||
.. versionchanged: 3.5
|
||||
Writable :term:`bytes-like object` is now accepted.
|
||||
|
||||
|
||||
.. 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.
|
||||
Returns ``-1`` on failure.
|
||||
|
||||
.. versionchanged: 3.5
|
||||
Writable :term:`bytes-like object` is now accepted.
|
||||
|
||||
|
||||
.. 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
|
||||
writing to it will raise a :exc:`TypeError` exception.
|
||||
|
||||
.. versionchanged: 3.5
|
||||
Writable :term:`bytes-like object` is now accepted.
|
||||
|
||||
|
||||
.. method:: write_byte(byte)
|
||||
|
||||
|
|
|
@ -148,21 +148,30 @@ and (read-only) attributes:
|
|||
|
||||
.. method:: oss_audio_device.write(data)
|
||||
|
||||
Write the Python string *data* to the audio device and return the number of
|
||||
bytes written. If the audio device is in blocking mode (the default), the
|
||||
entire string is always written (again, this is different from usual Unix device
|
||||
semantics). If the device is in non-blocking mode, some data may not be written
|
||||
Write a :term:`bytes-like object` *data* to the audio device and return the
|
||||
number of bytes written. If the audio device is in blocking mode (the
|
||||
default), the entire data is always written (again, this is different from
|
||||
usual Unix device semantics). If the device is in non-blocking mode, some
|
||||
data may not be written
|
||||
---see :meth:`writeall`.
|
||||
|
||||
.. versionchanged: 3.5
|
||||
Writable :term:`bytes-like object` is now accepted.
|
||||
|
||||
|
||||
.. method:: oss_audio_device.writeall(data)
|
||||
|
||||
Write the entire Python string *data* to the audio device: waits until the audio
|
||||
device is able to accept data, writes as much data as it will accept, and
|
||||
repeats until *data* has been completely written. If the device is in blocking
|
||||
mode (the default), this has the same effect as :meth:`write`; :meth:`writeall`
|
||||
is only useful in non-blocking mode. Has no return value, since the amount of
|
||||
data written is always equal to the amount of data supplied.
|
||||
Write a :term:`bytes-like object` *data* to the audio device: waits until
|
||||
the audio device is able to accept data, writes as much data as it will
|
||||
accept, and repeats until *data* has been completely written. If the device
|
||||
is in blocking mode (the default), this has the same effect as
|
||||
:meth:`write`; :meth:`writeall` is only useful in non-blocking mode. Has
|
||||
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
|
||||
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
|
||||
is represented as a string, using the file system encoding and the
|
||||
``'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
|
||||
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
|
||||
: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.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
Previously, :const:`AF_UNIX` socket paths were assumed to use UTF-8
|
||||
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,
|
||||
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'``,
|
||||
|
@ -609,8 +612,8 @@ The :mod:`socket` module also offers various network-related services:
|
|||
|
||||
.. function:: inet_ntoa(packed_ip)
|
||||
|
||||
Convert a 32-bit packed IPv4 address (a bytes object four characters in
|
||||
length) to its standard dotted-quad string representation (for example,
|
||||
Convert a 32-bit packed IPv4 address (a :term:`bytes-like object` four
|
||||
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
|
||||
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
|
||||
|
@ -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
|
||||
stack support.
|
||||
|
||||
.. versionchanged: 3.5
|
||||
Writable :term:`bytes-like object` is now accepted.
|
||||
|
||||
|
||||
.. 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)
|
||||
|
||||
Convert a packed IP address (a bytes object of some number of characters) to its
|
||||
standard, family-specific string representation (for example, ``'7.10.0.5'`` or
|
||||
``'5aef:2b::8'``). :func:`inet_ntop` is useful when a library or network protocol
|
||||
returns an object of type :c:type:`struct in_addr` (similar to :func:`inet_ntoa`)
|
||||
or :c:type:`struct in6_addr`.
|
||||
Convert a packed IP address (a :term:`bytes-like object` of some number of
|
||||
bytes) to its standard, family-specific string representation (for
|
||||
example, ``'7.10.0.5'`` or ``'5aef:2b::8'``).
|
||||
:func:`inet_ntop` is useful when a library or network protocol returns an
|
||||
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
|
||||
:const:`AF_INET6`. If the string *packed_ip* is not the correct length for the
|
||||
specified address family, :exc:`ValueError` will be raised. A
|
||||
:exc:`OSError` is raised for errors from the call to :func:`inet_ntop`.
|
||||
:const:`AF_INET6`. If the bytes object *packed_ip* is not the correct
|
||||
length for the specified address family, :exc:`ValueError` will be raised.
|
||||
A :exc:`OSError` is raised for errors from the call to :func:`inet_ntop`.
|
||||
|
||||
Availability: Unix (maybe not all platforms), Windows.
|
||||
|
||||
.. versionchanged:: 3.4
|
||||
Windows support added
|
||||
|
||||
.. versionchanged: 3.5
|
||||
Writable :term:`bytes-like object` is now accepted.
|
||||
|
||||
|
||||
..
|
||||
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
|
||||
: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
|
||||
bytes object representing a buffer. In the latter case it is up to the caller to
|
||||
:mod:`socket` module (:const:`SO_\*` etc.). The value can be an integer or
|
||||
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
|
||||
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)
|
||||
|
||||
|
|
|
@ -340,6 +340,9 @@ Random generation
|
|||
string (so you can always use :const:`0.0`). See :rfc:`1750` for more
|
||||
information on sources of entropy.
|
||||
|
||||
.. versionchanged: 3.5
|
||||
Writable :term:`bytes-like object` is now accepted.
|
||||
|
||||
Certificate handling
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -1086,6 +1086,7 @@ class UTF8SigTest(UTF8Test, unittest.TestCase):
|
|||
class EscapeDecodeTest(unittest.TestCase):
|
||||
def test_empty(self):
|
||||
self.assertEqual(codecs.escape_decode(b""), (b"", 0))
|
||||
self.assertEqual(codecs.escape_decode(bytearray()), (b"", 0))
|
||||
|
||||
def test_raw(self):
|
||||
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, -1), 8)
|
||||
self.assertEqual(m.find(b'one', 1, -2), -1)
|
||||
self.assertEqual(m.find(bytearray(b'one')), 0)
|
||||
|
||||
|
||||
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', 1, -1), 8)
|
||||
self.assertEqual(m.rfind(b'one', 1, -2), -1)
|
||||
self.assertEqual(m.rfind(bytearray(b'one')), 8)
|
||||
|
||||
|
||||
def test_double_close(self):
|
||||
|
@ -601,8 +603,10 @@ class MmapTests(unittest.TestCase):
|
|||
m.write(b"bar")
|
||||
self.assertEqual(m.tell(), 6)
|
||||
self.assertEqual(m[:], b"012bar6789")
|
||||
m.seek(8)
|
||||
self.assertRaises(ValueError, m.write, b"bar")
|
||||
m.write(bytearray(b"baz"))
|
||||
self.assertEqual(m.tell(), 9)
|
||||
self.assertEqual(m[:], b"012barbaz9")
|
||||
self.assertRaises(ValueError, m.write, b"ba")
|
||||
|
||||
def test_non_ascii_byte(self):
|
||||
for b in (129, 200, 255): # > 128
|
||||
|
|
|
@ -1074,6 +1074,7 @@ class GeneralModuleTests(unittest.TestCase):
|
|||
assertInvalid(f, b'\x00' * 3)
|
||||
assertInvalid(f, b'\x00' * 5)
|
||||
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('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' * 5)
|
||||
assertInvalid(g, b'\x00' * 16)
|
||||
self.assertEqual('170.85.170.85', g(bytearray(b'\xaa\x55\xaa\x55')))
|
||||
|
||||
@unittest.skipUnless(hasattr(socket, 'inet_ntop'),
|
||||
'test needs socket.inet_ntop()')
|
||||
|
@ -1110,6 +1112,7 @@ class GeneralModuleTests(unittest.TestCase):
|
|||
'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')
|
||||
)
|
||||
self.assertEqual('::1', f(bytearray(b'\x00' * 15 + b'\x01')))
|
||||
|
||||
assertInvalid(b'\x12' * 15)
|
||||
assertInvalid(b'\x12' * 17)
|
||||
|
@ -1497,6 +1500,7 @@ class BasicCANTest(unittest.TestCase):
|
|||
s.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, can_filter)
|
||||
self.assertEqual(can_filter,
|
||||
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.')
|
||||
|
@ -4508,6 +4512,12 @@ class TestLinuxAbstractNamespace(unittest.TestCase):
|
|||
finally:
|
||||
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')
|
||||
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, 'foo', 1)
|
||||
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')
|
||||
def test_random_fork(self):
|
||||
|
|
|
@ -21,6 +21,10 @@ Core and Builtins
|
|||
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
|
||||
retried with the recomputed delay, except if the signal handler raises an
|
||||
exception (PEP 475).
|
||||
|
|
|
@ -208,15 +208,18 @@ static PyObject *
|
|||
escape_decode(PyObject *self,
|
||||
PyObject *args)
|
||||
{
|
||||
Py_buffer pbuf;
|
||||
const char *errors = NULL;
|
||||
const char *data;
|
||||
Py_ssize_t size;
|
||||
PyObject *result;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s#|z:escape_decode",
|
||||
&data, &size, &errors))
|
||||
if (!PyArg_ParseTuple(args, "s*|z:escape_decode",
|
||||
&pbuf, &errors))
|
||||
return NULL;
|
||||
return codec_tuple(PyBytes_DecodeEscape(data, size, errors, 0, NULL),
|
||||
size);
|
||||
result = codec_tuple(
|
||||
PyBytes_DecodeEscape(pbuf.buf, pbuf.len, errors, 0, NULL),
|
||||
pbuf.len);
|
||||
PyBuffer_Release(&pbuf);
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
|
|
@ -3672,18 +3672,22 @@ static PyTypeObject PySSLMemoryBIO_Type = {
|
|||
static PyObject *
|
||||
PySSL_RAND_add(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *buf;
|
||||
Py_buffer view;
|
||||
const char *buf;
|
||||
Py_ssize_t len, written;
|
||||
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;
|
||||
buf = (const char *)view.buf;
|
||||
len = view.len;
|
||||
do {
|
||||
written = Py_MIN(len, INT_MAX);
|
||||
RAND_add(buf, (int)written, entropy);
|
||||
buf += written;
|
||||
len -= written;
|
||||
} while (len);
|
||||
PyBuffer_Release(&view);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
|
|
@ -301,16 +301,17 @@ mmap_gfind(mmap_object *self,
|
|||
{
|
||||
Py_ssize_t start = self->pos;
|
||||
Py_ssize_t end = self->size;
|
||||
const char *needle;
|
||||
Py_ssize_t len;
|
||||
Py_buffer view;
|
||||
|
||||
CHECK_VALID(NULL);
|
||||
if (!PyArg_ParseTuple(args, reverse ? "y#|nn:rfind" : "y#|nn:find",
|
||||
&needle, &len, &start, &end)) {
|
||||
if (!PyArg_ParseTuple(args, reverse ? "y*|nn:rfind" : "y*|nn:find",
|
||||
&view, &start, &end)) {
|
||||
return NULL;
|
||||
} else {
|
||||
const char *p, *start_p, *end_p;
|
||||
int sign = reverse ? -1 : 1;
|
||||
const char *needle = view.buf;
|
||||
Py_ssize_t len = view.len;
|
||||
|
||||
if (start < 0)
|
||||
start += self->size;
|
||||
|
@ -335,9 +336,11 @@ mmap_gfind(mmap_object *self,
|
|||
for (i = 0; i < len && needle[i] == p[i]; ++i)
|
||||
/* nothing */;
|
||||
if (i == len) {
|
||||
PyBuffer_Release(&view);
|
||||
return PyLong_FromSsize_t(p - self->data);
|
||||
}
|
||||
}
|
||||
PyBuffer_Release(&view);
|
||||
return PyLong_FromLong(-1);
|
||||
}
|
||||
}
|
||||
|
@ -385,22 +388,25 @@ static PyObject *
|
|||
mmap_write_method(mmap_object *self,
|
||||
PyObject *args)
|
||||
{
|
||||
Py_ssize_t length;
|
||||
char *data;
|
||||
Py_buffer data;
|
||||
|
||||
CHECK_VALID(NULL);
|
||||
if (!PyArg_ParseTuple(args, "y#:write", &data, &length))
|
||||
if (!PyArg_ParseTuple(args, "y*:write", &data))
|
||||
return(NULL);
|
||||
|
||||
if (!is_writable(self))
|
||||
return NULL;
|
||||
|
||||
if ((self->pos + length) > self->size) {
|
||||
PyErr_SetString(PyExc_ValueError, "data out of range");
|
||||
if (!is_writable(self)) {
|
||||
PyBuffer_Release(&data);
|
||||
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);
|
||||
return Py_None;
|
||||
}
|
||||
|
|
|
@ -426,17 +426,18 @@ oss_read(oss_audio_t *self, PyObject *args)
|
|||
static PyObject *
|
||||
oss_write(oss_audio_t *self, PyObject *args)
|
||||
{
|
||||
char *cp;
|
||||
int rv, size;
|
||||
Py_buffer data;
|
||||
int rv;
|
||||
|
||||
if (!_is_fd_valid(self->fd))
|
||||
return NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "y#:write", &cp, &size)) {
|
||||
if (!PyArg_ParseTuple(args, "y*:write", &data)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rv = _Py_write(self->fd, cp, size);
|
||||
rv = _Py_write(self->fd, data.buf, data.len);
|
||||
PyBuffer_Release(&data);
|
||||
if (rv == -1)
|
||||
return NULL;
|
||||
|
||||
|
@ -447,8 +448,10 @@ oss_write(oss_audio_t *self, PyObject *args)
|
|||
static PyObject *
|
||||
oss_writeall(oss_audio_t *self, PyObject *args)
|
||||
{
|
||||
char *cp;
|
||||
int rv, size;
|
||||
Py_buffer data;
|
||||
const char *cp;
|
||||
Py_ssize_t size;
|
||||
int rv;
|
||||
fd_set write_set_fds;
|
||||
int select_rv;
|
||||
|
||||
|
@ -462,17 +465,20 @@ oss_writeall(oss_audio_t *self, PyObject *args)
|
|||
if (!_is_fd_valid(self->fd))
|
||||
return NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "y#:write", &cp, &size))
|
||||
if (!PyArg_ParseTuple(args, "y*:writeall", &data))
|
||||
return NULL;
|
||||
|
||||
if (!_PyIsSelectable_fd(self->fd)) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"file descriptor out of range for select");
|
||||
PyBuffer_Release(&data);
|
||||
return NULL;
|
||||
}
|
||||
/* use select to wait for audio device to be available */
|
||||
FD_ZERO(&write_set_fds);
|
||||
FD_SET(self->fd, &write_set_fds);
|
||||
cp = (const char *)data.buf;
|
||||
size = data.len;
|
||||
|
||||
while (size > 0) {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
@ -480,10 +486,12 @@ oss_writeall(oss_audio_t *self, PyObject *args)
|
|||
Py_END_ALLOW_THREADS
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
rv = _Py_write(self->fd, cp, size);
|
||||
rv = _Py_write(self->fd, , cp, Py_MIN(size, INT_MAX));
|
||||
if (rv == -1) {
|
||||
/* buffer is full, try again */
|
||||
if (errno == EAGAIN) {
|
||||
|
@ -491,6 +499,7 @@ oss_writeall(oss_audio_t *self, PyObject *args)
|
|||
continue;
|
||||
}
|
||||
/* it's a real error */
|
||||
PyBuffer_Release(&data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -499,6 +508,7 @@ oss_writeall(oss_audio_t *self, PyObject *args)
|
|||
size -= rv;
|
||||
cp += rv;
|
||||
}
|
||||
PyBuffer_Release(&data);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
|
|
@ -1299,8 +1299,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
case AF_UNIX:
|
||||
{
|
||||
struct sockaddr_un* addr;
|
||||
char *path;
|
||||
int len;
|
||||
Py_buffer path;
|
||||
int retval = 0;
|
||||
|
||||
/* PEP 383. Not using PyUnicode_FSConverter since we need to
|
||||
|
@ -1311,15 +1310,17 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
}
|
||||
else
|
||||
Py_INCREF(args);
|
||||
if (!PyArg_Parse(args, "y#", &path, &len))
|
||||
goto unix_out;
|
||||
assert(len >= 0);
|
||||
if (!PyArg_Parse(args, "y*", &path)) {
|
||||
Py_DECREF(args);
|
||||
return retval;
|
||||
}
|
||||
assert(path.len >= 0);
|
||||
|
||||
addr = (struct sockaddr_un*)addr_ret;
|
||||
#ifdef linux
|
||||
if (len > 0 && path[0] == 0) {
|
||||
if (path.len > 0 && *(const char *)path.buf == 0) {
|
||||
/* 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,
|
||||
"AF_UNIX path too long");
|
||||
goto unix_out;
|
||||
|
@ -1329,18 +1330,19 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
#endif /* linux */
|
||||
{
|
||||
/* 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,
|
||||
"AF_UNIX path too long");
|
||||
goto unix_out;
|
||||
}
|
||||
addr->sun_path[len] = 0;
|
||||
addr->sun_path[path.len] = 0;
|
||||
}
|
||||
addr->sun_family = s->sock_family;
|
||||
memcpy(addr->sun_path, path, len);
|
||||
*len_ret = len + offsetof(struct sockaddr_un, sun_path);
|
||||
memcpy(addr->sun_path, path.buf, path.len);
|
||||
*len_ret = path.len + offsetof(struct sockaddr_un, sun_path);
|
||||
retval = 1;
|
||||
unix_out:
|
||||
PyBuffer_Release(&path);
|
||||
Py_DECREF(args);
|
||||
return retval;
|
||||
}
|
||||
|
@ -1562,8 +1564,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
int protoNumber;
|
||||
int hatype = 0;
|
||||
int pkttype = 0;
|
||||
char *haddr = NULL;
|
||||
unsigned int halen = 0;
|
||||
Py_buffer haddr = {NULL, NULL};
|
||||
|
||||
if (!PyTuple_Check(args)) {
|
||||
PyErr_Format(
|
||||
|
@ -1573,25 +1574,28 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
Py_TYPE(args)->tp_name);
|
||||
return 0;
|
||||
}
|
||||
if (!PyArg_ParseTuple(args, "si|iiy#", &interfaceName,
|
||||
if (!PyArg_ParseTuple(args, "si|iiy*", &interfaceName,
|
||||
&protoNumber, &pkttype, &hatype,
|
||||
&haddr, &halen))
|
||||
&haddr))
|
||||
return 0;
|
||||
strncpy(ifr.ifr_name, interfaceName, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0';
|
||||
if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr) < 0) {
|
||||
s->errorhandler();
|
||||
PyBuffer_Release(&haddr);
|
||||
return 0;
|
||||
}
|
||||
if (halen > 8) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Hardware address must be 8 bytes or less");
|
||||
return 0;
|
||||
if (haddr.buf && haddr.len > 8) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Hardware address must be 8 bytes or less");
|
||||
PyBuffer_Release(&haddr);
|
||||
return 0;
|
||||
}
|
||||
if (protoNumber < 0 || protoNumber > 0xffff) {
|
||||
PyErr_SetString(
|
||||
PyExc_OverflowError,
|
||||
"getsockaddrarg: protoNumber must be 0-65535.");
|
||||
PyBuffer_Release(&haddr);
|
||||
return 0;
|
||||
}
|
||||
addr = (struct sockaddr_ll*)addr_ret;
|
||||
|
@ -1600,11 +1604,14 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
|
|||
addr->sll_ifindex = ifr.ifr_ifindex;
|
||||
addr->sll_pkttype = pkttype;
|
||||
addr->sll_hatype = hatype;
|
||||
if (halen != 0) {
|
||||
memcpy(&addr->sll_addr, haddr, halen);
|
||||
if (haddr.buf) {
|
||||
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;
|
||||
PyBuffer_Release(&haddr);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
@ -2230,22 +2237,21 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)
|
|||
int level;
|
||||
int optname;
|
||||
int res;
|
||||
char *buf;
|
||||
int buflen;
|
||||
Py_buffer optval;
|
||||
int flag;
|
||||
|
||||
if (PyArg_ParseTuple(args, "iii:setsockopt",
|
||||
&level, &optname, &flag)) {
|
||||
buf = (char *) &flag;
|
||||
buflen = sizeof flag;
|
||||
res = setsockopt(s->sock_fd, level, optname, &flag, sizeof flag);
|
||||
}
|
||||
else {
|
||||
PyErr_Clear();
|
||||
if (!PyArg_ParseTuple(args, "iiy#:setsockopt",
|
||||
&level, &optname, &buf, &buflen))
|
||||
if (!PyArg_ParseTuple(args, "iiy*:setsockopt",
|
||||
&level, &optname, &optval))
|
||||
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)
|
||||
return s->errorhandler();
|
||||
Py_INCREF(Py_None);
|
||||
|
@ -5037,21 +5043,22 @@ Convert an IP address from 32-bit packed binary format to string format");
|
|||
static PyObject*
|
||||
socket_inet_ntoa(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *packed_str;
|
||||
int addr_len;
|
||||
Py_buffer packed_ip;
|
||||
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;
|
||||
}
|
||||
|
||||
if (addr_len != sizeof(packed_addr)) {
|
||||
if (packed_ip.len != sizeof(packed_addr)) {
|
||||
PyErr_SetString(PyExc_OSError,
|
||||
"packed IP wrong length for inet_ntoa");
|
||||
PyBuffer_Release(&packed_ip);
|
||||
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));
|
||||
}
|
||||
|
@ -5162,8 +5169,7 @@ static PyObject *
|
|||
socket_inet_ntop(PyObject *self, PyObject *args)
|
||||
{
|
||||
int af;
|
||||
char* packed;
|
||||
int len;
|
||||
Py_buffer packed_ip;
|
||||
const char* retval;
|
||||
#ifdef ENABLE_IPV6
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
if (af == AF_INET) {
|
||||
if (len != sizeof(struct in_addr)) {
|
||||
if (packed_ip.len != sizeof(struct in_addr)) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"invalid length of packed IP address string");
|
||||
PyBuffer_Release(&packed_ip);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef ENABLE_IPV6
|
||||
} else if (af == AF_INET6) {
|
||||
if (len != sizeof(struct in6_addr)) {
|
||||
if (packed_ip.len != sizeof(struct in6_addr)) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"invalid length of packed IP address string");
|
||||
PyBuffer_Release(&packed_ip);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"unknown address family %d", af);
|
||||
PyBuffer_Release(&packed_ip);
|
||||
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) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
return NULL;
|
||||
|
@ -5217,8 +5227,7 @@ static PyObject *
|
|||
socket_inet_ntop(PyObject *self, PyObject *args)
|
||||
{
|
||||
int af;
|
||||
char* packed;
|
||||
int len;
|
||||
Py_buffer packed_ip;
|
||||
struct sockaddr_in6 addr;
|
||||
DWORD addrlen, ret, retlen;
|
||||
#ifdef ENABLE_IPV6
|
||||
|
@ -5230,38 +5239,42 @@ socket_inet_ntop(PyObject *self, PyObject *args)
|
|||
/* Guarantee NUL-termination for PyUnicode_FromString() below */
|
||||
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;
|
||||
}
|
||||
|
||||
if (af == AF_INET) {
|
||||
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,
|
||||
"invalid length of packed IP address string");
|
||||
PyBuffer_Release(&packed_ip);
|
||||
return NULL;
|
||||
}
|
||||
memset(addr4, 0, sizeof(struct sockaddr_in));
|
||||
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);
|
||||
} else if (af == AF_INET6) {
|
||||
if (len != sizeof(struct in6_addr)) {
|
||||
if (packed_ip.len != sizeof(struct in6_addr)) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"invalid length of packed IP address string");
|
||||
PyBuffer_Release(&packed_ip);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
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);
|
||||
} else {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"unknown address family %d", af);
|
||||
PyBuffer_Release(&packed_ip);
|
||||
return NULL;
|
||||
}
|
||||
PyBuffer_Release(&packed_ip);
|
||||
|
||||
retlen = sizeof(ip);
|
||||
ret = WSAAddressToStringA((struct sockaddr*)&addr, addrlen, NULL,
|
||||
|
|
Loading…
Reference in New Issue