diff --git a/src/hci.c b/src/hci.c index 27e1befc1..99f0ed4d9 100644 --- a/src/hci.c +++ b/src/hci.c @@ -5332,6 +5332,48 @@ void hci_halting_defer(void){ } #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +void hci_setup_test_connections_fuzz(void){ + hci_connection_t * conn; + + // default address: 66:55:44:33:00:01 + bd_addr_t addr = { 0x66, 0x55, 0x44, 0x33, 0x00, 0x00}; + + // setup incoming Classic ACL connection with con handle 0x0001, 66:55:44:33:22:01 + addr[5] = 0x01; + conn = create_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_ACL); + conn->con_handle = addr[5]; + conn->role = HCI_ROLE_SLAVE; + conn->state = RECEIVED_CONNECTION_REQUEST; + + // setup incoming Classic SCO connection with con handle 0x0002 + addr[5] = 0x02; + conn = create_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_SCO); + conn->con_handle = addr[5]; + conn->role = HCI_ROLE_SLAVE; + conn->state = RECEIVED_CONNECTION_REQUEST; + + // setup ready Classic ACL connection with con handle 0x0003 + addr[5] = 0x03; + conn = create_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_ACL); + conn->con_handle = addr[5]; + conn->role = HCI_ROLE_SLAVE; + conn->state = OPEN; + + // setup ready Classic SCO connection with con handle 0x0004 + addr[5] = 0x04; + conn = create_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_SCO); + conn->con_handle = addr[5]; + conn->role = HCI_ROLE_SLAVE; + conn->state = OPEN; + + // setup ready LE ACL connection with con handle 0x005 and public address + addr[5] = 0x05; + conn = create_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_LE_PUBLIC); + conn->con_handle = addr[5]; + conn->role = HCI_ROLE_SLAVE; + conn->state = OPEN; +} + void hci_free_connections_fuzz(void){ btstack_linked_list_iterator_t it; btstack_linked_list_iterator_init(&it, &hci_stack->connections); diff --git a/src/hci.h b/src/hci.h index 073aecdf5..4be700d47 100644 --- a/src/hci.h +++ b/src/hci.h @@ -1246,6 +1246,9 @@ void hci_disable_l2cap_timeout_check(void); */ HCI_STATE hci_get_state(void); +// setup test connections, used for fuzzing +void hci_setup_test_connections_fuzz(void); + // free all connections, used for fuzzing void hci_free_connections_fuzz(void); diff --git a/test/fuzz/.gitignore b/test/fuzz/.gitignore index 3ae9e3a06..7dc7d92a7 100644 --- a/test/fuzz/.gitignore +++ b/test/fuzz/.gitignore @@ -2,3 +2,6 @@ build Makefile cmake-build-debug cmake_install.cmake +fuzz_hci +fuzz_hci_transport_h4 +libbtstack.a diff --git a/test/fuzz/fuzz_hci.c b/test/fuzz/fuzz_hci.c index bd85cd401..8f631a9f8 100644 --- a/test/fuzz/fuzz_hci.c +++ b/test/fuzz/fuzz_hci.c @@ -70,12 +70,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { btstack_run_loop_init(btstack_run_loop_posix_get_instance()); } - hci_init(&hci_transport_fuzz, NULL); + // prepare test data if (size < 3) return 0; uint8_t packet_type = (data[0] & 3) + 1; // only 1-4 size--; data++; uint8_t packet[1000]; + uint16_t packet_len; switch (packet_type){ case HCI_EVENT_PACKET: packet[0] = data[0]; @@ -84,31 +85,39 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size > 255) return 0; packet[1] = size; memcpy(&packet[2], data, size); - (*packet_handler)(packet_type, packet, size + 2); + packet_len = size + 2; break; case HCI_SCO_DATA_PACKET: packet[0] = data[0]; packet[1] = data[1]; - size-=2; - data+=2; + size -= 2; + data += 2; if (size > 255) return 0; packet[2] = size; memcpy(&packet[3], data, size); - (*packet_handler)(packet_type, packet, size + 3); + packet_len = size + 3; break; case HCI_ACL_DATA_PACKET: packet[0] = data[0]; packet[1] = data[1]; - size-=2; - data+=2; + size -= 2; + data += 2; if (size > (sizeof(packet) - 4)) return 0; little_endian_store_16(packet, 2, size); memcpy(&packet[4], data, size); - (*packet_handler)(packet_type, packet, size + 4); + packet_len = size + 4; break; default: return 0; } + + // init hci + hci_init(&hci_transport_fuzz, NULL); + hci_setup_test_connections_fuzz(); + + // deliver test data + (*packet_handler)(packet_type, packet, packet_len); + // teardown hci_free_connections_fuzz(); return 0;