diff --git a/browser-ext/proxy/proxy.js b/browser-ext/proxy/proxy.js index e31c5f98b..b30968979 100644 --- a/browser-ext/proxy/proxy.js +++ b/browser-ext/proxy/proxy.js @@ -74,7 +74,7 @@ wss.on('connection', (ws, req) => { port: config.dapPort, }); - let tcpBuffer = ''; + let tcpBuffer = Buffer.alloc(0); let tcpConnected = false; tcp.on('connect', () => { @@ -135,33 +135,45 @@ wss.on('connection', (ws, req) => { }); // TCP → WebSocket: Parse Content-Length framing + // IMPORTANT: We use Buffer (byte-based) operations because DAP's Content-Length + // header specifies the message length in bytes, not characters. Using string + // operations would cause buffer misalignment when the JSON contains multi-byte + // UTF-8 characters. tcp.on('data', (chunk) => { - tcpBuffer += chunk.toString(); + // Append chunk to buffer (chunk is already a Buffer) + tcpBuffer = Buffer.concat([tcpBuffer, chunk]); // Process complete DAP messages from buffer + const headerEndMarker = Buffer.from('\r\n\r\n'); + while (true) { - // Look for Content-Length header - const headerEnd = tcpBuffer.indexOf('\r\n\r\n'); + // Look for header end (\r\n\r\n) + const headerEnd = tcpBuffer.indexOf(headerEndMarker); if (headerEnd === -1) break; - const header = tcpBuffer.substring(0, headerEnd); + // Extract header as string to parse Content-Length + const header = tcpBuffer.slice(0, headerEnd).toString('utf8'); const match = header.match(/Content-Length:\s*(\d+)/i); if (!match) { console.error(`[Proxy] Invalid DAP header: ${header}`); - tcpBuffer = tcpBuffer.substring(headerEnd + 4); + // Skip past the invalid header + tcpBuffer = tcpBuffer.slice(headerEnd + 4); continue; } - const contentLength = parseInt(match[1]); - const messageStart = headerEnd + 4; + const contentLength = parseInt(match[1], 10); + const messageStart = headerEnd + 4; // After \r\n\r\n const messageEnd = messageStart + contentLength; - // Check if we have the complete message + // Check if we have the complete message (in bytes) if (tcpBuffer.length < messageEnd) break; - // Extract the JSON message - const json = tcpBuffer.substring(messageStart, messageEnd); - tcpBuffer = tcpBuffer.substring(messageEnd); + // Extract the JSON message (as bytes, then decode to string) + const jsonBuffer = tcpBuffer.slice(messageStart, messageEnd); + const json = jsonBuffer.toString('utf8'); + + // Remove processed message from buffer + tcpBuffer = tcpBuffer.slice(messageEnd); // Send to WebSocket try { @@ -175,6 +187,7 @@ wss.on('connection', (ws, req) => { } } catch (err) { console.error(`[Proxy] Invalid JSON from TCP: ${err.message}`); + console.error(`[Proxy] JSON content (first 200 chars): ${json.substring(0, 200)}`); } } });