https://github.com/python/cpython/commit/8cd29c2b533e5a1a262238695d05f2a7c44d6455 commit: 8cd29c2b533e5a1a262238695d05f2a7c44d6455 branch: main author: Victor Stinner <vstin...@python.org> committer: vstinner <vstin...@python.org> date: 2025-04-01T13:54:27Z summary:
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. files: A Misc/NEWS.d/next/Library/2025-03-28-11-26-31.gh-issue-131668.tcS4xS.rst M Modules/socketmodule.c diff --git a/Misc/NEWS.d/next/Library/2025-03-28-11-26-31.gh-issue-131668.tcS4xS.rst b/Misc/NEWS.d/next/Library/2025-03-28-11-26-31.gh-issue-131668.tcS4xS.rst new file mode 100644 index 00000000000000..ec04cdd30a2f28 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-03-28-11-26-31.gh-issue-131668.tcS4xS.rst @@ -0,0 +1 @@ +:mod:`socket`: Fix code parsing AF_BLUETOOTH socket addresses. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 2e48a72a72f27c..6e44a7ebfd10ae 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1526,11 +1526,15 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) struct sockaddr_hci *a = (struct sockaddr_hci *) addr; #if defined(__NetBSD__) || defined(__DragonFly__) return makebdaddr(&_BT_HCI_MEMB(a, bdaddr)); -#else /* __NetBSD__ || __DragonFly__ */ +#elif defined(__FreeBSD__) + 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); +#else PyObject *ret = NULL; ret = Py_BuildValue("i", _BT_HCI_MEMB(a, dev)); return ret; -#endif /* !(__NetBSD__ || __DragonFly__) */ +#endif } #if !defined(__FreeBSD__) @@ -2048,15 +2052,21 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, struct sockaddr_l2 *addr = &addrbuf->bt_l2; memset(addr, 0, sizeof(struct sockaddr_l2)); _BT_L2_MEMB(addr, family) = AF_BLUETOOTH; - _BT_L2_MEMB(addr, bdaddr_type) = BDADDR_BREDR; - if (!PyArg_ParseTuple(args, "si|iB", &straddr, - &_BT_L2_MEMB(addr, psm), - &_BT_L2_MEMB(addr, cid), - &_BT_L2_MEMB(addr, bdaddr_type))) { + unsigned short psm; + unsigned short cid = 0; + unsigned char bdaddr_type = BDADDR_BREDR; + if (!PyArg_ParseTuple(args, "sH|HB", &straddr, + &psm, + &cid, + &bdaddr_type)) { PyErr_Format(PyExc_OSError, "%s(): wrong format", caller); return 0; } + _BT_L2_MEMB(addr, psm) = psm; + _BT_L2_MEMB(addr, cid) = cid; + _BT_L2_MEMB(addr, bdaddr_type) = bdaddr_type; + if (setbdaddr(straddr, &_BT_L2_MEMB(addr, bdaddr)) < 0) return 0; @@ -2069,12 +2079,21 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, const char *straddr; struct sockaddr_rc *addr = &addrbuf->bt_rc; _BT_RC_MEMB(addr, family) = AF_BLUETOOTH; - if (!PyArg_ParseTuple(args, "si", &straddr, - &_BT_RC_MEMB(addr, channel))) { - PyErr_Format(PyExc_OSError, - "%s(): wrong format", caller); +#ifdef MS_WINDOWS + unsigned long channel; +# define FORMAT_CHANNEL "k" +#else + unsigned char channel; +# define FORMAT_CHANNEL "B" +#endif + if (!PyArg_ParseTuple(args, "s" FORMAT_CHANNEL, + &straddr, &channel)) { + PyErr_Format(PyExc_OSError, "%s(): wrong format", caller); return 0; } +#undef FORMAT_CHANNEL + _BT_RC_MEMB(addr, channel) = channel; + if (setbdaddr(straddr, &_BT_RC_MEMB(addr, bdaddr)) < 0) return 0; @@ -2096,14 +2115,37 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, straddr = PyBytes_AS_STRING(args); if (setbdaddr(straddr, &_BT_HCI_MEMB(addr, bdaddr)) < 0) return 0; -#else /* __NetBSD__ || __DragonFly__ */ +#elif defined(__FreeBSD__) + _BT_HCI_MEMB(addr, family) = AF_BLUETOOTH; + if (!PyBytes_Check(args)) { + 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); + return 0; + } + if (len > 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 _BT_HCI_MEMB(addr, family) = AF_BLUETOOTH; - if (!PyArg_ParseTuple(args, "i", &_BT_HCI_MEMB(addr, dev))) { + unsigned short dev = _BT_HCI_MEMB(addr, dev); + if (!PyArg_ParseTuple(args, "H", &dev)) { PyErr_Format(PyExc_OSError, "%s(): wrong format", caller); return 0; } -#endif /* !(__NetBSD__ || __DragonFly__) */ + _BT_HCI_MEMB(addr, dev) = dev; +#endif *len_ret = sizeof *addr; return 1; } _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com