Re: [PATCH v2] iio: adc: stm32-adc: fix possible division by zero in processed channel

From: Andy Shevchenko

Date: Wed Sep 16 2026 - 11:23:23 EST


On Wed, Sep 16, 2026 at 04:10:05PM +0200, Fabrice Gasnier wrote:
> In case the conversion has failed or returned zero, processing *val
> can lead to a division by zero. Need to check for errors, or converted
> value is zero, before processing the data. In case the converted value
> is zero, e.g. the Vrefint channel, this should be considered as invalid
> in all cases.

...

> Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
> Link: https://lore.kernel.org/all/20260911161555.244F31F000FF@xxxxxxxxxxxxxxx/

Closes: ^^^


> + if (mask == IIO_CHAN_INFO_PROCESSED) {
> + int vrefint_raw;
> +
> + if (ret < 0) {
> + iio_device_release_direct(indio_dev);
> + return ret;
> + }
> +
> + vrefint_raw = *val;

> +

Unneeded blank line.

> + if (vrefint_raw == 0) {
> + iio_device_release_direct(indio_dev);
> + return -EINVAL;
> + }
> +
> + *val = STM32_ADC_VREFINT_VOLTAGE * adc->vrefint.vrefint_cal / vrefint_raw;
> + }

Let's look at the current code in this switch-case

case IIO_CHAN_INFO_PROCESSED:
if (!iio_device_claim_direct(indio_dev))
return -EBUSY;
if (chan->type == IIO_VOLTAGE)
ret = stm32_adc_single_conv(indio_dev, chan, val);
else
ret = -EINVAL;

if (mask == IIO_CHAN_INFO_PROCESSED)
*val = STM32_ADC_VREFINT_VOLTAGE * adc->vrefint.vrefint_cal / *val;

iio_device_release_direct(indio_dev);
return ret;

In the previous version you were trying to keep goto-less approach.
However in the current state of affairs I don't think the goto is
too bad (after all we need to backport this to the kernels that may
not have IIO_DEV_ACQUIRE_DIRECT_MODE() macro).

Also checking 'ret' under another condition seems unusual.

What about

case IIO_CHAN_INFO_PROCESSED:
if (!iio_device_claim_direct(indio_dev))
return -EBUSY;
if (chan->type == IIO_VOLTAGE)
ret = stm32_adc_single_conv(indio_dev, chan, val);
else
ret = -EINVAL;
iio_device_release_direct(indio_dev);
if (ret)
return ret;

if (*val == 0)
return -EINVAL;

if (mask == IIO_CHAN_INFO_PROCESSED)
*val = STM32_ADC_VREFINT_VOLTAGE * adc->vrefint.vrefint_cal / *val;

return 0;

? (Yes, we leave that line untouched, but we get the change cleaner.)


--
With Best Regards,
Andy Shevchenko