audio: validate feature-unit channel number before indexing mute/volume in uac2_headset and uac2_speaker_fb
diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index c30b31f..c179296 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c
@@ -207,6 +207,10 @@ // If request is for our speaker feature unit if (entityID == UAC1_ENTITY_SPK_FEATURE_UNIT) { + // Channel number is host-controlled (0..255) but mute[]/volume[] hold only + // CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1 entries - reject out-of-range (STALL) + if (channelNum > CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) return false; + switch (ctrlSel) { case AUDIO10_FU_CTRL_MUTE: switch (p_request->bRequest) { @@ -255,6 +259,10 @@ // If request is for our speaker feature unit if (entityID == UAC1_ENTITY_SPK_FEATURE_UNIT) { + // Channel number is host-controlled (0..255) but mute[]/volume[] hold only + // CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1 entries - reject out-of-range (STALL) + if (channelNum > CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) return false; + switch (ctrlSel) { case AUDIO10_FU_CTRL_MUTE: // Audio control mute cur parameter block consists of only one byte - we thus can send it right away @@ -381,6 +389,10 @@ uint8_t const ctrl_sel = TU_U16_HIGH(p_request->wValue); uint8_t const channel_num = TU_U16_LOW(p_request->wValue); + // Channel number is host-controlled (0..255) but mute[]/volume[] hold only + // CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1 entries - reject out-of-range (STALL) + if (channel_num > CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) return false; + if (ctrl_sel == AUDIO20_FU_CTRL_MUTE && p_request->bRequest == AUDIO20_CS_REQ_CUR) { audio20_control_cur_1_t mute1 = {.bCur = mute[channel_num]}; TU_LOG1("Get channel %u mute %d\r\n", channel_num, mute1.bCur); @@ -412,6 +424,10 @@ uint8_t const ctrl_sel = TU_U16_HIGH(p_request->wValue); uint8_t const channel_num = TU_U16_LOW(p_request->wValue); + // Channel number is host-controlled (0..255) but mute[]/volume[] hold only + // CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1 entries - reject out-of-range (STALL) + if (channel_num > CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) return false; + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); if (ctrl_sel == AUDIO20_FU_CTRL_MUTE) {
diff --git a/examples/device/uac2_speaker_fb/src/main.c b/examples/device/uac2_speaker_fb/src/main.c index 7e4d27f..36642ac 100644 --- a/examples/device/uac2_speaker_fb/src/main.c +++ b/examples/device/uac2_speaker_fb/src/main.c
@@ -201,6 +201,10 @@ // If request is for our feature unit if (entityID == UAC1_ENTITY_FEATURE_UNIT) { + // Channel number is host-controlled (0..255) but mute[]/volume[] hold only + // CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1 entries - reject out-of-range (STALL) + if (channelNum > CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) return false; + switch (ctrlSel) { case AUDIO10_FU_CTRL_MUTE: switch (p_request->bRequest) { @@ -249,6 +253,10 @@ // If request is for our feature unit if (entityID == UAC1_ENTITY_FEATURE_UNIT) { + // Channel number is host-controlled (0..255) but mute[]/volume[] hold only + // CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1 entries - reject out-of-range (STALL) + if (channelNum > CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) return false; + switch (ctrlSel) { case AUDIO10_FU_CTRL_MUTE: // Audio control mute cur parameter block consists of only one byte - we thus can send it right away @@ -373,6 +381,10 @@ uint8_t const ctrl_sel = TU_U16_HIGH(p_request->wValue); uint8_t const channel_num = TU_U16_LOW(p_request->wValue); + // Channel number is host-controlled (0..255) but mute[]/volume[] hold only + // CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1 entries - reject out-of-range (STALL) + if (channel_num > CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) return false; + if (ctrl_sel == AUDIO20_FU_CTRL_MUTE && p_request->bRequest == AUDIO20_CS_REQ_CUR) { audio20_control_cur_1_t mute1 = {.bCur = mute[channel_num]}; TU_LOG1("Get channel %u mute %d\r\n", channel_num, mute1.bCur); @@ -401,6 +413,10 @@ uint8_t const ctrl_sel = TU_U16_HIGH(p_request->wValue); uint8_t const channel_num = TU_U16_LOW(p_request->wValue); + // Channel number is host-controlled (0..255) but mute[]/volume[] hold only + // CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1 entries - reject out-of-range (STALL) + if (channel_num > CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) return false; + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); if (ctrl_sel == AUDIO20_FU_CTRL_MUTE) {