1184c6242SDominic Chen // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.CastToStruct,core -verify %s 213264ebeSDaniel Marjamaki 313264ebeSDaniel Marjamaki struct AB { 413264ebeSDaniel Marjamaki int A; 513264ebeSDaniel Marjamaki int B; 613264ebeSDaniel Marjamaki }; 713264ebeSDaniel Marjamaki 813264ebeSDaniel Marjamaki struct ABC { 913264ebeSDaniel Marjamaki int A; 1013264ebeSDaniel Marjamaki int B; 1113264ebeSDaniel Marjamaki int C; 1213264ebeSDaniel Marjamaki }; 1313264ebeSDaniel Marjamaki 1413264ebeSDaniel Marjamaki struct Base { BaseBase1513264ebeSDaniel Marjamaki Base() : A(0), B(0) {} ~BaseBase1613264ebeSDaniel Marjamaki virtual ~Base() {} 1713264ebeSDaniel Marjamaki 1813264ebeSDaniel Marjamaki int A; 1913264ebeSDaniel Marjamaki int B; 2013264ebeSDaniel Marjamaki }; 2113264ebeSDaniel Marjamaki 2213264ebeSDaniel Marjamaki struct Derived : public Base { DerivedDerived2313264ebeSDaniel Marjamaki Derived() : Base(), C(0) {} 2413264ebeSDaniel Marjamaki int C; 2513264ebeSDaniel Marjamaki }; 2613264ebeSDaniel Marjamaki structToStruct(struct AB * P)2713264ebeSDaniel Marjamakivoid structToStruct(struct AB *P) { 2813264ebeSDaniel Marjamaki struct AB Ab; 2913264ebeSDaniel Marjamaki struct ABC *Abc; 3013264ebeSDaniel Marjamaki 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}} 3113264ebeSDaniel Marjamaki Abc = (struct ABC *)P; // No warning; It is not known what data P points at. 3213264ebeSDaniel Marjamaki Abc = (struct ABC *)&*P; 3313264ebeSDaniel Marjamaki 3413264ebeSDaniel Marjamaki // Don't warn when the cast is not widening. 3513264ebeSDaniel Marjamaki P = (struct AB *)&Ab; // struct AB * => struct AB * 3613264ebeSDaniel Marjamaki struct ABC Abc2; 3713264ebeSDaniel Marjamaki P = (struct AB *)&Abc2; // struct ABC * => struct AB * 3813264ebeSDaniel Marjamaki 3913264ebeSDaniel Marjamaki // True negatives when casting from Base to Derived. 4013264ebeSDaniel Marjamaki Derived D1, *D2; 4113264ebeSDaniel Marjamaki Base &B1 = D1; 4213264ebeSDaniel Marjamaki D2 = (Derived *)&B1; 4313264ebeSDaniel Marjamaki D2 = dynamic_cast<Derived *>(&B1); 4413264ebeSDaniel Marjamaki D2 = static_cast<Derived *>(&B1); 4513264ebeSDaniel Marjamaki 4613264ebeSDaniel Marjamaki // True positives when casting from Base to Derived. 4713264ebeSDaniel Marjamaki Base B2; 4813264ebeSDaniel Marjamaki 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}} 4913264ebeSDaniel Marjamaki 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}} 5013264ebeSDaniel Marjamaki 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}} 5113264ebeSDaniel Marjamaki 5213264ebeSDaniel Marjamaki // False negatives, cast from Base to Derived. With path sensitive analysis 5313264ebeSDaniel Marjamaki // these false negatives could be fixed. 5413264ebeSDaniel Marjamaki Base *B3 = &B2; 5513264ebeSDaniel Marjamaki D2 = (Derived *)B3; 5613264ebeSDaniel Marjamaki D2 = dynamic_cast<Derived *>(B3); 5713264ebeSDaniel Marjamaki D2 = static_cast<Derived *>(B3); 5813264ebeSDaniel Marjamaki } 5913264ebeSDaniel Marjamaki intToStruct(int * P)6013264ebeSDaniel Marjamakivoid intToStruct(int *P) { 6113264ebeSDaniel Marjamaki struct ABC *Abc; 6213264ebeSDaniel Marjamaki 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}} 6313264ebeSDaniel Marjamaki 6413264ebeSDaniel Marjamaki // Cast from void *. 6513264ebeSDaniel Marjamaki void *VP = P; 6613264ebeSDaniel Marjamaki Abc = (struct ABC *)VP; 6713264ebeSDaniel Marjamaki } 68*cf715bd3SDaniel Marjamaki 69*cf715bd3SDaniel Marjamaki // https://llvm.org/bugs/show_bug.cgi?id=31173 dontCrash1(struct AB X)70*cf715bd3SDaniel Marjamakivoid dontCrash1(struct AB X) { 71*cf715bd3SDaniel Marjamaki struct UndefS *S = (struct UndefS *)&X; 72*cf715bd3SDaniel Marjamaki } 73*cf715bd3SDaniel Marjamaki 74*cf715bd3SDaniel Marjamaki struct S; 75*cf715bd3SDaniel Marjamaki struct T { 76*cf715bd3SDaniel Marjamaki struct S *P; 77*cf715bd3SDaniel Marjamaki }; 78*cf715bd3SDaniel Marjamaki extern struct S Var1, Var2; dontCrash2()79*cf715bd3SDaniel Marjamakivoid dontCrash2() { 80*cf715bd3SDaniel Marjamaki ((struct T *) &Var1)->P = &Var2; 81*cf715bd3SDaniel Marjamaki } 82