[clang] [Clang] Fix UB in #131515 (PR #132091)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 19 13:18:55 PDT 2025
https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/132091
>From 68ebbf821176dd17a757c32771fa728f21d4dd11 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Wed, 19 Mar 2025 21:05:38 +0100
Subject: [PATCH] [Clang] Fix UB in #131515
It turns out trailing objects are uninitialized
and APValue assignment operator requires a fully initialized object.
---
clang/include/clang/AST/ExprCXX.h | 2 +-
clang/lib/AST/ExprCXX.cpp | 12 ++++++++++--
clang/lib/Sema/SemaDeclCXX.cpp | 4 ++--
.../test/SemaCXX/builtin-structured-binding-size.cpp | 4 ++--
4 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 724ed437f1075..223d74993e9e6 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -2777,7 +2777,7 @@ class TypeTraitExpr final
ArrayRef<TypeSourceInfo *> Args, SourceLocation RParenLoc,
std::variant<bool, APValue> Value);
- TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) {}
+ TypeTraitExpr(EmptyShell Empty, bool IsStoredAsBool);
size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const {
return getNumArgs();
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index c2cf4ffe506c6..a000e988e6834 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1868,7 +1868,8 @@ TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
if (TypeTraitExprBits.IsBooleanTypeTrait)
TypeTraitExprBits.Value = std::get<bool>(Value);
else
- *getTrailingObjects<APValue>() = std::get<APValue>(std::move(Value));
+ ::new (getTrailingObjects<APValue>())
+ APValue(std::get<APValue>(std::move(Value)));
TypeTraitExprBits.NumArgs = Args.size();
assert(Args.size() == TypeTraitExprBits.NumArgs &&
@@ -1884,6 +1885,13 @@ TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
"Only int values are supported by clang");
}
+TypeTraitExpr::TypeTraitExpr(EmptyShell Empty, bool IsStoredAsBool)
+ : Expr(TypeTraitExprClass, Empty) {
+ TypeTraitExprBits.IsBooleanTypeTrait = IsStoredAsBool;
+ if (!IsStoredAsBool)
+ ::new (getTrailingObjects<APValue>()) APValue();
+}
+
TypeTraitExpr *TypeTraitExpr::Create(const ASTContext &C, QualType T,
SourceLocation Loc,
TypeTrait Kind,
@@ -1909,7 +1917,7 @@ TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C,
unsigned NumArgs) {
void *Mem = C.Allocate(totalSizeToAlloc<APValue, TypeSourceInfo *>(
IsStoredAsBool ? 0 : 1, NumArgs));
- return new (Mem) TypeTraitExpr(EmptyShell());
+ return new (Mem) TypeTraitExpr(EmptyShell(), IsStoredAsBool);
}
CUDAKernelCallExpr::CUDAKernelCallExpr(Expr *Fn, CallExpr *Config,
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index bd6321c46a78f..a1551e8027cd3 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1681,7 +1681,7 @@ std::optional<unsigned> Sema::GetDecompositionElementCount(QualType T,
llvm::APSInt TupleSize(Ctx.getTypeSize(Ctx.getSizeType()));
switch (isTupleLike(*this, Loc, T, TupleSize)) {
case IsTupleLike::Error:
- return {};
+ return std::nullopt;
case IsTupleLike::TupleLike:
return TupleSize.getExtValue();
case IsTupleLike::NotTupleLike:
@@ -1706,7 +1706,7 @@ std::optional<unsigned> Sema::GetDecompositionElementCount(QualType T,
RD->fields(), [](FieldDecl *FD) { return !FD->isUnnamedBitField(); });
if (CheckMemberDecompositionFields(*this, Loc, OrigRD, T, BasePair))
- return true;
+ return std::nullopt;
return NumFields;
}
diff --git a/clang/test/SemaCXX/builtin-structured-binding-size.cpp b/clang/test/SemaCXX/builtin-structured-binding-size.cpp
index 85b1d81e08e33..53576048754ab 100644
--- a/clang/test/SemaCXX/builtin-structured-binding-size.cpp
+++ b/clang/test/SemaCXX/builtin-structured-binding-size.cpp
@@ -40,9 +40,9 @@ static_assert(__builtin_structured_binding_size(S5) == 2);
// expected-error at -1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S5) == 2'}} \
// expected-note at -1 {{expression evaluates to '1 == 2'}}
static_assert(__builtin_structured_binding_size(S6) == 2);
-// expected-error at -1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S6) == 2'}} \
// expected-error at -1 {{cannot decompose class type 'S6' because it has an anonymous union member}} \
-// expected-note at -1 {{expression evaluates to '1 == 2'}}
+// expected-error at -1 {{type 'S6' cannot be decomposed}} \
+// expected-error at -1 {{static assertion expression is not an integral constant expression}} \
// expected-note@#note-anon-union {{declared here}}
static_assert(__builtin_structured_binding_size(S7) == 1);
More information about the cfe-commits
mailing list