Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2025-07-25 07:33:44 +08:00
commit be6796bb20
9 changed files with 401 additions and 65 deletions

View file

@ -2316,28 +2316,32 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
}
}
// Don't allow view-source scheme.
// view-source is the only scheme to which this applies at the moment due to
// potential timing attacks to read data from cross-origin documents. If this
// widens we should add a protocol flag for whether the scheme is only allowed
// in top and use something like nsNetUtil::NS_URIChainHasFlags.
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element
// requires that `embed` and `object` go through `Fetch` with mode=navigate,
// see 1.3.5. This will in https://fetch.spec.whatwg.org/#fetching plumb us
// through to https://fetch.spec.whatwg.org/#concept-main-fetch where in step
// 12 a switch is performed. Since `object` and `embed` have mode=navigate the
// result of https://fetch.spec.whatwg.org/#concept-scheme-fetch will decide
// if main fetch proceeds. We short-circuit that scheme-fetch here, inspecting
// if the scheme of `mURI` is one that would return a network error. The
// following schemes are allowed through in scheme fetch:
// "about", "blob", "data", "file", "http", "https".
// XXXMC: Should we include "ftp" as well?
//
// Some accessibility tests use our internal "chrome" scheme.
if (mType != eType_Null) {
nsCOMPtr<nsIURI> tempURI = mURI;
nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
while (nestedURI) {
// view-source should always be an nsINestedURI, loop and check the
// scheme on this and all inner URIs that are also nested URIs.
bool isViewSource = false;
rv = tempURI->SchemeIs("view-source", &isViewSource);
if (NS_FAILED(rv) || isViewSource) {
LOG(("OBJLC [%p]: Blocking as effective URI has view-source scheme",
this));
mType = eType_Null;
bool isCandidate = false;
for (const auto& candidate :
{"about", "blob", "chrome", "data", "file", "http", "https"}) {
rv = mURI->SchemeIs(candidate, &isCandidate);
if (NS_SUCCEEDED(rv) && isCandidate) {
break;
}
nestedURI->GetInnerURI(getter_AddRefs(tempURI));
nestedURI = do_QueryInterface(tempURI);
}
if (!isCandidate) {
LOG(("OBJLC [%p]: Blocking as effective URI does not have an allowed scheme",
this));
mType = eType_Null;
}
}

View file

@ -808,33 +808,51 @@ StripURIForReporting(nsIURI* aURI,
nsIURI* aSelfURI,
nsACString& outStrippedURI)
{
// 1) If the origin of uri is a globally unique identifier (for example,
// aURI has a scheme of data, blob, or filesystem), then return the
// ASCII serialization of uris scheme.
bool isHttpOrFtp =
(NS_SUCCEEDED(aURI->SchemeIs("http", &isHttpOrFtp)) && isHttpOrFtp) ||
(NS_SUCCEEDED(aURI->SchemeIs("https", &isHttpOrFtp)) && isHttpOrFtp) ||
(NS_SUCCEEDED(aURI->SchemeIs("ftp", &isHttpOrFtp)) && isHttpOrFtp);
bool isAllowedScheme =
(NS_SUCCEEDED(aURI->SchemeIs("http", &isAllowedScheme)) && isAllowedScheme) ||
(NS_SUCCEEDED(aURI->SchemeIs("https", &isAllowedScheme)) && isAllowedScheme) ||
(NS_SUCCEEDED(aURI->SchemeIs("ftp", &isAllowedScheme)) && isAllowedScheme) ||
(NS_SUCCEEDED(aURI->SchemeIs("ws", &isAllowedScheme)) && isAllowedScheme) ||
(NS_SUCCEEDED(aURI->SchemeIs("wss", &isAllowedScheme)) && isAllowedScheme);
if (!isHttpOrFtp) {
// not strictly spec compliant, but what we really care about is
// http/https and also ftp. If it's not http/https or ftp, then treat aURI
// as if it's a globally unique identifier and just return the scheme.
if (!isAllowedScheme) {
// Step 1. If url's scheme is not an allowed scheme, then just return url's scheme,
// i.e. treat aURI as a globally unique identifier.
// What we really care about reporting is http/https/ftp.
// https://github.com/w3c/webappsec-csp/issues/735: We also allow WS(S) schemes.
aURI->GetScheme(outStrippedURI);
return;
}
// 2) If the origin of uri is not the same as the origin of the protected
// resource, then return the ASCII serialization of uris origin.
if (!NS_SecurityCompareURIs(aSelfURI, aURI, false)) {
// cross origin redirects also fall into this category, see:
// http://www.w3.org/TR/CSP/#violation-reports
aURI->GetPrePath(outStrippedURI);
// Step 2. Set url's fragment to the empty string.
// Implicit in GetSpecIgnoringRef() below.
// Step 3. Set url's username/password to the empty string.
nsCOMPtr<nsIURI> stripped;
nsresult rv = aURI->Clone(getter_AddRefs(stripped));
if (NS_FAILED(rv)) {
// Cloning the URI failed for some reason, just return the scheme.
aURI->GetScheme(outStrippedURI);
return;
}
rv = stripped->SetUserPass(EmptyCString());
if (NS_FAILED(rv)) {
// Mutating the URI failed for some reason, just return the scheme.
aURI->GetScheme(outStrippedURI);
return;
}
// 3) Return uri, with any fragment component removed.
aURI->GetSpecIgnoringRef(outStrippedURI);
// Non-standard: https://github.com/w3c/webappsec-csp/issues/735
// We match other browsers here: To avoid leaking the whole URL when blocking
// (or reporting!) cross-origin navigations inside a frame, we restrict the URLs
// to just the (ASCII serialization of) uri's origin.
if (!NS_SecurityCompareURIs(aSelfURI, stripped, false)) {
stripped->GetPrePath(outStrippedURI);
return;
}
// Step 4. Return uri, with any unwanted component removed.
stripped->GetSpecIgnoringRef(outStrippedURI);
}
nsresult

View file

@ -448,7 +448,7 @@ class gfxFontEntry::FontTableBlobData {
public:
explicit FontTableBlobData(nsTArray<uint8_t>&& aBuffer)
: mTableData(Move(aBuffer))
, mHashtable(nullptr)
, mFontEntry(nullptr)
, mHashKey(0)
{
MOZ_COUNT_CTOR(FontTableBlobData);
@ -456,8 +456,9 @@ public:
~FontTableBlobData() {
MOZ_COUNT_DTOR(FontTableBlobData);
if (mHashtable && mHashKey) {
mHashtable->RemoveEntry(mHashKey);
if (mFontEntry && mHashKey) {
RefPtr<gfxFontEntry> kungFuDeathGrip(mFontEntry);
mFontEntry->mFontTableCache->RemoveEntry(mHashKey);
}
}
@ -470,10 +471,10 @@ public:
// Tell this FontTableBlobData to remove the HashEntry when this is
// destroyed.
void ManageHashEntry(nsTHashtable<FontTableHashEntry> *aHashtable,
void ManageHashEntry(gfxFontEntry* aFontEntry,
uint32_t aHashKey)
{
mHashtable = aHashtable;
mFontEntry = aFontEntry;
mHashKey = aHashKey;
}
@ -481,7 +482,7 @@ public:
// removed from the hashtable).
void ForgetHashEntry()
{
mHashtable = nullptr;
mFontEntry = nullptr;
mHashKey = 0;
}
@ -496,10 +497,11 @@ private:
// The font table data block
nsTArray<uint8_t> mTableData;
// The blob destroy function needs to know the owning hashtable
// and the hashtable key, so that it can remove the entry.
nsTHashtable<FontTableHashEntry> *mHashtable;
uint32_t mHashKey;
// The blob destroy function needs to know the owning font entry
// so that it can hold the font-entry's reference while modifying the
// hashtable; and the hashtable key, so that it can remove the entry.
gfxFontEntry* mFontEntry;
uint32_t mHashKey;
// not implemented
FontTableBlobData(const FontTableBlobData&);
@ -508,7 +510,7 @@ private:
hb_blob_t *
gfxFontEntry::FontTableHashEntry::
ShareTableAndGetBlob(nsTArray<uint8_t>&& aTable,
nsTHashtable<FontTableHashEntry> *aHashtable)
gfxFontEntry* aFontEntry)
{
Clear();
// adopts elements of aTable
@ -528,7 +530,7 @@ ShareTableAndGetBlob(nsTArray<uint8_t>&& aTable,
// Tell the FontTableBlobData to remove this hash entry when destroyed.
// The hashtable does not keep a strong reference.
mSharedBlobData->ManageHashEntry(aHashtable, GetKey());
mSharedBlobData->ManageHashEntry(aFontEntry, GetKey());
return mBlob;
}
@ -600,7 +602,7 @@ gfxFontEntry::ShareFontTableAndGetBlob(uint32_t aTag,
return nullptr;
}
return entry->ShareTableAndGetBlob(Move(*aBuffer), mFontTableCache.get());
return entry->ShareTableAndGetBlob(Move(*aBuffer), this);
}
already_AddRefed<gfxCharacterMap>

View file

@ -534,11 +534,11 @@ private:
// Transfer (not copy) elements of aTable to a new hb_blob_t and
// return ownership to the caller. A weak reference to the blob is
// recorded in the hashtable entry so that others may use the same
// table.
// recorded in the font entry's table cache so that others may use
// the same table.
hb_blob_t *
ShareTableAndGetBlob(nsTArray<uint8_t>&& aTable,
nsTHashtable<FontTableHashEntry> *aHashtable);
gfxFontEntry* aFontEntry);
// Return a strong reference to the blob.
// Callers must hb_blob_destroy the returned blob.

View file

@ -148,11 +148,11 @@ var exp = asmLink(asmCompile(USE_ASM + "var x=0; function a() { return x|0 } fun
assertEq(exp.c(10), undefined);
assertEq(exp.a(), 10);
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case 1: i=-1; break; case 133742: i=2; break; default: i=42; break } return i|0 } return f"));
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case 1: i=-1; break; case 65520: i=2; break; default: i=42; break } return i|0 } return f"));
assertEq(f(1), -1);
assertEq(f(2), 42);
assertEq(f(133742), 2);
assertEq(f(133743), 42);
assertEq(f(65520), 2);
assertEq(f(65521), 42);
var f = asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; switch(i|0) { case 1: i=42; break; default: i=13 } return i|0 } return f"));
assertEq(f(-1), 13);

View file

@ -1332,7 +1332,7 @@ static const unsigned MaxTableElems = 1024 * 1024;
static const unsigned MaxDataSegments = 64 * 1024;
static const unsigned MaxElemSegments = 64 * 1024;
static const unsigned MaxArgsPerFunc = 4 * 1024;
static const unsigned MaxBrTableElems = 4 * 1024 * 1024;
static const unsigned MaxBrTableElems = 65520;
// To be able to assign function indices during compilation while the number of
// imports is still unknown, asm.js sets a maximum number of imports so it can

View file

@ -0,0 +1,304 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Conditional Tests: @supports selector() - Complete Test Suite</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.4;
margin: 20px;
max-width: 800px;
}
h1 {
text-align: center;
border-bottom: 1px solid #ccc;
padding-bottom: 10px;
}
.test {
border: 1px solid #ddd;
margin: 20px 0;
padding: 15px;
}
.test h2 {
margin: 0 0 10px 0;
font-size: 1.1em;
}
.test-output {
height: 100px;
width: 100px;
border: 1px solid #999;
margin: 10px 0;
}
.expected {
font-weight: bold;
color: green;
}
code {
background: #f5f5f5;
padding: 2px 4px;
}
</style>
</head>
<body>
<h1>CSS Conditional Tests: @supports selector() - Complete Test Suite</h1>
<!-- Test 1 -->
<div class="test">
<h2>Test 1: @supports selector() with multiple selectors doesn't work</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong> and <strong>no red</strong>.</p>
<p>This tests whether browsers correctly fail the condition for multiple selectors in <code>selector()</code>.</p>
<div class="test-output" id="test1-output"></div>
</div>
<!-- Test 2 -->
<div class="test">
<h2>Test 2: @supports selector() with -webkit- unknown pseudo-elements and negation</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong> and <strong>no red</strong>.</p>
<p>This tests whether browsers correctly handle negation with an unknown pseudo-element.</p>
<div class="test-output" id="test2-output"></div>
</div>
<!-- Test 3 -->
<div class="test">
<h2>Test 3: @supports selector() with pseudo-elements</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong> and <strong>no red</strong>.</p>
<p>This tests whether browsers recognize pseudo-elements in the <code>selector()</code> function.</p>
<div class="test-output" id="test3-output"></div>
</div>
<!-- Test 4 -->
<div class="test">
<h2>Test 4: @supports selector() with compound selector</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong> and <strong>no red</strong>.</p>
<p>This tests whether browsers can handle complex compound selectors in the <code>selector()</code> function.</p>
<div class="test-output" id="test4-output"></div>
</div>
<!-- Test 5 -->
<div class="test">
<h2>Test 5: @supports selector() with unsupported but valid pseudo and negation</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong> and <strong>no red</strong>.</p>
<p>This tests whether browsers give back a valid syntax selector<br />
(obscure edge case CSS used: <b>:nth-child(1 of .foo)</b>) that isn't actually supported.</p>
<div class="test-output" id="test5-output"></div>
</div>
<!-- Test 6 -->
<div class="test">
<h2>Test 6: @supports selector() with cascade of selectors</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong> and <strong>no red</strong>.</p>
<p>This tests whether browsers can handle passing cascaded selectors.</p>
<div class="test-output" id="test6-output"></div>
</div>
<!-- Test 7 -->
<div class="test">
<h2>Test 7: @supports selector() with :has() pseudo-class and negation</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong> and <strong>no red</strong>.</p>
<p>This tests whether browsers correctly identify support for the :has() pseudo-class. This is not supported yet.</p>
<div class="test-output" id="test7-output"></div>
</div>
<!-- Test 8.1 -->
<div class="test">
<h2>Test 8.1: @supports selector(:nth-child(5n))</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong>.</p>
<div class="test-output" id="test8-output-1"></div>
</div>
<!-- Test 8.2 -->
<div class="test">
<h2>Test 8.2: @supports selector(:nth-child(2n))</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong>.</p>
<div class="test-output" id="test8-output-2"></div>
</div>
<!-- Test 8.3 -->
<div class="test">
<h2>Test 8.3: @supports selector(li:nth-child(2n))</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong>.</p>
<div class="test-output" id="test8-output-3"></div>
</div>
<!-- Test 8.4 -->
<div class="test">
<h2>Test 8.4: @supports selector(:nth-child(odd))</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong>.</p>
<div class="test-output" id="test8-output-4"></div>
</div>
<!-- Test 8.5 -->
<div class="test">
<h2>Test 8.5: @supports selector(:nth-child(even))</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong>.</p>
<div class="test-output" id="test8-output-5"></div>
</div>
<!-- Test 8.6 -->
<div class="test">
<h2>Test 8.6: @supports selector(:nth-child(3n+1))</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong>.</p>
<div class="test-output" id="test8-output-6"></div>
</div>
<!-- Test 8.7 -->
<div class="test">
<h2>Test 8.7: @supports selector(:nth-child(2n + 2))</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong>.</p>
<div class="test-output" id="test8-output-7"></div>
</div>
<!-- Test 9 -->
<div class="test">
<h2>Test 9: @supports not selector(div)</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong>.</p>
<div class="test-output" id="test9-output"></div>
</div>
<!-- Test 10 -->
<div class="test">
<h2>Test 10: Complex selector chain<br>
@supports selector(section > div:nth-child(2n+1):not(.foo, .bar):hover)</h2>
<p>Test passes if there is a <strong class="expected">filled green square</strong>.</p>
<div class="test-output" id="test10-output"></div>
</div>
<style>
/* Test 1 Styles */
#test1-output {
background-color: green;
}
@supports selector(div, div) {
#test1-output { background: red; }
}
/* Test 2 Styles */
#test2-output {
background-color: red;
}
@supports not selector(::-webkit-unknown-pseudo) {
#test2-output { background: green; }
}
/* Test 3 Styles */
#test3-output {
background-color: red;
}
@supports selector(::before) {
#test3-output { background: green; }
}
/* Test 4 Styles */
#test4-output {
background-color: red;
}
@supports selector(a:link.class#ident) {
#test4-output { background: green; }
}
/* Test 5 Styles */
#test5-output {
background-color: red;
}
@supports not selector(:nth-child(1 of .foo)) {
#test5-output { background: green; }
}
/* Test 6 Styles */
#test6-output {
background-color: red;
}
@supports selector(div > h2 + p) {
#test6-output { background: green; }
}
/* Test 7 Styles */
#test7-output {
background-color: red;
}
@supports not selector(div:has(p)) {
#test7-output { background: green; }
}
/* Test 8.1 Styles */
#test8-output-1 {
background-color: red;
}
@supports selector(:nth-child(5n)) {
#test8-output-1 { background: green; }
}
/* Test 8.2 Styles */
#test8-output-2 {
background-color: red;
}
@supports selector(:nth-child(2n)) {
#test8-output-2 { background: green; }
}
/* Test 8.3 Styles */
#test8-output-3 {
background-color: red;
}
@supports selector(li:nth-child(2n)) {
#test8-output-3 { background: green; }
}
/* Test 8.4 Styles */
#test8-output-4 {
background-color: red;
}
@supports selector(:nth-child(odd)) {
#test8-output-4 { background: green; }
}
/* Test 8.5 Styles */
#test8-output-5 {
background-color: red;
}
@supports selector(:nth-child(even)) {
#test8-output-5 { background: green; }
}
/* Test 8.6 Styles */
#test8-output-6 {
background-color: red;
}
@supports selector(:nth-child(3n+1)) {
#test8-output-6 { background: green; }
}
/* Test 8.7 Styles */
#test8-output-7 {
background-color: red;
}
@supports selector(:nth-child(2n + 2)) {
#test8-output-7 { background: green; }
}
/* Test 9 Styles */
#test9-output {
background-color: green;
}
@supports not selector(div) {
#test9-output { background: red; }
}
/* Test 10 Styles */
#test10-output {
background-color: red;
}
@supports selector(section > div:nth-child(2n+1):not(.foo, .bar):hover) {
#test10-output { background: green; }
}
</style>
</body>
</html>

