8000 gh-132099: Harmonize Bluetooth address handling (GH-132486) · python/cpython@1fc1df8 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1fc1df8

Browse files
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.
1 parent ccad61e commit 1fc1df8

File tree

3 files changed

+57
-37
lines changed

3 files changed

+57
-37
lines changed

Doc/library/socket.rst

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,19 +158,18 @@ created. Socket addresses are represented as follows:
158158

159159
- On Linux it accepts a tuple ``(device_id,)`` where ``device_id``
160160
is an integer specifying the number of the Bluetooth device.
161-
- On FreeBSD, NetBSD and DragonFly BSD it accepts ``bdaddr`` where ``bdaddr``
162-
is a :class:`bytes` object containing the Bluetooth address in a
163-
string format. (ex. ``b'12:23:34:45:56:67'``)
161+
- On FreeBSD, NetBSD and DragonFly BSD it accepts ``bdaddr``
162+
where ``bdaddr`` is the Bluetooth address as a string.
164163

165164
.. versionchanged:: 3.2
166165
NetBSD and DragonFlyBSD support added.
167166

168167
.. versionchanged:: 3.13.3
169168
FreeBSD support added.
170169

171-
- :const:`BTPROTO_SCO` accepts ``bdaddr`` where ``bdaddr`` is a
172-
:class:`bytes` object containing the Bluetooth address in a
173-
string format. (ex. ``b'12:23:34:45:56:67'``)
170+
- :const:`BTPROTO_SCO` accepts ``bdaddr`` where ``bdaddr`` is
171+
the Bluetooth address as a string or a :class:`bytes` object.
172+
(ex. ``'12:23:34:45:56:67'`` or ``b'12:23:34:45:56:67'``)
174173

175174
.. versionchanged:: next
176175
FreeBSD support added.

Lib/test/test_socket.py

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2681,6 +2681,8 @@ def testBadL2capAddr(self):
26812681
f.bind(socket.BDADDR_ANY)
26822682
with self.assertRaises(OSError):
26832683
f.bind((socket.BDADDR_ANY.encode(), 0x1001))
2684+
with self.assertRaises(OSError):
2685+
10000 f.bind(('\ud812', 0x1001))
26842686

26852687
def testBindRfcommSocket(self):
26862688
with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM) as s:
@@ -2712,14 +2714,16 @@ def testBadRfcommAddr(self):
27122714
s.bind((socket.BDADDR_ANY, channel, 0))
27132715
with self.assertRaises(OSError):
27142716
s.bind((socket.BDADDR_ANY + '\0', channel))
2717+
with self.assertRaises(OSError):
2718+
s.bind('\ud812')
27152719
with self.assertRaises(OSError):
27162720
s.bind(('invalid', channel))
27172721

27182722
@unittest.skipUnless(hasattr(socket, 'BTPROTO_HCI'), 'Bluetooth HCI sockets required for this test')
27192723
def testBindHciSocket(self):
27202724
with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI) as s:
27212725
if sys.platform.startswith(('netbsd', 'dragonfly', 'freebsd')):
2722-
s.bind(socket.BDADDR_ANY.encode())
2726+
s.bind(socket.BDADDR_ANY)
27232727
addr = s.getsockname()
27242728
self.assertEqual(addr, socket.BDADDR_ANY)
27252729
else:
@@ -2738,14 +2742,17 @@ def testBadHciAddr(self):
27382742
with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI) as s:
27392743
if sys.platform.startswith(('netbsd', 'dragonfly', 'freebsd')):
27402744
with self.assertRaises(OSError):
2741-
s.bind(socket.BDADDR_ANY)
2745+
s.bind(socket.BDADDR_ANY.encode())
27422746
with self.assertRaises(OSError):
2743-
s.bind((socket.BDADDR_ANY.encode(),))
2744-
if sys.platform.startswith('freebsd'):
2745-
with self.assertRaises(ValueError):
2746-
s.bind(socket.BDADDR_ANY.encode() + b'\0')
2747-
with self.assertRaises(ValueError):
2748-
s.bind(socket.BDADDR_ANY.encode() + b' '*100)
2747+
s.bind((socket.BDADDR_ANY,))
2748+
with self.assertRaises(OSError):
2749+
s.bind(socket.BDADDR_ANY + '\0')
2750+
with self.assertRaises((ValueError, OSError)):
2751+
s.bind(socket.BDADDR_ANY + ' '*100)
2752+
with self.assertRaises(OSError):
2753+
s.bind('\ud812')
2754+
with self.assertRaises(OSError):
2755+
s.bind('invalid')
27492756
with self.assertRaises(OSError):
27502757
s.bind(b'invalid')
27512758
else:
@@ -2756,11 +2763,18 @@ def testBadHciAddr(self):
27562763
s.bind((dev, 0))
27572764
with self.assertRaises(OSError):
27582765
s.bind(dev)
2766+
with self.assertRaises(OSError):
2767+
s.bind(socket.BDADDR_ANY)
27592768
with self.assertRaises(OSError):
27602769
s.bind(socket.BDADDR_ANY.encode())
27612770

27622771
@unittest.skipUnless(hasattr(socket, 'BTPROTO_SCO'), 'Bluetooth SCO sockets required for this test')
27632772
def testBindScoSocket(self):
2773+
with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_SCO) as s:
2774+
s.bind(socket.BDADDR_ANY)
2775+
addr = s.getsockname()
2776+
self.assertEqual(addr, socket.BDADDR_ANY)
2777+
27642778
with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_SCO) as s:
27652779
s.bind(socket.BDADDR_ANY.encode())
27662780
addr = s.getsockname()
@@ -2770,9 +2784,17 @@ def testBindScoSocket(self):
27702784
def testBadScoAddr(self):
27712785
with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_SCO) as s:
27722786
with self.assertRaises(OSError):
2773-
s.bind(socket.BDADDR_ANY)
2787+
s.bind((socket.BDADDR_ANY,))
27742788
with self.assertRaises(OSError):
27752789
s.bind((socket.BDADDR_ANY.encode(),))
2790+
with self.assertRaises(ValueError):
2791+
s.bind(socket.BDADDR_ANY + '\0')
2792+
with self.assertRaises(ValueError):
2793+
s.bind(socket.BDADDR_ANY.encode() + b'\0')
2794+
with self.assertRaises(UnicodeEncodeError):
2795+
s.bind('\ud812')
2796+
with self.assertRaises(OSError):
2797+
s.bind('invalid')
27762798
with self.assertRaises(OSError):
27772799
s.bind(b'invalid')
27782800

Modules/socketmodule.c

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,7 +1546,7 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto)
15461546
#elif defined(__FreeBSD__)
15471547
const char *node = _BT_HCI_MEMB(a, node);
15481548
size_t len = strnlen(node, sizeof(_BT_HCI_MEMB(a, node)));
1549-
return PyBytes_FromStringAndSize(node, (Py_ssize_t)len);
1549+
return PyUnicode_FromStringAndSize(node, (Py_ssize_t)len);
15501550
#else
15511551
return makebdaddr(&_BT_HCI_MEMB(a, bdaddr));
15521552
#endif
@@ -2145,36 +2145,25 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
21452145
return 0;
21462146
}
21472147
_BT_HCI_MEMB(addr, dev) = dev;
2148-
#elif defined(__FreeBSD__)
2149-
if (!PyBytes_Check(args)) {
2148+
#else
2149+
const char *straddr;
2150+
if (!PyArg_Parse(args, "s", &straddr)) {
21502151
PyErr_Format(PyExc_OSError, "%s: "
2151-
"wrong node format", caller);
2152-
return 0;
2153-
}
2154-
const char *straddr = PyBytes_AS_STRING(args);
2155-
size_t len = PyBytes_GET_SIZE(args);
2156-
if (strlen(straddr) != len) {
2157-
PyErr_Format(PyExc_ValueError, "%s: "
2158-
"node contains embedded null character", caller);
2152+
"wrong format", caller);
21592153
return 0;
21602154
}
2161-
if (len > sizeof(_BT_HCI_MEMB(addr, node))) {
2155+
# if defined(__FreeBSD__)
2156+
if (strlen(straddr) > sizeof(_BT_HCI_MEMB(addr, node))) {
21622157
PyErr_Format(PyExc_ValueError, "%s: "
21632158
"node too long", caller);
21642159
return 0;
21652160
}
21662161
strncpy(_BT_HCI_MEMB(addr, node), straddr,
21672162
sizeof(_BT_HCI_MEMB(addr, node)));
2168-
#else
2169-
const char *straddr;
2170-
if (!PyBytes_Check(args)) {
2171-
PyErr_Format(PyExc_OSError, "%s: "
2172-
"wrong format", caller);
2173-
return 0;
2174-
}
2175-
straddr = PyBytes_AS_STRING(args);
2163+
# else
21762164
if (setbdaddr(straddr, &_BT_HCI_MEMB(addr, bdaddr)) < 0)
21772165
return 0;
2166+
# endif
21782167
#endif
21792168
*len_ret = sizeof *addr;
21802169
return 1;
@@ -2188,12 +2177,22 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
21882177
struct sockaddr_sco *addr = &addrbuf->bt_sco;
21892178
memset(addr, 0, sizeof(struct sockaddr_sco));
21902179
_BT_SCO_MEMB(addr, family) = AF_BLUETOOTH;
2191-
if (!PyBytes_Check(args)) {
2180+
2181+
if (PyBytes_Check(args)) {
2182+
if (!PyArg_Parse(args, "y", &straddr)) {
2183+
return 0;
2184+
}
2185+
}
2186+
else if (PyUnicode_Check(args)) {
2187+
if (!PyArg_Parse(args, "s", &straddr)) {
2188+
return 0;
2189+
}
2190+
}
2191+
else {
21922192
PyErr_Format(PyExc_OSError,
21932193
"%s(): wrong format", caller);
21942194
return 0;
21952195
}
2196-
straddr = PyBytes_AS_STRING(args);
21972196
if (setbdaddr(straddr, &_BT_SCO_MEMB(addr, bdaddr)) < 0)
21982197
return 0;
21992198

0 commit comments

Comments
 (0)
13 0