[clang] [clang][bytecode] Check for unknown size array pointers in InitField* (PR #154689)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 21 00:53:35 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
This can happen when the base pointer is an unknown size array, where !isOnePastEnd(), but isPastEnd().
Fixes #<!-- -->153990
---
Full diff: https://github.com/llvm/llvm-project/pull/154689.diff
2 Files Affected:
- (modified) clang/lib/AST/ByteCode/Interp.h (+20-2)
- (modified) clang/test/AST/ByteCode/arrays.cpp (+20)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 149ce3b1042db..86fca7f652a47 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -1640,6 +1640,9 @@ bool InitField(InterpState &S, CodePtr OpPC, uint32_t I) {
const Pointer &Ptr = S.Stk.peek<Pointer>();
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
return false;
+ if (!CheckArray(S, OpPC, Ptr))
+ return false;
+
const Pointer &Field = Ptr.atField(I);
Field.deref<T>() = Value;
Field.initialize();
@@ -1652,6 +1655,9 @@ bool InitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t I) {
const Pointer &Ptr = S.Stk.peek<Pointer>();
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
return false;
+ if (!CheckArray(S, OpPC, Ptr))
+ return false;
+
const Pointer &Field = Ptr.atField(I);
Field.deref<T>() = Value;
Field.activate();
@@ -1663,7 +1669,13 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
assert(F->isBitField());
const T &Value = S.Stk.pop<T>();
- const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset);
+ const Pointer &Ptr = S.Stk.peek<Pointer>();
+ if (!CheckRange(S, OpPC, Ptr, CSK_Field))
+ return false;
+ if (!CheckArray(S, OpPC, Ptr))
+ return false;
+
+ const Pointer &Field = Ptr.atField(F->Offset);
if constexpr (needsAlloc<T>()) {
T Result = S.allocAP<T>(Value.bitWidth());
@@ -1689,7 +1701,13 @@ bool InitBitFieldActivate(InterpState &S, CodePtr OpPC,
const Record::Field *F) {
assert(F->isBitField());
const T &Value = S.Stk.pop<T>();
- const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset);
+ const Pointer &Ptr = S.Stk.peek<Pointer>();
+ if (!CheckRange(S, OpPC, Ptr, CSK_Field))
+ return false;
+ if (!CheckArray(S, OpPC, Ptr))
+ return false;
+
+ const Pointer &Field = Ptr.atField(F->Offset);
if constexpr (needsAlloc<T>()) {
T Result = S.allocAP<T>(Value.bitWidth());
diff --git a/clang/test/AST/ByteCode/arrays.cpp b/clang/test/AST/ByteCode/arrays.cpp
index 68102b42f3820..22a4b41041eb3 100644
--- a/clang/test/AST/ByteCode/arrays.cpp
+++ b/clang/test/AST/ByteCode/arrays.cpp
@@ -800,3 +800,23 @@ namespace ZeroSizeArrayRead {
static_assert(s[0] == '0', ""); // both-error {{not an integral constant expression}} \
// both-note {{read of dereferenced one-past-the-end pointer}}
}
+
+namespace FAM {
+ char *strchr(const char *, int);
+
+ struct A {
+ char n, a[2];
+ };
+ struct B {
+ int n;
+ struct A a[]; // both-note {{here}}
+ };
+
+ const struct B b = {0, {{1, {2, 3}}, {4, {5, 6}}}};
+ void foo(void) { int sch = 0 != strchr(b.a[1].a, '\0'); }
+
+ int foo2() {
+ struct B b = {0, {{1, {2, 3}}, {4, {5, 6}}}}; // both-error {{initialization of flexible array member is not allowed}}
+ return 1;
+ }
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/154689
More information about the cfe-commits
mailing list