Skip to content

Commit 7c441b2

Browse files
authored
[clang][bytecode] Catch placement-new into invalid destination (#164804)
We failed to check for null and non-block pointers. Fixes #152952
1 parent 57ccb46 commit 7c441b2

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
@@ -3608,8 +3608,6 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
36083608
if (PlacementDest) {
36093609
if (!this->visit(PlacementDest))
36103610
return false;
3611-
if (!this->emitStartLifetime(E))
3612-
return false;
36133611
if (!this->emitGetLocal(SizeT, ArrayLen, E))
36143612
return false;
36153613
if (!this->emitCheckNewTypeMismatchArray(SizeT, E, E))
@@ -3749,10 +3747,9 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
37493747
if (PlacementDest) {
37503748
if (!this->visit(PlacementDest))
37513749
return false;
3752-
if (!this->emitStartLifetime(E))
3753-
return false;
37543750
if (!this->emitCheckNewTypeMismatch(E, E))
37553751
return false;
3752+
37563753
} else {
37573754
// Allocate just one element.
37583755
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
@@ -866,19 +866,13 @@ def Free : Opcode {
866866
let Args = [ArgBool, ArgBool];
867867
}
868868

869-
def CheckNewTypeMismatch : Opcode {
870-
let Args = [ArgExpr];
871-
}
872-
873-
def InvalidNewDeleteExpr : Opcode {
874-
let Args = [ArgExpr];
875-
}
876-
869+
def CheckNewTypeMismatch : Opcode { let Args = [ArgExpr]; }
877870
def CheckNewTypeMismatchArray : Opcode {
878871
let Types = [IntegerTypeClass];
879872
let Args = [ArgExpr];
880873
let HasGroup = 1;
881874
}
875+
def InvalidNewDeleteExpr : Opcode { let Args = [ArgExpr]; }
882876

883877
def IsConstantContext: Opcode;
884878
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)