https://github.com/python/cpython/commit/1fc1df8dcc7a853b0649bc8df37cd07cbd2b6230
commit: 1fc1df8dcc7a853b0649bc8df37cd07cbd2b6230
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2025-04-14T08:58:56+03:00
summary:
gh-132099: Harmonize Bluetooth address handling (GH-132486)
Now all protocols always accept the Bluetooth address as string and
getsockname() always returns the Bluetooth address as string.
* BTPROTO_SCO now accepts not only bytes, but str.
* BTPROTO_SCO now checks address for embedded null.
* On *BSD, BTPROTO_HCI now accepts str instead of bytes.
* On FreeBSD, getsockname() for BTPROTO_HCI now returns str instead of bytes.
* On NetBSD and DragonFly BDS, BTPROTO_HCI now checks address for embedded null.
files:
M Doc/library/socket.rst
M Lib/test/test_socket.py
M Modules/socketmodule.c
diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst
index 2e38101c01d89d..11f7f06c59e873 100644
--- a/Doc/library/socket.rst
+++ b/Doc/library/socket.rst
@@ -158,9 +158,8 @@ created. Socket addresses are represented as follows:
- On Linux it accepts a tuple ``(device_id,)`` where ``device_id``
is an integer specifying the number of the Bluetooth device.
- - On FreeBSD, NetBSD and DragonFly BSD it accepts ``bdaddr`` where
``bdaddr``
- is a :class:`bytes` object containing the Bluetooth address in a
- string format. (ex. ``b'12:23:34:45:56:67'``)
+ - On FreeBSD, NetBSD and DragonFly BSD it accepts ``bdaddr``
+ where ``bdaddr`` is the Bluetooth address as a string.
.. versionchanged:: 3.2
NetBSD and DragonFlyBSD support added.
@@ -168,9 +167,9 @@ created. Socket addresses are represented as follows:
.. versionchanged:: 3.13.3
FreeBSD support added.
- - :const:`BTPROTO_SCO` accepts ``bdaddr`` where ``bdaddr`` is a
- :class:`bytes` object containing the Bluetooth address in a
- string format. (ex. ``b'12:23:34:45:56:67'``)
+ - :const:`BTPROTO_SCO` accepts ``bdaddr`` where ``bdaddr`` is
+ the Bluetooth address as a string or a :class:`bytes` object.
+ (ex. ``'12:23:34:45:56:67'`` or ``b'12:23:34:45:56:67'``)
.. versionchanged:: next
FreeBSD support added.
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index 66cb63daca02ae..93dbcc981591ca 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -2681,6 +2681,8 @@ def testBadL2capAddr(self):
f.bind(socket.BDADDR_ANY)
with self.assertRaises(OSError):
f.bind((socket.BDADDR_ANY.encode(), 0x1001))
+ with self.assertRaises(OSError):
+ f.bind(('\ud812', 0x1001))
def testBindRfcommSocket(self):
with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM,
socket.BTPROTO_RFCOMM) as s:
@@ -2712,6 +2714,8 @@ def testBadRfcommAddr(self):
s.bind((socket.BDADDR_ANY, channel, 0))
with self.assertRaises(OSError):
s.bind((socket.BDADDR_ANY + '\0', channel))
+ with self.assertRaises(OSError):
+ s.bind('\ud812')
with self.assertRaises(OSError):
s.bind(('invalid', channel))
@@ -2719,7 +2723,7 @@ def testBadRfcommAddr(self):
def testBindHciSocket(self):
with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
socket.BTPROTO_HCI) as s:
if sys.platform.startswith(('netbsd', 'dragonfly', 'freebsd')):
- s.bind(socket.BDADDR_ANY.encode())
+ s.bind(socket.BDADDR_ANY)
addr = s.getsockname()
self.assertEqual(addr, socket.BDADDR_ANY)
else:
@@ -2738,14 +2742,17 @@ def testBadHciAddr(self):
with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
socket.BTPROTO_HCI) as s:
if sys.platform.startswith(('netbsd', 'dragonfly', 'freebsd')):
with self.assertRaises(OSError):
- s.bind(socket.BDADDR_ANY)
+ s.bind(socket.BDADDR_ANY.encode())
with self.assertRaises(OSError):
- s.bind((socket.BDADDR_ANY.encode(),))
- if sys.platform.startswith('freebsd'):
- with self.assertRaises(ValueError):
- s.bind(socket.BDADDR_ANY.encode() + b'\0')
- with self.assertRaises(ValueError):
- s.bind(socket.BDADDR_ANY.encode() + b' '*100)
+ s.bind((socket.BDADDR_ANY,))
+ with self.assertRaises(OSError):
+ s.bind(socket.BDADDR_ANY + '\0')
+ with self.assertRaises((ValueError, OSError)):
+ s.bind(socket.BDADDR_ANY + ' '*100)
+ with self.assertRaises(OSError):
+ s.bind('\ud812')
+ with self.assertRaises(OSError):
+ s.bind('invalid')
with self.assertRaises(OSError):
s.bind(b'invalid')
else:
@@ -2756,11 +2763,18 @@ def testBadHciAddr(self):
s.bind((dev, 0))
with self.assertRaises(OSError):
s.bind(dev)
+ with self.assertRaises(OSError):
+ s.bind(socket.BDADDR_ANY)
with self.assertRaises(OSError):
s.bind(socket.BDADDR_ANY.encode())
@unittest.skipUnless(hasattr(socket, 'BTPROTO_SCO'), 'Bluetooth SCO
sockets required for this test')
def testBindScoSocket(self):
+ with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET,
socket.BTPROTO_SCO) as s:
+ s.bind(socket.BDADDR_ANY)
+ addr = s.getsockname()
+ self.assertEqual(addr, socket.BDADDR_ANY)
+
with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET,
socket.BTPROTO_SCO) as s:
s.bind(socket.BDADDR_ANY.encode())
addr = s.getsockname()
@@ -2770,9 +2784,17 @@ def testBindScoSocket(self):
def testBadScoAddr(self):
with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET,
socket.BTPROTO_SCO) as s:
with self.assertRaises(OSError):
- s.bind(socket.BDADDR_ANY)
+ s.bind((socket.BDADDR_ANY,))
with self.assertRaises(OSError):
s.bind((socket.BDADDR_ANY.encode(),))
+ with self.assertRaises(ValueError):
+ s.bind(socket.BDADDR_ANY + '\0')
+ with self.assertRaises(ValueError):
+ s.bind(socket.BDADDR_ANY.encode() + b'\0')
+ with self.assertRaises(UnicodeEncodeError):
+ s.bind('\ud812')
+ with self.assertRaises(OSError):
+ s.bind('invalid')
with self.assertRaises(OSError):
s.bind(b'invalid')
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 76e16bc3a2d3ec..86c920aed9cf26 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -1546,7 +1546,7 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr,
size_t addrlen, int proto)
#elif defined(__FreeBSD__)
const char *node = _BT_HCI_MEMB(a, node);
size_t len = strnlen(node, sizeof(_BT_HCI_MEMB(a, node)));
- return PyBytes_FromStringAndSize(node, (Py_ssize_t)len);
+ return PyUnicode_FromStringAndSize(node, (Py_ssize_t)len);
#else
return makebdaddr(&_BT_HCI_MEMB(a, bdaddr));
#endif
@@ -2145,36 +2145,25 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
return 0;
}
_BT_HCI_MEMB(addr, dev) = dev;
-#elif defined(__FreeBSD__)
- if (!PyBytes_Check(args)) {
+#else
+ const char *straddr;
+ if (!PyArg_Parse(args, "s", &straddr)) {
PyErr_Format(PyExc_OSError, "%s: "
- "wrong node format", caller);
- return 0;
- }
- const char *straddr = PyBytes_AS_STRING(args);
- size_t len = PyBytes_GET_SIZE(args);
- if (strlen(straddr) != len) {
- PyErr_Format(PyExc_ValueError, "%s: "
- "node contains embedded null character", caller);
+ "wrong format", caller);
return 0;
}
- if (len > sizeof(_BT_HCI_MEMB(addr, node))) {
+# if defined(__FreeBSD__)
+ if (strlen(straddr) > sizeof(_BT_HCI_MEMB(addr, node))) {
PyErr_Format(PyExc_ValueError, "%s: "
"node too long", caller);
return 0;
}
strncpy(_BT_HCI_MEMB(addr, node), straddr,
sizeof(_BT_HCI_MEMB(addr, node)));
-#else
- const char *straddr;
- if (!PyBytes_Check(args)) {
- PyErr_Format(PyExc_OSError, "%s: "
- "wrong format", caller);
- return 0;
- }
- straddr = PyBytes_AS_STRING(args);
+# else
if (setbdaddr(straddr, &_BT_HCI_MEMB(addr, bdaddr)) < 0)
return 0;
+# endif
#endif
*len_ret = sizeof *addr;
return 1;
@@ -2188,12 +2177,22 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
struct sockaddr_sco *addr = &addrbuf->bt_sco;
memset(addr, 0, sizeof(struct sockaddr_sco));
_BT_SCO_MEMB(addr, family) = AF_BLUETOOTH;
- if (!PyBytes_Check(args)) {
+
+ if (PyBytes_Check(args)) {
+ if (!PyArg_Parse(args, "y", &straddr)) {
+ return 0;
+ }
+ }
+ else if (PyUnicode_Check(args)) {
+ if (!PyArg_Parse(args, "s", &straddr)) {
+ return 0;
+ }
+ }
+ else {
PyErr_Format(PyExc_OSError,
"%s(): wrong format", caller);
return 0;
}
- straddr = PyBytes_AS_STRING(args);
if (setbdaddr(straddr, &_BT_SCO_MEMB(addr, bdaddr)) < 0)
return 0;
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]