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 <corentinja...@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@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S5) == 2'}} \ // expected-note@-1 {{expression evaluates to '1 == 2'}} static_assert(__builtin_structured_binding_size(S6) == 2); -// expected-error@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S6) == 2'}} \ // expected-error@-1 {{cannot decompose class type 'S6' because it has an anonymous union member}} \ -// expected-note@-1 {{expression evaluates to '1 == 2'}} +// expected-error@-1 {{type 'S6' cannot be decomposed}} \ +// expected-error@-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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits