https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/164804
We failed to check for null and non-block pointers. Fixes https://github.com/llvm/llvm-project/issues/152952 >From 720b3460dc2852736bfd192059b935dd3ac548b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]> Date: Thu, 23 Oct 2025 13:06:54 +0200 Subject: [PATCH] [clang][bytecode] Catch placement-new into invalid destination We failed to check for null and non-block pointers. Fixes https://github.com/llvm/llvm-project/issues/152952 --- clang/lib/AST/ByteCode/Compiler.cpp | 5 +--- clang/lib/AST/ByteCode/Interp.cpp | 7 ++++++ clang/lib/AST/ByteCode/Opcodes.td | 10 ++------ clang/test/AST/ByteCode/placement-new.cpp | 29 +++++++++++++++++++++++ 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 6b989276e6d7d..228c6f4b11804 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -3600,8 +3600,6 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) { if (PlacementDest) { if (!this->visit(PlacementDest)) return false; - if (!this->emitStartLifetime(E)) - return false; if (!this->emitGetLocal(SizeT, ArrayLen, E)) return false; if (!this->emitCheckNewTypeMismatchArray(SizeT, E, E)) @@ -3741,10 +3739,9 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) { if (PlacementDest) { if (!this->visit(PlacementDest)) return false; - if (!this->emitStartLifetime(E)) - return false; if (!this->emitCheckNewTypeMismatch(E, E)) return false; + } else { // Allocate just one element. if (!this->emitAlloc(Desc, E)) diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index a72282caf5e73..939eefc8d2b67 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1903,9 +1903,16 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E, if (Ptr.inUnion() && Ptr.getBase().getRecord()->isUnion()) Ptr.activate(); + if (Ptr.isZero()) { + S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null) + << AK_Construct; + return false; + } + if (!Ptr.isBlockPointer()) return false; + startLifetimeRecurse(Ptr); // Similar to CheckStore(), but with the additional CheckTemporary() call and // the AccessKinds are different. diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 532c4448e6f40..cc52e06d031a2 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -853,19 +853,13 @@ def Free : Opcode { let Args = [ArgBool, ArgBool]; } -def CheckNewTypeMismatch : Opcode { - let Args = [ArgExpr]; -} - -def InvalidNewDeleteExpr : Opcode { - let Args = [ArgExpr]; -} - +def CheckNewTypeMismatch : Opcode { let Args = [ArgExpr]; } def CheckNewTypeMismatchArray : Opcode { let Types = [IntegerTypeClass]; let Args = [ArgExpr]; let HasGroup = 1; } +def InvalidNewDeleteExpr : Opcode { let Args = [ArgExpr]; } def IsConstantContext: Opcode; def CheckAllocations : Opcode; diff --git a/clang/test/AST/ByteCode/placement-new.cpp b/clang/test/AST/ByteCode/placement-new.cpp index b587cd6eaf89c..1c015da7be54f 100644 --- a/clang/test/AST/ByteCode/placement-new.cpp +++ b/clang/test/AST/ByteCode/placement-new.cpp @@ -494,3 +494,32 @@ constexpr int modify_const_variable() { } static_assert(modify_const_variable()); // both-error {{not an integral constant expression}} \ // both-note {{in call to}} + +constexpr int nullDest() { + new (nullptr) int{12}; // both-note {{construction of dereferenced null pointer}} + return 0; +} +static_assert(nullDest() == 0); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + +constexpr int nullArrayDest() { + new (nullptr) int{12}; // both-note {{construction of dereferenced null pointer}} + return 0; +} +static_assert(nullArrayDest() == 0); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + +constexpr int intDest() { + new ((void*)2) int{3}; // both-note {{cast that performs the conversions of a reinterpret_cast}} + return 0; +} +static_assert(intDest() == 0); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + +constexpr int intDestArray() { + new ((void*)2) int[4]; // both-note {{cast that performs the conversions of a reinterpret_cast}} + return 0; +} +static_assert(intDestArray() == 0); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
