diff --git a/extensions/fetch/21_formdata.js b/extensions/fetch/21_formdata.js index db4cfafa35..7b519ddc2a 100644 --- a/extensions/fetch/21_formdata.js +++ b/extensions/fetch/21_formdata.js @@ -323,11 +323,13 @@ filename, type, ) { + const escapedField = this.#headerEscape(field); + const escapedFilename = this.#headerEscape(filename, true); /** @type {[string, string][]} */ const headers = [ [ "Content-Disposition", - `form-data; name="${field}"; filename="${filename}"`, + `form-data; name="${escapedField}"; filename="${escapedFilename}"`, ], ["Content-Type", type || "application/octet-stream"], ]; @@ -340,7 +342,10 @@ */ #writeFieldHeaders(field) { /** @type {[string, string][]} */ - const headers = [["Content-Disposition", `form-data; name="${field}"`]]; + const headers = [[ + "Content-Disposition", + `form-data; name="${this.#headerEscape(field)}"`, + ]]; return this.#writeHeaders(headers); } @@ -351,7 +356,7 @@ */ #writeField(field, value) { this.#writeFieldHeaders(field); - this.chunks.push(encoder.encode(value)); + this.chunks.push(encoder.encode(this.#normalizeNewlines(value))); } /** @@ -363,6 +368,32 @@ this.#writeFileHeaders(field, value.name, value.type); this.chunks.push(value[_byteSequence]); } + + /** + * @param {string} string + * @returns {string} + */ + #normalizeNewlines(string) { + return string.replace(/\r(?!\n)|(?