@@ -39,9 +39,8 @@ export namespace Pty {
|
|||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = (ws: unknown) => {
|
const token = (ws: Socket) => {
|
||||||
if (!ws || typeof ws !== "object") return ws
|
const data = ws.data
|
||||||
const data = (ws as { data?: unknown }).data
|
|
||||||
if (data === undefined) return
|
if (data === undefined) return
|
||||||
if (data === null) return
|
if (data === null) return
|
||||||
if (typeof data !== "object") return data
|
if (typeof data !== "object") return data
|
||||||
@@ -318,7 +317,7 @@ export namespace Pty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function connect(id: string, ws: Socket, cursor?: number, identity?: unknown) {
|
export function connect(id: string, ws: Socket, cursor?: number) {
|
||||||
const session = state().get(id)
|
const session = state().get(id)
|
||||||
if (!session) {
|
if (!session) {
|
||||||
ws.close()
|
ws.close()
|
||||||
@@ -338,7 +337,7 @@ export namespace Pty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
owners.set(ws, id)
|
owners.set(ws, id)
|
||||||
session.subscribers.set(ws, { id: socketId, token: token(identity ?? ws) })
|
session.subscribers.set(ws, { id: socketId, token: token(ws) })
|
||||||
|
|
||||||
const cleanup = () => {
|
const cleanup = () => {
|
||||||
session.subscribers.delete(ws)
|
session.subscribers.delete(ws)
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ export const PtyRoutes = lazy(() =>
|
|||||||
ws.close()
|
ws.close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handler = Pty.connect(id, socket, cursor, ws)
|
handler = Pty.connect(id, socket, cursor)
|
||||||
},
|
},
|
||||||
onMessage(event) {
|
onMessage(event) {
|
||||||
if (typeof event.data !== "string") return
|
if (typeof event.data !== "string") return
|
||||||
|
|||||||
@@ -98,54 +98,6 @@ describe("pty", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test("does not leak when identity token is only on websocket wrapper", async () => {
|
|
||||||
await using dir = await tmpdir({ git: true })
|
|
||||||
|
|
||||||
await Instance.provide({
|
|
||||||
directory: dir.path,
|
|
||||||
fn: async () => {
|
|
||||||
const a = await Pty.create({ command: "cat", title: "a" })
|
|
||||||
try {
|
|
||||||
const outA: string[] = []
|
|
||||||
const outB: string[] = []
|
|
||||||
const text = (data: string | Uint8Array | ArrayBuffer) => {
|
|
||||||
if (typeof data === "string") return data
|
|
||||||
if (data instanceof ArrayBuffer) return Buffer.from(new Uint8Array(data)).toString("utf8")
|
|
||||||
return Buffer.from(data).toString("utf8")
|
|
||||||
}
|
|
||||||
|
|
||||||
const raw: Parameters<typeof Pty.connect>[1] = {
|
|
||||||
readyState: 1,
|
|
||||||
send: (data) => {
|
|
||||||
outA.push(text(data))
|
|
||||||
},
|
|
||||||
close: () => {
|
|
||||||
// no-op
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const wrap = { data: { events: { connection: "a" } } }
|
|
||||||
|
|
||||||
Pty.connect(a.id, raw, undefined, wrap)
|
|
||||||
outA.length = 0
|
|
||||||
|
|
||||||
// Simulate Bun reusing the raw socket object before the next onOpen,
|
|
||||||
// while the connection token only exists on the wrapper socket.
|
|
||||||
raw.send = (data) => {
|
|
||||||
outB.push(text(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
Pty.write(a.id, "AAA\n")
|
|
||||||
await Bun.sleep(100)
|
|
||||||
|
|
||||||
expect(outB.join("")).not.toContain("AAA")
|
|
||||||
} finally {
|
|
||||||
await Pty.remove(a.id)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test("does not leak output when socket data mutates in-place", async () => {
|
test("does not leak output when socket data mutates in-place", async () => {
|
||||||
await using dir = await tmpdir({ git: true })
|
await using dir = await tmpdir({ git: true })
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user