Skip to content

Commit

Permalink
[clang][Interp] Check one-past-the-end pointers in GetPtrField
Browse files Browse the repository at this point in the history
Rename CheckBaseDerived to something more general and call it in
GetPtrField() as well, so we don't crash later in Pointer::toAPValue().

Differential Revision: https://reviews.llvm.org/D149149
  • Loading branch information
tbaederr committed Sep 5, 2023
1 parent a21a0a6 commit a13f036
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 8 deletions.
4 changes: 2 additions & 2 deletions clang/lib/AST/Interp/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return false;
}

bool CheckBaseDerived(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
CheckSubobjectKind CSK) {
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
CheckSubobjectKind CSK) {
if (!Ptr.isOnePastEnd())
return true;

Expand Down
15 changes: 9 additions & 6 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
CheckSubobjectKind CSK);

/// Checks if accessing a base or derived record of the given pointer is valid.
bool CheckBaseDerived(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
CheckSubobjectKind CSK);
/// Checks if Ptr is a one-past-the-end pointer.
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
CheckSubobjectKind CSK);

/// Checks if a pointer points to const storage.
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
Expand Down Expand Up @@ -1121,6 +1121,9 @@ inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
return false;
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
return false;
if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
return false;

S.Stk.push<Pointer>(Ptr.atField(Off));
return true;
}
Expand Down Expand Up @@ -1165,7 +1168,7 @@ inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
const Pointer &Ptr = S.Stk.pop<Pointer>();
if (!CheckNull(S, OpPC, Ptr, CSK_Derived))
return false;
if (!CheckBaseDerived(S, OpPC, Ptr, CSK_Derived))
if (!CheckSubobject(S, OpPC, Ptr, CSK_Derived))
return false;
S.Stk.push<Pointer>(Ptr.atFieldSub(Off));
return true;
Expand All @@ -1175,7 +1178,7 @@ inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
const Pointer &Ptr = S.Stk.peek<Pointer>();
if (!CheckNull(S, OpPC, Ptr, CSK_Base))
return false;
if (!CheckBaseDerived(S, OpPC, Ptr, CSK_Base))
if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
return false;
S.Stk.push<Pointer>(Ptr.atField(Off));
return true;
Expand All @@ -1185,7 +1188,7 @@ inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off) {
const Pointer &Ptr = S.Stk.pop<Pointer>();
if (!CheckNull(S, OpPC, Ptr, CSK_Base))
return false;
if (!CheckBaseDerived(S, OpPC, Ptr, CSK_Base))
if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
return false;
S.Stk.push<Pointer>(Ptr.atField(Off));
return true;
Expand Down
23 changes: 23 additions & 0 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,29 @@ namespace DeclRefs {
//static_assert(b.a.f == 100, "");
}

namespace PointerArith {
struct A {};
struct B : A { int n; };

B b = {};
constexpr A *a1 = &b;
constexpr B *b1 = &b + 1;
constexpr B *b2 = &b + 0;

#if 0
constexpr A *a2 = &b + 1; // expected-error {{must be initialized by a constant expression}} \
// expected-note {{cannot access base class of pointer past the end of object}} \
// ref-error {{must be initialized by a constant expression}} \
// ref-note {{cannot access base class of pointer past the end of object}}

#endif
constexpr const int *pn = &(&b + 1)->n; // expected-error {{must be initialized by a constant expression}} \
// expected-note {{cannot access field of pointer past the end of object}} \
// ref-error {{must be initialized by a constant expression}} \
// ref-note {{cannot access field of pointer past the end of object}}

}

#if __cplusplus >= 202002L
namespace VirtualCalls {
namespace Obvious {
Expand Down

0 comments on commit a13f036

Please sign in to comment.