View file

@ -3125,6 +3125,15 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader, "invalid name character");
return newCookie;
}
// RFC 6265 *explicitly* forbids nameless cookies (5.2 step 5)
// Note: we ignore RFC 6265 (bis)'s conflicting stipulation and treat equal-less cookies
// as value-less cookies, not nameless ones.
// This aligns with webkit/Safari and avoids serious sec issues like CVE-2025-8037.
if (cookieAttributes.name.IsEmpty()) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader, "nameless cookies are not allowed");
return newCookie;
}
// domain & path checks
if (!CheckDomain(cookieAttributes, aHostURI, aKey.mBaseDomain, aRequireHostMatch)) {
@ -3574,15 +3583,11 @@ nsCookieService::ParseAttributes(nsDependentCString &aCookieHeader,
// extract cookie <NAME> & <VALUE> (first attribute), and copy the strings.
// if we find multiple cookies, return for processing
// note: if there's no '=', we assume token is <VALUE>. this is required by
// some sites (see bug 169091).
// XXX fix the parser to parse according to <VALUE> grammar for this case
// note: if there's no '=', we assume token is <NAME>.
newCookie = GetTokenValue(cookieStart, cookieEnd, tokenString, tokenValue, equalsFound);
aCookieAttributes.name = tokenString;
if (equalsFound) {
aCookieAttributes.name = tokenString;
aCookieAttributes.value = tokenValue;
} else {
aCookieAttributes.value = tokenString;
}
// extract remaining attributes

View file

@ -3164,6 +3164,9 @@ XREMain::XRE_mainStartup(bool* aExitFlag)
#endif
#if defined(MOZ_WIDGET_GTK)
// Set up fontconfig.
FcInit();
// setup for private colormap. Ideally we'd like to do this
// in nsAppShell::Create, but we need to get in before gtk
// has been initialized to make sure everything is running