diff --git a/components/bt/host/bluedroid/hci/packet_fragmenter.c b/components/bt/host/bluedroid/hci/packet_fragmenter.c index e280a98183..06b933c69b 100644 --- a/components/bt/host/bluedroid/hci/packet_fragmenter.c +++ b/components/bt/host/bluedroid/hci/packet_fragmenter.c @@ -150,20 +150,33 @@ static void reassemble_and_dispatch(BT_HDR *packet) uint16_t l2cap_length; uint16_t acl_length __attribute__((unused)); - if (packet->len < HCI_ACL_PREAMBLE_SIZE + L2CAP_LENGTH_SIZE) { + /* All ACL packets need at least the 4-byte HCI ACL preamble (handle + length) */ + if (packet->len < HCI_ACL_PREAMBLE_SIZE) { HCI_TRACE_ERROR("ACL packet too short (len=%u)\n", packet->len); osi_free(packet); return; } + STREAM_TO_UINT16(handle, stream); STREAM_TO_UINT16(acl_length, stream); - STREAM_TO_UINT16(l2cap_length, stream); - - assert(acl_length == packet->len - HCI_ACL_PREAMBLE_SIZE); uint8_t boundary_flag = GET_BOUNDARY_FLAG(handle); handle = handle & HANDLE_MASK; + assert(acl_length == packet->len - HCI_ACL_PREAMBLE_SIZE); + + if (boundary_flag == START_PACKET_BOUNDARY) { + /* START packets must also contain the L2CAP header (length field) */ + if (packet->len < HCI_ACL_PREAMBLE_SIZE + L2CAP_LENGTH_SIZE) { + HCI_TRACE_ERROR("ACL START packet too short for L2CAP header (len=%u)\n", packet->len); + osi_free(packet); + return; + } + STREAM_TO_UINT16(l2cap_length, stream); + } else { + l2cap_length = 0; /* Not used for continuation packets */ + } + BT_HDR *partial_packet = (BT_HDR *)hash_map_get(partial_packets, (void *)(uintptr_t)handle); if (boundary_flag == START_PACKET_BOUNDARY) {