[clang] [clang][bytecode] Check allocation size limit for operator new (PR #109590)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 22 13:35:22 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/109590.diff
3 Files Affected:
- (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+10-1)
- (modified) clang/lib/AST/ByteCode/InterpFrame.cpp (+14-2)
- (modified) clang/test/AST/ByteCode/new-delete.cpp (+26-1)
``````````diff
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 51c77b7da1a655..523f5cb993dbc7 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1306,7 +1306,16 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
return false;
}
- // FIXME: CheckArraySize for NumElems?
+ // NB: The same check we're using in CheckArraySize()
+ if (NumElems.getActiveBits() >
+ ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||
+ NumElems.ugt(Descriptor::MaxArrayElemBytes / ElemSize.getQuantity())) {
+ // FIXME: NoThrow check?
+ const SourceInfo &Loc = S.Current->getSource(OpPC);
+ S.FFDiag(Loc, diag::note_constexpr_new_too_large)
+ << NumElems.getZExtValue();
+ return false;
+ }
std::optional<PrimType> ElemT = S.getContext().classify(ElemType);
DynamicAllocator &Allocator = S.getAllocator();
diff --git a/clang/lib/AST/ByteCode/InterpFrame.cpp b/clang/lib/AST/ByteCode/InterpFrame.cpp
index 28e189bb339e62..7c877a70fe6b97 100644
--- a/clang/lib/AST/ByteCode/InterpFrame.cpp
+++ b/clang/lib/AST/ByteCode/InterpFrame.cpp
@@ -102,14 +102,26 @@ static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx,
V.toAPValue(ASTCtx).printPretty(OS, ASTCtx, Ty);
}
+static bool shouldSkipInBacktrace(const Function *F) {
+ if (F->isBuiltin())
+ return true;
+ if (F->isLambdaStaticInvoker())
+ return true;
+
+ const FunctionDecl *FD = F->getDecl();
+ if (FD->getDeclName().getCXXOverloadedOperator() == OO_New ||
+ FD->getDeclName().getCXXOverloadedOperator() == OO_Array_New)
+ return true;
+ return false;
+}
+
void InterpFrame::describe(llvm::raw_ostream &OS) const {
// We create frames for builtin functions as well, but we can't reliably
// diagnose them. The 'in call to' diagnostics for them add no value to the
// user _and_ it doesn't generally work since the argument types don't always
// match the function prototype. Just ignore them.
// Similarly, for lambda static invokers, we would just print __invoke().
- if (const auto *F = getFunction();
- F && (F->isBuiltin() || F->isLambdaStaticInvoker()))
+ if (const auto *F = getFunction(); F && shouldSkipInBacktrace(F))
return;
const Expr *CallExpr = Caller->getExpr(getRetPC());
diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp
index 2ba1286b250dc6..6cefbba307215a 100644
--- a/clang/test/AST/ByteCode/new-delete.cpp
+++ b/clang/test/AST/ByteCode/new-delete.cpp
@@ -592,7 +592,8 @@ namespace std {
using size_t = decltype(sizeof(0));
template<typename T> struct allocator {
constexpr T *allocate(size_t N) {
- return (T*)__builtin_operator_new(sizeof(T) * N); // both-note 2{{allocation performed here}}
+ return (T*)__builtin_operator_new(sizeof(T) * N); // both-note 2{{allocation performed here}} \
+ // #alloc
}
constexpr void deallocate(void *p) {
__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 {
return n;
}
static_assert(dynarray<char>(5, 0) == 'f');
+
+
+#if __LP64__
+ template <typename T>
+ struct S {
+ constexpr S(unsigned long long N)
+ : data(nullptr){
+ data = alloc.allocate(N); // both-note {{in call to 'this->alloc.allocate(18446744073709551615)}}
+ }
+ constexpr T operator[](std::size_t i) const {
+ return data[i];
+ }
+
+ constexpr ~S() {
+ alloc.deallocate(data);
+ }
+ std::allocator<T> alloc;
+ T* data;
+ };
+
+ constexpr std::size_t s = S<std::size_t>(~0UL)[42]; // both-error {{constexpr variable 's' must be initialized by a constant expression}} \
+ // both-note@#alloc {{cannot allocate array; evaluated array bound 2305843009213693951 is too large}} \
+ // both-note {{in call to}}
+#endif
}
#else
``````````
</details>
https://github.com/llvm/llvm-project/pull/109590
More information about the cfe-commits
mailing list