Skip to content

Commit 4468eda

Browse files
committed
Refrain from setting array indices outside the array length
The code `array[i] = foo` where `i >= array.length` does, for obvious reasons, not work inside unchecked contexts. Code like this was the cause of crashes when compiling with `--uncheckedBehavior always`. In my opinion, this practice is sloppy, although my workarounds can be considered equally sloppy.
1 parent b05502a commit 4468eda

File tree

4 files changed

+19
-9
lines changed

4 files changed

+19
-9
lines changed

src/builtins.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10329,17 +10329,17 @@ export function compileVisitMembers(compiler: Compiler): void {
1032910329
let instanceId = _keys[i];
1033010330
assert(instanceId == nextId++);
1033110331
let instance = assert(managedClasses.get(instanceId));
10332-
names[i] = instance.internalName;
10332+
names.push(instance.internalName);
1033310333
if (instance.isPointerfree) {
10334-
cases[i] = module.return();
10334+
cases.push(module.return());
1033510335
} else {
10336-
cases[i] = module.block(null, [
10336+
cases.push(module.block(null, [
1033710337
module.call(`${instance.internalName}~visit`, [
1033810338
module.local_get(0, sizeTypeRef), // this
1033910339
module.local_get(1, TypeRef.I32) // cookie
1034010340
], TypeRef.None),
1034110341
module.return()
10342-
], TypeRef.None);
10342+
], TypeRef.None));
1034310343
ensureVisitMembersOf(compiler, instance);
1034410344
}
1034510345
}

src/compiler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6379,7 +6379,7 @@ export class Compiler extends DiagnosticEmitter {
63796379
}
63806380
let numOptional = assert(maxOperands - minOperands);
63816381

6382-
let forwardedOperands = new Array<ExpressionRef>(minOperands);
6382+
let forwardedOperands = new Array<ExpressionRef>(maxOperands);
63836383
let operandIndex = 0;
63846384
let stmts = new Array<ExpressionRef>();
63856385

@@ -6609,7 +6609,7 @@ export class Compiler extends DiagnosticEmitter {
66096609
let body: ExpressionRef;
66106610
let instanceClass = instance.getBoundClassOrInterface();
66116611
if (!instance.is(CommonFlags.Abstract) && !(instanceClass && instanceClass.kind == ElementKind.Interface)) {
6612-
let paramExprs = new Array<ExpressionRef>(numParameters);
6612+
let paramExprs = new Array<ExpressionRef>(numParameters + 1);
66136613
paramExprs[0] = module.local_get(0, sizeTypeRef); // this
66146614
for (let i = 0, k = parameterTypes.length; i < k; ++i) {
66156615
paramExprs[1 + i] = module.local_get(1 + i, parameterTypes[i].toRef());

src/flow.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,15 +524,25 @@ export class Flow {
524524
setLocalFlag(index: i32, flag: LocalFlags): void {
525525
if (index < 0) return;
526526
let localFlags = this.localFlags;
527-
let flags = index < localFlags.length ? unchecked(localFlags[index]) : 0;
527+
let flags = 0;
528+
if (index < localFlags.length) {
529+
flags = unchecked(localFlags[index]);
530+
} else {
531+
localFlags.length = index + 1;
532+
}
528533
localFlags[index] = flags | flag;
529534
}
530535

531536
/** Unsets the specified flag or flags on the local at the specified index. */
532537
unsetLocalFlag(index: i32, flag: LocalFlags): void {
533538
if (index < 0) return;
534539
let localFlags = this.localFlags;
535-
let flags = index < localFlags.length ? unchecked(localFlags[index]) : 0;
540+
let flags = 0;
541+
if (index < localFlags.length) {
542+
flags = unchecked(localFlags[index]);
543+
} else {
544+
localFlags.length = index + 1;
545+
}
536546
localFlags[index] = flags & ~flag;
537547
}
538548

src/passes/shadowstack.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ export class ShadowStackPass extends Pass {
467467
let results = _BinaryenFunctionGetResults(funcRef);
468468
let body = assert(_BinaryenFunctionGetBody(funcRef));
469469
let numVars = _BinaryenFunctionGetNumVars(funcRef);
470-
let vars = new Array<TypeRef>();
470+
let vars = new Array<TypeRef>(numVars);
471471
for (let i: Index = 0; i < numVars; ++i) {
472472
vars[i] = _BinaryenFunctionGetVar(funcRef, i);
473473
}

0 commit comments

Comments
 (0)