summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGab Virebent <gabriel1@virebent.art>2026-07-02 18:01:21 +0200
committerGab Virebent <gabriel1@virebent.art>2026-07-02 18:01:21 +0200
commit25fb52dc5c587acca2f4457d5c6f7b8032b7829c (patch)
tree7af788ccbb71c0ae5dbc278b4e5cfa8cbd6f48d2
parent52eb46afad75d76c707ed11bbddddbcf5e121deb (diff)
downloadnymdrop-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.js15
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;
}