Bug 1687820 - Fix bugs with null bytes in form payloads. r=smaug
On `multipart/form-data` payloads, a null byte on the name, filename or string value cuts off the rest of the name, filename or value. On `text/plain` payloads, a null byte anywhere cuts off the rest of the entire payload. This is because `nsLinebreakConverter::ConvertLineBreaks` is called without giving a length parameter, which causes it to treat the input C string as null-terminated. The tests for `text/plain` are under review on WPT: https://github.com/web-platform-tests/wpt/pull/26740 (https://wpt.fyi/results/html/semantics/forms/form-submission-0/text-plain.window.html?label=pr_head&max-count=1&pr=26740) Differential Revision: https://phabricator.services.mozilla.com/D102625
This commit is contained in:
@@ -388,9 +388,12 @@ nsresult FSMultipartFormData::AddNameValuePair(const nsAString& aName,
|
|||||||
nsresult rv = EncodeVal(aValue, encodedVal, false);
|
nsresult rv = EncodeVal(aValue, encodedVal, false);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
valueStr.Adopt(nsLinebreakConverter::ConvertLineBreaks(
|
int32_t convertedBufLength = 0;
|
||||||
|
char* convertedBuf = nsLinebreakConverter::ConvertLineBreaks(
|
||||||
encodedVal.get(), nsLinebreakConverter::eLinebreakAny,
|
encodedVal.get(), nsLinebreakConverter::eLinebreakAny,
|
||||||
nsLinebreakConverter::eLinebreakNet));
|
nsLinebreakConverter::eLinebreakNet, encodedVal.Length(),
|
||||||
|
&convertedBufLength);
|
||||||
|
valueStr.Adopt(convertedBuf, convertedBufLength);
|
||||||
|
|
||||||
nsAutoCString nameStr;
|
nsAutoCString nameStr;
|
||||||
rv = EncodeVal(aName, nameStr, true);
|
rv = EncodeVal(aName, nameStr, true);
|
||||||
@@ -450,10 +453,13 @@ nsresult FSMultipartFormData::AddNameBlobOrNullPair(const nsAString& aName,
|
|||||||
contentType16.AssignLiteral("application/octet-stream");
|
contentType16.AssignLiteral("application/octet-stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
contentType.Adopt(nsLinebreakConverter::ConvertLineBreaks(
|
NS_ConvertUTF16toUTF8 contentType8(contentType16);
|
||||||
NS_ConvertUTF16toUTF8(contentType16).get(),
|
int32_t convertedBufLength = 0;
|
||||||
nsLinebreakConverter::eLinebreakAny,
|
char* convertedBuf = nsLinebreakConverter::ConvertLineBreaks(
|
||||||
nsLinebreakConverter::eLinebreakSpace));
|
contentType8.get(), nsLinebreakConverter::eLinebreakAny,
|
||||||
|
nsLinebreakConverter::eLinebreakSpace, contentType8.Length(),
|
||||||
|
&convertedBufLength);
|
||||||
|
contentType.Adopt(convertedBuf, convertedBufLength);
|
||||||
|
|
||||||
// Get input stream
|
// Get input stream
|
||||||
aBlob->CreateInputStream(getter_AddRefs(fileStream), error);
|
aBlob->CreateInputStream(getter_AddRefs(fileStream), error);
|
||||||
@@ -681,9 +687,14 @@ nsresult FSTextPlain::GetEncodedSubmission(nsIURI* aURI,
|
|||||||
// encoded, but that how text/plain is specced.
|
// encoded, but that how text/plain is specced.
|
||||||
nsCString cbody;
|
nsCString cbody;
|
||||||
EncodeVal(mBody, cbody, false);
|
EncodeVal(mBody, cbody, false);
|
||||||
cbody.Adopt(nsLinebreakConverter::ConvertLineBreaks(
|
|
||||||
|
int32_t convertedBufLength = 0;
|
||||||
|
char* convertedBuf = nsLinebreakConverter::ConvertLineBreaks(
|
||||||
cbody.get(), nsLinebreakConverter::eLinebreakAny,
|
cbody.get(), nsLinebreakConverter::eLinebreakAny,
|
||||||
nsLinebreakConverter::eLinebreakNet));
|
nsLinebreakConverter::eLinebreakNet, cbody.Length(),
|
||||||
|
&convertedBufLength);
|
||||||
|
cbody.Adopt(convertedBuf, convertedBufLength);
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> bodyStream;
|
nsCOMPtr<nsIInputStream> bodyStream;
|
||||||
rv = NS_NewCStringInputStream(getter_AddRefs(bodyStream), std::move(cbody));
|
rv = NS_NewCStringInputStream(getter_AddRefs(bodyStream), std::move(cbody));
|
||||||
if (!bodyStream) {
|
if (!bodyStream) {
|
||||||
@@ -746,9 +757,12 @@ nsresult EncodingFormSubmission::EncodeVal(const nsAString& aStr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (aHeaderEncode) {
|
if (aHeaderEncode) {
|
||||||
aOut.Adopt(nsLinebreakConverter::ConvertLineBreaks(
|
int32_t convertedBufLength = 0;
|
||||||
|
char* convertedBuf = nsLinebreakConverter::ConvertLineBreaks(
|
||||||
aOut.get(), nsLinebreakConverter::eLinebreakAny,
|
aOut.get(), nsLinebreakConverter::eLinebreakAny,
|
||||||
nsLinebreakConverter::eLinebreakSpace));
|
nsLinebreakConverter::eLinebreakSpace, aOut.Length(),
|
||||||
|
&convertedBufLength);
|
||||||
|
aOut.Adopt(convertedBuf, convertedBufLength);
|
||||||
aOut.ReplaceSubstring("\""_ns, "\\\""_ns);
|
aOut.ReplaceSubstring("\""_ns, "\\\""_ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
[send-file-form-controls.html]
|
[send-file-form-controls.html]
|
||||||
[Upload file-for-upload-in-form-NUL-[\x00\].txt (ASCII) in UTF-8 form]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Upload file-for-upload-in-form-LF-[\n\].txt (ASCII) in UTF-8 form]
|
[Upload file-for-upload-in-form-LF-[\n\].txt (ASCII) in UTF-8 form]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
[send-file-formdata-controls.tentative.html]
|
[send-file-formdata-controls.tentative.html]
|
||||||
[Upload file-for-upload-in-form-NUL-[\x00\].txt (ASCII) in fetch with FormData]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Upload file-for-upload-in-form-LF-[\n\].txt (ASCII) in fetch with FormData]
|
[Upload file-for-upload-in-form-LF-[\n\].txt (ASCII) in fetch with FormData]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user