gatt_client: avoid out of bounds reads, #337

This commit is contained in:
Matthias Ringwald 2021-02-25 22:44:10 +01:00
parent 8046a24a19
commit 39ac97114d

View File

@ -479,17 +479,23 @@ static void send_gatt_signed_write_request(gatt_client_t * gatt_client, uint32_t
#endif
static uint16_t get_last_result_handle_from_service_list(uint8_t * packet, uint16_t size){
if (size < 2) return 0xffff;
uint8_t attr_length = packet[1];
if ((2 + attr_length) > size) return 0xffff;
return little_endian_read_16(packet, size - attr_length + 2u);
}
static uint16_t get_last_result_handle_from_characteristics_list(uint8_t * packet, uint16_t size){
if (size < 2) return 0xffff;
uint8_t attr_length = packet[1];
if ((2 + attr_length) > size) return 0xffff;
return little_endian_read_16(packet, size - attr_length + 3u);
}
static uint16_t get_last_result_handle_from_included_services_list(uint8_t * packet, uint16_t size){
if (size < 2) return 0xffff;
uint8_t attr_length = packet[1];
if ((2 + attr_length) > size) return 0xffff;
return little_endian_read_16(packet, size - attr_length);
}
@ -609,11 +615,12 @@ static void emit_gatt_mtu_exchanged_result_event(gatt_client_t * gatt_client, ui
}
///
static void report_gatt_services(gatt_client_t * gatt_client, uint8_t * packet, uint16_t size){
if (size < 2) return;
uint8_t attr_length = packet[1];
uint8_t uuid_length = attr_length - 4u;
int i;
for (i = 2; i < size; i += attr_length){
for (i = 2; (i+attr_length) <= size; i += attr_length){
uint16_t start_group_handle = little_endian_read_16(packet,i);
uint16_t end_group_handle = little_endian_read_16(packet,i+2);
uint8_t uuid128[16];
@ -622,8 +629,10 @@ static void report_gatt_services(gatt_client_t * gatt_client, uint8_t * packet,
if (uuid_length == 2u){
uuid16 = little_endian_read_16(packet, i+4);
uuid_add_bluetooth_prefix((uint8_t*) &uuid128, uuid16);
} else {
} else if (uuid_length == 16u) {
reverse_128(&packet[i+4], uuid128);
} else {
return;
}
emit_gatt_service_query_result_event(gatt_client, start_group_handle, end_group_handle, uuid128);
}
@ -1410,12 +1419,15 @@ static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle,
#endif
case P_W4_READ_BY_TYPE_RESPONSE: {
uint16_t pair_size = packet[1];
uint16_t offset;
uint16_t last_result_handle = 0;
for (offset = 2; offset < size ; offset += pair_size){
uint16_t value_handle = little_endian_read_16(packet, offset);
report_gatt_characteristic_value(gatt_client, value_handle, &packet[offset + 2u], pair_size - 2u);
last_result_handle = value_handle;
// set last result handle to last valid handle, only used if pair_size invalid
uint16_t last_result_handle = 0xffff;
if (pair_size > 2){
uint16_t offset;
for (offset = 2; offset < size ; offset += pair_size){
uint16_t value_handle = little_endian_read_16(packet, offset);
report_gatt_characteristic_value(gatt_client, value_handle, &packet[offset + 2u], pair_size - 2u);
last_result_handle = value_handle;
}
}
trigger_next_read_by_type_query(gatt_client, last_result_handle);
break;
@ -1427,9 +1439,11 @@ static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle,
case ATT_READ_RESPONSE:
switch (gatt_client->gatt_client_state){
case P_W4_INCLUDED_SERVICE_UUID_WITH_QUERY_RESULT: {
uint8_t uuid128[16];
reverse_128(&packet[1], uuid128);
report_gatt_included_service_uuid128(gatt_client, gatt_client->start_group_handle, uuid128);
if (size >= 17){
uint8_t uuid128[16];
reverse_128(&packet[1], uuid128);
report_gatt_included_service_uuid128(gatt_client, gatt_client->start_group_handle, uuid128);
}
trigger_next_included_service_query(gatt_client, gatt_client->start_group_handle);
// GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
break;