https://github.com/cakgok updated https://github.com/llvm/llvm-project/pull/195741
>From 26357ddf1a56f4fe62567b4ea271f939df23376d Mon Sep 17 00:00:00 2001 From: Cem <[email protected]> Date: Mon, 4 May 2026 23:13:10 +0300 Subject: [PATCH 1/2] [Clang][ByteCode] Fix stack corruption in builtin delete handler --- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 12 ++++++++++++ clang/test/AST/ByteCode/new-delete.cpp | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 77ea83605cc16..8fdedd4f783ba 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1633,6 +1633,18 @@ static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC, const Expr *Source = nullptr; const Block *BlockToDelete = nullptr; + assert(Call->getNumArgs() >= 1); + unsigned NumArgs = Call->getNumArgs(); + + // The std::nothrow_t argument never put on the stack. + if (Call->getArg(NumArgs - 1)->getType()->isNothrowT()) + --NumArgs; + + // Args are pushed in source order. The trailing sized/aligned delete + // operands are above the pointer on the stack. + for (unsigned I = NumArgs; I > 1; --I) + discard(S.Stk, *S.getContext().classify(Call->getArg(I - 1))); + if (S.checkingPotentialConstantExpression()) { S.Stk.discard<Pointer>(); return false; diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp index 4ade50b7c02e4..ac2c2ff4a73c6 100644 --- a/clang/test/AST/ByteCode/new-delete.cpp +++ b/clang/test/AST/ByteCode/new-delete.cpp @@ -643,6 +643,9 @@ namespace std { // both-note {{used to delete a null pointer}} \ // both-note {{delete of pointer '&no_deallocate_nonalloc' that does not point to a heap-allocated object}} } + constexpr void deallocate(void *p, size_t N) { + __builtin_operator_delete(p, sizeof(T) * N); + } }; template<typename T, typename ...Args> constexpr void construct_at(void *p, Args &&...args) { // #construct @@ -767,6 +770,13 @@ namespace OperatorNewDelete { // both-note {{in call}} static_assert((std::allocator<float>().deallocate(std::allocator<float>().allocate(10)), 1) == 1); + + constexpr bool sizedDeallocate() { + int *p = std::allocator<int>().allocate(1); + std::allocator<int>().deallocate(p, 1); + return true; + } + static_assert(sizedDeallocate()); } namespace Limits { >From c3109d979a3c87425f8cd44a37f012d301b3a7df Mon Sep 17 00:00:00 2001 From: cakgok <[email protected]> Date: Tue, 5 May 2026 09:41:24 +0300 Subject: [PATCH 2/2] Update clang/lib/AST/ByteCode/InterpBuiltin.cpp Co-authored-by: Timm Baeder <[email protected]> --- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 8fdedd4f783ba..56d93363226e5 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1643,7 +1643,7 @@ static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC, // Args are pushed in source order. The trailing sized/aligned delete // operands are above the pointer on the stack. for (unsigned I = NumArgs; I > 1; --I) - discard(S.Stk, *S.getContext().classify(Call->getArg(I - 1))); + discard(S.Stk, *S.getContext().classify(Call->getArg(I))); if (S.checkingPotentialConstantExpression()) { S.Stk.discard<Pointer>(); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
