Re: Sparse false-positive warnings

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Em Fri, 6 Apr 2018 14:41:11 -0700
Christopher Li <sparse@xxxxxxxxxxx> escreveu:

> On Fri, Apr 6, 2018 at 11:59 AM, Mauro Carvalho Chehab
> <mchehab@xxxxxxxxxx> wrote:
> > drivers/media/pci/ddbridge/ddbridge-core.c:442:9: warning: context imbalance in 'ddb_output_start' - different lock contexts for basic block
> > drivers/media/pci/ddbridge/ddbridge-core.c:457:9: warning: context imbalance in 'ddb_output_stop' - different lock contexts for basic block
> > drivers/media/pci/ddbridge/ddbridge-core.c:472:9: warning: context imbalance in 'ddb_input_stop' - different lock contexts for basic block
> > drivers/media/pci/ddbridge/ddbridge-core.c:504:9: warning: context imbalance in 'ddb_input_start' - different lock contexts for basic block
> >
> > IMO, the problem here is at the sparce logic. Basically, this driver can
> > work with output->dma filled or with NULL. when it is filled, there's a
> > lock to protect the DMA. Otherwise, no lock is needed.  
> 
> There is possible risk there. What if output->dma get changed
> before you try to unlock?

> 
> Of course, from the code  context there is no reason to see output->dma
> can be changed, from developer point of view. However, for sparse,
> there is not way of knowing that.

Hmm... it could try to track the if conditions and check if
"let" statements changing it would be there, but to be frank,
I never studied sparse code (nor did any work with lexical analyzers).

So, I've no idea about how it would track it.

> 
> 
> >
> > Patches like the one below would make sparse to stop complaining:
> >
> > diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
> > index 90687eff5909..69a29d4bf86d 100644
> > --- a/drivers/media/pci/ddbridge/ddbridge-core.c
> > +++ b/drivers/media/pci/ddbridge/ddbridge-core.c
> > @@ -449,15 +449,16 @@ static void ddb_output_stop(struct ddb_output *output)
> >  {
> >         struct ddb *dev = output->port->dev;
> >
> > -       if (output->dma)
> > +       if (output->dma) {
> >                 spin_lock_irq(&output->dma->lock);
> >
> > -       ddbwritel(dev, 0, TS_CONTROL(output));
> > +               ddbwritel(dev, 0, TS_CONTROL(output));
> >
> > -       if (output->dma) {
> >                 ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma));
> >                 output->dma->running = 0;
> >                 spin_unlock_irq(&output->dma->lock);
> > +       } else {
> > +               ddbwritel(dev, 0, TS_CONTROL(output));
> >         }
> >  }  
> 
> if you change that as:
> 
> int locking = output->dma;

Actually output->dma is a pointer, but I got the idea. 

> 
> if (locking)
>         spin_lock_irq();
> 
> ddbwritel();
> 
> if (locking)
>         spin_unlock_irq();
> 
> That will take care of the output->dma changing in between.

I tried that approach on two ways:

1) Doing:

	struct ddb_dma *dma = output->dma;

And replacing all occurrences of output->dma to dma inside the
function (not replacing cause an extra warning from either sparse
or smatch, as it assigns dma then it checks if it is NULL);

2) with the enclosed patch:

diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
index 90687eff5909..02646f0c41ff 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -448,13 +448,14 @@ static void ddb_output_start(struct ddb_output *output)
 static void ddb_output_stop(struct ddb_output *output)
 {
 	struct ddb *dev = output->port->dev;
+	const bool has_dma = output->dma ? true : false;
 
-	if (output->dma)
+	if (has_dma)
 		spin_lock_irq(&output->dma->lock);
 
 	ddbwritel(dev, 0, TS_CONTROL(output));
 
-	if (output->dma) {
+	if (has_dma) {
 		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma));
 		output->dma->running = 0;
 		spin_unlock_irq(&output->dma->lock);

Even in this case, where has_dma is const, sparse still generates the
warning. Just in case, I also tried changing has_dma to just
"bool" and just "int".

The warning is still there:

drivers/media/pci/ddbridge/ddbridge-core.c:458:9: warning: context imbalance in 'ddb_output_stop' - different lock contexts for basic block

> 
> > The problem here is that sparse is not considering the conditional code
> > for output->dma.
> >
> > I'd appreciate if you could look into it and add a patch fixing it
> > there, if possible.  
> 
> 
> The current balance checking is simple and dumb.
> There is possibility that using symbolic execution
> to eliminate some of false positive like the above example.
> 
> Unfortunately,  there is not much you can do in the more general
> complicate case.

IMO, it should be a little smarter, in order to at least work on codes
similar to the one produced with the above patch.

Thanks,
Mauro
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux