[clang] [clang][bytecode] Check pointer types in ::toRValue() (PR #206712)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 30 04:34:48 PDT 2026
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/206712
Now that we let more reinterpret_casts through, we need to check we have the proper type here, too. We already did that for some of the types but not for records and arrays.
>From 8a4b1440a38c367204e37cac5118a109de5b2e62 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Tue, 30 Jun 2026 13:19:21 +0200
Subject: [PATCH] [clang][bytecode] Check pointer types in ::toRValue()
Now that we let more reinterpret_casts through, we need to check we have
the proper type here, too. We already did that for some of the types but
not for records and arrays.
---
clang/lib/AST/ByteCode/Pointer.cpp | 24 ++++++++++++++----------
clang/test/AST/ByteCode/codegen.cpp | 9 +++++++++
2 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp
index 37659eb79e1df..4eb6df2f0d6a1 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -915,8 +915,12 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
// Primitives should never end up here.
assert(!Ctx.canClassify(Ty));
+ const Descriptor *FieldDesc = Ptr.getFieldDesc();
+ assert(FieldDesc);
if (const auto *RT = Ty->getAsCanonical<RecordType>()) {
+ if (!FieldDesc->isRecord())
+ return false;
const auto *Record = Ptr.getRecord();
assert(Record && "Missing record descriptor");
@@ -986,6 +990,8 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
}
if (const auto *AT = Ty->getAsArrayTypeUnsafe()) {
+ if (!FieldDesc->isArray())
+ return false;
const size_t NumElems = Ptr.getNumElems();
QualType ElemTy = AT->getElementType();
R = APValue(APValue::UninitArray{}, NumElems, NumElems);
@@ -1005,14 +1011,12 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
// Complex types.
if (Ty->isAnyComplexType()) {
- const Descriptor *Desc = Ptr.getFieldDesc();
// Can happen via C casts.
- if (!Desc->getType()->isAnyComplexType())
+ if (!FieldDesc->getType()->isAnyComplexType())
return false;
- PrimType ElemT = Desc->getPrimType();
+ PrimType ElemT = FieldDesc->getPrimType();
if (isIntegerOrBoolType(ElemT)) {
- PrimType ElemT = Desc->getPrimType();
INT_TYPE_SWITCH(ElemT, {
auto V1 = Ptr.elem<T>(0);
auto V2 = Ptr.elem<T>(1);
@@ -1029,10 +1033,10 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
// Vector types.
if (const auto *VT = Ty->getAs<VectorType>()) {
- const Descriptor *Desc = Ptr.getFieldDesc();
- assert(Ptr.getFieldDesc()->isPrimitiveArray());
- PrimType ElemT = Desc->getPrimType();
+ if (!FieldDesc->isPrimitiveArray())
+ return false;
+ PrimType ElemT = FieldDesc->getPrimType();
SmallVector<APValue> Values;
Values.reserve(VT->getNumElements());
for (unsigned I = 0; I != VT->getNumElements(); ++I) {
@@ -1047,9 +1051,9 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
// Constant Matrix types.
if (const auto *MT = Ty->getAs<ConstantMatrixType>()) {
- assert(Ptr.getFieldDesc()->isPrimitiveArray());
- const Descriptor *Desc = Ptr.getFieldDesc();
- PrimType ElemT = Desc->getPrimType();
+ if (!FieldDesc->isPrimitiveArray())
+ return false;
+ PrimType ElemT = FieldDesc->getPrimType();
unsigned NumElems = MT->getNumElementsFlattened();
SmallVector<APValue> Values;
diff --git a/clang/test/AST/ByteCode/codegen.cpp b/clang/test/AST/ByteCode/codegen.cpp
index 53698f13a17a2..385b9a1338d91 100644
--- a/clang/test/AST/ByteCode/codegen.cpp
+++ b/clang/test/AST/ByteCode/codegen.cpp
@@ -151,3 +151,12 @@ X test24() {
/// Used to crash in codegen because the cast worked.
auto MemcpySemantics = *(_Complex double *)&(float[2]){};
+
+namespace InvalidReinterpretCast {
+ struct X {};
+ const X &_S_ti() {
+ constexpr char __tag{};
+ // CHECK: ret ptr %__tag
+ return reinterpret_cast<const X &>(__tag);
+ }
+}
More information about the cfe-commits
mailing list