mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-17 23:36:40 +00:00
[-Wunsafe-buffer-usage] Fix bug in unsafe casts to incomplete types (#116433)
Fixed the crash coming from attempting to get size of incomplete types. Casting `span.data()` to a pointer-to-incomplete-type should be immediately considered unsafe. Solving issue #116286. Co-authored-by: Ziqing Luo <ziqing_luo@apple.com>
This commit is contained in:
parent
6e2b77d469
commit
78606af606
@ -2262,19 +2262,28 @@ public:
|
||||
MsgParam = 5;
|
||||
} else if (const auto *ECE = dyn_cast<ExplicitCastExpr>(Operation)) {
|
||||
QualType destType = ECE->getType();
|
||||
bool destTypeComplete = true;
|
||||
|
||||
if (!isa<PointerType>(destType))
|
||||
return;
|
||||
destType = destType.getTypePtr()->getPointeeType();
|
||||
if (const auto *D = destType->getAsTagDecl())
|
||||
destTypeComplete = D->isCompleteDefinition();
|
||||
|
||||
const uint64_t dSize =
|
||||
Ctx.getTypeSize(destType.getTypePtr()->getPointeeType());
|
||||
// If destination type is incomplete, it is unsafe to cast to anyway, no
|
||||
// need to check its type:
|
||||
if (destTypeComplete) {
|
||||
const uint64_t dSize = Ctx.getTypeSize(destType);
|
||||
QualType srcType = ECE->getSubExpr()->getType();
|
||||
|
||||
QualType srcType = ECE->getSubExpr()->getType();
|
||||
const uint64_t sSize =
|
||||
Ctx.getTypeSize(srcType.getTypePtr()->getPointeeType());
|
||||
assert(srcType->isPointerType());
|
||||
|
||||
if (sSize >= dSize)
|
||||
return;
|
||||
const uint64_t sSize =
|
||||
Ctx.getTypeSize(srcType.getTypePtr()->getPointeeType());
|
||||
|
||||
if (sSize >= dSize)
|
||||
return;
|
||||
}
|
||||
if (const auto *CE = dyn_cast<CXXMemberCallExpr>(
|
||||
ECE->getSubExpr()->IgnoreParens())) {
|
||||
D = CE->getMethodDecl();
|
||||
|
@ -173,4 +173,21 @@ A false_negatives(std::span<int> span_pt, span<A> span_A) {
|
||||
return *a2; // TODO: Can cause OOB if span_pt is empty
|
||||
|
||||
}
|
||||
|
||||
void test_incomplete_type(std::span<char> S) {
|
||||
(struct IncompleteStruct *)S.data(); // expected-warning{{unsafe invocation of 'data'}}
|
||||
(class IncompleteClass *)S.data(); // expected-warning{{unsafe invocation of 'data'}}
|
||||
(union IncompleteUnion *)S.data(); // expected-warning{{unsafe invocation of 'data'}}
|
||||
}
|
||||
|
||||
void test_complete_type(std::span<long> S) {
|
||||
(struct CompleteStruct *)S.data(); // no warn as the struct size is smaller than long
|
||||
(class CompleteClass *)S.data(); // no warn as the class size is smaller than long
|
||||
(union CompleteUnion *)S.data(); // no warn as the union size is smaller than long
|
||||
|
||||
struct CompleteStruct {};
|
||||
class CompleteClass {};
|
||||
union CompleteUnion {};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user