ma1 pushed to branch tor-browser-115.28.0esr-13.5-1 at The Tor Project / Applications / Tor Browser
Commits:
-
2bd05cc0
by Daniel Holbert at 2025-09-15T19:02:10+02:00
-
ecda4d58
by Jon Coppeard at 2025-09-15T19:36:49+02:00
-
688debf8
by Lee Salzman at 2025-09-15T19:57:24+02:00
-
1a51c17d
by Jed Davis at 2025-09-15T20:11:50+02:00
5 changed files:
- dom/canvas/WebGLContext.cpp
- dom/security/nsContentSecurityManager.cpp
- js/src/gc/Statistics.cpp
- modules/libpref/init/StaticPrefList.yaml
- security/sandbox/linux/launch/SandboxLaunch.cpp
Changes:
... | ... | @@ -7,8 +7,9 @@ |
7 | 7 | |
8 | 8 | #include <algorithm>
|
9 | 9 | #include <bitset>
|
10 | +#include <cctype>
|
|
11 | +#include <iterator>
|
|
10 | 12 | #include <queue>
|
11 | -#include <regex>
|
|
12 | 13 | |
13 | 14 | #include "AccessCheck.h"
|
14 | 15 | #include "CompositableHost.h"
|
... | ... | @@ -2011,30 +2012,59 @@ Maybe<std::string> WebGLContext::GetString(const GLenum pname) const { |
2011 | 2012 | // ---------------------------------
|
2012 | 2013 | |
2013 | 2014 | Maybe<webgl::IndexedName> webgl::ParseIndexed(const std::string& str) {
|
2014 | - static const std::regex kRegex("(.*)\\[([0-9]+)\\]");
|
|
2015 | - |
|
2016 | - std::smatch match;
|
|
2017 | - if (!std::regex_match(str, match, kRegex)) return {};
|
|
2015 | + // Check if the string ends with a close bracket
|
|
2016 | + if (str.size() < 2 || str.back() != ']') {
|
|
2017 | + return {};
|
|
2018 | + }
|
|
2019 | + // Search for the open bracket, only allow digits between brackets
|
|
2020 | + const size_t closeBracket = str.size() - 1;
|
|
2021 | + size_t openBracket = closeBracket;
|
|
2022 | + for (;;) {
|
|
2023 | + char c = str[--openBracket];
|
|
2024 | + if (isdigit(c)) {
|
|
2025 | + if (openBracket <= 0) {
|
|
2026 | + // At the beginning of string without an open bracket
|
|
2027 | + return {};
|
|
2028 | + }
|
|
2029 | + } else if (c == '[') {
|
|
2030 | + // Found the open bracket
|
|
2031 | + break;
|
|
2032 | + } else {
|
|
2033 | + // Found a non-digit
|
|
2034 | + return {};
|
|
2035 | + }
|
|
2036 | + }
|
|
2018 | 2037 | |
2019 | - const auto index = std::stoull(match[2]);
|
|
2020 | - return Some(webgl::IndexedName{match[1], index});
|
|
2038 | + // Ensure non-empty digit sequence
|
|
2039 | + size_t firstDigit = openBracket + 1;
|
|
2040 | + if (firstDigit >= closeBracket) {
|
|
2041 | + return {};
|
|
2042 | + }
|
|
2043 | + const auto index =
|
|
2044 | + std::stoull(str.substr(firstDigit, closeBracket - firstDigit));
|
|
2045 | + std::string name = str.substr(0, openBracket);
|
|
2046 | + return Some(webgl::IndexedName{name, index});
|
|
2021 | 2047 | }
|
2022 | 2048 | |
2023 | 2049 | // ExplodeName("foo.bar[3].x") -> ["foo", ".", "bar", "[", "3", "]", ".", "x"]
|
2024 | 2050 | static std::vector<std::string> ExplodeName(const std::string& str) {
|
2025 | 2051 | std::vector<std::string> ret;
|
2026 | - |
|
2027 | - static const std::regex kSep("[.[\\]]");
|
|
2028 | - |
|
2029 | - auto itr = std::regex_token_iterator<decltype(str.begin())>(
|
|
2030 | - str.begin(), str.end(), kSep, {-1, 0});
|
|
2031 | - const auto end = decltype(itr)();
|
|
2032 | - |
|
2033 | - for (; itr != end; ++itr) {
|
|
2034 | - const auto& part = itr->str();
|
|
2035 | - if (part.size()) {
|
|
2036 | - ret.push_back(part);
|
|
2052 | + size_t curPos = 0;
|
|
2053 | + while (curPos < str.size()) {
|
|
2054 | + // Find the next separator
|
|
2055 | + size_t nextPos = str.find_first_of(".[]", curPos);
|
|
2056 | + if (nextPos == std::string::npos) {
|
|
2057 | + // If no separator found, add remaining substring
|
|
2058 | + ret.push_back(str.substr(curPos));
|
|
2059 | + break;
|
|
2060 | + }
|
|
2061 | + // Add string between separators, if not empty
|
|
2062 | + if (curPos < nextPos) {
|
|
2063 | + ret.push_back(str.substr(curPos, nextPos - curPos));
|
|
2037 | 2064 | }
|
2065 | + // Add the separator
|
|
2066 | + ret.push_back(str.substr(nextPos, 1));
|
|
2067 | + curPos = nextPos + 1;
|
|
2038 | 2068 | }
|
2039 | 2069 | return ret;
|
2040 | 2070 | }
|
... | ... | @@ -45,6 +45,7 @@ |
45 | 45 | #include "mozilla/Logging.h"
|
46 | 46 | #include "mozilla/Maybe.h"
|
47 | 47 | #include "mozilla/Preferences.h"
|
48 | +#include "mozilla/StaticPrefs_content.h"
|
|
48 | 49 | #include "mozilla/StaticPrefs_dom.h"
|
49 | 50 | #include "mozilla/StaticPrefs_security.h"
|
50 | 51 | #include "mozilla/Telemetry.h"
|
... | ... | @@ -364,10 +365,17 @@ static nsresult DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo, |
364 | 365 | return NS_OK;
|
365 | 366 | }
|
366 | 367 | |
367 | - // We use the triggering principal here, rather than the loading principal
|
|
368 | - // to ensure that anonymous CORS content in the browser resources and in
|
|
369 | - // WebExtensions is allowed to load.
|
|
370 | - nsIPrincipal* principal = aLoadInfo->TriggeringPrincipal();
|
|
368 | + nsIPrincipal* principal = aLoadInfo->GetLoadingPrincipal();
|
|
369 | + if (StaticPrefs::content_cors_use_triggering_principal()) {
|
|
370 | + // We use the triggering principal here, rather than the loading principal,
|
|
371 | + // to ensure that WebExtensions can reuse their own resources from content
|
|
372 | + // that they inject into a page.
|
|
373 | + //
|
|
374 | + // TODO(dholbert): Is there actually a legitimate reason that WebExtensions
|
|
375 | + // might need this (as opposed to exposing their resources for use in
|
|
376 | + // web-content via the 'web_accessible_resources' manifest field)?
|
|
377 | + principal = aLoadInfo->TriggeringPrincipal();
|
|
378 | + }
|
|
371 | 379 | RefPtr<nsCORSListenerProxy> corsListener = new nsCORSListenerProxy(
|
372 | 380 | aInAndOutListener, principal,
|
373 | 381 | aLoadInfo->GetCookiePolicy() == nsILoadInfo::SEC_COOKIES_INCLUDE);
|
... | ... | @@ -1515,7 +1515,7 @@ void Statistics::recordParallelPhase(PhaseKind phaseKind, |
1515 | 1515 | TimeDuration duration) {
|
1516 | 1516 | MOZ_ASSERT(CurrentThreadCanAccessRuntime(gc->rt));
|
1517 | 1517 | |
1518 | - if (aborted) {
|
|
1518 | + if (slices_.empty()) {
|
|
1519 | 1519 | return;
|
1520 | 1520 | }
|
1521 | 1521 |
... | ... | @@ -1915,6 +1915,14 @@ |
1915 | 1915 | value: false
|
1916 | 1916 | mirror: always
|
1917 | 1917 | |
1918 | +# If true, we'll use the triggering principal rather than the loading principal
|
|
1919 | +# when doing CORS checks. This might be needed for WebExtensions to load their
|
|
1920 | +# own resources from content that they inject into sites.
|
|
1921 | +- name: content.cors.use_triggering_principal
|
|
1922 | + type: bool
|
|
1923 | + value: false
|
|
1924 | + mirror: always
|
|
1925 | + |
|
1918 | 1926 | # Back off timer notification after count.
|
1919 | 1927 | # -1 means never.
|
1920 | 1928 | - name: content.notify.backoffcount
|
... | ... | @@ -317,6 +317,8 @@ void SandboxLaunchPrepare(GeckoProcessType aType, |
317 | 317 | return;
|
318 | 318 | }
|
319 | 319 | |
320 | + // Warning: don't combine multiple case labels, even if the code is
|
|
321 | + // currently the same, to avoid mistakes when changes are made.
|
|
320 | 322 | switch (aType) {
|
321 | 323 | case GeckoProcessType_Socket:
|
322 | 324 | if (level >= 1) {
|
... | ... | @@ -325,6 +327,12 @@ void SandboxLaunchPrepare(GeckoProcessType aType, |
325 | 327 | }
|
326 | 328 | break;
|
327 | 329 | case GeckoProcessType_GMPlugin:
|
330 | + if (level >= 1) {
|
|
331 | + canChroot = true;
|
|
332 | + flags |= CLONE_NEWIPC;
|
|
333 | + flags |= CLONE_NEWNET;
|
|
334 | + }
|
|
335 | + break;
|
|
328 | 336 | case GeckoProcessType_RDD:
|
329 | 337 | if (level >= 1) {
|
330 | 338 | canChroot = true;
|