Skip to content

Commit 3fd0aa5

Browse files
nodejs-github-botRafaelGSS
authored andcommitted
deps: update undici to 6.28.0
PR-URL: #64714 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
1 parent 0d07248 commit 3fd0aa5

8 files changed

Lines changed: 159 additions & 19 deletions

File tree

deps/undici/src/lib/core/request.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,13 @@ function processHeader (request, key, val) {
350350
} else if (typeof val[i] === 'object') {
351351
throw new InvalidArgumentError(`invalid ${key} header`)
352352
} else {
353-
arr.push(`${val[i]}`)
353+
// Coerce primitives (and reject unsafe coercions such as functions
354+
// with a crafted toString/Symbol.toPrimitive).
355+
const str = `${val[i]}`
356+
if (!isValidHeaderValue(str)) {
357+
throw new InvalidArgumentError(`invalid ${key} header`)
358+
}
359+
arr.push(str)
354360
}
355361
}
356362
val = arr
@@ -361,7 +367,12 @@ function processHeader (request, key, val) {
361367
} else if (val === null) {
362368
val = ''
363369
} else {
370+
// Coerce primitives (and reject unsafe coercions such as functions
371+
// with a crafted toString/Symbol.toPrimitive).
364372
val = `${val}`
373+
if (!isValidHeaderValue(val)) {
374+
throw new InvalidArgumentError(`invalid ${key} header`)
375+
}
365376
}
366377

