Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions clang/lib/AST/ByteCode/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1448,6 +1448,10 @@ static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return false;
}

// We can't get the field of something that's not a record.
if (!Ptr.getFieldDesc()->isRecord())
return false;

if ((Ptr.getByteOffset() + Off) >= Ptr.block()->getSize())
return false;

Expand Down
22 changes: 10 additions & 12 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -2317,13 +2317,11 @@ std::optional<Pointer> OffsetHelper(InterpState &S, CodePtr OpPC,
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool AddOffset(InterpState &S, CodePtr OpPC) {
const T &Offset = S.Stk.pop<T>();
Pointer Ptr = S.Stk.pop<Pointer>();
if (Ptr.isBlockPointer())
Ptr = Ptr.expand();
const Pointer &Ptr = S.Stk.pop<Pointer>().expand();

if (std::optional<Pointer> Result = OffsetHelper<T, ArithOp::Add>(
S, OpPC, Offset, Ptr, /*IsPointerArith=*/true)) {
S.Stk.push<Pointer>(*Result);
S.Stk.push<Pointer>(Result->narrow());
return true;
}
return false;
Expand All @@ -2332,11 +2330,11 @@ bool AddOffset(InterpState &S, CodePtr OpPC) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool SubOffset(InterpState &S, CodePtr OpPC) {
const T &Offset = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.pop<Pointer>();
const Pointer &Ptr = S.Stk.pop<Pointer>().expand();

if (std::optional<Pointer> Result = OffsetHelper<T, ArithOp::Sub>(
S, OpPC, Offset, Ptr, /*IsPointerArith=*/true)) {
S.Stk.push<Pointer>(*Result);
S.Stk.push<Pointer>(Result->narrow());
return true;
}
return false;
Expand All @@ -2362,7 +2360,7 @@ static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC,
if (std::optional<Pointer> Result =
OffsetHelper<OneT, Op>(S, OpPC, One, P, /*IsPointerArith=*/true)) {
// Store the new value.
Ptr.deref<Pointer>() = *Result;
Ptr.deref<Pointer>() = Result->narrow();
return true;
}
return false;
Expand Down Expand Up @@ -2391,8 +2389,8 @@ static inline bool DecPtr(InterpState &S, CodePtr OpPC) {
/// 3) Pushes the difference of the indices of the two pointers on the stack.
template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool SubPtr(InterpState &S, CodePtr OpPC, bool ElemSizeIsZero) {
const Pointer &LHS = S.Stk.pop<Pointer>();
const Pointer &RHS = S.Stk.pop<Pointer>();
const Pointer &LHS = S.Stk.pop<Pointer>().expand();
const Pointer &RHS = S.Stk.pop<Pointer>().expand();

if (!Pointer::hasSameBase(LHS, RHS) && S.getLangOpts().CPlusPlus) {
S.FFDiag(S.Current->getSource(OpPC),
Expand Down Expand Up @@ -3083,7 +3081,7 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
S.Stk.push<Pointer>(Ptr.atIndex(0).narrow());
return true;
}
S.Stk.push<Pointer>(Ptr);
S.Stk.push<Pointer>(Ptr.narrow());
return true;
}

Expand Down Expand Up @@ -3114,7 +3112,7 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
S.Stk.push<Pointer>(Ptr.atIndex(0).narrow());
return true;
}
S.Stk.push<Pointer>(Ptr);
S.Stk.push<Pointer>(Ptr.narrow());
return true;
}

Expand Down Expand Up @@ -3189,7 +3187,7 @@ inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
}

if (Ptr.isRoot() || !Ptr.isUnknownSizeArray()) {
S.Stk.push<Pointer>(Ptr.atIndex(0));
S.Stk.push<Pointer>(Ptr.atIndex(0).narrow());
return true;
}

Expand Down
8 changes: 4 additions & 4 deletions clang/lib/AST/ByteCode/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call, unsigned ID) {
const Pointer &StrPtr = S.Stk.pop<Pointer>();
const Pointer &StrPtr = S.Stk.pop<Pointer>().expand();

if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen)
diagnoseNonConstexprBuiltin(S, OpPC, ID);
Expand Down Expand Up @@ -1439,7 +1439,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
Allocator.allocate(Desc, NumElems.getZExtValue(), S.Ctx.getEvalID(),
DynamicAllocator::Form::Operator);
assert(B);
S.Stk.push<Pointer>(Pointer(B).atIndex(0));
S.Stk.push<Pointer>(Pointer(B).atIndex(0).narrow());
return true;
}

Expand Down Expand Up @@ -1763,8 +1763,8 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
assert(Call->getNumArgs() == 3);
const ASTContext &ASTCtx = S.getASTContext();
APSInt Size = popToAPSInt(S, Call->getArg(2));
const Pointer SrcPtr = S.Stk.pop<Pointer>();
const Pointer DestPtr = S.Stk.pop<Pointer>();
Pointer SrcPtr = S.Stk.pop<Pointer>().expand();
Pointer DestPtr = S.Stk.pop<Pointer>().expand();

assert(!Size.isSigned() && "memcpy and friends take an unsigned size");

Expand Down
24 changes: 14 additions & 10 deletions clang/lib/AST/ByteCode/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,17 +199,19 @@ class Pointer {
return Pointer(BS.Pointee, sizeof(InlineDescriptor),
Offset == 0 ? Offset : PastEndMark);

// Pointer is one past end - magic offset marks that.
if (isOnePastEnd())
return Pointer(BS.Pointee, Base, PastEndMark);

if (Offset != Base) {
// If we're pointing to a primitive array element, there's nothing to do.
if (inPrimitiveArray())
return *this;
// Pointer is to a composite array element - enter it.
if (Offset != Base)
if (inArray()) {
// Pointer is one past end - magic offset marks that.
if (isOnePastEnd())
return Pointer(BS.Pointee, Base, PastEndMark);

if (Offset != Base) {
// If we're pointing to a primitive array element, there's nothing to
// do.
if (inPrimitiveArray())
return *this;
// Pointer is to a composite array element - enter it.
return Pointer(BS.Pointee, Offset, Offset);
}
}

// Otherwise, we're pointing to a non-array element or
Expand All @@ -219,6 +221,8 @@ class Pointer {

/// Expands a pointer to the containing array, undoing narrowing.
[[nodiscard]] Pointer expand() const {
if (!isBlockPointer())
return *this;
assert(isBlockPointer());
Block *Pointee = BS.Pointee;

Expand Down
24 changes: 24 additions & 0 deletions clang/test/AST/ByteCode/cxx23.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,3 +449,27 @@ namespace VolatileWrites {
static_assert(test7(12)); // all-error {{not an integral constant expression}} \
// all-note {{in call to}}
}

namespace AIEWithIndex0Narrows {
template <class _Tp> struct greater {
constexpr void operator()(_Tp, _Tp) {}
};
struct S {
constexpr S() : i_() {}
int i_;
};

constexpr void sort(S *__first) {
for (int __start = 0; __start >= 0; --__start) {
greater<S>{}(__first[0], __first[0]);
}
}
constexpr bool test() {
S *ia = new S[2];

sort(ia + 1);
delete[] ia;
return true;
}
static_assert(test());
}
4 changes: 4 additions & 0 deletions clang/test/AST/ByteCode/invalid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,8 @@ namespace InvalidBitCast {
return ((sockaddr_in *)&addr)->sin_addr.s_addr;
}


struct s { int a; int b[1]; };
struct s myx;
int *myy = ((struct s *)&myx.a)->b;
}
Loading