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:
Andreu Botella
2021-01-23 20:25:05 +00:00
parent 0dd3b1bc1c
commit 70b6deef58
3 changed files with 24 additions and 16 deletions

View File

@@ -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);
} }

View File

@@ -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

View File

@@ -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