295 lines · c
1// RUN: %check_clang_tidy %s bugprone-suspicious-memory-comparison %t \2// RUN: -- -- -target x86_64-unknown-unknown -std=c993 4typedef __SIZE_TYPE__ size_t;5int memcmp(const void *lhs, const void *rhs, size_t count);6 7// Examples from cert rule exp42-c8 9struct S {10 char c;11 int i;12 char buffer[13];13};14 15void exp42_c_noncompliant(const struct S *left, const struct S *right) {16 if ((left && right) && (0 == memcmp(left, right, sizeof(struct S)))) {17 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: comparing object representation of type 'struct S' which does not have a unique object representation; consider comparing the members of the object manually18 }19}20 21void exp42_c_compliant(const struct S *left, const struct S *right) {22 if ((left && right) && (left->c == right->c) && (left->i == right->i) &&23 (0 == memcmp(left->buffer, right->buffer, 13))) {24 }25}26 27#pragma pack(push, 1)28struct Packed_S {29 char c;30 int i;31 char buffer[13];32};33#pragma pack(pop)34 35void compliant_packed(const struct Packed_S *left,36 const struct Packed_S *right) {37 if ((left && right) && (0 == memcmp(left, right, sizeof(struct Packed_S)))) {38 // no-warning39 }40}41 42// Examples from cert rule flp37-c43 44struct S2 {45 int i;46 float f;47};48 49int flp37_c_noncompliant(const struct S2 *s1, const struct S2 *s2) {50 if (!s1 && !s2)51 return 1;52 else if (!s1 || !s2)53 return 0;54 return 0 == memcmp(s1, s2, sizeof(struct S2));55 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: comparing object representation of type 'struct S2' which does not have a unique object representation; consider comparing the members of the object manually56}57 58int flp37_c_compliant(const struct S2 *s1, const struct S2 *s2) {59 if (!s1 && !s2)60 return 1;61 else if (!s1 || !s2)62 return 0;63 return s1->i == s2->i && s1->f == s2->f;64 // no-warning65}66 67void Test_Float(void) {68 float a, b;69 memcmp(&a, &b, sizeof(float));70 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'float' which does not have a unique object representation; consider comparing the values manually71}72 73void TestArray_Float(void) {74 float a[3], b[3];75 memcmp(a, b, sizeof(a));76 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'float' which does not have a unique object representation; consider comparing the values manually77}78 79struct PredeclaredType;80 81void Test_PredeclaredType(const struct PredeclaredType *lhs,82 const struct PredeclaredType *rhs) {83 memcmp(lhs, rhs, 1); // no-warning: predeclared type84}85 86struct NoPadding {87 int x;88 int y;89};90 91void Test_NoPadding(void) {92 struct NoPadding a, b;93 memcmp(&a, &b, sizeof(struct NoPadding));94}95 96void TestArray_NoPadding(void) {97 struct NoPadding a[3], b[3];98 memcmp(a, b, 3 * sizeof(struct NoPadding));99}100 101struct TrailingPadding {102 int i;103 char c;104};105 106void Test_TrailingPadding(void) {107 struct TrailingPadding a, b;108 memcmp(&a, &b, sizeof(struct TrailingPadding));109 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct TrailingPadding' which does not have a unique object representation; consider comparing the members of the object manually110 memcmp(&a, &b, sizeof(int)); // no-warning: not comparing entire object111 memcmp(&a, &b, 2 * sizeof(int));112 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct TrailingPadding' which does not have a unique object representation; consider comparing the members of the object manually113}114 115struct TrailingPadding2 {116 int i[2];117 char c;118};119 120void Test_TrailingPadding2(void) {121 struct TrailingPadding2 a, b;122 memcmp(&a, &b, 2 * sizeof(int)); // no-warning: not comparing entire object123 memcmp(&a, &b, sizeof(struct TrailingPadding2));124 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct TrailingPadding2' which does not have a unique object representation; consider comparing the members of the object manually125}126 127void Test_UnknownCount(size_t count) {128 struct TrailingPadding a, b;129 memcmp(&a, &b, count); // no-warning: unknown count value130}131 132void Test_ExplicitVoidCast(void) {133 struct TrailingPadding a, b;134 memcmp((void *)&a, (void *)&b,135 sizeof(struct TrailingPadding)); // no-warning: explicit cast136}137 138void TestArray_TrailingPadding(void) {139 struct TrailingPadding a[3], b[3];140 memcmp(a, b, 3 * sizeof(struct TrailingPadding));141 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct TrailingPadding' which does not have a unique object representation; consider comparing the members of the object manually142}143 144struct InnerPadding {145 char c;146 int i;147};148 149void Test_InnerPadding(void) {150 struct InnerPadding a, b;151 memcmp(&a, &b, sizeof(struct InnerPadding));152 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct InnerPadding' which does not have a unique object representation; consider comparing the members of the object manually153}154 155struct Bitfield_TrailingPaddingBytes {156 int x : 10;157 int y : 6;158};159 160void Test_Bitfield_TrailingPaddingBytes(void) {161 struct Bitfield_TrailingPaddingBytes a, b;162 memcmp(&a, &b, sizeof(struct S));163 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct Bitfield_TrailingPaddingBytes' which does not have a unique object representation; consider comparing the members of the object manually164}165 166struct Bitfield_TrailingPaddingBits {167 int x : 10;168 int y : 20;169};170 171void Test_Bitfield_TrailingPaddingBits(void) {172 struct Bitfield_TrailingPaddingBits a, b;173 memcmp(&a, &b, sizeof(struct Bitfield_TrailingPaddingBits));174 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct Bitfield_TrailingPaddingBits' which does not have a unique object representation; consider comparing the members of the object manually175}176 177struct Bitfield_InnerPaddingBits {178 char x : 2;179 int : 0;180 char y : 8;181};182 183void Test_Bitfield_InnerPaddingBits(void) {184 struct Bitfield_InnerPaddingBits a, b;185 memcmp(&a, &b, sizeof(struct Bitfield_InnerPaddingBits));186 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct Bitfield_InnerPaddingBits' which does not have a unique object representation; consider comparing the members of the object manually187}188 189struct Bitfield_NoPadding {190 int i : 10;191 int j : 10;192 int k : 10;193 int l : 2;194};195_Static_assert(sizeof(struct Bitfield_NoPadding) == sizeof(int),196 "Bit-fields should line up perfectly");197 198void Test_Bitfield_NoPadding(void) {199 struct Bitfield_NoPadding a, b;200 memcmp(&a, &b, sizeof(struct Bitfield_NoPadding)); // no-warning201}202 203struct Bitfield_TrailingUnnamed {204 int i[2];205 int : 0;206};207 208void Bitfield_TrailingUnnamed(void) {209 struct Bitfield_TrailingUnnamed a, b;210 memcmp(&a, &b, 2 * sizeof(int)); // no-warning211 memcmp(&a, &b, sizeof(struct Bitfield_TrailingUnnamed)); // no-warning212}213 214struct PaddingAfterUnion {215 union {216 unsigned short a;217 short b;218 } x;219 220 int y;221};222 223void Test_PaddingAfterUnion(void) {224 struct PaddingAfterUnion a, b;225 memcmp(&a, &b, sizeof(struct PaddingAfterUnion));226 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct PaddingAfterUnion' which does not have a unique object representation; consider comparing the members of the object manually227}228 229struct Union_NoPadding {230 union {231 int a;232 unsigned int b;233 } x;234 235 int y;236};237 238void Test_Union_NoPadding(void) {239 struct Union_NoPadding a, b;240 memcmp(&a, &b, 2 * sizeof(int));241 memcmp(&a, &b, sizeof(struct Union_NoPadding));242}243 244union UnionWithPaddingInNestedStruct {245 int i;246 247 struct {248 int i;249 char c;250 } x;251};252 253void Test_UnionWithPaddingInNestedStruct(void) {254 union UnionWithPaddingInNestedStruct a, b;255 memcmp(&a, &b, sizeof(union UnionWithPaddingInNestedStruct));256 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'union UnionWithPaddingInNestedStruct' which does not have a unique object representation; consider comparing the members of the object manually257}258 259struct PaddingInNested {260 struct TrailingPadding x;261 char y;262};263 264void Test_PaddingInNested(void) {265 struct PaddingInNested a, b;266 memcmp(&a, &b, sizeof(struct PaddingInNested));267 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct PaddingInNested' which does not have a unique object representation; consider comparing the members of the object manually268}269 270struct PaddingAfterNested {271 struct {272 char a;273 char b;274 } x;275 int y;276};277 278void Test_PaddingAfterNested(void) {279 struct PaddingAfterNested a, b;280 memcmp(&a, &b, sizeof(struct PaddingAfterNested));281 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct PaddingAfterNested' which does not have a unique object representation; consider comparing the members of the object manually282}283 284struct AtomicMember {285 _Atomic(int) x;286};287 288void Test_AtomicMember(void) {289 // FIXME: this is a false positive as the list of objects with unique object290 // representations is incomplete.291 struct AtomicMember a, b;292 memcmp(&a, &b, sizeof(struct AtomicMember));293 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: comparing object representation of type 'struct AtomicMember' which does not have a unique object representation; consider comparing the members of the object manually294}295