Skip to content

Commit

Permalink
fix: data corruption in protocol.handle (#41933)
Browse files Browse the repository at this point in the history
* fix: data corruption in protocol.handle

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* slice instead of subarray

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
  • Loading branch information
trop[bot] and nornagon committed Apr 23, 2024
1 parent 8fd8757 commit 8d69c95
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/browser/api/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function makeStreamFromPipe (pipe: any): ReadableStream {
try {
const rv = await pipe.read(buf);
if (rv > 0) {
controller.enqueue(buf.subarray(0, rv));
controller.enqueue(buf.slice(0, rv));
} else {
controller.close();
}
Expand Down
43 changes: 43 additions & 0 deletions spec/api-protocol-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,49 @@ describe('protocol module', () => {
expect(body).to.equal(text);
});

it('can receive stream request body asynchronously', async () => {
let done: any;
const requestReceived: Promise<Buffer[]> = new Promise(resolve => { done = resolve; });
protocol.handle('http-like', async (req) => {
const chunks = [];
for await (const chunk of (req.body as any)) {
chunks.push(chunk);
}
done(chunks);
return new Response('ok');
});
defer(() => { protocol.unhandle('http-like'); });
const w = new BrowserWindow({ show: false });
w.loadURL('about:blank');
const expectedHashChunks = await w.webContents.executeJavaScript(`
const dataStream = () =>
new ReadableStream({
async start(controller) {
for (let i = 0; i < 10; i++) { controller.enqueue(Array(1024 * 128).fill(+i).join("\\n")); }
controller.close();
},
}).pipeThrough(new TextEncoderStream());
fetch(
new Request("http-like://host", {
method: "POST",
body: dataStream(),
duplex: "half",
})
);
(async () => {
const chunks = []
for await (const chunk of dataStream()) {
chunks.push(chunk);
}
return chunks;
})()
`);
const expectedHash = Buffer.from(await crypto.subtle.digest('SHA-256', Buffer.concat(expectedHashChunks))).toString('hex');
const body = Buffer.concat(await requestReceived);
const actualHash = Buffer.from(await crypto.subtle.digest('SHA-256', Buffer.from(body))).toString('hex');
expect(actualHash).to.equal(expectedHash);
});

it('can receive multi-part postData from loadURL', async () => {
protocol.handle('test-scheme', (req) => new Response(req.body));
defer(() => { protocol.unhandle('test-scheme'); });
Expand Down
1 change: 1 addition & 0 deletions spec/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ protocol.registerSchemesAsPrivileged([
{ scheme: global.standardScheme, privileges: { standard: true, secure: true, stream: false } },
{ scheme: global.zoomScheme, privileges: { standard: true, secure: true } },
{ scheme: global.serviceWorkerScheme, privileges: { allowServiceWorkers: true, standard: true, secure: true } },
{ scheme: 'http-like', privileges: { standard: true, secure: true, corsEnabled: true, supportFetchAPI: true } },
{ scheme: 'cors-blob', privileges: { corsEnabled: true, supportFetchAPI: true } },
{ scheme: 'cors', privileges: { corsEnabled: true, supportFetchAPI: true } },
{ scheme: 'no-cors', privileges: { supportFetchAPI: true } },
Expand Down

0 comments on commit 8d69c95

Please sign in to comment.