Skip to content

Commit 8cd29c2

Browse files
authored
gh-111178: Fix getsockaddrarg() undefined behavior (#131668)
Don't pass direct references to sockaddr members since their type may not match PyArg_ParseTuple() types. Instead, use temporary 'int' and 'unsigned char' variables, and update sockaddr members afterwards. On FreeBSD, treat BTPROTO_HCI node name as a bytes string, not as an integer.
1 parent 3b3720f commit 8cd29c2

File tree

2 files changed

+57
-14
lines changed

2 files changed

+57
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:mod:`socket`: Fix code parsing AF_BLUETOOTH socket addresses.

Modules/socketmodule.c

+56-14
Original file line numberDiff line numberDiff line change
@@ -1526,11 +1526,15 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto)
15261526
struct sockaddr_hci *a = (struct sockaddr_hci *) addr;
15271527
#if defined(__NetBSD__) || defined(__DragonFly__)
15281528
return makebdaddr(&_BT_HCI_MEMB(a, bdaddr));
1529-
#else /* __NetBSD__ || __DragonFly__ */
1529+
#elif defined(__FreeBSD__)
1530+
char *node = _BT_HCI_MEMB(a, node);
1531+
size_t len = strnlen(node, sizeof(_BT_HCI_MEMB(a, node)));
1532+
return PyBytes_FromStringAndSize(node, (Py_ssize_t)len);
1533+
#else
15301534
PyObject *ret = NULL;
15311535
ret = Py_BuildValue("i", _BT_HCI_MEMB(a, dev));
15321536
return ret;
1533-
#endif /* !(__NetBSD__ || __DragonFly__) */
1537+
#endif
15341538
}
15351539

15361540
#if !defined(__FreeBSD__)
@@ -2048,15 +2052,21 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
20482052
struct sockaddr_l2 *addr = &addrbuf->bt_l2;
20492053
memset(addr, 0, sizeof(struct sockaddr_l2));
20502054
_BT_L2_MEMB(addr, family) = AF_BLUETOOTH;
2051-
_BT_L2_MEMB(addr, bdaddr_type) = BDADDR_BREDR;
2052-
if (!PyArg_ParseTuple(args, "si|iB", &straddr,
2053-
&_BT_L2_MEMB(addr, psm),
2054-
&_BT_L2_MEMB(addr, cid),
2055-
&_BT_L2_MEMB(addr, bdaddr_type))) {
2055+
unsigned short psm;
2056+
unsigned short cid = 0;
2057+
unsigned char bdaddr_type = BDADDR_BREDR;
2058+
if (!PyArg_ParseTuple(args, "sH|HB", &straddr,
2059+
&psm,
2060+
&cid,
2061+
&bdaddr_type)) {
20562062
PyErr_Format(PyExc_OSError,
20572063
"%s(): wrong format", caller);
20582064
return 0;
20592065
}
2066+
_BT_L2_MEMB(addr, psm) = psm;
2067+
_BT_L2_MEMB(addr, cid) = cid;
2068+
_BT_L2_MEMB(addr, bdaddr_type) = bdaddr_type;
2069+
20602070
if (setbdaddr(straddr, &_BT_L2_MEMB(addr, bdaddr)) < 0)
20612071
return 0;
20622072

@@ -2069,12 +2079,21 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
20692079
const char *straddr;
20702080
struct sockaddr_rc *addr = &addrbuf->bt_rc;
20712081
_BT_RC_MEMB(addr, family) = AF_BLUETOOTH;
2072-
if (!PyArg_ParseTuple(args, "si", &straddr,
2073-
&_BT_RC_MEMB(addr, channel))) {
2074-
PyErr_Format(PyExc_OSError,
2075-
"%s(): wrong format", caller);
2082+
#ifdef MS_WINDOWS
2083+
unsigned long channel;
2084+
# define FORMAT_CHANNEL "k"
2085+
#else
2086+
unsigned char channel;
2087+
# define FORMAT_CHANNEL "B"
2088+
#endif
2089+
if (!PyArg_ParseTuple(args, "s" FORMAT_CHANNEL,
2090+
&straddr, &channel)) {
2091+
PyErr_Format(PyExc_OSError, "%s(): wrong format", caller);
20762092
return 0;
20772093
}
2094+
#undef FORMAT_CHANNEL
2095+
_BT_RC_MEMB(addr, channel) = channel;
2096+
20782097
if (setbdaddr(straddr, &_BT_RC_MEMB(addr, bdaddr)) < 0)
20792098
return 0;
20802099

@@ -2096,14 +2115,37 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
20962115
straddr = PyBytes_AS_STRING(args);
20972116
if (setbdaddr(straddr, &_BT_HCI_MEMB(addr, bdaddr)) < 0)
20982117
return 0;
2099-
#else /* __NetBSD__ || __DragonFly__ */
2118+
#elif defined(__FreeBSD__)
2119+
_BT_HCI_MEMB(addr, family) = AF_BLUETOOTH;
2120+
if (!PyBytes_Check(args)) {
2121+
PyErr_Format(PyExc_OSError, "%s: "
2122+
"wrong node format", caller);
2123+
return 0;
2124+
}
2125+
const char *straddr = PyBytes_AS_STRING(args);
2126+
size_t len = PyBytes_GET_SIZE(args);
2127+
if (strlen(straddr) != len) {
2128+
PyErr_Format(PyExc_ValueError, "%s: "
2129+
"node contains embedded null character", caller);
2130+
return 0;
2131+
}
2132+
if (len > sizeof(_BT_HCI_MEMB(addr, node))) {
2133+
PyErr_Format(PyExc_ValueError, "%s: "
2134+
"node too long", caller);
2135+
return 0;
2136+
}
2137+
strncpy(_BT_HCI_MEMB(addr, node), straddr,
2138+
sizeof(_BT_HCI_MEMB(addr, node)));
2139+
#else
21002140
_BT_HCI_MEMB(addr, family) = AF_BLUETOOTH;
2101-
if (!PyArg_ParseTuple(args, "i", &_BT_HCI_MEMB(addr, dev))) {
2141+
unsigned short dev = _BT_HCI_MEMB(addr, dev);
2142+
if (!PyArg_ParseTuple(args, "H", &dev)) {
21022143
PyErr_Format(PyExc_OSError,
21032144
"%s(): wrong format", caller);
21042145
return 0;
21052146
}
2106-
#endif /* !(__NetBSD__ || __DragonFly__) */
2147+
_BT_HCI_MEMB(addr, dev) = dev;
2148+
#endif
21072149
*len_ret = sizeof *addr;
21082150
return 1;
21092151
}

0 commit comments

Comments
 (0)