From 2ae31ce2c6834051fda547d7ed86313efd42b2ec Mon Sep 17 00:00:00 2001 From: jay23606 <4602056+jay23606@users.noreply.github.com> Date: Mon, 19 Oct 2026 21:07:16 -0400 Subject: [PATCH 1/2] fix(ascii85): reject short tail groups whose padded value overflows uint32 Short tail groups (2-4 chars) are padded with 'u' to five digits before decoding. The uint32 overflow check only ran for full 5-char groups, so a short tail whose padded value exceeds 0xFFFFFFFF wrapped silently and emitted wrong bytes. The check now applies to every group and returns null for such input. Co-Authored-By: Claude Haiku 5.5 Signed-off-by: jay23606 <4602056+jay23606@users.noreply.github.com> --- lib/utils/ascii85.test.ts | 14 ++++++++++++++ lib/utils/ascii85.ts | 6 +++--- 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 lib/utils/ascii85.test.ts diff --git a/lib/utils/ascii85.test.ts b/lib/utils/ascii85.test.ts new file mode 100644 index 00000000..e37aac1d --- /dev/null +++ b/lib/utils/ascii85.test.ts @@ -0,0 +1,14 @@ +import { ascii85Decode } from './ascii85'; + +describe('ascii85Decode', () => { + it('decodes a full 5-character group', () => { + expect(ascii85Decode('<~9jqo^~>')).toEqual(new Uint8Array([0x4d, 0x61, 0x6e, 0x20])); + }); + + it.each(['<~uu~>', '<~uuu~>', '<~uuuu~>'])( + 'rejects the short tail group %s whose padded value overflows uint32', + (input) => { + expect(ascii85Decode(input)).toBeNull(); + }, + ); +}); diff --git a/lib/utils/ascii85.ts b/lib/utils/ascii85.ts index 5a3a7fe2..0843ba80 100644 --- a/lib/utils/ascii85.ts +++ b/lib/utils/ascii85.ts @@ -34,10 +34,10 @@ export function ascii85Decode(input: string): Uint8Array | null { value = value * 85 + digit; } - if (chunkLen === 5 && value > 0xffffffff) return null; + // Applies to padded short tails too: a group whose value exceeds uint32 is invalid input. + if (value > 0xffffffff) return null; - // Use >>> 0 to simulate uint32 overflow for padded groups - const v = value >>> 0; + const v = value; const numBytes = chunkLen === 5 ? 4 : chunkLen - 1; if (numBytes >= 1) output.push((v >>> 24) & 0xff); if (numBytes >= 2) output.push((v >>> 16) & 0xff); From 9b14489acbceb7696eddd6b3c122e389f66f82a9 Mon Sep 17 00:00:00 2001 From: jay23606 <4602056+jay23606@users.noreply.github.com> Date: Mon, 19 Oct 2026 21:19:47 -0400 Subject: [PATCH 2/2] style(test): wrap the ascii85 tail-group expect call for prettier ESLint's prettier/prettier rule flags the expect line in lib/utils/ascii85.test.ts. Wrap it as prettier requires. No behaviour change. Co-Authored-By: Claude Haiku 5.5 Signed-off-by: jay23606 <4602056+jay23606@users.noreply.github.com> --- lib/utils/ascii85.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/utils/ascii85.test.ts b/lib/utils/ascii85.test.ts index e37aac1d..b643c879 100644 --- a/lib/utils/ascii85.test.ts +++ b/lib/utils/ascii85.test.ts @@ -2,7 +2,9 @@ import { ascii85Decode } from './ascii85'; describe('ascii85Decode', () => { it('decodes a full 5-character group', () => { - expect(ascii85Decode('<~9jqo^~>')).toEqual(new Uint8Array([0x4d, 0x61, 0x6e, 0x20])); + expect(ascii85Decode('<~9jqo^~>')).toEqual( + new Uint8Array([0x4d, 0x61, 0x6e, 0x20]), + ); }); it.each(['<~uu~>', '<~uuu~>', '<~uuuu~>'])(