Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ export { PilotError } from './ffi.js';

export const DEFAULT_SOCKET_PATH = '/tmp/pilot.sock';

// Wire-frame safety caps: reject frames whose declared length exceeds
// these limits BEFORE allocating memory.
const MAX_PAYLOAD_SIZE = 1_048_576; // 1 MiB — matches Pilot wire protocol max message
export const MAX_TOPIC_SIZE = 4_096; // 4 KiB — event-stream topic strings are short

// Module-level singleton for the loaded library
let _lib: PilotLib | null = null;

Expand Down Expand Up @@ -491,6 +496,9 @@ export class Driver {
const ackHeader = conn.read(8);
if (ackHeader && ackHeader.length === 8) {
const ackLen = ackHeader.readUInt32BE(4);
if (ackLen > MAX_PAYLOAD_SIZE) {
return { sent: buf.length, type: msgType, target: addr };
}
const ackPayload = conn.read(ackLen);
if (ackPayload && ackPayload.length > 0) {
const ackMsg = ackPayload.toString('utf-8');
Expand Down Expand Up @@ -542,6 +550,9 @@ export class Driver {
const ackHeader = conn.read(8);
if (ackHeader && ackHeader.length === 8) {
const ackLen = ackHeader.readUInt32BE(4);
if (ackLen > MAX_PAYLOAD_SIZE) {
return { sent: fileData.length, filename, target: addr };
}
const ackPayload = conn.read(ackLen);
if (ackPayload && ackPayload.length > 0) {
const ackMsg = ackPayload.toString('utf-8');
Expand Down Expand Up @@ -642,6 +653,7 @@ function readEventFrame(conn: Conn): { topic: string; data: Buffer } | null {
const topicLenBuf = conn.read(2);
if (!topicLenBuf || topicLenBuf.length < 2) return null;
const topicLen = topicLenBuf.readUInt16BE(0);
if (topicLen > MAX_TOPIC_SIZE) return null;

const topicBuf = conn.read(topicLen);
if (!topicBuf || topicBuf.length < topicLen) return null;
Expand All @@ -650,6 +662,7 @@ function readEventFrame(conn: Conn): { topic: string; data: Buffer } | null {
const payloadLenBuf = conn.read(4);
if (!payloadLenBuf || payloadLenBuf.length < 4) return null;
const payloadLen = payloadLenBuf.readUInt32BE(0);
if (payloadLen > MAX_PAYLOAD_SIZE) return null;

const data = conn.read(payloadLen);
if (!data || data.length < payloadLen) return null;
Expand Down
11 changes: 11 additions & 0 deletions tests/client_extra.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,14 @@ describe('sendMessage / sendFile ack-read fallback', () => {
d.close();
});
});

// ---------------------------------------------------------------------------
// Wire-frame size caps (PILOT-103)
// ---------------------------------------------------------------------------

describe('wire-frame size caps', () => {
it('MAX_TOPIC_SIZE is 4 KiB and exported', async () => {
const mod = await import('../src/client.js');
expect(mod.MAX_TOPIC_SIZE).toBe(4096);
});
});
Loading