Skip to content

[-Wunsafe-buffer-usage] Fix bug in unsafe casts to incomplete types #116433

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions clang/lib/Sema/AnalysisBasedWarnings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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