summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extensions/fetch/21_formdata.js37
-rw-r--r--tools/wpt/expectation.json12
2 files changed, 36 insertions, 13 deletions
diff --git a/extensions/fetch/21_formdata.js b/extensions/fetch/21_formdata.js
index db4cfafa3..7b519ddc2 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)|(?<!\r)\n/g, "\r\n");
+ }
+
+ /**
+ * Performs the percent-escaping and the normalization required for field
+ * names and filenames in Content-Disposition headers.
+ * @param {string} name
+ * @param {boolean} isFilename Whether we are encoding a filename. This
+ * skips the newline normalization that takes place for field names.
+ * @returns {string}
+ */
+ #headerEscape(name, isFilename = false) {
+ if (!isFilename) {
+ name = this.#normalizeNewlines(name);
+ }
+ return name
+ .replaceAll("\n", "%0A")
+ .replaceAll("\r", "%0D")
+ .replaceAll('"', "%22");
+ }
}
/**
diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json
index a18e16b8f..f12aa16fd 100644
--- a/tools/wpt/expectation.json
+++ b/tools/wpt/expectation.json
@@ -990,16 +990,8 @@
},
"file": {
"File-constructor.any.html": true,
- "send-file-formdata-controls.any.html": [
- "Upload file-for-upload-in-form-LF-[\n].txt (ASCII) in fetch with FormData",
- "Upload file-for-upload-in-form-LF-CR-[\n\r].txt (ASCII) in fetch with FormData",
- "Upload file-for-upload-in-form-CR-[\r].txt (ASCII) in fetch with FormData",
- "Upload file-for-upload-in-form-CR-LF-[\r\n].txt (ASCII) in fetch with FormData"
- ],
- "send-file-formdata-punctuation.any.html": [
- "Upload file-for-upload-in-form-QUOTATION-MARK-[\"].txt (ASCII) in fetch with FormData",
- "Upload \"file-for-upload-in-form-double-quoted.txt\" (ASCII) in fetch with FormData"
- ],
+ "send-file-formdata-controls.any.html": true,
+ "send-file-formdata-punctuation.any.html": true,
"send-file-formdata-utf-8.any.html": true,
"send-file-formdata.any.html": true
},