From ffda6a078251f42823cdc52b50f2b2500ff490c5 Mon Sep 17 00:00:00 2001 From: Jens Fursund Date: Wed, 10 Jun 2026 21:25:52 +0000 Subject: [PATCH] fix(STLLoader): guard isBinary against buffers shorter than 84 bytes STLLoader.parse() calls isBinary() first, which reads a little-endian uint32 at offset 80 via DataView.getUint32(80, true) to compute the expected binary file size. This call is unconditional and throws RangeError: Offset is outside the bounds of the DataView for any STL whose total payload is shorter than 84 bytes (the binary STL header: 80 bytes + 4-byte face count). Such files do exist in the wild: minimal/empty ASCII solids such as solid s endsolid s are only 19 bytes and crash the parser before the ASCII-vs-binary disambiguation runs at all. A short ASCII STL is a perfectly legal STL. Return false from isBinary() when the buffer is shorter than the binary header so short payloads cleanly fall through to parseASCII(). The same bug exists in three.js's examples/jsm/loaders/STLLoader.js. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/loaders/STLLoader.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/loaders/STLLoader.js b/src/loaders/STLLoader.js index 536366a9..0b4980c0 100644 --- a/src/loaders/STLLoader.js +++ b/src/loaders/STLLoader.js @@ -97,6 +97,13 @@ class STLLoader extends Loader { parse(data) { function isBinary(data) { const reader = new DataView(data) + + // A binary STL is at minimum an 80-byte header followed by a 4-byte + // uint32 face count (84 bytes total). Anything shorter cannot be + // binary; treat it as ASCII to avoid an out-of-bounds DataView read + // on short but legal ASCII solids (e.g. "solid s\nendsolid s\n"). + if (reader.byteLength < 84) return false + const face_size = (32 / 8) * 3 + (32 / 8) * 3 * 3 + 16 / 8 const n_faces = reader.getUint32(80, true) const expect = 80 + 32 / 8 + n_faces * face_size