Re: esp_scsi incorrect unsigned test

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

 



On Sat, 2008-04-19 at 08:05 -0600, Matthew Wilcox wrote:
> On Fri, Apr 18, 2008 at 09:08:55PM +0200, Julia Lawall wrote:
> > I found 63 occurrences of this problem with the following semantic match
> > (http://www.emn.fr/x-info/coccinelle/):
> > 
> > @@ unsigned int i; @@
> > 
> > * i < 0
> > 
> > I looked through all of the results by hand, and they all seem to be 
> > problems.  In many cases, it seems like the variable should not be 
> > unsigned as it is used to hold the return value of a function that might 
> > return a negative error code, but I haven't looked into this in detail.
> > 
> > In the output below, the lines that begin with a single start contain a 
> > test of whether an unsigned variable or structure field is less than 0.
> > The output is actually generated with diff, but I converted the -s to *s 
> > to avoid confusion.
> 
> > diff -u -p a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
> > *** a/drivers/scsi/esp_scsi.c 2008-03-12 14:13:14.000000000 +0100
> > @@ -380,7 +380,7 @@ static void esp_advance_dma(struct esp *
> >  
> >  	p->cur_residue -= len;
> >  	p->tot_residue -= len;
> > *	if (p->cur_residue < 0 || p->tot_residue < 0) {
> >  		printk(KERN_ERR PFX "esp%d: Data transfer overflow.\n",
> >  		       esp->host->unique_id);
> >  		printk(KERN_ERR PFX "esp%d: cur_residue[%d] tot_residue[%d] "
> 
> This is clearly buggy.  A residue is, though, inherently unsigned, so I
> don't think we should change the type of the variable.  Rather, we
> should test it before subtraction.  Dave, what do you think?
> 
> ----
> 
> Fix ESP data transfer overflow checks
> 
> The current code attempts to detect data transfer overflow by checking
> whether an unsigned variable is negative.  Instead, we should
> compare the two variables before subtracting them.
> 
> Reported-by: Julia Lawall <julia@xxxxxxx>
> Signed-off-by: Matthew Wilcox <willy@xxxxxxxxxxxxxxx>
> 
> diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
> index bfdee59..b5e8a94 100644
> --- a/drivers/scsi/esp_scsi.c
> +++ b/drivers/scsi/esp_scsi.c
> @@ -378,9 +378,7 @@ static void esp_advance_dma(struct esp *esp, struct esp_cmd_entry *ent,
>  		return;
>  	}
>  
> -	p->cur_residue -= len;
> -	p->tot_residue -= len;
> -	if (p->cur_residue < 0 || p->tot_residue < 0) {
> +	if (unlikely(p->cur_residue < len || p->tot_residue < len)) {
>  		printk(KERN_ERR PFX "esp%d: Data transfer overflow.\n",
>  		       esp->host->unique_id);
>  		printk(KERN_ERR PFX "esp%d: cur_residue[%d] tot_residue[%d] "

To be pedantic, this should be %u not %d for unsigned.

> @@ -389,7 +387,11 @@ static void esp_advance_dma(struct esp *esp, struct esp_cmd_entry *ent,
>  		       p->cur_residue, p->tot_residue, len);
>  		p->cur_residue = 0;
>  		p->tot_residue = 0;
> +	} else {
> +		p->cur_residue -= len;
> +		p->tot_residue -= len;
>  	}
> +
>  	if (!p->cur_residue && p->tot_residue) {
>  		p->cur_sg++;
>  		p->cur_residue = sg_dma_len(p->cur_sg);

It look fine to me ... although an alternative (and possibly simpler)
fix would just be to remove the unsigned from the two residue
definitions in the struct.

James


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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux