Skip to content

[Clang] Fix UB in #131515 #132091

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
Mar 19, 2025
Merged

[Clang] Fix UB in #131515 #132091

merged 1 commit into from
Mar 19, 2025

Conversation

cor3ntin
Copy link
Contributor

@cor3ntin cor3ntin commented Mar 19, 2025

It turns out trailing objects are uninitialized
and APValue assignment operator requires a fully initialized object.

Additionally, do some drive-by post-commit-review fixes.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Mar 19, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 19, 2025

@llvm/pr-subscribers-clang

Author: cor3ntin (cor3ntin)

Changes

It turns out trailing objects are uninitialized
and APValue assignment operator requires a fully initialized object.


Full diff: https://github.com/llvm/llvm-project/pull/132091.diff

3 Files Affected:

  • (modified) clang/include/clang/AST/ExprCXX.h (+1-1)
  • (modified) clang/lib/AST/ExprCXX.cpp (+10-2)
  • (modified) clang/lib/Sema/SemaDeclCXX.cpp (+2-2)
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;
 }

It turns out trailing objects are uninitialized
and APValue assignment operator requires a fully initialized object.
@cor3ntin cor3ntin merged commit fecd937 into llvm:main Mar 19, 2025
7 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants