https://github.com/ziqingluo-90 updated https://github.com/llvm/llvm-project/pull/116433
>From 429dd67554681595390828c990050c85dcbb557b Mon Sep 17 00:00:00 2001 From: Ziqing Luo <ziqing_...@apple.com> Date: Thu, 14 Nov 2024 23:08:47 -0800 Subject: [PATCH] [-Wunsafe-buffer-usage] Fix bug in unsafe cast to incomplete types Fixed the crash coming from attempting to get size of incomplete types. Casting `span.data()` to pointer-to-incomplete-type should be directly considered unsafe. Solving issue #116286. --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 23 +++++++++++++------ ...e-buffer-usage-warning-data-invocation.cpp | 17 ++++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index c76733e9a774b6..95d14c492e1ea5 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2270,19 +2270,28 @@ class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler { 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(); diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp index 0228e42652bd95..a6a334d247023c 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits