Skip to content

Commit 4fd12c2

Browse files
committed
[clang][bytecode] Check for unknown size array pointers in InitField*
This can happen when the base pointer is an unknown size array, where !isOnePastEnd(), but isPastEnd(). Fixes #153990
1 parent e16ced3 commit 4fd12c2

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

clang/lib/AST/ByteCode/Interp.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,9 @@ bool InitField(InterpState &S, CodePtr OpPC, uint32_t I) {
16401640
const Pointer &Ptr = S.Stk.peek<Pointer>();
16411641
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
16421642
return false;
1643+
if (!CheckArray(S, OpPC, Ptr))
1644+
return false;
1645+
16431646
const Pointer &Field = Ptr.atField(I);
16441647
Field.deref<T>() = Value;
16451648
Field.initialize();
@@ -1652,6 +1655,9 @@ bool InitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t I) {
16521655
const Pointer &Ptr = S.Stk.peek<Pointer>();
16531656
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
16541657
return false;
1658+
if (!CheckArray(S, OpPC, Ptr))
1659+
return false;
1660+
16551661
const Pointer &Field = Ptr.atField(I);
16561662
Field.deref<T>() = Value;
16571663
Field.activate();
@@ -1663,7 +1669,13 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
16631669
bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
16641670
assert(F->isBitField());
16651671
const T &Value = S.Stk.pop<T>();
1666-
const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset);
1672+
const Pointer &Ptr = S.Stk.peek<Pointer>();
1673+
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
1674+
return false;
1675+
if (!CheckArray(S, OpPC, Ptr))
1676+
return false;
1677+
1678+
const Pointer &Field = Ptr.atField(F->Offset);
16671679

16681680
if constexpr (needsAlloc<T>()) {
16691681
T Result = S.allocAP<T>(Value.bitWidth());
@@ -1689,7 +1701,13 @@ bool InitBitFieldActivate(InterpState &S, CodePtr OpPC,
16891701
const Record::Field *F) {
16901702
assert(F->isBitField());
16911703
const T &Value = S.Stk.pop<T>();
1692-
const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset);
1704+
const Pointer &Ptr = S.Stk.peek<Pointer>();
1705+
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
1706+
return false;
1707+
if (!CheckArray(S, OpPC, Ptr))
1708+
return false;
1709+
1710+
const Pointer &Field = Ptr.atField(F->Offset);
16931711

16941712
if constexpr (needsAlloc<T>()) {
16951713
T Result = S.allocAP<T>(Value.bitWidth());

clang/test/AST/ByteCode/arrays.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,3 +800,23 @@ namespace ZeroSizeArrayRead {
800800
static_assert(s[0] == '0', ""); // both-error {{not an integral constant expression}} \
801801
// both-note {{read of dereferenced one-past-the-end pointer}}
802802
}
803+
804+
namespace FAM {
805+
char *strchr(const char *, int);
806+
807+
struct A {
808+
char n, a[2];
809+
};
810+
struct B {
811+
int n;
812+
struct A a[]; // both-note {{here}}
813+
};
814+
815+
const struct B b = {0, {{1, {2, 3}}, {4, {5, 6}}}};
816+
void foo(void) { int sch = 0 != strchr(b.a[1].a, '\0'); }
817+
818+
int foo2() {
819+
struct B b = {0, {{1, {2, 3}}, {4, {5, 6}}}}; // both-error {{initialization of flexible array member is not allowed}}
820+
return 1;
821+
}
822+
}

0 commit comments

Comments
 (0)