Skip to content

Commit ece771c

Browse files
fix(fetch): use || for CRLF check in multipart formdata-parser (#5049)
1 parent d2e8178 commit ece771c

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

lib/web/fetch/formdata-parser.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,8 @@ function parseMultipartFormDataHeaders (input, position) {
383383
// Parse attributes recursively until CRLF
384384
while (
385385
position.position < input.length &&
386-
input[position.position] !== 0x0d &&
387-
input[position.position + 1] !== 0x0a
386+
(input[position.position] !== 0x0d ||
387+
input[position.position + 1] !== 0x0a)
388388
) {
389389
const attribute = parseContentDispositionAttribute(input, position)
390390

@@ -448,7 +448,7 @@ function parseMultipartFormDataHeaders (input, position) {
448448

449449
// 2.9. If position does not point to a sequence of bytes starting with 0x0D 0x0A
450450
// (CR LF), return failure. Otherwise, advance position by 2 (past the newline).
451-
if (input[position.position] !== 0x0d && input[position.position + 1] !== 0x0a) {
451+
if (input[position.position] !== 0x0d || input[position.position + 1] !== 0x0a) {
452452
throw parsingError('expected CRLF')
453453
} else {
454454
position.position += 2

test/fetch/formdata.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,3 +383,26 @@ test('.formData() with multipart/form-data body that ends with --\r\n', async (t
383383

384384
await request.formData()
385385
})
386+
387+
test('.formData() rejects malformed multipart header line ending with bare CR', async (t) => {
388+
const boundary = '----formdata-undici-bare-cr-0000000000'
389+
const body = Buffer.concat([
390+
Buffer.from('--' + boundary + '\r\n'),
391+
Buffer.from('Content-Disposition: form-data; name="x"'),
392+
Buffer.from([0x0d]), // bare CR (no LF)
393+
Buffer.from('Content-Type: text/plain\r\n'),
394+
Buffer.from('\r\n'),
395+
Buffer.from('hello\r\n'),
396+
Buffer.from('--' + boundary + '--\r\n')
397+
])
398+
399+
const request = new Request('http://localhost', {
400+
method: 'POST',
401+
headers: {
402+
'Content-Type': 'multipart/form-data; boundary=' + boundary
403+
},
404+
body
405+
})
406+
407+
await t.assert.rejects(request.formData(), TypeError)
408+
})

0 commit comments

Comments
 (0)