Skip to content

Commit 3c1e395

Browse files
committed
try to validate assets before committing them
1 parent 7341bb0 commit 3c1e395

File tree

2 files changed

+71
-8
lines changed

2 files changed

+71
-8
lines changed

pxtlib/spriteutils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ namespace pxt.sprite {
145145
}
146146
}
147147

148-
protected dataLength() {
148+
dataLength() {
149149
return Math.ceil(this.width * this.height / 2);
150150
}
151151
}
@@ -179,7 +179,7 @@ namespace pxt.sprite {
179179
this.buf[index] = value;
180180
}
181181

182-
protected dataLength() {
182+
dataLength() {
183183
return this.width * this.height;
184184
}
185185
}

pxtlib/tilemap.ts

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ namespace pxt {
154154
const existing = this.lookupByID(id);
155155

156156
if (!assetEquals(existing, newValue)) {
157+
if (!validateAsset(newValue) && validateAsset(existing)) {
158+
pxt.warn("Refusing to overwrite asset with invalid version");
159+
pxt.tickEvent("assets.invalidAssetOverwrite", { assetType: newValue.type });
160+
return existing;
161+
}
162+
157163
this.removeByID(id);
158164
asset = this.add(newValue);
159165
this.notifyListener(newValue.internalID);
@@ -1940,6 +1946,69 @@ namespace pxt {
19401946
return getShortIDCore(asset.type, asset.id);
19411947
}
19421948

1949+
export function validateAsset(asset: pxt.Asset) {
1950+
if (!asset) return false;
1951+
1952+
switch (asset.type) {
1953+
case AssetType.Image:
1954+
case AssetType.Tile:
1955+
return validateImageAsset(asset as ProjectImage | Tile);
1956+
case AssetType.Tilemap:
1957+
return validateTilemap(asset as ProjectTilemap);
1958+
case AssetType.Animation:
1959+
return validateAnimation(asset as Animation)
1960+
case AssetType.Song:
1961+
return validateSong(asset as Song);
1962+
}
1963+
}
1964+
1965+
function validateImageAsset(asset: ProjectImage | Tile) {
1966+
if (!asset.bitmap) return false;
1967+
1968+
return validateBitmap(sprite.Bitmap.fromData(asset.bitmap));
1969+
}
1970+
1971+
function validateTilemap(tilemap: ProjectTilemap) {
1972+
if (
1973+
!tilemap.data ||
1974+
!tilemap.data.tilemap ||
1975+
!tilemap.data.tileset ||
1976+
!tilemap.data.tileset.tileWidth ||
1977+
!tilemap.data.tileset.tiles?.length ||
1978+
!tilemap.data.layers
1979+
) {
1980+
return false;
1981+
}
1982+
1983+
return validateBitmap(sprite.Bitmap.fromData(tilemap.data.layers)) &&
1984+
validateBitmap(tilemap.data.tilemap);
1985+
}
1986+
1987+
function validateAnimation(animation: Animation) {
1988+
if (!animation.frames?.length || animation.interval <= 0) {
1989+
return false;
1990+
}
1991+
1992+
return !animation.frames.some(frame => !validateBitmap(sprite.Bitmap.fromData(frame)));
1993+
}
1994+
1995+
function validateBitmap(bitmap: sprite.Bitmap) {
1996+
return bitmap.width > 0 &&
1997+
bitmap.height > 0 &&
1998+
!Number.isNaN(bitmap.x0) &&
1999+
!Number.isNaN(bitmap.y0) &&
2000+
bitmap.data().data.length === bitmap.dataLength();
2001+
}
2002+
2003+
function validateSong(song: Song) {
2004+
return song.song &&
2005+
song.song.ticksPerBeat > 0 &&
2006+
song.song.beatsPerMeasure > 0 &&
2007+
song.song.measures > 0 &&
2008+
song.song.beatsPerMinute > 0 &&
2009+
!!song.song.tracks;
2010+
}
2011+
19432012
function getShortIDCore(assetType: pxt.AssetType, id: string, allowNoPrefix = false) {
19442013
let prefix: string;
19452014
switch (assetType) {
@@ -2054,12 +2123,6 @@ namespace pxt {
20542123
}
20552124
}
20562125

2057-
2058-
function set16Bit(buf: Uint8ClampedArray, offset: number, value: number) {
2059-
buf[offset] = value & 0xff;
2060-
buf[offset + 1] = (value >> 8) & 0xff;
2061-
}
2062-
20632126
function read16Bit(buf: Uint8ClampedArray, offset: number) {
20642127
return buf[offset] | (buf[offset + 1] << 8)
20652128
}

0 commit comments

Comments
 (0)