diff options
| author | Gab Virebent <gabriel1@virebent.art> | 2026-07-02 18:01:21 +0200 |
|---|---|---|
| committer | Gab Virebent <gabriel1@virebent.art> | 2026-07-02 18:01:21 +0200 |
| commit | 25fb52dc5c587acca2f4457d5c6f7b8032b7829c (patch) | |
| tree | 7af788ccbb71c0ae5dbc278b4e5cfa8cbd6f48d2 | |
| parent | 52eb46afad75d76c707ed11bbddddbcf5e121deb (diff) | |
| download | nymdrop-25fb52dc5c587acca2f4457d5c6f7b8032b7829c.tar.gz nymdrop-25fb52dc5c587acca2f4457d5c6f7b8032b7829c.tar.xz nymdrop-25fb52dc5c587acca2f4457d5c6f7b8032b7829c.zip | |
Fix base64 encoding crash on file attachments over ~1MB
String.fromCharCode(...bytes) spreads every byte as a separate call
argument, exceeding the engine's max-arguments limit on multi-MB files
(RangeError: Maximum call stack size exceeded). Chunk the conversion
instead. Reported by a real submitter trying a 1.5MB file.
| -rw-r--r-- | static/crypto.js | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/static/crypto.js b/static/crypto.js index 04a1400..f1cc6c9 100644 --- a/static/crypto.js +++ b/static/crypto.js @@ -8,6 +8,19 @@ const NYMDROP_PUBKEY_HEX = "6aa99a672c48cb8eee65ddd5c5e5f8947a8d52d39a8b8eb4e11b // server's --pow-difficulty flag. const NYMDROP_POW_DIFFICULTY = 18; +// String.fromCharCode(...bytes) blows the call stack on large files: the +// spread passes every byte as a separate function argument, and engines cap +// argument count well below what a multi-MB file needs. Chunking keeps each +// call under that limit. +function bytesToBase64(bytes) { + const chunkSize = 0x8000; + let binary = ""; + for (let i = 0; i < bytes.length; i += chunkSize) { + binary += String.fromCharCode.apply(null, bytes.subarray(i, i + chunkSize)); + } + return btoa(binary); +} + async function hexToBytes(hex) { const bytes = new Uint8Array(hex.length / 2); for (let i = 0; i < hex.length; i += 2) @@ -126,7 +139,7 @@ document.getElementById("drop-form").addEventListener("submit", async (e) => { const fileInput = document.getElementById("file"); if (fileInput.files.length > 0) { const fileBytes = await fileInput.files[0].arrayBuffer(); - const fileB64 = btoa(String.fromCharCode(...new Uint8Array(fileBytes))); + const fileB64 = bytesToBase64(new Uint8Array(fileBytes)); plaintext += "\n---FILE:" + fileInput.files[0].name + "---\n" + fileB64; } |
