[clang] [clang][Interp] Bail out from type-punning casts (PR #163809)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 16 08:51:09 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: None (term-est)
<details>
<summary>Changes</summary>
Fixes #<!-- -->163778 (fix might be indirect?)
Prevents emitting byte-code for UB casts
---
Full diff: https://github.com/llvm/llvm-project/pull/163809.diff
2 Files Affected:
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+44)
- (modified) clang/lib/AST/ByteCode/Compiler.h (+2)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 74cae030bb9bb..c30262dd8a323 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -212,6 +212,10 @@ template <class Emitter>
bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
const Expr *SubExpr = CE->getSubExpr();
+ if (isPunningDereference(SubExpr))
+ return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true,
+ CE);
+
if (DiscardResult)
return this->delegate(SubExpr);
@@ -5511,6 +5515,46 @@ bool Compiler<Emitter>::maybeEmitDeferredVarInit(const VarDecl *VD) {
return true;
}
+template <class Emitter>
+bool Compiler<Emitter>::isPunningDereference(const Expr *E)
+{
+ E = E->IgnoreParenImpCasts();
+
+ const auto *UO = dyn_cast<UnaryOperator>(E);
+ if (!UO || UO->getOpcode() != UO_Deref)
+ return false;
+
+ const Expr *Base = UO->getSubExpr()->IgnoreParenImpCasts();
+ const auto *Cast = dyn_cast<CastExpr>(Base);
+ if (!Cast)
+ return false;
+
+ // Only consider reinterpret-ish casts
+ switch (Cast->getCastKind()) {
+ case CK_BitCast:
+ case CK_PointerToIntegral:
+ case CK_IntegralToPointer:
+ case CK_AddressSpaceConversion:
+ break;
+ default:
+ return false; // CK_NoOp etc. are fine
+ }
+
+ QualType DestPtrTy = Cast->getType();
+ QualType SrcPtrTy = Cast->getSubExpr()->getType();
+ if (!DestPtrTy->isPointerType() || !SrcPtrTy->isPointerType())
+ return true; // super fishy, treat it as a pun
+
+ QualType DestPointee = DestPtrTy->getPointeeType();
+ QualType SrcPointee = SrcPtrTy->getPointeeType();
+
+ // If pointee types differ (ignoring qualifiers), its a pun
+ if (!Ctx.getASTContext().hasSameUnqualifiedType(DestPointee, SrcPointee))
+ return true;
+
+ return false;
+}
+
static bool hasTrivialDefaultCtorParent(const FieldDecl *FD) {
assert(FD);
assert(FD->getParent()->isUnion());
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 5c46f75af4da3..2e814fe3e623b 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -423,6 +423,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
bool checkLiteralType(const Expr *E);
bool maybeEmitDeferredVarInit(const VarDecl *VD);
+ bool isPunningDereference(const Expr *E);
+
bool refersToUnion(const Expr *E);
protected:
``````````
</details>
https://github.com/llvm/llvm-project/pull/163809
More information about the cfe-commits
mailing list