Bug 1819280 - [websocket] Enforce full subprotocol char checks r=valentin

Enforce all subprotocol character checks as per RFC 6455 with a new method.
(See bug for full check details.)

Differential Revision: https://phabricator.services.mozilla.com/D171219
This commit is contained in:
CanadaHonk
2023-03-08 07:34:26 +00:00
parent baba174259
commit e30aa8a2d5
4 changed files with 38 additions and 42 deletions

View File

@@ -1255,6 +1255,34 @@ class AsyncOpenRunnable final : public WebSocketMainThreadRunnable {
} // namespace
// Check a protocol entry contains only valid characters
bool WebSocket::IsValidProtocolString(const nsString& aValue) {
// RFC 6455 (4.1): "not including separator characters as defined in RFC 2616"
const char16_t illegalCharacters[] = {0x28, 0x29, 0x3C, 0x3E, 0x40, 0x2C,
0x3B, 0x3A, 0x5C, 0x22, 0x2F, 0x5B,
0x5D, 0x3F, 0x3D, 0x7B, 0x7D};
// Cannot be empty string
if (aValue.IsEmpty()) {
return false;
}
const auto* start = aValue.BeginReading();
const auto* end = aValue.EndReading();
auto charFilter = [&](char16_t c) {
// RFC 6455 (4.1 P18): "in the range U+0021 to U+007E"
if (c < 0x21 || c > 0x7E) {
return true;
}
return std::find(std::begin(illegalCharacters), std::end(illegalCharacters),
c) != std::end(illegalCharacters);
};
return std::find_if(start, end, charFilter) == end;
}
already_AddRefed<WebSocket> WebSocket::ConstructorCommon(
const GlobalObject& aGlobal, const nsAString& aUrl,
const Sequence<nsString>& aProtocols,
@@ -1291,15 +1319,14 @@ already_AddRefed<WebSocket> WebSocket::ConstructorCommon(
for (uint32_t index = 0, len = aProtocols.Length(); index < len; ++index) {
const nsString& protocolElement = aProtocols[index];
if (protocolElement.IsEmpty()) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return nullptr;
}
// Repeated protocols are not allowed
if (protocolArray.Contains(protocolElement)) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return nullptr;
}
if (protocolElement.FindChar(',') != -1) /* interferes w/list */ {
// Protocol string value must match constraints
if (!IsValidProtocolString(protocolElement)) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return nullptr;
}
@@ -1718,11 +1745,8 @@ nsresult WebSocketImpl::Init(JSContext* aCx, bool aIsSecure,
// Assign the sub protocol list and scan it for illegal values
for (uint32_t index = 0; index < aProtocolArray.Length(); ++index) {
for (uint32_t i = 0; i < aProtocolArray[index].Length(); ++i) {
if (aProtocolArray[index][i] < static_cast<char16_t>(0x0021) ||
aProtocolArray[index][i] > static_cast<char16_t>(0x007E)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (!WebSocket::IsValidProtocolString(aProtocolArray[index])) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (!mRequestedProtocolList.IsEmpty()) {