[Python-checkins] cpython: Issue #23001: Few functions in modules mmap, ossaudiodev, socket, ssl, and

serhiy.storchaka python-checkins at python.org
Fri Mar 20 08:04:47 CET 2015


https://hg.python.org/cpython/rev/17c77938c4e2
changeset: 95084:17c77938c4e2
user: Serhiy Storchaka <storchaka at gmail.com>
date: Fri Mar 20 09:00:36 2015 +0200
summary:
 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.
files:
 Doc/library/mmap.rst | 9 +
 Doc/library/ossaudiodev.rst | 29 ++++--
 Doc/library/socket.rst | 42 ++++++---
 Doc/library/ssl.rst | 3 +
 Lib/test/test_codecs.py | 1 +
 Lib/test/test_mmap.py | 8 +-
 Lib/test/test_socket.py | 10 ++
 Lib/test/test_ssl.py | 2 +
 Misc/NEWS | 4 +
 Modules/_codecsmodule.c | 15 +-
 Modules/_ssl.c | 8 +-
 Modules/mmapmodule.c | 34 ++++---
 Modules/ossaudiodev.c | 28 ++++-
 Modules/socketmodule.c | 109 +++++++++++++----------
 14 files changed, 197 insertions(+), 105 deletions(-)
diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst
--- a/Doc/library/mmap.rst
+++ b/Doc/library/mmap.rst
@@ -174,6 +174,9 @@
 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 @@
 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 @@
 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)
 
diff --git a/Doc/library/ossaudiodev.rst b/Doc/library/ossaudiodev.rst
--- a/Doc/library/ossaudiodev.rst
+++ b/Doc/library/ossaudiodev.rst
@@ -148,21 +148,30 @@
 
 .. 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
diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst
--- a/Doc/library/socket.rst
+++ b/Doc/library/socket.rst
@@ -46,17 +46,20 @@
 - 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 @@
 
 .. 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 @@
 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 @@
 
 .. 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 @@
 
 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)
 
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -340,6 +340,9 @@
 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
 ^^^^^^^^^^^^^^^^^^^^
 
diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py
--- a/Lib/test/test_codecs.py
+++ b/Lib/test/test_codecs.py
@@ -1086,6 +1086,7 @@
 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
diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py
--- a/Lib/test/test_mmap.py
+++ b/Lib/test/test_mmap.py
@@ -282,6 +282,7 @@
 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 @@
 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 @@
 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
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -1074,6 +1074,7 @@
 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 @@
 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 @@
 'aef:b01:506:1001:ffff:.&checktime(9997,55,17,':')0',
 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 @@
 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 @@
 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):
 
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -171,6 +171,8 @@
 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):
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -21,6 +21,10 @@
 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).
diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c
--- a/Modules/_codecsmodule.c
+++ b/Modules/_codecsmodule.c
@@ -208,15 +208,18 @@
 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 *
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -3672,18 +3672,22 @@
 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;
 }
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -301,16 +301,17 @@
 {
 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 @@
 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 @@
 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;
 }
diff --git a/Modules/ossaudiodev.c b/Modules/ossaudiodev.c
--- a/Modules/ossaudiodev.c
+++ b/Modules/ossaudiodev.c
@@ -426,17 +426,18 @@
 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 @@
 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 @@
 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 @@
 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 @@
 continue;
 }
 /* it's a real error */
+ PyBuffer_Release(&data);
 return NULL;
 }
 
@@ -499,6 +508,7 @@
 size -= rv;
 cp += rv;
 }
+ PyBuffer_Release(&data);
 Py_INCREF(Py_None);
 return Py_None;
 }
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -1299,8 +1299,7 @@
 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 @@
 }
 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 @@
 #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 @@
 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 @@
 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 @@
 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 @@
 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, (void *)buf, buflen);
+ res = setsockopt(s->sock_fd, level, optname, optval.buf, optval.len);
+ PyBuffer_Release(&optval);
+ }
 if (res < 0)
 return s->errorhandler();
 Py_INCREF(Py_None);
@@ -5037,21 +5043,22 @@
 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 @@
 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 @@
 /* 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 @@
 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 @@
 /* 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,
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /