Repository navigation
Description
Bug description
Three differences from TypeScript/JavaScript semantics inside the documented subset (same results with -O0 and -O3):
-
Field initializers of a derived class with an explicit constructor run before
super()In a subclass with an explicit constructor, field initializers are prepended to the constructor body (
compiler.ts,makeFieldInitializationInConstructorbeforebodyStartIndex), so they run before thesuper(...)call and before the base class's own field initializers. Without an explicit subclass constructor the order is right. -
Array#fill(value, start)withstart < -lengthwrites before the bufferIn
FILL(std/assembly/util/bytes.ts),lenhas typeusize(unsigned), somax(len + start, 0)does not clamp a negative sum to0whenstart < -<isize>lenand the loop writes beforedataStart, corrupting the heap. -
copyWithin(target, start, end)withend < starttrapsIn
Array#copyWithin(std/assembly/array.ts) andTypedArray#copyWithin(std/assembly/typedarray.ts),count = min(last - from, len - to)goes negative whenlast < fromand is cast tousizeformemory.copy, trapping withmemory access out of boundsinstead of being a no-op.
Steps to reproduce
// 1. Derived field initializer runs before super()
class A { a: i32 = 1; constructor(a: i32) { this.a = a; } }
class B extends A { b: i32 = this.a * 10; constructor() { super(5); } }
export function f(): i32 { return new B().b; } // returns 0, expected 50
// 2. Array#fill with start < -length corrupts heap memory before the buffer
export function g(): i32 {
const a: i32[] = [1, 2, 3, 4];
a.fill(7, -9); // expected [7, 7, 7, 7]
__collect();
return a[0]; // aborts: "null in ~lib/rt/itcms.ts:229:20"
}
// 3. copyWithin with end < start traps
export function h(): i32 {
const a: i32[] = [1, 2, 3];
a.copyWithin(1, 2, 1); // traps: "memory access out of bounds" (expected no-op)
return a.length;
}Compile with asc repro.ts -O0 (or -O3) and invoke f(), g(), and h().
AssemblyScript version
v0.28.20 (main b6bda05)
Credit: https://ucsbplse.github.io/
Activity