1 | // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.CastToStruct,core -verify %s |
2 | |
3 | struct AB { |
4 | int A; |
5 | int B; |
6 | }; |
7 | |
8 | struct ABC { |
9 | int A; |
10 | int B; |
11 | int C; |
12 | }; |
13 | |
14 | struct Base { |
15 | Base() : A(0), B(0) {} |
16 | virtual ~Base() {} |
17 | |
18 | int A; |
19 | int B; |
20 | }; |
21 | |
22 | struct Derived : public Base { |
23 | Derived() : Base(), C(0) {} |
24 | int C; |
25 | }; |
26 | |
27 | void structToStruct(struct AB *P) { |
28 | struct AB Ab; |
29 | struct ABC *Abc; |
30 | Abc = (struct ABC *)&Ab; // expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}} |
31 | Abc = (struct ABC *)P; // No warning; It is not known what data P points at. |
32 | Abc = (struct ABC *)&*P; |
33 | |
34 | // Don't warn when the cast is not widening. |
35 | P = (struct AB *)&Ab; // struct AB * => struct AB * |
36 | struct ABC Abc2; |
37 | P = (struct AB *)&Abc2; // struct ABC * => struct AB * |
38 | |
39 | // True negatives when casting from Base to Derived. |
40 | Derived D1, *D2; |
41 | Base &B1 = D1; |
42 | D2 = (Derived *)&B1; |
43 | D2 = dynamic_cast<Derived *>(&B1); |
44 | D2 = static_cast<Derived *>(&B1); |
45 | |
46 | // True positives when casting from Base to Derived. |
47 | Base B2; |
48 | D2 = (Derived *)&B2;// expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}} |
49 | D2 = dynamic_cast<Derived *>(&B2);// expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}} |
50 | D2 = static_cast<Derived *>(&B2);// expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}} |
51 | |
52 | // False negatives, cast from Base to Derived. With path sensitive analysis |
53 | // these false negatives could be fixed. |
54 | Base *B3 = &B2; |
55 | D2 = (Derived *)B3; |
56 | D2 = dynamic_cast<Derived *>(B3); |
57 | D2 = static_cast<Derived *>(B3); |
58 | } |
59 | |
60 | void intToStruct(int *P) { |
61 | struct ABC *Abc; |
62 | Abc = (struct ABC *)P; // expected-warning {{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}} |
63 | |
64 | // Cast from void *. |
65 | void *VP = P; |
66 | Abc = (struct ABC *)VP; |
67 | } |
68 | |
69 | // https://llvm.org/bugs/show_bug.cgi?id=31173 |
70 | void dontCrash1(struct AB X) { |
71 | struct UndefS *S = (struct UndefS *)&X; |
72 | } |
73 | |
74 | struct S; |
75 | struct T { |
76 | struct S *P; |
77 | }; |
78 | extern struct S Var1, Var2; |
79 | void dontCrash2() { |
80 | ((struct T *) &Var1)->P = &Var2; |
81 | } |
82 | |