Quantcast
Viewing all articles
Browse latest Browse all 49

Evil Casts

Spot the difference in

#include <iostream>
struct S1 { int s1 = 2; };
struct S2;
S2 * f(S1 * s) { return (S2 *) s; }
struct T { int t = 1; };
struct S2: T, S1 {};
int main() { S2 s2; std::cout << f(s2)->t << '\n'; }

vs.

#include <iostream>
struct S1 { int s1 = 2; };
struct T { int t = 1; };
struct S2: T, S1 {};
S2 * f(S1 * s) { return (S2 *) s; }
int main() { S2 s2; std::cout << f(s2)->t << '\n'; }

The latter will print “1”, as would be expected. The former will probably print “2”. Or “1”.

The trouble is that in C++ a C-style cast involving a pointer to an incomplete type will “resolve” to a reinterpret_cast. (Or, at the compiler’s discretion, to a static_cast, if the type later becomes complete within this translation unit.) With no incomplete types involved, the C-style cast will consistently resolve to a static_cast.

“Broken cast” shows how such C-sytle casts on incomplete types are the worst of the worst. (The reason it went unnoticed for 10+ years is that the corrupted pFact member happens to always contain a null pointer when that code is executed, so writing false into it doesn’t really hurt. But also doesn’t reset bVisible from true to false, so that hot hack of yore is probably not needed so desparately after all…)

Noel Grandin wrote a Clang plugin to flag many of the clearly bad uses of C-style casts across the LibreOffice code base. Since “loplugin:cstylecast: warn about casts involving incomplete types” it now also flags “the worst kind of all.” (And unearthed the above WTF.)


Image may be NSFW.
Clik here to view.
Image may be NSFW.
Clik here to view.

Viewing all articles
Browse latest Browse all 49

Trending Articles