aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/plugin/taint-pr112975.c
blob: 9f312cb33487482233ca5d0c7162f23f219d0358 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/* Reduced from false positive in Linux kernel in
   drivers/xen/privcmd.c.  */

/* { dg-do compile } */
/* { dg-options "-fanalyzer" } */
/* { dg-require-effective-target analyzer } */

typedef __SIZE_TYPE__ size_t;
typedef unsigned short __u16;
typedef unsigned int gfp_t;
void
kfree(const void* objp);

extern void *
__attribute__((__alloc_size__(1, 2)))
__attribute__((__malloc__))
kcalloc(size_t n, size_t size, gfp_t flags);

extern unsigned long
copy_from_user(void*, const void*, unsigned long);

typedef __u16 domid_t;
struct privcmd_dm_op_buf
{
  void* uptr;
  size_t size;
};
struct privcmd_dm_op
{
  domid_t dom;
  __u16 num;
};
static unsigned int privcmd_dm_op_max_num = 16;
long
privcmd_ioctl_dm_op(void* udata)
{
  struct privcmd_dm_op kdata;
  struct privcmd_dm_op_buf* kbufs;
  if (copy_from_user(&kdata, udata, sizeof(kdata)))
    return -14;
  if (kdata.num == 0)
    return 0;
  if (kdata.num > privcmd_dm_op_max_num)
    return -7;
  kbufs =
    kcalloc(kdata.num,  /* { dg-bogus "attacker-controlled value" }  */
            sizeof(*kbufs),
            (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u)));
  if (!kbufs)
    return -12;
  kfree(kbufs);
  return 0;
}