Author: Timm Bäder Date: 2023-09-05T11:00:40+02:00 New Revision: a13f036949b05e5f9d1ac1e33fed465c939aca62
URL: https://github.com/llvm/llvm-project/commit/a13f036949b05e5f9d1ac1e33fed465c939aca62 DIFF: https://github.com/llvm/llvm-project/commit/a13f036949b05e5f9d1ac1e33fed465c939aca62.diff LOG: [clang][Interp] Check one-past-the-end pointers in GetPtrField 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 Added: Modified: clang/lib/AST/Interp/Interp.cpp clang/lib/AST/Interp/Interp.h clang/test/AST/Interp/records.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 23c54b3898e102..719a96daaebdd7 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -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; diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 006abc0f0e94ac..b87a5c1cbd0e48 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -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); @@ -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; } @@ -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; @@ -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; @@ -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; diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index b559f1f8b95b0a..2b79ec8be0311d 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -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 { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits