|
|
@@ -754,7 +754,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
|
|
|
struct uac_mixer_unit_descriptor *desc)
|
|
|
{
|
|
|
int mu_channels;
|
|
|
- void *c;
|
|
|
|
|
|
if (desc->bLength < sizeof(*desc))
|
|
|
return -EINVAL;
|
|
|
@@ -777,13 +776,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- if (!mu_channels)
|
|
|
- return 0;
|
|
|
-
|
|
|
- c = uac_mixer_unit_bmControls(desc, state->mixer->protocol);
|
|
|
- if (c - (void *)desc + (mu_channels - 1) / 8 >= desc->bLength)
|
|
|
- return 0; /* no bmControls -> skip */
|
|
|
-
|
|
|
return mu_channels;
|
|
|
}
|
|
|
|
|
|
@@ -2028,6 +2020,31 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
|
|
|
* Mixer Unit
|
|
|
*/
|
|
|
|
|
|
+/* check whether the given in/out overflows bmMixerControls matrix */
|
|
|
+static bool mixer_bitmap_overflow(struct uac_mixer_unit_descriptor *desc,
|
|
|
+ int protocol, int num_ins, int num_outs)
|
|
|
+{
|
|
|
+ u8 *hdr = (u8 *)desc;
|
|
|
+ u8 *c = uac_mixer_unit_bmControls(desc, protocol);
|
|
|
+ size_t rest; /* remaining bytes after bmMixerControls */
|
|
|
+
|
|
|
+ switch (protocol) {
|
|
|
+ case UAC_VERSION_1:
|
|
|
+ default:
|
|
|
+ rest = 1; /* iMixer */
|
|
|
+ break;
|
|
|
+ case UAC_VERSION_2:
|
|
|
+ rest = 2; /* bmControls + iMixer */
|
|
|
+ break;
|
|
|
+ case UAC_VERSION_3:
|
|
|
+ rest = 6; /* bmControls + wMixerDescrStr */
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* overflow? */
|
|
|
+ return c + (num_ins * num_outs + 7) / 8 + rest > hdr + hdr[0];
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* build a mixer unit control
|
|
|
*
|
|
|
@@ -2156,6 +2173,9 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
num_ins += iterm.channels;
|
|
|
+ if (mixer_bitmap_overflow(desc, state->mixer->protocol,
|
|
|
+ num_ins, num_outs))
|
|
|
+ break;
|
|
|
for (; ich < num_ins; ich++) {
|
|
|
int och, ich_has_controls = 0;
|
|
|
|