Back to Powder Tool V600Billion
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.

source/test/bzip2.test.mjs
/**
 * 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);
});