ASoC: ops: Check for negative values before reading them
authorMark Brown <broonie@kernel.org>
Fri, 28 Jan 2022 19:24:43 +0000 (19:24 +0000)
committerMark Brown <broonie@kernel.org>
Fri, 28 Jan 2022 20:55:39 +0000 (20:55 +0000)
The controls allow inputs to be specified as negative but our manipulating
them into register fields need to be done on unsigned variables so the
checks for negative numbers weren't taking effect properly. Do the checks
for negative values on the variable in the ABI struct rather than on our
local unsigned copy.

Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20220128192443.3504823-1-broonie@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/soc-ops.c

index dc0e7c8d31f37832deb1e317e27d48c790fc4c61..9833611b83d1fc638f861a239be7b8ce38fb1915 100644 (file)
@@ -316,26 +316,26 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
        if (sign_bit)
                mask = BIT(sign_bit + 1) - 1;
 
+       if (ucontrol->value.integer.value[0] < 0)
+               return -EINVAL;
        val = ucontrol->value.integer.value[0];
        if (mc->platform_max && val > mc->platform_max)
                return -EINVAL;
        if (val > max - min)
                return -EINVAL;
-       if (val < 0)
-               return -EINVAL;
        val = (val + min) & mask;
        if (invert)
                val = max - val;
        val_mask = mask << shift;
        val = val << shift;
        if (snd_soc_volsw_is_stereo(mc)) {
+               if (ucontrol->value.integer.value[1] < 0)
+                       return -EINVAL;
                val2 = ucontrol->value.integer.value[1];
                if (mc->platform_max && val2 > mc->platform_max)
                        return -EINVAL;
                if (val2 > max - min)
                        return -EINVAL;
-               if (val2 < 0)
-                       return -EINVAL;
                val2 = (val2 + min) & mask;
                if (invert)
                        val2 = max - val2;
@@ -423,13 +423,13 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
        int err = 0;
        unsigned int val, val_mask;
 
+       if (ucontrol->value.integer.value[0] < 0)
+               return -EINVAL;
        val = ucontrol->value.integer.value[0];
        if (mc->platform_max && val > mc->platform_max)
                return -EINVAL;
        if (val > max - min)
                return -EINVAL;
-       if (val < 0)
-               return -EINVAL;
        val_mask = mask << shift;
        val = (val + min) & mask;
        val = val << shift;