Skip to content

Commit bd82225

Browse files
committed
[clang][bytecode] Catch placement-new into invalid destination
We failed to check for null and non-block pointers. Fixes #152952
1 parent 655de70 commit bd82225

File tree

4 files changed

+40
-13
lines changed

4 files changed

+40
-13
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3600,8 +3600,6 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
36003600
if (PlacementDest) {
36013601
if (!this->visit(PlacementDest))
36023602
return false;
3603-
if (!this->emitStartLifetime(E))
3604-
return false;
36053603
if (!this->emitGetLocal(SizeT, ArrayLen, E))
36063604
return false;
36073605
if (!this->emitCheckNewTypeMismatchArray(SizeT, E, E))
@@ -3741,10 +3739,9 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
37413739
if (PlacementDest) {
37423740
if (!this->visit(PlacementDest))
37433741
return false;
3744-
if (!this->emitStartLifetime(E))
3745-
return false;
37463742
if (!this->emitCheckNewTypeMismatch(E, E))
37473743
return false;
3744+
37483745
} else {
37493746
// Allocate just one element.
37503747
if (!this->emitAlloc(Desc, E))

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1903,12 +1903,19 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
19031903
if (Ptr.inUnion() && Ptr.getBase().getRecord()->isUnion())
19041904
Ptr.activate();
19051905

1906+
if (Ptr.isZero()) {
1907+
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)
1908+
<< AK_Construct;
1909+
return false;
1910+
}
1911+
19061912
if (!Ptr.isBlockPointer())
19071913
return false;
19081914

1915+
startLifetimeRecurse(Ptr);
1916+
19091917
// Similar to CheckStore(), but with the additional CheckTemporary() call and
19101918
// the AccessKinds are different.
1911-
19121919
if (!Ptr.block()->isAccessible()) {
19131920
if (!CheckExtern(S, OpPC, Ptr))
19141921
return false;

clang/lib/AST/ByteCode/Opcodes.td

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -853,19 +853,13 @@ def Free : Opcode {
853853
let Args = [ArgBool, ArgBool];
854854
}
855855

856-
def CheckNewTypeMismatch : Opcode {
857-
let Args = [ArgExpr];
858-
}
859-
860-
def InvalidNewDeleteExpr : Opcode {
861-
let Args = [ArgExpr];
862-
}
863-
856+
def CheckNewTypeMismatch : Opcode { let Args = [ArgExpr]; }
864857
def CheckNewTypeMismatchArray : Opcode {
865858
let Types = [IntegerTypeClass];
866859
let Args = [ArgExpr];
867860
let HasGroup = 1;
868861
}
862+
def InvalidNewDeleteExpr : Opcode { let Args = [ArgExpr]; }
869863

870864
def IsConstantContext: Opcode;
871865
def CheckAllocations : Opcode;

clang/test/AST/ByteCode/placement-new.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,3 +494,32 @@ constexpr int modify_const_variable() {
494494
}
495495
static_assert(modify_const_variable()); // both-error {{not an integral constant expression}} \
496496
// both-note {{in call to}}
497+
498+
constexpr int nullDest() {
499+
new (nullptr) int{12}; // both-note {{construction of dereferenced null pointer}}
500+
return 0;
501+
}
502+
static_assert(nullDest() == 0); // both-error {{not an integral constant expression}} \
503+
// both-note {{in call to}}
504+
505+
constexpr int nullArrayDest() {
506+
new (nullptr) int{12}; // both-note {{construction of dereferenced null pointer}}
507+
return 0;
508+
}
509+
static_assert(nullArrayDest() == 0); // both-error {{not an integral constant expression}} \
510+
// both-note {{in call to}}
511+
512+
constexpr int intDest() {
513+
new ((void*)2) int{3}; // both-note {{cast that performs the conversions of a reinterpret_cast}}
514+
return 0;
515+
}
516+
static_assert(intDest() == 0); // both-error {{not an integral constant expression}} \
517+
// both-note {{in call to}}
518+
519+
constexpr int intDestArray() {
520+
new ((void*)2) int[4]; // both-note {{cast that performs the conversions of a reinterpret_cast}}
521+
return 0;
522+
}
523+
static_assert(intDestArray() == 0); // both-error {{not an integral constant expression}} \
524+
// both-note {{in call to}}
525+

0 commit comments

Comments
 (0)