llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> The pointer needs to point to a record. Fixes https://github.com/llvm/llvm-project/issues/166371 --- Full diff: https://github.com/llvm/llvm-project/pull/167335.diff 6 Files Affected: - (modified) clang/lib/AST/ByteCode/Interp.cpp (+4) - (modified) clang/lib/AST/ByteCode/Interp.h (+8-4) - (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+6-4) - (modified) clang/lib/AST/ByteCode/Opcodes.td (+16-4) - (modified) clang/lib/AST/ByteCode/Pointer.h (+16-11) - (modified) clang/test/AST/ByteCode/invalid.cpp (+4) ``````````diff diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 1f2ae92f6068b..280911c324bb1 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -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; diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index cbd60c9f2b37c..3ff6ed6eb68d5 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -2318,12 +2318,13 @@ 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(); 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; @@ -2332,11 +2333,14 @@ 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>(); + Pointer Ptr = S.Stk.pop<Pointer>(); + + if (Ptr.isBlockPointer()) + Ptr = Ptr.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; @@ -3191,7 +3195,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; } diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 0ef130c0a55df..664d98b7e0390 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -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); @@ -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; } @@ -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"); @@ -1910,6 +1910,8 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC, } } + // SrcPtr = SrcPtr.expand(); + assert(Size.getZExtValue() % DestElemSize == 0); if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size.getZExtValue()).toBits())) return false; diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 1785fcf4a7b20..8818579f020ea 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -361,8 +361,14 @@ def NarrowPtr : Opcode; // [Pointer] -> [Pointer] def ExpandPtr : Opcode; // [Pointer, Offset] -> [Pointer] -def ArrayElemPtr : AluOpcode; -def ArrayElemPtrPop : AluOpcode; +def ArrayElemPtr : Opcode { + let Types = [IntegralTypeClass]; + let HasGroup = 1; +} +def ArrayElemPtrPop : Opcode { + let Types = [IntegralTypeClass]; + let HasGroup = 1; +} def ArrayElemPop : Opcode { let Args = [ArgUint32]; @@ -536,9 +542,15 @@ def InitElemPop : Opcode { //===----------------------------------------------------------------------===// // [Pointer, Integral] -> [Pointer] -def AddOffset : AluOpcode; +def AddOffset : Opcode { + let Types = [IntegralTypeClass]; + let HasGroup = 1; +} // [Pointer, Integral] -> [Pointer] -def SubOffset : AluOpcode; +def SubOffset : Opcode { + let Types = [IntegralTypeClass]; + let HasGroup = 1; +} // [Pointer, Pointer] -> [Integral] def SubPtr : Opcode { diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index cd738ce8b2a3e..0f5de4f6c72b6 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -199,17 +199,20 @@ 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) - return Pointer(BS.Pointee, Offset, Offset); + 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. + if (Offset != Base) + return Pointer(BS.Pointee, Offset, Offset); + } } // Otherwise, we're pointing to a non-array element or @@ -219,6 +222,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; diff --git a/clang/test/AST/ByteCode/invalid.cpp b/clang/test/AST/ByteCode/invalid.cpp index 115c8663079a1..6b49cc44d64df 100644 --- a/clang/test/AST/ByteCode/invalid.cpp +++ b/clang/test/AST/ByteCode/invalid.cpp @@ -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; } `````````` </details> https://github.com/llvm/llvm-project/pull/167335 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
