Skip to content

Commit 898fd39

Browse files
authored
[clang][bytecode] Check allocation size limit for operator new (#109590)
1 parent c8e0672 commit 898fd39

File tree

3 files changed

+50
-4
lines changed

3 files changed

+50
-4
lines changed

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1306,7 +1306,16 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
13061306
return false;
13071307
}
13081308

1309-
// FIXME: CheckArraySize for NumElems?
1309+
// NB: The same check we're using in CheckArraySize()
1310+
if (NumElems.getActiveBits() >
1311+
ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||
1312+
NumElems.ugt(Descriptor::MaxArrayElemBytes / ElemSize.getQuantity())) {
1313+
// FIXME: NoThrow check?
1314+
const SourceInfo &Loc = S.Current->getSource(OpPC);
1315+
S.FFDiag(Loc, diag::note_constexpr_new_too_large)
1316+
<< NumElems.getZExtValue();
1317+
return false;
1318+
}
13101319

13111320
std::optional<PrimType> ElemT = S.getContext().classify(ElemType);
13121321
DynamicAllocator &Allocator = S.getAllocator();

clang/lib/AST/ByteCode/InterpFrame.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,26 @@ static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx,
102102
V.toAPValue(ASTCtx).printPretty(OS, ASTCtx, Ty);
103103
}
104104

105+
static bool shouldSkipInBacktrace(const Function *F) {
106+
if (F->isBuiltin())
107+
return true;
108+
if (F->isLambdaStaticInvoker())
109+
return true;
110+
111+
const FunctionDecl *FD = F->getDecl();
112+
if (FD->getDeclName().getCXXOverloadedOperator() == OO_New ||
113+
FD->getDeclName().getCXXOverloadedOperator() == OO_Array_New)
114+
return true;
115+
return false;
116+
}
117+
105118
void InterpFrame::describe(llvm::raw_ostream &OS) const {
106119
// We create frames for builtin functions as well, but we can't reliably
107120
// diagnose them. The 'in call to' diagnostics for them add no value to the
108121
// user _and_ it doesn't generally work since the argument types don't always
109122
// match the function prototype. Just ignore them.
110123
// Similarly, for lambda static invokers, we would just print __invoke().
111-
if (const auto *F = getFunction();
112-
F && (F->isBuiltin() || F->isLambdaStaticInvoker()))
124+
if (const auto *F = getFunction(); F && shouldSkipInBacktrace(F))
113125
return;
114126

115127
const Expr *CallExpr = Caller->getExpr(getRetPC());

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

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,8 @@ namespace std {
592592
using size_t = decltype(sizeof(0));
593593
template<typename T> struct allocator {
594594
constexpr T *allocate(size_t N) {
595-
return (T*)__builtin_operator_new(sizeof(T) * N); // both-note 2{{allocation performed here}}
595+
return (T*)__builtin_operator_new(sizeof(T) * N); // both-note 2{{allocation performed here}} \
596+
// #alloc
596597
}
597598
constexpr void deallocate(void *p) {
598599
__builtin_operator_delete(p); // both-note 2{{std::allocator<...>::deallocate' used to delete pointer to object allocated with 'new'}} \
@@ -731,6 +732,30 @@ namespace Limits {
731732
return n;
732733
}
733734
static_assert(dynarray<char>(5, 0) == 'f');
735+
736+
737+
#if __LP64__
738+
template <typename T>
739+
struct S {
740+
constexpr S(unsigned long long N)
741+
: data(nullptr){
742+
data = alloc.allocate(N); // both-note {{in call to 'this->alloc.allocate(18446744073709551615)}}
743+
}
744+
constexpr T operator[](std::size_t i) const {
745+
return data[i];
746+
}
747+
748+
constexpr ~S() {
749+
alloc.deallocate(data);
750+
}
751+
std::allocator<T> alloc;
752+
T* data;
753+
};
754+
755+
constexpr std::size_t s = S<std::size_t>(~0UL)[42]; // both-error {{constexpr variable 's' must be initialized by a constant expression}} \
756+
// both-note@#alloc {{cannot allocate array; evaluated array bound 2305843009213693951 is too large}} \
757+
// both-note {{in call to}}
758+
#endif
734759
}
735760

736761
#else

0 commit comments

Comments
 (0)