SOURCE / PINNED RELEASE
Made of little things.
Powder Tool V600Billion
- Release
- 142767edcab8…
- Author-recorded commit
- 6d92971effd0…
- License
- LICENSE
- Author’s source reference
- nostr://npub1fllw8kw0thjj55wds0uugcnp5kej2nfxd36eruq39d56wwz8r44q5q78wj/wss%3A%2F%2Fgit.napplet.soy%2F/powder-toy
Archive hash verified: ed7d6a8ea7083197…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
/**
* The bounded bzip2 decoder against streams from a real compressor (Python's
* bz2 module, fixtures/bzip2-vectors.json), and against the inputs a hostile
* save could carry: truncation, flipped bits, garbage, and a bomb that asks
* for more than the output limit. Every bad input must end in an exception,
* quickly.
*/
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import test from 'node:test';
import { Bzip2Error, decompress } from '../src/save/bzip2.js';
const vectors = JSON.parse(readFileSync(new URL('./fixtures/bzip2-vectors.json', import.meta.url), 'utf8'));
const bytes = (b64) => new Uint8Array(Buffer.from(b64, 'base64'));
for (const vector of vectors) {
test(`decodes: ${vector.name} (level ${vector.level})`, () => {
const plain = bytes(vector.plain);
const result = decompress(bytes(vector.packed));
assert.equal(result.length, plain.length);
assert.ok(Buffer.from(result).equals(Buffer.from(plain)), 'output differs from the original');
});
}
test('refuses output beyond the limit', () => {
const run = vectors.find((vector) => vector.name === 'long run');
assert.throws(() => decompress(bytes(run.packed), { maxOutput: 999 }), Bzip2Error);
assert.equal(decompress(bytes(run.packed), { maxOutput: 1000 }).length, 1000);
});
test('truncated streams throw instead of spinning', () => {
const packed = bytes(vectors.find((vector) => vector.name === 'random 20k').packed);
for (const cut of [5, 20, 100, packed.length >> 1, packed.length - 1]) {
const started = Date.now();
assert.throws(() => decompress(packed.subarray(0, cut)), Bzip2Error, `cut at ${cut}`);
assert.ok(Date.now() - started < 2000, `cut at ${cut} took too long`);
}
});
test('flipped bits are caught (by structure or by CRC)', () => {
const packed = bytes(vectors.find((vector) => vector.name === 'structured').packed);
let caught = 0;
for (let i = 10; i < packed.length; i += Math.max(1, packed.length >> 6)) {
const damaged = packed.slice();
damaged[i] ^= 0x10;
try { decompress(damaged); } catch (error) { assert.ok(error instanceof Bzip2Error, String(error)); caught++; }
}
assert.ok(caught > 0);
});
test('garbage and wrong headers throw', () => {
assert.throws(() => decompress(new Uint8Array([1, 2, 3, 4, 5, 6])), Bzip2Error);
assert.throws(() => decompress(new Uint8Array([0x42, 0x5a, 0x68, 0x30])), Bzip2Error); // level 0
const random = new Uint8Array(4096);
for (let i = 0; i < random.length; i++) random[i] = (i * 2654435761) >>> 24;
random.set([0x42, 0x5a, 0x68, 0x39], 0);
assert.throws(() => decompress(random), Bzip2Error);
assert.throws(() => decompress('BZh9'), TypeError);
});
