Skip to content

Commit 3b150fb

Browse files
authored
[clang][bytecode] Handle negative array sizes in constexpr new instead of asserting (#155737)
This patch fixes a crash in the constexpr interpreter when evaluating `new T[n]` with a negative element count. Fixes #152904
1 parent 868e596 commit 3b150fb

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

clang/lib/AST/ByteCode/Interp.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3490,7 +3490,15 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source,
34903490
S.Stk.push<Pointer>(0, nullptr);
34913491
return true;
34923492
}
3493-
assert(NumElements.isPositive());
3493+
if (NumElements.isNegative()) {
3494+
if (!IsNoThrow) {
3495+
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_negative)
3496+
<< NumElements.toDiagnosticString(S.getASTContext());
3497+
return false;
3498+
}
3499+
S.Stk.push<Pointer>(0, nullptr);
3500+
return true;
3501+
}
34943502

34953503
if (!CheckArraySize(S, OpPC, static_cast<uint64_t>(NumElements)))
34963504
return false;

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,28 @@ namespace BaseCompare {
10691069
static_assert(foo());
10701070
}
10711071

1072+
1073+
namespace NegativeArraySize {
1074+
constexpr void f() { // both-error {{constexpr function never produces a constant expression}}
1075+
int x = -1;
1076+
int *p = new int[x]; //both-note {{cannot allocate array; evaluated array bound -1 is negative}}
1077+
}
1078+
} // namespace NegativeArraySize
1079+
1080+
namespace NewNegSizeNothrow {
1081+
constexpr int get_neg_size() {
1082+
return -1;
1083+
}
1084+
1085+
constexpr bool test_nothrow_neg_size() {
1086+
int x = get_neg_size();
1087+
int* p = new (std::nothrow) int[x];
1088+
return p == nullptr;
1089+
}
1090+
1091+
static_assert(test_nothrow_neg_size(), "expected nullptr");
1092+
} // namespace NewNegSizeNothrow
1093+
10721094
#else
10731095
/// Make sure we reject this prior to C++20
10741096
constexpr int a() { // both-error {{never produces a constant expression}}

0 commit comments

Comments
 (0)