Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c7c81af

Browse files
alexmarkovcommit-bot@chromium.org
authored andcommitted
[vm/bytecode] Check for overflow of bytecode limits
Change-Id: I452596fb6f0fa72d76f26981adae2910ba1a179c Reviewed-on: https://dart-review.googlesource.com/c/81336 Reviewed-by: Régis Crelier <regis@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
1 parent 655310d commit c7c81af

File tree

4 files changed

+60
-23
lines changed

4 files changed

+60
-23
lines changed

pkg/vm/lib/bytecode/constant_pool.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import 'dart:typed_data';
99
import 'package:kernel/ast.dart' hide MapEntry;
1010
import 'package:kernel/text/ast_to_text.dart' show Printer;
1111

12+
import 'dbc.dart' show constantPoolIndexLimit, BytecodeLimitExceededException;
13+
1214
/*
1315
1416
In kernel binary, constant pool is encoded in the following way
@@ -1166,6 +1168,9 @@ class ConstantPool {
11661168
int add(ConstantPoolEntry entry) {
11671169
return _canonicalizationCache.putIfAbsent(entry, () {
11681170
int index = entries.length;
1171+
if (index >= constantPoolIndexLimit) {
1172+
throw new ConstantPoolIndexOverflowException();
1173+
}
11691174
_addEntry(entry);
11701175
return index;
11711176
});
@@ -1252,3 +1257,6 @@ class ConstantPool {
12521257

12531258
int _combineHashes(int hash1, int hash2) =>
12541259
(((hash1 * 31) & 0x3fffffff) + hash2) & 0x3fffffff;
1260+
1261+
class ConstantPoolIndexOverflowException
1262+
extends BytecodeLimitExceededException {}

pkg/vm/lib/bytecode/dbc.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,3 +303,17 @@ enum SpecialIndex {
303303
}
304304

305305
bool isJump(Opcode opcode) => BytecodeFormats[opcode].encoding == Encoding.kT;
306+
307+
// Bytecode instructions reference constant pool indices using
308+
// unsigned 16-bit operands.
309+
const int constantPoolIndexLimit = 1 << 16;
310+
311+
// Local variables are referenced using 16-bit signed operands.
312+
const int localVariableIndexLimit = 1 << 15;
313+
314+
// Captured variables are referenced using 16-bit unsigned operands.
315+
const int capturedVariableIndexLimit = 1 << 16;
316+
317+
// Base class for exceptions thrown when certain limit of bytecode
318+
// format is exceeded.
319+
abstract class BytecodeLimitExceededException {}

pkg/vm/lib/bytecode/gen_bytecode.dart

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -141,35 +141,41 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
141141
if (node.isAbstract) {
142142
return;
143143
}
144-
if (node is Field) {
145-
if (node.isStatic && !_hasTrivialInitializer(node)) {
144+
try {
145+
if (node is Field) {
146+
if (node.isStatic && !_hasTrivialInitializer(node)) {
147+
start(node);
148+
if (node.isConst) {
149+
_genPushConstExpr(node.initializer);
150+
} else {
151+
node.initializer.accept(this);
152+
}
153+
_genReturnTOS();
154+
end(node);
155+
}
156+
} else if ((node is Procedure && !node.isRedirectingFactoryConstructor) ||
157+
(node is Constructor)) {
146158
start(node);
147-
if (node.isConst) {
148-
_genPushConstExpr(node.initializer);
159+
if (node is Constructor) {
160+
_genConstructorInitializers(node);
161+
}
162+
if (node.isExternal) {
163+
final String nativeName = getExternalName(node);
164+
if (nativeName == null) {
165+
return;
166+
}
167+
_genNativeCall(nativeName);
149168
} else {
150-
node.initializer.accept(this);
169+
node.function?.body?.accept(this);
170+
// BytecodeAssembler eliminates this bytecode if it is unreachable.
171+
asm.emitPushNull();
151172
}
152173
_genReturnTOS();
153174
end(node);
154175
}
155-
} else if ((node is Procedure && !node.isRedirectingFactoryConstructor) ||
156-
(node is Constructor)) {
157-
start(node);
158-
if (node is Constructor) {
159-
_genConstructorInitializers(node);
160-
}
161-
if (node.isExternal) {
162-
final String nativeName = getExternalName(node);
163-
if (nativeName == null) {
164-
return;
165-
}
166-
_genNativeCall(nativeName);
167-
} else {
168-
node.function?.body?.accept(this);
169-
// BytecodeAssembler eliminates this bytecode if it is unreachable.
170-
asm.emitPushNull();
171-
}
172-
_genReturnTOS();
176+
} on BytecodeLimitExceededException {
177+
// Do not generate bytecode and fall back to using kernel AST.
178+
hasErrors = true;
173179
end(node);
174180
}
175181
}

pkg/vm/lib/bytecode/local_vars.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,9 @@ class _Allocator extends RecursiveVisitor<Null> {
832832

833833
if (v.isCaptured) {
834834
v.index = _currentScope.contextOwner.contextUsed++;
835+
if (v.index >= capturedVariableIndexLimit) {
836+
throw new LocalVariableIndexOverflowException();
837+
}
835838
v.originalParamSlotIndex = paramSlotIndex;
836839
return;
837840
}
@@ -843,6 +846,9 @@ class _Allocator extends RecursiveVisitor<Null> {
843846
v.index = paramSlotIndex;
844847
} else {
845848
v.index = _currentScope.localsUsed++;
849+
if (v.index >= localVariableIndexLimit) {
850+
throw new LocalVariableIndexOverflowException();
851+
}
846852
}
847853
_updateFrameSize();
848854
}
@@ -1139,3 +1145,6 @@ class _Allocator extends RecursiveVisitor<Null> {
11391145
_visit(node, temps: 3);
11401146
}
11411147
}
1148+
1149+
class LocalVariableIndexOverflowException
1150+
extends BytecodeLimitExceededException {}

0 commit comments

Comments
 (0)