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