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 { BaseBase15 Base() : A(0), B(0) {} ~BaseBase16 virtual ~Base() {} 17 18 int A; 19 int B; 20 }; 21 22 struct Derived : public Base { DerivedDerived23 Derived() : Base(), C(0) {} 24 int C; 25 }; 26 structToStruct(struct AB * P)27void 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 intToStruct(int * P)60void 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 dontCrash1(struct AB X)70void 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; dontCrash2()79void dontCrash2() { 80 ((struct T *) &Var1)->P = &Var2; 81 } 82