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:
Serhiy Storchaka 2015-03-20 09:00:36 +02:00
parent 0eac13052c
commit 8490f5acfe
14 changed files with 196 additions and 104 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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
^^^^^^^^^^^^^^^^^^^^

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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):

View File

@ -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).

View File

@ -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 *

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,