summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorHiFiPHile <[email protected]>2026-08-25 09:29:08 +0200
committerHiFiPHile <[email protected]>2026-08-25 09:29:08 +0200
commitd494b7c5f1fb690ea559dd3f09bb9f84c0c6d80f (patch)
tree9f6b238756ef43125205c7fa89c1ceb9828e3ba2 /test
parent28a63e7c75c7e430ed3820d2b3658614411ca307 (diff)
fix(audio): validate descriptors before parsing
Check descriptor bounds, minimum lengths, frequency counts, and interface types with the host validation helpers before accessing fields. Malformed UAC1 functions now fail enumeration without out-of-bounds reads. Signed-off-by: HiFiPHile <[email protected]>
Diffstat (limited to 'test')
-rw-r--r--test/unit-test/test/host/audio/test_audio_host.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/test/unit-test/test/host/audio/test_audio_host.c b/test/unit-test/test/host/audio/test_audio_host.c
index b64335910..2b0f2fa3d 100644
--- a/test/unit-test/test/host/audio/test_audio_host.c
+++ b/test/unit-test/test/host/audio/test_audio_host.c
@@ -417,6 +417,31 @@ static const uint8_t playback_with_cs_ep_before_data_ep[] = {
TEST_UAC1_DATA_EP(0x01, TUSB_ISO_EP_ATT_ADAPTIVE, 192, 1),
};
+static const uint8_t malformed_zero_length_ac_descriptor[] = {
+ TEST_UAC1_AC_HEADER,
+ 0, TUSB_DESC_CS_INTERFACE,
+};
+
+static const uint8_t malformed_sampling_frequency_list[] = {
+ TEST_UAC1_AC_HEADER,
+ TEST_UAC1_INPUT_TERM(PLAYBACK_INPUT_TERM, AUDIO_TERM_TYPE_USB_STREAMING, 2),
+ TEST_UAC1_AS_ALT0,
+ TEST_UAC1_AS_INTERFACE(1, 1),
+ TEST_UAC1_AS_GENERAL(PLAYBACK_INPUT_TERM),
+ 11, TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO10_FORMAT_TYPE_I, 2, 2, 16, 2,
+ U24_TO_U8S_LE(48000),
+};
+
+static const uint8_t malformed_short_endpoint[] = {
+ TEST_UAC1_AC_HEADER,
+ TEST_UAC1_INPUT_TERM(PLAYBACK_INPUT_TERM, AUDIO_TERM_TYPE_USB_STREAMING, 2),
+ TEST_UAC1_AS_ALT0,
+ TEST_UAC1_AS_INTERFACE(1, 1),
+ TEST_UAC1_AS_GENERAL(PLAYBACK_INPUT_TERM),
+ TEST_UAC1_FORMAT(2, 2, 16, 48000),
+ 6, TUSB_DESC_ENDPOINT, 0x01, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE), U16_TO_U8S_LE(192),
+};
+
static const uint8_t playback_with_two_alternates[] = {
TEST_UAC1_AC_HEADER,
TEST_UAC1_INPUT_TERM(PLAYBACK_INPUT_TERM, AUDIO_TERM_TYPE_USB_STREAMING, 2),
@@ -719,6 +744,23 @@ void test_audio_host_rejects_overflowed_frame_size_for_large_channel_count(void)
TEST_ASSERT_EQUAL_UINT8(0, tuh_audio_get_dev_addr(0));
}
+void test_audio_host_rejects_malformed_descriptors_and_releases_instance(void) {
+ const struct {
+ const uint8_t *desc;
+ uint16_t len;
+ } malformed[] = {
+ {malformed_zero_length_ac_descriptor, sizeof(malformed_zero_length_ac_descriptor)},
+ {malformed_sampling_frequency_list, sizeof(malformed_sampling_frequency_list)},
+ {malformed_short_endpoint, sizeof(malformed_short_endpoint)},
+ };
+
+ for (uint8_t i = 0; i < TU_ARRAY_SIZE(malformed); i++) {
+ TEST_ASSERT_EQUAL_UINT16(
+ 0, audioh_open(0, AUDIO_DEV_ADDR, (const tusb_desc_interface_t *)malformed[i].desc, malformed[i].len));
+ TEST_ASSERT_EQUAL_UINT8(0, tuh_audio_get_dev_addr(0));
+ }
+}
+
void test_audio_host_uses_cs_endpoint_declared_before_data_endpoint_on_start(void) {
mount_descriptors(playback_with_cs_ep_before_data_ep, sizeof(playback_with_cs_ep_before_data_ep));