From a4e7b53d4b267c28dd885b0f3e7aede8a1f8651e Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Thu, 1 Jun 2023 14:42:04 +0200 Subject: [PATCH] Bluetooth: Host: Fix `bt_addr_from_str` for str starting with ':' The previous implementation would read from `addr->val[0]` before it was initialized if the input string started with a colon ':'. Signed-off-by: Aleksander Wasaznik --- include/zephyr/bluetooth/addr.h | 3 ++- subsys/bluetooth/host/addr.c | 29 +++++++++++++++++------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/include/zephyr/bluetooth/addr.h b/include/zephyr/bluetooth/addr.h index 32d4d06fb724c6..3afb5f4a9035cc 100644 --- a/include/zephyr/bluetooth/addr.h +++ b/include/zephyr/bluetooth/addr.h @@ -272,7 +272,8 @@ static inline int bt_addr_le_to_str(const bt_addr_le_t *addr, char *str, * @param[in] str The string representation of a Bluetooth address. * @param[out] addr Address of buffer to store the Bluetooth address * - * @return Zero on success or (negative) error code otherwise. + * @retval 0 Success. The parsed address is stored in @p addr. + * @return -EINVAL Invalid address string. @p str is not a well-formed Bluetooth address. */ int bt_addr_from_str(const char *str, bt_addr_t *addr); diff --git a/subsys/bluetooth/host/addr.c b/subsys/bluetooth/host/addr.c index cc4da7b3e4efb9..24e0303efbea0b 100644 --- a/subsys/bluetooth/host/addr.c +++ b/subsys/bluetooth/host/addr.c @@ -53,28 +53,33 @@ int bt_addr_le_create_static(bt_addr_le_t *addr) int bt_addr_from_str(const char *str, bt_addr_t *addr) { - int i, j; - uint8_t tmp; + /* Parse a null-terminated string with a Bluetooth address in + * canonical "XX:XX:XX:XX:XX:XX" format. + */ - if (strlen(str) != 17U) { + const size_t len = strlen(str); + + /* Verify length. */ + if (len != BT_ADDR_STR_LEN - 1) { return -EINVAL; } - for (i = 5, j = 1; *str != '\0'; str++, j++) { - if (!(j % 3) && (*str != ':')) { + /* Verify that all the colons are present. */ + for (size_t i = 2; i < len; i += 3) { + if (str[i] != ':') { return -EINVAL; - } else if (*str == ':') { - i--; - continue; } + } - addr->val[i] = addr->val[i] << 4; + /* Parse each octet as hex and populate `addr->val`. It must be + * reversed since `bt_addr_t` is in 'on-air' format. + */ + for (size_t i = 0; i < ARRAY_SIZE(addr->val); i++) { + const size_t reverse_i = ARRAY_SIZE(addr->val) - 1 - i; - if (char2hex(*str, &tmp) < 0) { + if (!hex2bin(&str[i * 3], 2, &addr->val[reverse_i], 1)) { return -EINVAL; } - - addr->val[i] |= tmp; } return 0;