367378
if (headerName === 'host') {

deps/undici/src/lib/dispatcher/client-h1.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const {
1010
RequestContentLengthMismatchError,
1111
ResponseContentLengthMismatchError,
1212
RequestAbortedError,
13+
InvalidArgumentError,
1314
HeadersTimeoutError,
1415
HeadersOverflowError,
1516
SocketError,
@@ -993,8 +994,16 @@ function writeH1 (client, request) {
993994
}
994995
body = bodyStream.stream
995996
contentLength = bodyStream.length
996-
} else if (util.isBlobLike(body) && request.contentType == null && body.type) {
997-
headers.push('content-type', body.type)
997+
} else if (util.isBlobLike(body) && request.contentType == null) {
998+
const contentType = body.type
999+
if (contentType) {
1000+
const contentTypeValue = `${contentType}`
1001+
if (!util.isValidHeaderValue(contentTypeValue)) {
1002+
util.errorRequest(client, request, new InvalidArgumentError('invalid content-type header'))
1003+
return false
1004+
}
1005+
headers.push('content-type', contentTypeValue)
1006+
}
9981007
}
9991008

10001009
if (body && typeof body.read === 'function') {

deps/undici/src/lib/handler/retry-handler.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,28 @@ function calculateRetryAfterHeader (retryAfter) {
1515
return new Date(retryAfter).getTime() - current
1616
}
1717

18+
function validatePartialResponseContentLength (headers, range, statusCode, retryCount) {
19+
const contentLength = headers['content-length']
20+
if (contentLength == null) {
21+
return null
22+
}
23+
24+
if (!Number.isFinite(range.start) || !Number.isFinite(range.end)) {
25+
return null
26+
}
27+
28+
const length = Number(contentLength)
29+
const expectedLength = range.end - range.start + 1
30+
if (!Number.isFinite(length) || length !== expectedLength) {
31+
return new RequestRetryError('Content-Length mismatch', statusCode, {
32+
headers,
33+
data: { count: retryCount }
34+
})
35+
}
36+
37+
return null
38+
}
39+
1840
class RetryHandler {
1941
constructor (opts, handlers) {
2042
const { retryOptions, ...dispatchOpts } = opts
@@ -229,6 +251,12 @@ class RetryHandler {
229251
return false
230252
}
231253

254+
const contentLengthError = validatePartialResponseContentLength(headers, contentRange, statusCode, this.retryCount)
255+
if (contentLengthError != null) {
256+
this.abort(contentLengthError)
257+
return false
258+
}
259+
232260
const { start, size, end = size - 1 } = contentRange
233261

234262
assert(this.start === start, 'content-range mismatch')
@@ -252,6 +280,12 @@ class RetryHandler {
252280
)
253281
}
254282

283+
const contentLengthError = validatePartialResponseContentLength(headers, range, statusCode, this.retryCount)
284+
if (contentLengthError != null) {
285+
this.abort(contentLengthError)
286+
return false
287+
}
288+
255289
const { start, size, end = size - 1 } = range
256290
assert(
257291
start != null && Number.isFinite(start),

deps/undici/src/lib/llhttp/wasm_build_env.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11

2-
> undici@6.27.0 prebuild:wasm
2+
> undici@6.28.0 prebuild:wasm
33
> node build/wasm.js --prebuild
44

55
> docker build --platform=linux/x86_64 -t llhttp_wasm_builder -f /home/runner/work/node/node/deps/undici/src/build/Dockerfile /home/runner/work/node/node/deps/undici/src
66

77

88

9-
> undici@6.27.0 build:wasm
9+
> undici@6.28.0 build:wasm
1010
> node build/wasm.js --docker
1111

1212
> docker run --rm -t --platform=linux/x86_64 --user 1001:1001 --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/lib/llhttp,target=/home/node/undici/lib/llhttp llhttp_wasm_builder node build/wasm.js

deps/undici/src/lib/web/cookies/util.js

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ function validateCookiePath (path) {
105105

106106
if (
107107
code < 0x20 || // exclude CTLs (0-31)
108-
code === 0x7F || // DEL
108+
code > 0x7E || // exclude DEL and non-ascii
109109
code === 0x3B // ;
110110
) {
111111
throw new Error('Invalid cookie path')
@@ -114,16 +114,80 @@ function validateCookiePath (path) {
114114
}
115115

116116
/**
117-
* I have no idea why these values aren't allowed to be honest,
118-
* but Deno tests these. - Khafra
117+
* <let-dig> ::= <letter> | <digit>
118+
*
119+
* <letter> ::= any one of the 52 alphabetic characters A through Z in
120+
* upper case and a through z in lower case
121+
*
122+
* <digit> ::= any one of the ten digits 0 through 9r
123+
*
124+
* @see https://www.rfc-editor.org/rfc/rfc1034#section-3.5
125+
* @param {number} code
126+
*/
127+
function isLetterOrDigit (code) {
128+
return (
129+
(code >= 0x30 && code <= 0x39) || // 0-9
130+
(code >= 0x41 && code <= 0x5A) || // A-Z
131+
(code >= 0x61 && code <= 0x7A) // a-z
132+
)
133+
}
134+
135+
/**
136+
* Validates a cookie domain against the "preferred name syntax".
137+
*
138+
* <domain> ::= <subdomain> | " "
139+
* <subdomain> ::= <label> | <subdomain> "." <label>
140+
* <label> ::= <let-dig> [ [ <ldh-str> ] <let-dig> ]
141+
* <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
142+
* <let-dig-hyp> ::= <let-dig> | "-"
143+
*
144+
* @see https://www.rfc-editor.org/rfc/rfc1034#section-3.5
145+
* @see https://www.rfc-editor.org/rfc/rfc1123#section-2.1
146+
* @see https://www.rfc-editor.org/rfc/rfc1035#section-2.3.4
119147
* @param {string} domain
120148
*/
121149
function validateCookieDomain (domain) {
122-
if (
123-
domain.startsWith('-') ||
124-
domain.endsWith('.') ||
125-
domain.endsWith('-')
126-
) {
150+
// <domain> ::= <subdomain> | " "
151+
if (domain === ' ') {
152+
return
153+
}
154+
155+
if (domain.length > 255) {
156+
throw new Error('Invalid cookie domain')
157+
}
158+
159+
let labelLength = 0
160+
161+
for (let i = 0; i < domain.length; ++i) {
162+
const code = domain.charCodeAt(i)
163+
164+
if (code === 0x2E) {
165+
if (labelLength === 0) {
166+
throw new Error('Invalid cookie domain')
167+
}
168+
169+
if (domain.charCodeAt(i - 1) === 0x2D) { // "-"
170+
throw new Error('Invalid cookie domain')
171+
}
172+
173+
labelLength = 0
174+
continue
175+
}
176+
177+
if (labelLength === 0 && !isLetterOrDigit(code)) {
178+
throw new Error('Invalid cookie domain')
179+
}
180+
181+
if (!isLetterOrDigit(code) && code !== 0x2D) { // "-"
182+
throw new Error('Invalid cookie domain')
183+
}
184+
185+
if (++labelLength > 63) {
186+
throw new Error('Invalid cookie domain')
187+
}
188+
}
189+
190+
if (labelLength === 0 || domain.charCodeAt(domain.length - 1) === 0x2D) { // "-"
127191
throw new Error('Invalid cookie domain')
128192
}
129193
}
@@ -266,7 +330,13 @@ function stringify (cookie) {
266330

267331
const [key, ...value] = part.split('=')
268332

269-
out.push(`${key.trim()}=${value.join('=')}`)
333+
const trimmedKey = key.trim()
334+
const joinedValue = value.join('=')
335+
336+
validateCookieName(trimmedKey)
337+
validateCookieValue(joinedValue)
338+
339+
out.push(`${trimmedKey}=${joinedValue}`)
270340
}
271341

272342
return out.join('; ')

deps/undici/src/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "undici",
3-
"version": "6.27.0",
3+
"version": "6.28.0",
44
"description": "An HTTP/1.1 client, written from scratch for Node.js",
55
"homepage": "https://undici.nodejs.org",
66
"bugs": {

deps/undici/undici.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2280,7 +2280,11 @@ var require_request = __commonJS({
22802280
} else if (typeof val[i] === "object") {
22812281
throw new InvalidArgumentError(`invalid ${key} header`);
22822282
} else {
2283-
arr.push(`${val[i]}`);
2283+
const str = `${val[i]}`;
2284+
if (!isValidHeaderValue(str)) {
2285+
throw new InvalidArgumentError(`invalid ${key} header`);
2286+
}
2287+
arr.push(str);
22842288
}
22852289
}
22862290
val = arr;
@@ -2292,6 +2296,9 @@ var require_request = __commonJS({
22922296
val = "";
22932297
} else {
22942298
val = `${val}`;
2299+
if (!isValidHeaderValue(val)) {
2300+
throw new InvalidArgumentError(`invalid ${key} header`);
2301+
}
22952302
}
22962303
if (headerName === "host") {
22972304
if (request.host !== null) {
@@ -5921,6 +5928,7 @@ var require_client_h1 = __commonJS({
59215928
RequestContentLengthMismatchError,
59225929
ResponseContentLengthMismatchError,
59235930
RequestAbortedError,
5931+
InvalidArgumentError,
59245932
HeadersTimeoutError,
59255933
HeadersOverflowError,
59265934
SocketError,
@@ -6657,8 +6665,16 @@ var require_client_h1 = __commonJS({
66576665
}
66586666
body = bodyStream.stream;
66596667
contentLength = bodyStream.length;
6660-
} else if (util.isBlobLike(body) && request.contentType == null && body.type) {
6661-
headers.push("content-type", body.type);
6668+
} else if (util.isBlobLike(body) && request.contentType == null) {
6669+
const contentType = body.type;
6670+
if (contentType) {
6671+
const contentTypeValue = `${contentType}`;
6672+
if (!util.isValidHeaderValue(contentTypeValue)) {
6673+
util.errorRequest(client, request, new InvalidArgumentError("invalid content-type header"));
6674+
return false;
6675+
}
6676+
headers.push("content-type", contentTypeValue);
6677+
}
66626678
}
66636679
if (body && typeof body.read === "function") {
66646680
body.read(0);

src/undici_version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
// Refer to tools/dep_updaters/update-undici.sh
33
#ifndef SRC_UNDICI_VERSION_H_
44
#define SRC_UNDICI_VERSION_H_
5-
#define UNDICI_VERSION "6.27.0"
5+
#define UNDICI_VERSION "6.28.0"
66
#endif // SRC_UNDICI_VERSION_H_

0 commit comments

Comments
 (0)