1  /* { dg-do compile } */
       2  // TODO: remove need for -fanalyzer-checker=taint here:
       3  // TODO: remove need for --param=analyzer-max-svalue-depth=25 here:
       4  /* { dg-options "-fanalyzer -fanalyzer-checker=taint --param=analyzer-max-svalue-depth=25" } */
       5  /* { dg-require-effective-target analyzer } */
       6  
       7  /* See notes in this header.  */
       8  #include "taint-CVE-2011-0521.h"
       9  
      10  /* Adapted from dvb_ca_ioctl in drivers/media/dvb/ttpci/av7110_ca.c and
      11     dvb_usercopy in drivers/media/dvb/dvb-core/dvbdev.c
      12  
      13     Further simplified from -4; avoid parg and the cast to char[128].  */
      14  
      15  int test_1(struct file *file, unsigned int cmd, unsigned long arg)
      16  {
      17  	ca_slot_info_t sbuf;
      18  
      19  	if (copy_from_user(&sbuf, (void __user *)arg, sizeof(sbuf)) != 0)
      20  		return -1;
      21  
      22  	{
      23  		struct dvb_device *dvbdev = file->private_data;
      24  		struct av7110 *av7110 = dvbdev->priv;
      25  
      26  		/* case CA_GET_SLOT_INFO:  */
      27  		ca_slot_info_t *info= &sbuf;
      28  
      29  		__analyzer_dump_state ("taint", info->num); /* { dg-warning "tainted" } */
      30  
      31  		if (info->num > 1)
      32  			return -EINVAL;
      33  
      34  		__analyzer_dump_state ("taint", info->num); /* { dg-warning "has_ub" } */
      35  
      36  		av7110->ci_slot[info->num].num = info->num; /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without checking for negative" } */
      37  		av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without checking for negative" } */
      38  							CA_CI_LINK : CA_CI;
      39  		memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-warning "use of attacker-controlled value in array lookup without bounds checking" } */
      40  	}
      41  
      42  	copy_to_user((void __user *)arg, &sbuf, sizeof(sbuf));
      43  
      44  	return 0;
      45  }