Bug 1754320 - Re-escape existing escape sequences in precursor origins, r=ckerschb

Apparently the esc_NonASCIIOnly and esc_Forced flags to NS_EscapeURL are
incompatible, meaning that the escaping and unescaping code was not
handling existing escape sequences properly. This patch adds an explicit
gtest to make sure sequences round-trip correctly, and switches
serialization to use `esc_Query | esc_Forced` instead, which may escape
more aggressively than required but should work correctly.

Differential Revision: https://phabricator.services.mozilla.com/D142111
This commit is contained in:
Nika Layzell 2022-03-28 15:12:36 +00:00
parent b012e973e6
commit 5b2b8bc288
4 changed files with 63 additions and 4 deletions

View File

@ -76,18 +76,17 @@ already_AddRefed<NullPrincipal> NullPrincipal::CreateWithoutOriginAttributes() {
return NullPrincipal::Create(OriginAttributes(), nullptr);
}
static void EscapePrecursorQuery(nsACString& aPrecursorQuery) {
void NullPrincipal::EscapePrecursorQuery(nsACString& aPrecursorQuery) {
// origins should not contain existing escape sequences, so set `esc_Forced`
// to force any `%` in the input to be escaped in addition to non-ascii,
// control characters and DEL.
nsCString modified;
if (NS_EscapeURLSpan(aPrecursorQuery, esc_OnlyNonASCII | esc_Forced,
modified)) {
if (NS_EscapeURLSpan(aPrecursorQuery, esc_Query | esc_Forced, modified)) {
aPrecursorQuery.Assign(std::move(modified));
}
}
static void UnescapePrecursorQuery(nsACString& aPrecursorQuery) {
void NullPrincipal::UnescapePrecursorQuery(nsACString& aPrecursorQuery) {
nsCString modified;
if (NS_UnescapeURL(aPrecursorQuery.BeginReading(), aPrecursorQuery.Length(),
/* aFlags */ 0, modified)) {

View File

@ -116,6 +116,10 @@ class NullPrincipal final : public BasePrincipal {
private:
FRIEND_TEST(OriginAttributes, NullPrincipal);
FRIEND_TEST(NullPrincipalPrecursor, EscapingRoundTrips);
static void EscapePrecursorQuery(nsACString& aPrecursorQuery);
static void UnescapePrecursorQuery(nsACString& aPrecursorQuery);
// If aIsFirstParty is true, this NullPrincipal will be initialized based on
// the aOriginAttributes with FirstPartyDomain set to a unique value. This

View File

@ -0,0 +1,55 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/NullPrincipal.h"
#include "nsIURIMutator.h"
#include "nsPrintfCString.h"
namespace mozilla {
TEST(NullPrincipalPrecursor, EscapingRoundTrips)
{
nsTArray<nsCString> inputs;
inputs.AppendElements(mozilla::Span(std::array{
"mailbox:///dev/shm/tmp5wkt9ff_.mozrunner/Mail/Local%20Folders/secure-mail?number=5"_ns,
}));
// Add a string for every ASCII byte both escaped and unescaped.
for (uint8_t c = 0; c < 128; ++c) {
inputs.AppendElement(nsPrintfCString("%02X: %c", c, (char)c));
inputs.AppendElement(nsPrintfCString("%02X: %%%02X", c, c));
}
nsID dummyID{0xddf15eaf,
0x3837,
0x4678,
{0x80, 0x3b, 0x86, 0x86, 0xe8, 0x17, 0x66, 0x71}};
nsCOMPtr<nsIURI> baseURI = NullPrincipal::CreateURI(nullptr, &dummyID);
ASSERT_TRUE(baseURI);
for (auto& input : inputs) {
// First build an escaped version of the input string using
// `EscapePrecursorQuery`.
nsCString escaped(input);
NullPrincipal::EscapePrecursorQuery(escaped);
// Make sure that this escaped URI round-trips through a `moz-nullprincipal`
// URI's query without any additional escapes.
nsCOMPtr<nsIURI> clone;
EXPECT_TRUE(
NS_SUCCEEDED(NS_MutateURI(baseURI).SetQuery(escaped).Finalize(clone)));
nsCString query;
EXPECT_TRUE(NS_SUCCEEDED(clone->GetQuery(query)));
EXPECT_EQ(escaped, query);
// Try to unescape our escaped URI and make sure we recover the input
// string.
nsCString unescaped(escaped);
NullPrincipal::UnescapePrecursorQuery(unescaped);
EXPECT_EQ(input, unescaped);
}
}
} // namespace mozilla

View File

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
"TestNullPrincipalPrecursor.cpp",
"TestOriginAttributes.cpp",
"TestPrincipalAttributes.cpp",
"TestPrincipalSerialization.cpp",