Skip to content

Commit

Permalink
Do not crash on big streams
Browse files Browse the repository at this point in the history
  • Loading branch information
ehmicky committed Aug 7, 2023
1 parent c960887 commit 5ad2a98
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 7 deletions.
12 changes: 6 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import {Buffer, constants as BufferConstants} from 'node:buffer';
import {Buffer} from 'node:buffer';
import {compose, PassThrough as PassThroughStream} from 'node:stream';

const maxHighWaterMark = 2_147_483_647;

export class MaxBufferError extends Error {
name = 'MaxBufferError';

Expand All @@ -19,7 +17,7 @@ export default async function getStream(inputStream, options = {}) {
const {maxBuffer = Number.POSITIVE_INFINITY, encoding = 'utf8'} = options;
const isBuffer = encoding === 'buffer';

const stream = new PassThroughStream({highWaterMark: maxHighWaterMark, encoding: isBuffer ? undefined : encoding});
const stream = new PassThroughStream({encoding: isBuffer ? undefined : encoding});

const newStream = compose(inputStream, stream);

Expand All @@ -40,9 +38,11 @@ export default async function getStream(inputStream, options = {}) {

return getBufferedValue();
} catch (error) {
if (length <= BufferConstants.MAX_LENGTH) {
try {
error.bufferedData = getBufferedValue();
}
// This throws when the buffered data is larger than the maximum length
// for a string or buffer
} catch {}

throw error;
}
Expand Down
18 changes: 17 additions & 1 deletion test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Buffer} from 'node:buffer';
import {Buffer, constants as BufferConstants} from 'node:buffer';
import {setTimeout} from 'node:timers/promises';
import {compose} from 'node:stream';
import {text, buffer} from 'node:stream/consumers';
Expand Down Expand Up @@ -88,6 +88,22 @@ test('handles infinite stream', async t => {
await t.throwsAsync(setup(infiniteIteration(), {maxBuffer: 1}), {instanceOf: MaxBufferError});
});

test('handles streams larger than buffer max length', async t => {
const chunkSize = 2 ** 16;
const chunkCount = Math.floor(BufferConstants.MAX_LENGTH / chunkSize * 2);
const chunk = Buffer.alloc(chunkSize);
const chunks = Array.from({length: chunkCount}, () => chunk);
await t.throwsAsync(setupBuffer(chunks));
});

test('handles streams larger than string max length', async t => {
const chunkSize = 2 ** 16;
const chunkCount = Math.floor(BufferConstants.MAX_STRING_LENGTH / chunkSize * 2);
const chunk = '.'.repeat(chunkSize);
const chunks = Array.from({length: chunkCount}, () => chunk);
await t.throwsAsync(setup(chunks));
});

test('native string', async t => {
const result = await text(compose(fixtureString));
t.is(result, fixtureString);
Expand Down

0 comments on commit 5ad2a98

Please sign in to comment.