aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp11
-rw-r--r--clang/lib/AST/ByteCode/Interp.h19
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp3
-rw-r--r--clang/lib/AST/ByteCode/Opcodes.td2
4 files changed, 31 insertions, 4 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 9a1e61b..fe8d05c 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -1862,6 +1862,13 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
if (Inits.size() == 1 && QT == Inits[0]->getType())
return this->delegate(Inits[0]);
+ const ConstantArrayType *CAT =
+ Ctx.getASTContext().getAsConstantArrayType(QT);
+ uint64_t NumElems = CAT->getZExtSize();
+
+ if (!this->emitCheckArraySize(NumElems, E))
+ return false;
+
unsigned ElementIndex = 0;
for (const Expr *Init : Inits) {
if (const auto *EmbedS =
@@ -1890,10 +1897,6 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
// Expand the filler expression.
// FIXME: This should go away.
if (ArrayFiller) {
- const ConstantArrayType *CAT =
- Ctx.getASTContext().getAsConstantArrayType(QT);
- uint64_t NumElems = CAT->getZExtSize();
-
for (; ElementIndex != NumElems; ++ElementIndex) {
if (!this->visitArrayElemInit(ElementIndex, ArrayFiller))
return false;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 6cd9952..80488b5 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -175,6 +175,8 @@ bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC,
bool isConstexprUnknown(const Pointer &P);
+inline bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems);
+
enum class ShiftDir { Left, Right };
/// Checks if the shift operation is legal.
@@ -3110,6 +3112,9 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source,
}
assert(NumElements.isPositive());
+ if (!CheckArraySize(S, OpPC, static_cast<uint64_t>(NumElements)))
+ return false;
+
DynamicAllocator &Allocator = S.getAllocator();
Block *B =
Allocator.allocate(Source, T, static_cast<size_t>(NumElements),
@@ -3140,6 +3145,9 @@ inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc,
}
assert(NumElements.isPositive());
+ if (!CheckArraySize(S, OpPC, static_cast<uint64_t>(NumElements)))
+ return false;
+
DynamicAllocator &Allocator = S.getAllocator();
Block *B =
Allocator.allocate(ElementDesc, static_cast<size_t>(NumElements),
@@ -3246,6 +3254,17 @@ inline bool CheckDestruction(InterpState &S, CodePtr OpPC) {
return CheckDestructor(S, OpPC, Ptr);
}
+inline bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems) {
+ uint64_t Limit = S.getLangOpts().ConstexprStepLimit;
+ if (NumElems > Limit) {
+ S.FFDiag(S.Current->getSource(OpPC),
+ diag::note_constexpr_new_exceeds_limits)
+ << NumElems << Limit;
+ return false;
+ }
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// Read opcode arguments
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index e3d7632..0b4585a 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1533,6 +1533,9 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
return false;
}
+ if (!CheckArraySize(S, OpPC, NumElems.getZExtValue()))
+ return false;
+
bool IsArray = NumElems.ugt(1);
std::optional<PrimType> ElemT = S.getContext().classify(ElemType);
DynamicAllocator &Allocator = S.getAllocator();
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index e717902..65a9a0c 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -414,6 +414,8 @@ def CheckLiteralType : Opcode {
let Args = [ArgTypePtr];
}
+def CheckArraySize : Opcode { let Args = [ArgUint64]; }
+
// [] -> [Value]
def GetGlobal : AccessOpcode;
def GetGlobalUnchecked : AccessOpcode;