shared/ad: Fix hardcoding maximum data length
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 7 Jul 2023 21:54:56 +0000 (14:54 -0700)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 5 Jan 2024 13:34:03 +0000 (19:04 +0530)
Instances shall not assume BT_AD_MAX_DATA_LEN is always the maximum
length as they could be used with EA which supports bigger length.

src/shared/ad.c
src/shared/ad.h

index b2bba95..50c7c46 100755 (executable)
@@ -16,6 +16,7 @@
 
 struct bt_ad {
        int ref_count;
+       uint8_t max_len;
        char *name;
        uint16_t appearance;
        struct queue *service_uuids;
@@ -36,6 +37,7 @@ struct bt_ad *bt_ad_new(void)
        struct bt_ad *ad;
 
        ad = new0(struct bt_ad, 1);
+       ad->max_len = BT_AD_MAX_DATA_LEN;
        ad->service_uuids = queue_new();
        ad->manufacturer_data = queue_new();
        ad->solicit_uuids = queue_new();
@@ -46,6 +48,16 @@ struct bt_ad *bt_ad_new(void)
        return bt_ad_ref(ad);
 }
 
+bool bt_ad_set_max_len(struct bt_ad *ad, uint8_t len)
+{
+       if (!ad || len < BT_AD_MAX_DATA_LEN)
+               return false;
+
+       ad->max_len = len;
+
+       return true;
+}
+
 static bool ad_replace_data(struct bt_ad *ad, uint8_t type, const void *data,
                                                        size_t len);
 
@@ -292,17 +304,17 @@ static size_t uuid_data_length(struct queue *uuid_data)
        return length;
 }
 
-static size_t name_length(const char *name, size_t *pos)
+static size_t name_length(struct bt_ad *ad, size_t *pos)
 {
        size_t len;
 
-       if (!name)
+       if (!ad->name)
                return 0;
 
-       len = 2 + strlen(name);
+       len = 2 + strlen(ad->name);
 
-       if (len > BT_AD_MAX_DATA_LEN - *pos)
-               len = BT_AD_MAX_DATA_LEN - *pos;
+       if (len > ad->max_len - (*pos))
+               len = ad->max_len - (*pos);
 
        return len;
 }
@@ -337,7 +349,7 @@ static size_t calculate_length(struct bt_ad *ad)
 
        length += uuid_data_length(ad->service_data);
 
-       length += name_length(ad->name, &length);
+       length += name_length(ad, &length);
 
        length += ad->appearance != UINT16_MAX ? 4 : 0;
 
@@ -461,36 +473,36 @@ static void serialize_service_data(struct queue *service_data, uint8_t *buf,
        }
 }
 
-static void serialize_name(const char *name, uint8_t *buf, uint8_t *pos)
+static void serialize_name(struct bt_ad *ad, uint8_t *buf, uint8_t *pos)
 {
        int len;
        uint8_t type = BT_AD_NAME_COMPLETE;
 
-       if (!name)
+       if (!ad->name)
                return;
 
-       len = strlen(name);
-       if (len > BT_AD_MAX_DATA_LEN - (*pos + 2)) {
+       len = strlen(ad->name);
+       if (len > ad->max_len - (*pos + 2)) {
                type = BT_AD_NAME_SHORT;
-               len = BT_AD_MAX_DATA_LEN - (*pos + 2);
+               len = ad->max_len - (*pos + 2);
        }
 
        buf[(*pos)++] = len + 1;
        buf[(*pos)++] = type;
 
-       memcpy(buf + *pos, name, len);
+       memcpy(buf + *pos, ad->name, len);
        *pos += len;
 }
 
-static void serialize_appearance(uint16_t value, uint8_t *buf, uint8_t *pos)
+static void serialize_appearance(struct bt_ad *ad, uint8_t *buf, uint8_t *pos)
 {
-       if (value == UINT16_MAX)
+       if (ad->appearance == UINT16_MAX)
                return;
 
-       buf[(*pos)++] = sizeof(value) + 1;
+       buf[(*pos)++] = sizeof(ad->appearance) + 1;
        buf[(*pos)++] = BT_AD_GAP_APPEARANCE;
 
-       bt_put_le16(value, buf + (*pos));
+       bt_put_le16(ad->appearance, buf + (*pos));
        *pos += 2;
 }
 
@@ -522,7 +534,7 @@ uint8_t *bt_ad_generate(struct bt_ad *ad, size_t *length)
 
        *length = calculate_length(ad);
 
-       if (*length > BT_AD_MAX_DATA_LEN)
+       if (*length > ad->max_len)
                return NULL;
 
        adv_data = malloc0(*length);
@@ -537,9 +549,9 @@ uint8_t *bt_ad_generate(struct bt_ad *ad, size_t *length)
 
        serialize_service_data(ad->service_data, adv_data, &pos);
 
-       serialize_name(ad->name, adv_data, &pos);
+       serialize_name(ad, adv_data, &pos);
 
-       serialize_appearance(ad->appearance, adv_data, &pos);
+       serialize_appearance(ad, adv_data, &pos);
 
        serialize_data(ad->data, adv_data, &pos);
 
@@ -647,7 +659,7 @@ bool bt_ad_add_manufacturer_data(struct bt_ad *ad, uint16_t manufacturer_id,
        if (!ad)
                return false;
 
-       if (len > (BT_AD_MAX_DATA_LEN - 2 - sizeof(uint16_t)))
+       if (len > (ad->max_len - 2 - sizeof(uint16_t)))
                return false;
 
        new_data = queue_find(ad->manufacturer_data, manufacturer_id_data_match,
@@ -784,7 +796,7 @@ bool bt_ad_add_service_data(struct bt_ad *ad, const bt_uuid_t *uuid, void *data,
        if (!ad)
                return false;
 
-       if (len > (BT_AD_MAX_DATA_LEN - 2 - (size_t)bt_uuid_len(uuid)))
+       if (len > (ad->max_len - 2 - (size_t)bt_uuid_len(uuid)))
                return false;
 
        new_data = queue_find(ad->service_data, service_uuid_match, uuid);
@@ -1003,7 +1015,7 @@ bool bt_ad_add_data(struct bt_ad *ad, uint8_t type, void *data, size_t len)
        if (!ad)
                return false;
 
-       if (len > (BT_AD_MAX_DATA_LEN - 2))
+       if (len > (size_t)(ad->max_len - 2))
                return false;
 
        for (i = 0; i < sizeof(type_reject_list); i++) {
index b100a67..93ba1b6 100755 (executable)
@@ -98,6 +98,8 @@ struct bt_ad_pattern {
 
 struct bt_ad *bt_ad_new(void);
 
+bool bt_ad_set_max_len(struct bt_ad *ad, uint8_t len);
+
 struct bt_ad *bt_ad_new_with_data(size_t len, const uint8_t *data);
 
 struct bt_ad *bt_ad_ref(struct bt_ad *ad);