Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp
Warning:line 2083, column 5
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_dom_security0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/security -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/security -resource-dir /usr/lib/llvm-20/lib/clang/20 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/dom/security -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/security -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/caps -I /var/lib/jenkins/workspace/firefox-scan-build/docshell/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/data -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-20/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-01-20-090804-167946-1 -x c++ Unified_cpp_dom_security0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include <string>
8#include <unordered_set>
9#include <utility>
10
11#include "nsCOMPtr.h"
12#include "nsContentPolicyUtils.h"
13#include "nsContentSecurityUtils.h"
14#include "nsContentUtils.h"
15#include "nsCSPContext.h"
16#include "nsCSPParser.h"
17#include "nsCSPService.h"
18#include "nsCSPUtils.h"
19#include "nsGlobalWindowOuter.h"
20#include "nsError.h"
21#include "nsIAsyncVerifyRedirectCallback.h"
22#include "nsIClassInfoImpl.h"
23#include "mozilla/dom/Document.h"
24#include "nsIHttpChannel.h"
25#include "nsIInterfaceRequestor.h"
26#include "nsIInterfaceRequestorUtils.h"
27#include "nsIObjectInputStream.h"
28#include "nsIObjectOutputStream.h"
29#include "nsIObserver.h"
30#include "nsIObserverService.h"
31#include "nsIStringStream.h"
32#include "nsISupportsPrimitives.h"
33#include "nsIUploadChannel.h"
34#include "nsIURIMutator.h"
35#include "nsIScriptError.h"
36#include "nsMimeTypes.h"
37#include "nsNetUtil.h"
38#include "nsIContentPolicy.h"
39#include "nsSupportsPrimitives.h"
40#include "nsThreadUtils.h"
41#include "nsString.h"
42#include "nsScriptSecurityManager.h"
43#include "nsStringStream.h"
44#include "mozilla/Logging.h"
45#include "mozilla/Preferences.h"
46#include "mozilla/StaticPrefs_security.h"
47#include "mozilla/dom/CSPReportBinding.h"
48#include "mozilla/dom/CSPDictionariesBinding.h"
49#include "mozilla/dom/CSPViolationReportBody.h"
50#include "mozilla/ipc/PBackgroundSharedTypes.h"
51#include "mozilla/dom/ReportingUtils.h"
52#include "mozilla/dom/WindowGlobalParent.h"
53#include "nsINetworkInterceptController.h"
54#include "nsSandboxFlags.h"
55#include "nsIScriptElement.h"
56#include "nsIEventTarget.h"
57#include "mozilla/dom/DocGroup.h"
58#include "mozilla/dom/Element.h"
59#include "nsXULAppAPI.h"
60#include "nsJSUtils.h"
61
62using namespace mozilla;
63using namespace mozilla::dom;
64using namespace mozilla::ipc;
65
66static LogModule* GetCspContextLog() {
67 static LazyLogModule gCspContextPRLog("CSPContext");
68 return gCspContextPRLog;
69}
70
71#define CSPCONTEXTLOG(args)do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
args); } } while (0)
\
72 MOZ_LOG(GetCspContextLog(), mozilla::LogLevel::Debug, args)do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
args); } } while (0)
73#define CSPCONTEXTLOGENABLED()(__builtin_expect(!!(mozilla::detail::log_test(GetCspContextLog
(), mozilla::LogLevel::Debug)), 0))
\
74 MOZ_LOG_TEST(GetCspContextLog(), mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(GetCspContextLog
(), mozilla::LogLevel::Debug)), 0))
75
76static LogModule* GetCspOriginLogLog() {
77 static LazyLogModule gCspOriginPRLog("CSPOrigin");
78 return gCspOriginPRLog;
79}
80
81#define CSPORIGINLOG(args)do { const ::mozilla::LogModule* moz_real_module = GetCspOriginLogLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
args); } } while (0)
\
82 MOZ_LOG(GetCspOriginLogLog(), mozilla::LogLevel::Debug, args)do { const ::mozilla::LogModule* moz_real_module = GetCspOriginLogLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
args); } } while (0)
83#define CSPORIGINLOGENABLED()(__builtin_expect(!!(mozilla::detail::log_test(GetCspOriginLogLog
(), mozilla::LogLevel::Debug)), 0))
\
84 MOZ_LOG_TEST(GetCspOriginLogLog(), mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(GetCspOriginLogLog
(), mozilla::LogLevel::Debug)), 0))
85
86#ifdef DEBUG1
87/**
88 * This function is only used for verification purposes within
89 * GatherSecurityPolicyViolationEventData.
90 */
91static bool ValidateDirectiveName(const nsAString& aDirective) {
92 static const auto directives = []() {
93 std::unordered_set<std::string> directives;
94 constexpr size_t dirLen =
95 sizeof(CSPStrDirectives) / sizeof(CSPStrDirectives[0]);
96 for (size_t i = 0; i < dirLen; ++i) {
97 directives.insert(CSPStrDirectives[i]);
98 }
99 return directives;
100 }();
101
102 nsAutoString directive(aDirective);
103 auto itr = directives.find(NS_ConvertUTF16toUTF8(directive).get());
104 return itr != directives.end();
105}
106#endif // DEBUG
107
108static void BlockedContentSourceToString(
109 CSPViolationData::BlockedContentSource aSource, nsACString& aString) {
110 switch (aSource) {
111 case CSPViolationData::BlockedContentSource::Unknown:
112 aString.Truncate();
113 break;
114
115 case CSPViolationData::BlockedContentSource::Inline:
116 aString.AssignLiteral("inline");
117 break;
118
119 case CSPViolationData::BlockedContentSource::Eval:
120 aString.AssignLiteral("eval");
121 break;
122
123 case CSPViolationData::BlockedContentSource::Self:
124 aString.AssignLiteral("self");
125 break;
126
127 case CSPViolationData::BlockedContentSource::WasmEval:
128 aString.AssignLiteral("wasm-eval");
129 break;
130 case CSPViolationData::BlockedContentSource::TrustedTypesPolicy:
131 aString.AssignLiteral("trusted-types-policy");
132 break;
133 case CSPViolationData::BlockedContentSource::TrustedTypesSink:
134 aString.AssignLiteral("trusted-types-sink");
135 break;
136 }
137}
138
139/* ===== nsIContentSecurityPolicy impl ====== */
140
141NS_IMETHODIMPnsresult
142nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
143 nsICSPEventListener* aCSPEventListener,
144 nsILoadInfo* aLoadInfo, nsIURI* aContentLocation,
145 nsIURI* aOriginalURIIfRedirect,
146 bool aSendViolationReports, int16_t* outDecision) {
147 if (CSPCONTEXTLOGENABLED()(__builtin_expect(!!(mozilla::detail::log_test(GetCspContextLog
(), mozilla::LogLevel::Debug)), 0))
) {
148 CSPCONTEXTLOG(("nsCSPContext::ShouldLoad, aContentLocation: %s",do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::ShouldLoad, aContentLocation: %s"
, aContentLocation->GetSpecOrDefault().get()); } } while (
0)
149 aContentLocation->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::ShouldLoad, aContentLocation: %s"
, aContentLocation->GetSpecOrDefault().get()); } } while (
0)
;
150 CSPCONTEXTLOG((">>>> aContentType: %s",do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, ">>>> aContentType: %s"
, NS_CP_ContentTypeName(aContentType)); } } while (0)
151 NS_CP_ContentTypeName(aContentType)))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, ">>>> aContentType: %s"
, NS_CP_ContentTypeName(aContentType)); } } while (0)
;
152 }
153
154 // This ShouldLoad function is called from nsCSPService::ShouldLoad,
155 // which already checked a number of things, including:
156 // * aContentLocation is not null; we can consume this without further checks
157 // * scheme is not a allowlisted scheme (about: chrome:, etc).
158 // * CSP is enabled
159 // * Content Type is not allowlisted (CSP Reports, TYPE_DOCUMENT, etc).
160 // * Fast Path for Apps
161
162 // Default decision, CSP can revise it if there's a policy to enforce
163 *outDecision = nsIContentPolicy::ACCEPT;
164
165 // If the content type doesn't map to a CSP directive, there's nothing for
166 // CSP to do.
167 CSPDirective dir = CSP_ContentTypeToDirective(aContentType);
168 if (dir == nsIContentSecurityPolicy::NO_DIRECTIVE) {
169 return NS_OK;
170 }
171
172 bool permitted = permitsInternal(
173 dir,
174 nullptr, // aTriggeringElement
175 aCSPEventListener, aLoadInfo, aContentLocation, aOriginalURIIfRedirect,
176 false, // allow fallback to default-src
177 aSendViolationReports,
178 true); // send blocked URI in violation reports
179
180 *outDecision =
181 permitted ? nsIContentPolicy::ACCEPT : nsIContentPolicy::REJECT_SERVER;
182
183 if (CSPCONTEXTLOGENABLED()(__builtin_expect(!!(mozilla::detail::log_test(GetCspContextLog
(), mozilla::LogLevel::Debug)), 0))
) {
184 CSPCONTEXTLOG(do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::ShouldLoad, decision: %s, "
"aContentLocation: %s", *outDecision > 0 ? "load" : "deny"
, aContentLocation->GetSpecOrDefault().get()); } } while (
0)
185 ("nsCSPContext::ShouldLoad, decision: %s, "do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::ShouldLoad, decision: %s, "
"aContentLocation: %s", *outDecision > 0 ? "load" : "deny"
, aContentLocation->GetSpecOrDefault().get()); } } while (
0)
186 "aContentLocation: %s",do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::ShouldLoad, decision: %s, "
"aContentLocation: %s", *outDecision > 0 ? "load" : "deny"
, aContentLocation->GetSpecOrDefault().get()); } } while (
0)
187 *outDecision > 0 ? "load" : "deny",do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::ShouldLoad, decision: %s, "
"aContentLocation: %s", *outDecision > 0 ? "load" : "deny"
, aContentLocation->GetSpecOrDefault().get()); } } while (
0)
188 aContentLocation->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::ShouldLoad, decision: %s, "
"aContentLocation: %s", *outDecision > 0 ? "load" : "deny"
, aContentLocation->GetSpecOrDefault().get()); } } while (
0)
;
189 }
190 return NS_OK;
191}
192
193bool nsCSPContext::permitsInternal(
194 CSPDirective aDir, Element* aTriggeringElement,
195 nsICSPEventListener* aCSPEventListener, nsILoadInfo* aLoadInfo,
196 nsIURI* aContentLocation, nsIURI* aOriginalURIIfRedirect, bool aSpecific,
197 bool aSendViolationReports, bool aSendContentLocationInViolationReports) {
198 EnsureIPCPoliciesRead();
199 bool permits = true;
200
201 nsAutoString violatedDirective;
202 nsAutoString violatedDirectiveString;
203 for (uint32_t p = 0; p < mPolicies.Length(); p++) {
204 if (!mPolicies[p]->permits(aDir, aLoadInfo, aContentLocation,
205 !!aOriginalURIIfRedirect, aSpecific,
206 violatedDirective, violatedDirectiveString)) {
207 // If the policy is violated and not report-only, reject the load and
208 // report to the console
209 if (!mPolicies[p]->getReportOnlyFlag()) {
210 CSPCONTEXTLOG(("nsCSPContext::permitsInternal, false"))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::permitsInternal, false"
); } } while (0)
;
211 permits = false;
212 }
213
214 // Callers should set |aSendViolationReports| to false if this is a
215 // preload - the decision may be wrong due to the inability to get the
216 // nonce, and will incorrectly fail the unit tests.
217 if (aSendViolationReports) {
218 auto loc = JSCallingLocation::Get();
219
220 using Resource = CSPViolationData::Resource;
221 Resource resource =
222 aSendContentLocationInViolationReports
223 ? Resource{nsCOMPtr<nsIURI>{aContentLocation}}
224 : Resource{CSPViolationData::BlockedContentSource::Unknown};
225
226 CSPViolationData cspViolationData{p,
227 std::move(resource),
228 aDir,
229 loc.FileName(),
230 loc.mLine,
231 loc.mColumn,
232 aTriggeringElement,
233 /* aSample */ u""_ns};
234
235 AsyncReportViolation(
236 aCSPEventListener, std::move(cspViolationData),
237 aOriginalURIIfRedirect, /* in case of redirect originalURI is not
238 null */
239 violatedDirective, violatedDirectiveString,
240 u""_ns, // no observer subject
241 false); // aReportSample (no sample)
242 }
243 }
244 }
245
246 return permits;
247}
248
249/* ===== nsISupports implementation ========== */
250
251NS_IMPL_CLASSINFO(nsCSPContext, nullptr, 0, NS_CSPCONTEXT_CID)extern nsresult nsCSPContext_GetInterfacesHelper(nsTArray<
nsIID> & array); static const GenericClassInfo::ClassInfoData
knsCSPContextClassInfoData = { nsCSPContext_GetInterfacesHelper
, nullptr, 0 | nsIClassInfo::SINGLETON_CLASSINFO, {0x09d9ed1a
, 0xe5d4, 0x4004, {0xbf, 0xe0, 0x27, 0xce, 0xb9, 0x23, 0xd9, 0xac
}}, }; mozilla::AlignedStorage2<GenericClassInfo> knsCSPContextClassInfoDataPlace
; nsIClassInfo* gnsCSPContext_classInfoGlobal = nullptr;
252
253NS_IMPL_ISUPPORTS_CI(nsCSPContext, nsIContentSecurityPolicy, nsISerializable)MozExternalRefCountType nsCSPContext::AddRef(void) { static_assert
(!std::is_destructible_v<nsCSPContext>, "Reference-counted class "
"nsCSPContext" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
253; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCSPContext" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsCSPContext" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsCSPContext\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCSPContext\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 253; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCSPContext" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsCSPContext"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsCSPContext::Release(void) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(int32_t(mRefCnt) > 0)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 253
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCSPContext" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsCSPContext" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsCSPContext\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCSPContext\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 253; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCSPContext" " not thread-safe"); const char
* const nametmp = "nsCSPContext"; nsrefcnt count = --mRefCnt;
NS_LogRelease((this), (count), (nametmp)); if (count == 0) {
mRefCnt = 1; delete (this); return 0; } return count; } static_assert
(2 > 0, "Need more arguments to NS_IMPL_QUERY_INTERFACE_CI"
); nsresult nsCSPContext::QueryInterface(const nsIID& aIID
, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 253); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
; if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIContentSecurityPolicy>)) foundInterface
= static_cast<nsIContentSecurityPolicy*>(this); else if
(aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISerializable>)) foundInterface
= static_cast<nsISerializable*>(this); else if (aIID.Equals
(mozilla::detail::kImplementedIID<std::remove_reference_t<
decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<nsIContentSecurityPolicy*
>(this)); else if (aIID.Equals((nsIClassInfo::COMTypeInfo<
nsIClassInfo, void>::kIID))) { if (!gnsCSPContext_classInfoGlobal
) gnsCSPContext_classInfoGlobal = new (knsCSPContextClassInfoDataPlace
.addr()) GenericClassInfo(&knsCSPContextClassInfoData); foundInterface
= gnsCSPContext_classInfoGlobal; } else foundInterface = 0; nsresult
status; if (!foundInterface) { do { static_assert( mozilla::
detail::AssertionConditionType<decltype(!aIID.Equals((nsISupports
::COMTypeInfo<nsISupports, void>::kIID)))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void
>::kIID))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 253; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; } static_assert
(2 > 0, "Need more arguments to NS_IMPL_CI_INTERFACE_GETTER"
); nsresult nsCSPContext_GetInterfacesHelper(nsTArray<nsIID
> & array) { array.Clear(); array.SetCapacity(2); array
.AppendElement((nsIContentSecurityPolicy::COMTypeInfo<nsIContentSecurityPolicy
, void>::kIID)); array.AppendElement((nsISerializable::COMTypeInfo
<nsISerializable, void>::kIID)); return NS_OK; }
254
255nsCSPContext::nsCSPContext()
256 : mInnerWindowID(0),
257 mSkipAllowInlineStyleCheck(false),
258 mLoadingContext(nullptr),
259 mLoadingPrincipal(nullptr),
260 mQueueUpMessages(true) {
261 CSPCONTEXTLOG(("nsCSPContext::nsCSPContext"))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::nsCSPContext"
); } } while (0)
;
262}
263
264nsCSPContext::~nsCSPContext() {
265 CSPCONTEXTLOG(("nsCSPContext::~nsCSPContext"))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::~nsCSPContext"
); } } while (0)
;
266 for (uint32_t i = 0; i < mPolicies.Length(); i++) {
267 delete mPolicies[i];
268 }
269}
270
271/* static */
272bool nsCSPContext::Equals(nsIContentSecurityPolicy* aCSP,
273 nsIContentSecurityPolicy* aOtherCSP) {
274 if (aCSP == aOtherCSP) {
275 // fast path for pointer equality
276 return true;
277 }
278
279 uint32_t policyCount = 0;
280 if (aCSP) {
281 aCSP->GetPolicyCount(&policyCount);
282 }
283
284 uint32_t otherPolicyCount = 0;
285 if (aOtherCSP) {
286 aOtherCSP->GetPolicyCount(&otherPolicyCount);
287 }
288
289 if (policyCount != otherPolicyCount) {
290 return false;
291 }
292
293 nsAutoString policyStr, otherPolicyStr;
294 for (uint32_t i = 0; i < policyCount; ++i) {
295 aCSP->GetPolicyString(i, policyStr);
296 aOtherCSP->GetPolicyString(i, otherPolicyStr);
297 if (!policyStr.Equals(otherPolicyStr)) {
298 return false;
299 }
300 }
301
302 return true;
303}
304
305nsresult nsCSPContext::InitFromOther(nsCSPContext* aOtherContext) {
306 NS_ENSURE_ARG(aOtherContext)do { if ((__builtin_expect(!!(!(aOtherContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aOtherContext" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 306); return NS_ERROR_INVALID_ARG; } } while (false)
;
307
308 nsresult rv = NS_OK;
309 nsCOMPtr<Document> doc = do_QueryReferent(aOtherContext->mLoadingContext);
310 if (doc) {
311 rv = SetRequestContextWithDocument(doc);
312 } else {
313 rv = SetRequestContextWithPrincipal(
314 aOtherContext->mLoadingPrincipal, aOtherContext->mSelfURI,
315 aOtherContext->mReferrer, aOtherContext->mInnerWindowID);
316 }
317 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 317); return rv; } } while (false)
;
318
319 mSkipAllowInlineStyleCheck = aOtherContext->mSkipAllowInlineStyleCheck;
320
321 // This policy was already parsed somewhere else, don't emit parsing errors.
322 mSuppressParserLogMessages = true;
323 for (auto policy : aOtherContext->mPolicies) {
324 nsAutoString policyStr;
325 policy->toString(policyStr);
326 AppendPolicy(policyStr, policy->getReportOnlyFlag(),
327 policy->getDeliveredViaMetaTagFlag());
328 }
329
330 mSuppressParserLogMessages = aOtherContext->mSuppressParserLogMessages;
331
332 mIPCPolicies = aOtherContext->mIPCPolicies.Clone();
333 return NS_OK;
334}
335
336NS_IMETHODIMPnsresult
337nsCSPContext::EnsureIPCPoliciesRead() {
338 // Most likely the parser errors already happened before serializing
339 // the policy for IPC.
340 bool previous = mSuppressParserLogMessages;
341 mSuppressParserLogMessages = true;
342
343 if (mIPCPolicies.Length() > 0) {
344 nsresult rv;
345 for (auto& policy : mIPCPolicies) {
346 rv = AppendPolicy(policy.policy(), policy.reportOnlyFlag(),
347 policy.deliveredViaMetaTagFlag());
348 Unused << NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 348)
;
349 }
350 mIPCPolicies.Clear();
351 }
352
353 mSuppressParserLogMessages = previous;
354 return NS_OK;
355}
356
357NS_IMETHODIMPnsresult
358nsCSPContext::GetPolicyString(uint32_t aIndex, nsAString& outStr) {
359 outStr.Truncate();
360 EnsureIPCPoliciesRead();
361 if (aIndex >= mPolicies.Length()) {
362 return NS_ERROR_ILLEGAL_VALUE;
363 }
364 mPolicies[aIndex]->toString(outStr);
365 return NS_OK;
366}
367
368const nsCSPPolicy* nsCSPContext::GetPolicy(uint32_t aIndex) {
369 EnsureIPCPoliciesRead();
370 if (aIndex >= mPolicies.Length()) {
371 return nullptr;
372 }
373 return mPolicies[aIndex];
374}
375
376NS_IMETHODIMPnsresult
377nsCSPContext::GetPolicyCount(uint32_t* outPolicyCount) {
378 EnsureIPCPoliciesRead();
379 *outPolicyCount = mPolicies.Length();
380 return NS_OK;
381}
382
383NS_IMETHODIMPnsresult
384nsCSPContext::GetUpgradeInsecureRequests(bool* outUpgradeRequest) {
385 EnsureIPCPoliciesRead();
386 *outUpgradeRequest = false;
387 for (uint32_t i = 0; i < mPolicies.Length(); i++) {
388 if (mPolicies[i]->hasDirective(
389 nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE) &&
390 !mPolicies[i]->getReportOnlyFlag()) {
391 *outUpgradeRequest = true;
392 return NS_OK;
393 }
394 }
395 return NS_OK;
396}
397
398NS_IMETHODIMPnsresult
399nsCSPContext::GetBlockAllMixedContent(bool* outBlockAllMixedContent) {
400 EnsureIPCPoliciesRead();
401 *outBlockAllMixedContent = false;
402 for (uint32_t i = 0; i < mPolicies.Length(); i++) {
403 if (!mPolicies[i]->getReportOnlyFlag() &&
404 mPolicies[i]->hasDirective(
405 nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT)) {
406 *outBlockAllMixedContent = true;
407 return NS_OK;
408 }
409 }
410 return NS_OK;
411}
412
413NS_IMETHODIMPnsresult
414nsCSPContext::GetEnforcesFrameAncestors(bool* outEnforcesFrameAncestors) {
415 EnsureIPCPoliciesRead();
416 *outEnforcesFrameAncestors = false;
417 for (uint32_t i = 0; i < mPolicies.Length(); i++) {
418 if (!mPolicies[i]->getReportOnlyFlag() &&
419 mPolicies[i]->hasDirective(
420 nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE)) {
421 *outEnforcesFrameAncestors = true;
422 return NS_OK;
423 }
424 }
425 return NS_OK;
426}
427
428NS_IMETHODIMPnsresult
429nsCSPContext::AppendPolicy(const nsAString& aPolicyString, bool aReportOnly,
430 bool aDeliveredViaMetaTag) {
431 CSPCONTEXTLOG(("nsCSPContext::AppendPolicy: %s",do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::AppendPolicy: %s"
, NS_ConvertUTF16toUTF8(aPolicyString).get()); } } while (0)
432 NS_ConvertUTF16toUTF8(aPolicyString).get()))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::AppendPolicy: %s"
, NS_ConvertUTF16toUTF8(aPolicyString).get()); } } while (0)
;
433
434 // Use mSelfURI from setRequestContextWith{Document,Principal} (bug 991474)
435 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadingPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadingPrincipal))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadingPrincipal"
" (" "did you forget to call setRequestContextWith{Document,Principal}?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 437); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadingPrincipal"
") (" "did you forget to call setRequestContextWith{Document,Principal}?"
")"); do { *((volatile int*)__null) = 437; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
436 mLoadingPrincipal,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadingPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadingPrincipal))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadingPrincipal"
" (" "did you forget to call setRequestContextWith{Document,Principal}?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 437); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadingPrincipal"
") (" "did you forget to call setRequestContextWith{Document,Principal}?"
")"); do { *((volatile int*)__null) = 437; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
437 "did you forget to call setRequestContextWith{Document,Principal}?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadingPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadingPrincipal))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadingPrincipal"
" (" "did you forget to call setRequestContextWith{Document,Principal}?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 437); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadingPrincipal"
") (" "did you forget to call setRequestContextWith{Document,Principal}?"
")"); do { *((volatile int*)__null) = 437; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
438 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSelfURI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSelfURI))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mSelfURI" " (" "did you forget to call setRequestContextWith{Document,Principal}?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSelfURI" ") ("
"did you forget to call setRequestContextWith{Document,Principal}?"
")"); do { *((volatile int*)__null) = 440; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
439 mSelfURI,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSelfURI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSelfURI))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mSelfURI" " (" "did you forget to call setRequestContextWith{Document,Principal}?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSelfURI" ") ("
"did you forget to call setRequestContextWith{Document,Principal}?"
")"); do { *((volatile int*)__null) = 440; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
440 "did you forget to call setRequestContextWith{Document,Principal}?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSelfURI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSelfURI))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mSelfURI" " (" "did you forget to call setRequestContextWith{Document,Principal}?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSelfURI" ") ("
"did you forget to call setRequestContextWith{Document,Principal}?"
")"); do { *((volatile int*)__null) = 440; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
441 NS_ENSURE_TRUE(mLoadingPrincipal, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(mLoadingPrincipal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mLoadingPrincipal" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 441); return NS_ERROR_UNEXPECTED; } } while (false)
;
442 NS_ENSURE_TRUE(mSelfURI, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(mSelfURI)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mSelfURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 442); return NS_ERROR_UNEXPECTED; } } while (false)
;
443
444 if (CSPORIGINLOGENABLED()(__builtin_expect(!!(mozilla::detail::log_test(GetCspOriginLogLog
(), mozilla::LogLevel::Debug)), 0))
) {
445 nsAutoCString selfURISpec;
446 mSelfURI->GetSpec(selfURISpec);
447 CSPORIGINLOG(("CSP - AppendPolicy"))do { const ::mozilla::LogModule* moz_real_module = GetCspOriginLogLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "CSP - AppendPolicy"
); } } while (0)
;
448 CSPORIGINLOG((" * selfURI: %s", selfURISpec.get()))do { const ::mozilla::LogModule* moz_real_module = GetCspOriginLogLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " * selfURI: %s",
selfURISpec.get()); } } while (0)
;
449 CSPORIGINLOG((" * reportOnly: %s", aReportOnly ? "yes" : "no"))do { const ::mozilla::LogModule* moz_real_module = GetCspOriginLogLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " * reportOnly: %s"
, aReportOnly ? "yes" : "no"); } } while (0)
;
450 CSPORIGINLOG(do { const ::mozilla::LogModule* moz_real_module = GetCspOriginLogLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " * deliveredViaMetaTag: %s"
, aDeliveredViaMetaTag ? "yes" : "no"); } } while (0)
451 (" * deliveredViaMetaTag: %s", aDeliveredViaMetaTag ? "yes" : "no"))do { const ::mozilla::LogModule* moz_real_module = GetCspOriginLogLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " * deliveredViaMetaTag: %s"
, aDeliveredViaMetaTag ? "yes" : "no"); } } while (0)
;
452 CSPORIGINLOG(do { const ::mozilla::LogModule* moz_real_module = GetCspOriginLogLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " * policy: %s\n"
, NS_ConvertUTF16toUTF8(aPolicyString).get()); } } while (0)
453 (" * policy: %s\n", NS_ConvertUTF16toUTF8(aPolicyString).get()))do { const ::mozilla::LogModule* moz_real_module = GetCspOriginLogLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " * policy: %s\n"
, NS_ConvertUTF16toUTF8(aPolicyString).get()); } } while (0)
;
454 }
455
456 nsCSPPolicy* policy = nsCSPParser::parseContentSecurityPolicy(
457 aPolicyString, mSelfURI, aReportOnly, this, aDeliveredViaMetaTag,
458 mSuppressParserLogMessages);
459 if (policy) {
460 if (policy->hasDirective(
461 nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
462 nsAutoCString selfURIspec;
463 if (mSelfURI) {
464 mSelfURI->GetAsciiSpec(selfURIspec);
465 }
466 CSPCONTEXTLOG(do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::AppendPolicy added UPGRADE_IF_INSECURE_DIRECTIVE "
"self-uri=%s referrer=%s", selfURIspec.get(), mReferrer.get(
)); } } while (0)
467 ("nsCSPContext::AppendPolicy added UPGRADE_IF_INSECURE_DIRECTIVE "do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::AppendPolicy added UPGRADE_IF_INSECURE_DIRECTIVE "
"self-uri=%s referrer=%s", selfURIspec.get(), mReferrer.get(
)); } } while (0)
468 "self-uri=%s referrer=%s",do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::AppendPolicy added UPGRADE_IF_INSECURE_DIRECTIVE "
"self-uri=%s referrer=%s", selfURIspec.get(), mReferrer.get(
)); } } while (0)
469 selfURIspec.get(), mReferrer.get()))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::AppendPolicy added UPGRADE_IF_INSECURE_DIRECTIVE "
"self-uri=%s referrer=%s", selfURIspec.get(), mReferrer.get(
)); } } while (0)
;
470 }
471 if (policy->hasDirective(
472 nsIContentSecurityPolicy::REQUIRE_TRUSTED_TYPES_FOR_DIRECTIVE)) {
473 if (mRequireTrustedTypesForDirectiveState !=
474 RequireTrustedTypesForDirectiveState::ENFORCE) {
475 mRequireTrustedTypesForDirectiveState =
476 policy->getReportOnlyFlag()
477 ? RequireTrustedTypesForDirectiveState::REPORT_ONLY
478 : RequireTrustedTypesForDirectiveState::ENFORCE;
479 }
480 if (nsCOMPtr<Document> doc = do_QueryReferent(mLoadingContext)) {
481 doc->SetHasPolicyWithRequireTrustedTypesForDirective(true);
482 }
483 }
484
485 mPolicies.AppendElement(policy);
486 }
487
488 return NS_OK;
489}
490
491NS_IMETHODIMPnsresult
492nsCSPContext::GetRequireTrustedTypesForDirectiveState(
493 RequireTrustedTypesForDirectiveState*
494 aRequireTrustedTypesForDirectiveState) {
495 *aRequireTrustedTypesForDirectiveState =
496 mRequireTrustedTypesForDirectiveState;
497 return NS_OK;
498}
499
500NS_IMETHODIMPnsresult
501nsCSPContext::GetAllowsEval(bool* outShouldReportViolation,
502 bool* outAllowsEval) {
503 EnsureIPCPoliciesRead();
504 *outShouldReportViolation = false;
505 *outAllowsEval = true;
506
507 for (uint32_t i = 0; i < mPolicies.Length(); i++) {
508 if (!mPolicies[i]->allows(SCRIPT_SRC_DIRECTIVE, CSP_UNSAFE_EVAL, u""_ns)) {
509 // policy is violated: must report the violation and allow the inline
510 // script if the policy is report-only.
511 *outShouldReportViolation = true;
512 if (!mPolicies[i]->getReportOnlyFlag()) {
513 *outAllowsEval = false;
514 }
515 }
516 }
517 return NS_OK;
518}
519
520NS_IMETHODIMPnsresult
521nsCSPContext::GetAllowsWasmEval(bool* outShouldReportViolation,
522 bool* outAllowsWasmEval) {
523 EnsureIPCPoliciesRead();
524 *outShouldReportViolation = false;
525 *outAllowsWasmEval = true;
526
527 for (uint32_t i = 0; i < mPolicies.Length(); i++) {
528 // Either 'unsafe-eval' or 'wasm-unsafe-eval' can allow this
529 if (!mPolicies[i]->allows(SCRIPT_SRC_DIRECTIVE, CSP_WASM_UNSAFE_EVAL,
530 u""_ns) &&
531 !mPolicies[i]->allows(SCRIPT_SRC_DIRECTIVE, CSP_UNSAFE_EVAL, u""_ns)) {
532 // policy is violated: must report the violation and allow the inline
533 // script if the policy is report-only.
534 *outShouldReportViolation = true;
535 if (!mPolicies[i]->getReportOnlyFlag()) {
536 *outAllowsWasmEval = false;
537 }
538 }
539 }
540
541 return NS_OK;
542}
543
544// Helper function to report inline violations
545void nsCSPContext::reportInlineViolation(
546 CSPDirective aDirective, Element* aTriggeringElement,
547 nsICSPEventListener* aCSPEventListener, const nsAString& aNonce,
548 bool aReportSample, const nsAString& aSample,
549 const nsAString& aViolatedDirective,
550 const nsAString& aViolatedDirectiveString, CSPDirective aEffectiveDirective,
551 uint32_t aViolatedPolicyIndex, // TODO, use report only flag for that
552 uint32_t aLineNumber, uint32_t aColumnNumber) {
553 nsString observerSubject;
554 // if the nonce is non empty, then we report the nonce error, otherwise
555 // let's report the hash error; no need to report the unsafe-inline error
556 // anymore.
557 if (!aNonce.IsEmpty()) {
558 observerSubject = (aDirective == SCRIPT_SRC_ELEM_DIRECTIVE ||
559 aDirective == SCRIPT_SRC_ATTR_DIRECTIVE)
560 ? NS_LITERAL_STRING_FROM_CSTRING(static_cast<const nsLiteralString&>( nsLiteralString
(u"" "Inline Script had invalid nonce"))
561 SCRIPT_NONCE_VIOLATION_OBSERVER_TOPIC)static_cast<const nsLiteralString&>( nsLiteralString
(u"" "Inline Script had invalid nonce"))
562 : NS_LITERAL_STRING_FROM_CSTRING(static_cast<const nsLiteralString&>( nsLiteralString
(u"" "Inline Style had invalid nonce"))
563 STYLE_NONCE_VIOLATION_OBSERVER_TOPIC)static_cast<const nsLiteralString&>( nsLiteralString
(u"" "Inline Style had invalid nonce"))
;
564 } else {
565 observerSubject = (aDirective == SCRIPT_SRC_ELEM_DIRECTIVE ||
566 aDirective == SCRIPT_SRC_ATTR_DIRECTIVE)
567 ? NS_LITERAL_STRING_FROM_CSTRING(static_cast<const nsLiteralString&>( nsLiteralString
(u"" "Inline Script had invalid hash"))
568 SCRIPT_HASH_VIOLATION_OBSERVER_TOPIC)static_cast<const nsLiteralString&>( nsLiteralString
(u"" "Inline Script had invalid hash"))
569 : NS_LITERAL_STRING_FROM_CSTRING(static_cast<const nsLiteralString&>( nsLiteralString
(u"" "Inline Style had invalid hash"))
570 STYLE_HASH_VIOLATION_OBSERVER_TOPIC)static_cast<const nsLiteralString&>( nsLiteralString
(u"" "Inline Style had invalid hash"))
;
571 }
572
573 auto loc = JSCallingLocation::Get();
574 if (!loc) {
575 nsCString sourceFile;
576 // use selfURI as the source
577 if (mSelfURI) {
578 mSelfURI->GetSpec(sourceFile);
579 loc.mResource = AsVariant(std::move(sourceFile));
580 }
581 loc.mLine = aLineNumber;
582 loc.mColumn = aColumnNumber;
583 }
584
585 CSPViolationData cspViolationData{
586 aViolatedPolicyIndex,
587 CSPViolationData::Resource{
588 CSPViolationData::BlockedContentSource::Inline},
589 aEffectiveDirective,
590 loc.FileName(),
591 loc.mLine,
592 loc.mColumn,
593 aTriggeringElement,
594 aSample};
595
596 AsyncReportViolation(aCSPEventListener, std::move(cspViolationData),
597 mSelfURI, // aOriginalURI
598 aViolatedDirective, // aViolatedDirective
599 aViolatedDirectiveString,
600 observerSubject, // aObserverSubject
601 aReportSample); // aReportSample
602}
603
604NS_IMETHODIMPnsresult
605nsCSPContext::GetAllowsInline(CSPDirective aDirective, bool aHasUnsafeHash,
606 const nsAString& aNonce, bool aParserCreated,
607 Element* aTriggeringElement,
608 nsICSPEventListener* aCSPEventListener,
609 const nsAString& aContentOfPseudoScript,
610 uint32_t aLineNumber, uint32_t aColumnNumber,
611 bool* outAllowsInline) {
612 *outAllowsInline = true;
613
614 if (aDirective != SCRIPT_SRC_ELEM_DIRECTIVE &&
615 aDirective != SCRIPT_SRC_ATTR_DIRECTIVE &&
616 aDirective != STYLE_SRC_ELEM_DIRECTIVE &&
617 aDirective != STYLE_SRC_ATTR_DIRECTIVE) {
618 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "can only allow inline for (script/style)-src-(attr/elem)"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 619); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"can only allow inline for (script/style)-src-(attr/elem)" ")"
); do { *((volatile int*)__null) = 619; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
619 "can only allow inline for (script/style)-src-(attr/elem)")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "can only allow inline for (script/style)-src-(attr/elem)"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 619); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"can only allow inline for (script/style)-src-(attr/elem)" ")"
); do { *((volatile int*)__null) = 619; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
620 return NS_OK;
621 }
622
623 EnsureIPCPoliciesRead();
624 nsAutoString content;
625
626 // always iterate all policies, otherwise we might not send out all reports
627 for (uint32_t i = 0; i < mPolicies.Length(); i++) {
628 // https://w3c.github.io/webappsec-csp/#match-element-to-source-list
629
630 // Step 1. If §6.7.3.2 Does a source list allow all inline behavior for
631 // type? returns "Allows" given list and type, return "Matches".
632 if (mPolicies[i]->allowsAllInlineBehavior(aDirective)) {
633 continue;
634 }
635
636 // Step 2. If type is "script" or "style", and §6.7.3.1 Is element
637 // nonceable? returns "Nonceable" when executed upon element:
638 if ((aDirective == SCRIPT_SRC_ELEM_DIRECTIVE ||
639 aDirective == STYLE_SRC_ELEM_DIRECTIVE) &&
640 aTriggeringElement && !aNonce.IsEmpty()) {
641#ifdef DEBUG1
642 // NOTE: Folllowing Chrome "Is element nonceable?" doesn't apply to
643 // <style>.
644 if (aDirective == SCRIPT_SRC_ELEM_DIRECTIVE) {
645 // Our callers should have checked this.
646 MOZ_ASSERT(nsContentSecurityUtils::GetIsElementNonceableNonce(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nsContentSecurityUtils::GetIsElementNonceableNonce( *
aTriggeringElement) == aNonce)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentSecurityUtils::GetIsElementNonceableNonce
( *aTriggeringElement) == aNonce))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("nsContentSecurityUtils::GetIsElementNonceableNonce( *aTriggeringElement) == aNonce"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 647); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentSecurityUtils::GetIsElementNonceableNonce( *aTriggeringElement) == aNonce"
")"); do { *((volatile int*)__null) = 647; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
647 *aTriggeringElement) == aNonce)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nsContentSecurityUtils::GetIsElementNonceableNonce( *
aTriggeringElement) == aNonce)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentSecurityUtils::GetIsElementNonceableNonce
( *aTriggeringElement) == aNonce))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("nsContentSecurityUtils::GetIsElementNonceableNonce( *aTriggeringElement) == aNonce"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 647); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentSecurityUtils::GetIsElementNonceableNonce( *aTriggeringElement) == aNonce"
")"); do { *((volatile int*)__null) = 647; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
648 }
649#endif
650
651 // Step 2.1. For each expression of list: [...]
652 if (mPolicies[i]->allows(aDirective, CSP_NONCE, aNonce)) {
653 continue;
654 }
655 }
656
657 // Check the content length to ensure the content is not allocated more than
658 // once. Even though we are in a for loop, it is probable that there is only
659 // one policy, so this check may be unnecessary.
660 if (content.IsEmpty() && aTriggeringElement) {
661 nsCOMPtr<nsIScriptElement> element =
662 do_QueryInterface(aTriggeringElement);
663 if (element) {
664 element->GetScriptText(content);
665 }
666 }
667 if (content.IsEmpty()) {
668 content = aContentOfPseudoScript;
669 }
670
671 // Step 3. Let unsafe-hashes flag be false.
672 // Step 4. For each expression of list: [...]
673 bool unsafeHashesFlag =
674 mPolicies[i]->allows(aDirective, CSP_UNSAFE_HASHES, u""_ns);
675
676 // Step 5. If type is "script" or "style", or unsafe-hashes flag is true:
677 //
678 // aHasUnsafeHash is true for event handlers (type "script attribute"),
679 // style= attributes (type "style attribute") and the javascript: protocol.
680 if (!aHasUnsafeHash || unsafeHashesFlag) {
681 if (mPolicies[i]->allows(aDirective, CSP_HASH, content)) {
682 continue;
683 }
684 }
685
686 // TODO(Bug 1844290): Figure out how/if strict-dynamic for inline scripts is
687 // specified
688 bool allowed = false;
689 if ((aDirective == SCRIPT_SRC_ELEM_DIRECTIVE ||
690 aDirective == SCRIPT_SRC_ATTR_DIRECTIVE) &&
691 mPolicies[i]->allows(aDirective, CSP_STRICT_DYNAMIC, u""_ns)) {
692 allowed = !aParserCreated;
693 }
694
695 if (!allowed) {
696 // policy is violoated: deny the load unless policy is report only and
697 // report the violation.
698 if (!mPolicies[i]->getReportOnlyFlag()) {
699 *outAllowsInline = false;
700 }
701 nsAutoString violatedDirective;
702 nsAutoString violatedDirectiveString;
703 bool reportSample = false;
704 mPolicies[i]->getViolatedDirectiveInformation(
705 aDirective, violatedDirective, violatedDirectiveString,
706 &reportSample);
707
708 reportInlineViolation(aDirective, aTriggeringElement, aCSPEventListener,
709 aNonce, reportSample, content, violatedDirective,
710 violatedDirectiveString, aDirective, i, aLineNumber,
711 aColumnNumber);
712 }
713 }
714
715 return NS_OK;
716}
717
718/**
719 * For each policy, log any violation on the Error Console and send a report
720 * if a report-uri is present in the policy
721 *
722 * @param aViolationType
723 * one of the VIOLATION_TYPE_* constants, e.g. inline-script or eval
724 * @param aSourceFile
725 * name of the source file containing the violation (if available)
726 * @param aContentSample
727 * sample of the violating content (to aid debugging)
728 * @param aLineNum
729 * source line number of the violation (if available)
730 * @param aColumnNum
731 * source column number of the violation (if available)
732 * @param aNonce
733 * (optional) If this is a nonce violation, include the nonce so we can
734 * recheck to determine which policies were violated and send the
735 * appropriate reports.
736 * @param aContent
737 * (optional) If this is a hash violation, include contents of the inline
738 * resource in the question so we can recheck the hash in order to
739 * determine which policies were violated and send the appropriate
740 * reports.
741 */
742NS_IMETHODIMPnsresult
743nsCSPContext::LogViolationDetails(
744 uint16_t aViolationType, Element* aTriggeringElement,
745 nsICSPEventListener* aCSPEventListener, const nsACString& aSourceFile,
746 const nsAString& aScriptSample, int32_t aLineNum, int32_t aColumnNum,
747 const nsAString& aNonce, const nsAString& aContent) {
748 EnsureIPCPoliciesRead();
749
750 CSPViolationData::BlockedContentSource blockedContentSource;
751 enum CSPKeyword keyword;
752 nsAutoString observerSubject;
753 if (aViolationType == nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL) {
754 blockedContentSource = CSPViolationData::BlockedContentSource::Eval;
755 keyword = CSP_UNSAFE_EVAL;
756 observerSubject.AssignLiteral(EVAL_VIOLATION_OBSERVER_TOPIC"violated base restriction: Code will not be created from strings");
757 } else {
758 NS_ASSERTION(do { if (!(aViolationType == nsIContentSecurityPolicy::VIOLATION_TYPE_WASM_EVAL
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "unexpected aViolationType"
, "aViolationType == nsIContentSecurityPolicy::VIOLATION_TYPE_WASM_EVAL"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 760); MOZ_PretendNoReturn(); } } while (0)
759 aViolationType == nsIContentSecurityPolicy::VIOLATION_TYPE_WASM_EVAL,do { if (!(aViolationType == nsIContentSecurityPolicy::VIOLATION_TYPE_WASM_EVAL
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "unexpected aViolationType"
, "aViolationType == nsIContentSecurityPolicy::VIOLATION_TYPE_WASM_EVAL"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 760); MOZ_PretendNoReturn(); } } while (0)
760 "unexpected aViolationType")do { if (!(aViolationType == nsIContentSecurityPolicy::VIOLATION_TYPE_WASM_EVAL
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "unexpected aViolationType"
, "aViolationType == nsIContentSecurityPolicy::VIOLATION_TYPE_WASM_EVAL"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 760); MOZ_PretendNoReturn(); } } while (0)
;
761 blockedContentSource = CSPViolationData::BlockedContentSource::WasmEval;
762 keyword = CSP_WASM_UNSAFE_EVAL;
763 observerSubject.AssignLiteral(WASM_EVAL_VIOLATION_OBSERVER_TOPIC"violated base restriction: WebAssembly code will not be created from "
"dynamically"
);
764 }
765
766 for (uint32_t p = 0; p < mPolicies.Length(); p++) {
767 NS_ASSERTION(mPolicies[p], "null pointer in nsTArray<nsCSPPolicy>")do { if (!(mPolicies[p])) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"null pointer in nsTArray<nsCSPPolicy>", "mPolicies[p]"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 767); MOZ_PretendNoReturn(); } } while (0)
;
768
769 if (mPolicies[p]->allows(SCRIPT_SRC_DIRECTIVE, keyword, u""_ns)) {
770 continue;
771 }
772
773 CSPViolationData cspViolationData{
774 p,
775 CSPViolationData::Resource{blockedContentSource},
776 /* aEffectiveDirective */ CSPDirective::SCRIPT_SRC_DIRECTIVE,
777 aSourceFile,
778 static_cast<uint32_t>(aLineNum),
779 static_cast<uint32_t>(aColumnNum),
780 aTriggeringElement,
781 aScriptSample};
782
783 LogViolationDetailsUnchecked(aCSPEventListener, std::move(cspViolationData),
784 observerSubject, ForceReportSample::No);
785 }
786 return NS_OK;
787}
788
789void nsCSPContext::LogViolationDetailsUnchecked(
790 nsICSPEventListener* aCSPEventListener,
791 mozilla::dom::CSPViolationData&& aCSPViolationData,
792 const nsAString& aObserverSubject, ForceReportSample aForceReportSample) {
793 EnsureIPCPoliciesRead();
794
795 nsAutoString violatedDirectiveName;
796 nsAutoString violatedDirectiveNameAndValue;
797 bool reportSample = false;
798 mPolicies[aCSPViolationData.mViolatedPolicyIndex]
799 ->getViolatedDirectiveInformation(
800 aCSPViolationData.mEffectiveDirective, violatedDirectiveName,
801 violatedDirectiveNameAndValue, &reportSample);
802
803 if (aForceReportSample == ForceReportSample::Yes) {
804 reportSample = true;
805 }
806
807 AsyncReportViolation(aCSPEventListener, std::move(aCSPViolationData), nullptr,
808 violatedDirectiveName, violatedDirectiveNameAndValue,
809 aObserverSubject, reportSample);
810}
811
812NS_IMETHODIMPnsresult nsCSPContext::LogTrustedTypesViolationDetailsUnchecked(
813 CSPViolationData&& aCSPViolationData, const nsAString& aObserverSubject,
814 nsICSPEventListener* aCSPEventListener) {
815 EnsureIPCPoliciesRead();
816
817 // Trusted types don't support the "report-sample" keyword
818 // (https://github.com/w3c/trusted-types/issues/531#issuecomment-2194166146).
819 LogViolationDetailsUnchecked(aCSPEventListener, std::move(aCSPViolationData),
820 aObserverSubject, ForceReportSample::Yes);
821 return NS_OK;
822}
823
824#undef CASE_CHECK_AND_REPORT
825
826NS_IMETHODIMPnsresult
827nsCSPContext::SetRequestContextWithDocument(Document* aDocument) {
828 MOZ_ASSERT(aDocument, "Can't set context without doc")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDocument" " (" "Can't set context without doc"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 828); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ") ("
"Can't set context without doc" ")"); do { *((volatile int*)
__null) = 828; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
829 NS_ENSURE_ARG(aDocument)do { if ((__builtin_expect(!!(!(aDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 829); return NS_ERROR_INVALID_ARG; } } while (false)
;
830
831 mLoadingContext = do_GetWeakReference(aDocument);
832 mSelfURI = aDocument->GetDocumentURI();
833 mLoadingPrincipal = aDocument->NodePrincipal();
834 aDocument->GetReferrer(mReferrer);
835 mInnerWindowID = aDocument->InnerWindowID();
836 // the innerWindowID is not available for CSPs delivered through the
837 // header at the time setReqeustContext is called - let's queue up
838 // console messages until it becomes available, see flushConsoleMessages
839 mQueueUpMessages = !mInnerWindowID;
840 mCallingChannelLoadGroup = aDocument->GetDocumentLoadGroup();
841 // set the flag on the document for CSP telemetry
842 mEventTarget = GetMainThreadSerialEventTarget();
843
844 MOZ_ASSERT(mLoadingPrincipal, "need a valid requestPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadingPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadingPrincipal))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadingPrincipal"
" (" "need a valid requestPrincipal" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 844); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadingPrincipal"
") (" "need a valid requestPrincipal" ")"); do { *((volatile
int*)__null) = 844; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
845 MOZ_ASSERT(mSelfURI, "need mSelfURI to translate 'self' into actual URI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSelfURI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSelfURI))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mSelfURI" " (" "need mSelfURI to translate 'self' into actual URI"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 845); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSelfURI" ") ("
"need mSelfURI to translate 'self' into actual URI" ")"); do
{ *((volatile int*)__null) = 845; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
846 return NS_OK;
847}
848
849NS_IMETHODIMPnsresult
850nsCSPContext::SetRequestContextWithPrincipal(nsIPrincipal* aRequestPrincipal,
851 nsIURI* aSelfURI,
852 const nsACString& aReferrer,
853 uint64_t aInnerWindowId) {
854 NS_ENSURE_ARG(aRequestPrincipal)do { if ((__builtin_expect(!!(!(aRequestPrincipal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRequestPrincipal" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 854); return NS_ERROR_INVALID_ARG; } } while (false)
;
855
856 mLoadingPrincipal = aRequestPrincipal;
857 mSelfURI = aSelfURI;
858 mReferrer = aReferrer;
859 mInnerWindowID = aInnerWindowId;
860 // if no document is available, then it also does not make sense to queue
861 // console messages sending messages to the browser console instead of the web
862 // console in that case.
863 mQueueUpMessages = false;
864 mCallingChannelLoadGroup = nullptr;
865 mEventTarget = nullptr;
866
867 MOZ_ASSERT(mLoadingPrincipal, "need a valid requestPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadingPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadingPrincipal))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadingPrincipal"
" (" "need a valid requestPrincipal" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadingPrincipal"
") (" "need a valid requestPrincipal" ")"); do { *((volatile
int*)__null) = 867; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
868 MOZ_ASSERT(mSelfURI, "need mSelfURI to translate 'self' into actual URI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSelfURI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSelfURI))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mSelfURI" " (" "need mSelfURI to translate 'self' into actual URI"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 868); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSelfURI" ") ("
"need mSelfURI to translate 'self' into actual URI" ")"); do
{ *((volatile int*)__null) = 868; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
869 return NS_OK;
870}
871
872nsIPrincipal* nsCSPContext::GetRequestPrincipal() { return mLoadingPrincipal; }
873
874nsIURI* nsCSPContext::GetSelfURI() { return mSelfURI; }
875
876NS_IMETHODIMPnsresult
877nsCSPContext::GetReferrer(nsACString& outReferrer) {
878 outReferrer.Assign(mReferrer);
879 return NS_OK;
880}
881
882uint64_t nsCSPContext::GetInnerWindowID() { return mInnerWindowID; }
883
884bool nsCSPContext::GetSkipAllowInlineStyleCheck() {
885 return mSkipAllowInlineStyleCheck;
886}
887
888void nsCSPContext::SetSkipAllowInlineStyleCheck(
889 bool aSkipAllowInlineStyleCheck) {
890 mSkipAllowInlineStyleCheck = aSkipAllowInlineStyleCheck;
891}
892
893NS_IMETHODIMPnsresult
894nsCSPContext::EnsureEventTarget(nsIEventTarget* aEventTarget) {
895 NS_ENSURE_ARG(aEventTarget)do { if ((__builtin_expect(!!(!(aEventTarget)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEventTarget" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 895); return NS_ERROR_INVALID_ARG; } } while (false)
;
896 // Don't bother if we did have a valid event target (if the csp object is
897 // tied to a document in SetRequestContextWithDocument)
898 if (mEventTarget) {
899 return NS_OK;
900 }
901
902 mEventTarget = aEventTarget;
903 return NS_OK;
904}
905
906struct ConsoleMsgQueueElem {
907 nsString mMsg;
908 nsCString mSourceName;
909 nsString mSourceLine;
910 uint32_t mLineNumber;
911 uint32_t mColumnNumber;
912 uint32_t mSeverityFlag;
913 nsCString mCategory;
914};
915
916void nsCSPContext::flushConsoleMessages() {
917 bool privateWindow = false;
918
919 // should flush messages even if doc is not available
920 nsCOMPtr<Document> doc = do_QueryReferent(mLoadingContext);
921 if (doc) {
922 mInnerWindowID = doc->InnerWindowID();
923 privateWindow =
924 doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
925 }
926
927 mQueueUpMessages = false;
928
929 for (uint32_t i = 0; i < mConsoleMsgQueue.Length(); i++) {
930 ConsoleMsgQueueElem& elem = mConsoleMsgQueue[i];
931 CSP_LogMessage(elem.mMsg, elem.mSourceName, elem.mSourceLine,
932 elem.mLineNumber, elem.mColumnNumber, elem.mSeverityFlag,
933 elem.mCategory, mInnerWindowID, privateWindow);
934 }
935 mConsoleMsgQueue.Clear();
936}
937
938void nsCSPContext::logToConsole(const char* aName,
939 const nsTArray<nsString>& aParams,
940 const nsACString& aSourceName,
941 const nsAString& aSourceLine,
942 uint32_t aLineNumber, uint32_t aColumnNumber,
943 uint32_t aSeverityFlag) {
944 // we are passing aName as the category so we can link to the
945 // appropriate MDN docs depending on the specific error.
946 nsDependentCString category(aName);
947
948 // Fallback
949 nsAutoCString spec;
950 if (aSourceName.IsEmpty() && mSelfURI) {
951 mSelfURI->GetSpec(spec);
952 }
953
954 const auto& sourceName = aSourceName.IsEmpty() ? spec : aSourceName;
955
956 // let's check if we have to queue up console messages
957 if (mQueueUpMessages) {
958 nsAutoString msg;
959 CSP_GetLocalizedStr(aName, aParams, msg);
960 ConsoleMsgQueueElem& elem = *mConsoleMsgQueue.AppendElement();
961 elem.mMsg = msg;
962 elem.mSourceName = sourceName;
963 elem.mSourceLine = PromiseFlatStringTPromiseFlatString<char16_t>(aSourceLine);
964 elem.mLineNumber = aLineNumber;
965 elem.mColumnNumber = aColumnNumber;
966 elem.mSeverityFlag = aSeverityFlag;
967 elem.mCategory = category;
968 return;
969 }
970
971 bool privateWindow = false;
972 if (nsCOMPtr<Document> doc = do_QueryReferent(mLoadingContext)) {
973 privateWindow =
974 doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
975 }
976
977 CSP_LogLocalizedStr(aName, aParams, sourceName, aSourceLine, aLineNumber,
978 aColumnNumber, aSeverityFlag, category, mInnerWindowID,
979 privateWindow);
980}
981
982/**
983 * Strip URI for reporting according to:
984 * https://w3c.github.io/webappsec-csp/#security-violation-reports
985 *
986 * @param aSelfURI
987 * The URI of the CSP policy. Used for cross-origin checks.
988 * @param aURI
989 * The URI of the blocked resource. In case of a redirect, this it the
990 * initial URI the request started out with, not the redirected URI.
991 * @param aEffectiveDirective
992 * The effective directive that triggered this report
993 * @return The ASCII serialization of the uri to be reported ignoring
994 * the ref part of the URI.
995 */
996void StripURIForReporting(nsIURI* aSelfURI, nsIURI* aURI,
997 const nsAString& aEffectiveDirective,
998 nsACString& outStrippedURI) {
999 if (aSelfURI->SchemeIs("chrome")) {
1000 aURI->GetSpecIgnoringRef(outStrippedURI);
1001 return;
1002 }
1003
1004 // If the origin of aURI is a globally unique identifier (for example,
1005 // aURI has a scheme of data, blob, or filesystem), then
1006 // return the ASCII serialization of uri’s scheme.
1007 bool isHttpOrWs = (aURI->SchemeIs("http") || aURI->SchemeIs("https") ||
1008 aURI->SchemeIs("ws") || aURI->SchemeIs("wss"));
1009
1010 if (!isHttpOrWs) {
1011 // not strictly spec compliant, but what we really care about is
1012 // http/https. If it's not http/https, then treat aURI
1013 // as if it's a globally unique identifier and just return the scheme.
1014 aURI->GetScheme(outStrippedURI);
1015 return;
1016 }
1017
1018 // For cross-origin URIs in frame-src also strip the path.
1019 // This prevents detailed tracking of pages loaded into an iframe
1020 // by the embedding page using a report-only policy.
1021 if (aEffectiveDirective.EqualsLiteral("frame-src") ||
1022 aEffectiveDirective.EqualsLiteral("object-src")) {
1023 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
1024 if (NS_FAILED(ssm->CheckSameOriginURI(aSelfURI, aURI, false, false))((bool)(__builtin_expect(!!(NS_FAILED_impl(ssm->CheckSameOriginURI
(aSelfURI, aURI, false, false))), 0)))
) {
1025 aURI->GetPrePath(outStrippedURI);
1026 return;
1027 }
1028 }
1029
1030 // Return aURI, with any fragment component removed.
1031 aURI->GetSpecIgnoringRef(outStrippedURI);
1032}
1033
1034nsresult nsCSPContext::GatherSecurityPolicyViolationEventData(
1035 nsIURI* aOriginalURI, const nsAString& aEffectiveDirective,
1036 const mozilla::dom::CSPViolationData& aCSPViolationData, bool aReportSample,
1037 mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit) {
1038 EnsureIPCPoliciesRead();
1039 NS_ENSURE_ARG_MAX(aCSPViolationData.mViolatedPolicyIndex,do { if ((__builtin_expect(!!(!((aCSPViolationData.mViolatedPolicyIndex
) <= mPolicies.Length() - 1)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "(aCSPViolationData.mViolatedPolicyIndex) <= mPolicies.Length() - 1"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1040); return NS_ERROR_INVALID_ARG; } } while (false)
1040 mPolicies.Length() - 1)do { if ((__builtin_expect(!!(!((aCSPViolationData.mViolatedPolicyIndex
) <= mPolicies.Length() - 1)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "(aCSPViolationData.mViolatedPolicyIndex) <= mPolicies.Length() - 1"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1040); return NS_ERROR_INVALID_ARG; } } while (false)
;
1041
1042 MOZ_ASSERT(ValidateDirectiveName(aEffectiveDirective),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ValidateDirectiveName(aEffectiveDirective))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(ValidateDirectiveName(aEffectiveDirective)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("ValidateDirectiveName(aEffectiveDirective)"
" (" "Invalid directive name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1043); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ValidateDirectiveName(aEffectiveDirective)"
") (" "Invalid directive name" ")"); do { *((volatile int*)__null
) = 1043; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
1043 "Invalid directive name")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ValidateDirectiveName(aEffectiveDirective))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(ValidateDirectiveName(aEffectiveDirective)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("ValidateDirectiveName(aEffectiveDirective)"
" (" "Invalid directive name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1043); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ValidateDirectiveName(aEffectiveDirective)"
") (" "Invalid directive name" ")"); do { *((volatile int*)__null
) = 1043; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1044
1045 nsresult rv;
1046
1047 // document-uri
1048 nsAutoCString reportDocumentURI;
1049 StripURIForReporting(mSelfURI, mSelfURI, aEffectiveDirective,
1050 reportDocumentURI);
1051 CopyUTF8toUTF16(reportDocumentURI, aViolationEventInit.mDocumentURI);
1052
1053 // referrer
1054 CopyUTF8toUTF16(mReferrer, aViolationEventInit.mReferrer);
1055
1056 // blocked-uri
1057 // Corresponds to
1058 // <https://w3c.github.io/webappsec-csp/#obtain-violation-blocked-uri>.
1059 if (aCSPViolationData.mResource.is<nsCOMPtr<nsIURI>>()) {
1060 nsAutoCString reportBlockedURI;
1061 StripURIForReporting(
1062 mSelfURI,
1063 aOriginalURI ? aOriginalURI
1064 : aCSPViolationData.mResource.as<nsCOMPtr<nsIURI>>().get(),
1065 aEffectiveDirective, reportBlockedURI);
1066 CopyUTF8toUTF16(reportBlockedURI, aViolationEventInit.mBlockedURI);
1067 } else {
1068 nsAutoCString blockedContentSource;
1069 BlockedContentSourceToString(
1070 aCSPViolationData.mResource
1071 .as<CSPViolationData::BlockedContentSource>(),
1072 blockedContentSource);
1073 CopyUTF8toUTF16(blockedContentSource, aViolationEventInit.mBlockedURI);
1074 }
1075
1076 // effective-directive
1077 // The name of the policy directive that was violated.
1078 aViolationEventInit.mEffectiveDirective = aEffectiveDirective;
1079
1080 // violated-directive
1081 // In CSP2, the policy directive that was violated, as it appears in the
1082 // policy. In CSP3, the same as effective-directive.
1083 aViolationEventInit.mViolatedDirective = aEffectiveDirective;
1084
1085 // original-policy
1086 nsAutoString originalPolicy;
1087 rv = this->GetPolicyString(aCSPViolationData.mViolatedPolicyIndex,
1088 originalPolicy);
1089 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1089); return rv; } } while (false)
;
1090 aViolationEventInit.mOriginalPolicy = originalPolicy;
1091
1092 // source-file
1093 if (!aCSPViolationData.mSourceFile.IsEmpty()) {
1094 // if aSourceFile is a URI, we have to make sure to strip fragments
1095 nsCOMPtr<nsIURI> sourceURI;
1096 NS_NewURI(getter_AddRefs(sourceURI), aCSPViolationData.mSourceFile);
1097 if (sourceURI) {
1098 nsAutoCString stripped;
1099 StripURIForReporting(mSelfURI, sourceURI, aEffectiveDirective, stripped);
1100 CopyUTF8toUTF16(stripped, aViolationEventInit.mSourceFile);
1101 } else {
1102 CopyUTF8toUTF16(aCSPViolationData.mSourceFile,
1103 aViolationEventInit.mSourceFile);
1104 }
1105 }
1106
1107 // sample (already truncated)
1108 aViolationEventInit.mSample =
1109 aReportSample ? aCSPViolationData.mSample : EmptyString();
1110
1111 // disposition
1112 aViolationEventInit.mDisposition =
1113 mPolicies[aCSPViolationData.mViolatedPolicyIndex]->getReportOnlyFlag()
1114 ? mozilla::dom::SecurityPolicyViolationEventDisposition::Report
1115 : mozilla::dom::SecurityPolicyViolationEventDisposition::Enforce;
1116
1117 // status-code
1118 uint16_t statusCode = 0;
1119 {
1120 nsCOMPtr<Document> doc = do_QueryReferent(mLoadingContext);
1121 if (doc) {
1122 nsCOMPtr<nsIHttpChannel> channel = do_QueryInterface(doc->GetChannel());
1123 if (channel) {
1124 uint32_t responseStatus = 0;
1125 nsresult rv = channel->GetResponseStatus(&responseStatus);
1126 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && (responseStatus <= UINT16_MAX(65535))) {
1127 statusCode = static_cast<uint16_t>(responseStatus);
1128 }
1129 }
1130 }
1131 }
1132 aViolationEventInit.mStatusCode = statusCode;
1133
1134 // line-number
1135 aViolationEventInit.mLineNumber = aCSPViolationData.mLineNumber;
1136
1137 // column-number
1138 aViolationEventInit.mColumnNumber = aCSPViolationData.mColumnNumber;
1139
1140 aViolationEventInit.mBubbles = true;
1141 aViolationEventInit.mComposed = true;
1142
1143 return NS_OK;
1144}
1145
1146bool nsCSPContext::ShouldThrottleReport(
1147 const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit) {
1148 // Fetch rate limiting preferences
1149 const uint32_t kLimitCount =
1150 StaticPrefs::security_csp_reporting_limit_count();
1151 const uint32_t kTimeSpanSeconds =
1152 StaticPrefs::security_csp_reporting_limit_timespan();
1153
1154 // Disable throttling if either of the preferences is set to 0.
1155 if (kLimitCount == 0 || kTimeSpanSeconds == 0) {
1156 return false;
1157 }
1158
1159 TimeDuration throttleSpan = TimeDuration::FromSeconds(kTimeSpanSeconds);
1160 if (mSendReportLimitSpanStart.IsNull() ||
1161 ((TimeStamp::Now() - mSendReportLimitSpanStart) > throttleSpan)) {
1162 // Initial call or timespan exceeded, reset counter and timespan.
1163 mSendReportLimitSpanStart = TimeStamp::Now();
1164 mSendReportLimitCount = 1;
1165 // Also make sure we warn about omitted messages. (XXX or only do this once
1166 // per context?)
1167 mWarnedAboutTooManyReports = false;
1168 return false;
1169 }
1170
1171 if (mSendReportLimitCount < kLimitCount) {
1172 mSendReportLimitCount++;
1173 return false;
1174 }
1175
1176 // Rate limit reached
1177 if (!mWarnedAboutTooManyReports) {
1178 logToConsole("tooManyReports", {},
1179 NS_ConvertUTF16toUTF8(aViolationEventInit.mSourceFile),
1180 aViolationEventInit.mSample, aViolationEventInit.mLineNumber,
1181 aViolationEventInit.mColumnNumber, nsIScriptError::errorFlag);
1182 mWarnedAboutTooManyReports = true;
1183 }
1184 return true;
1185}
1186
1187nsresult nsCSPContext::SendReports(
1188 const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit,
1189 uint32_t aViolatedPolicyIndex) {
1190 EnsureIPCPoliciesRead();
1191 NS_ENSURE_ARG_MAX(aViolatedPolicyIndex, mPolicies.Length() - 1)do { if ((__builtin_expect(!!(!((aViolatedPolicyIndex) <= mPolicies
.Length() - 1)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"(aViolatedPolicyIndex) <= mPolicies.Length() - 1" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1191); return NS_ERROR_INVALID_ARG; } } while (false)
;
1192
1193 if (ShouldThrottleReport(aViolationEventInit)) {
1194 return NS_OK;
1195 }
1196
1197 nsAutoString reportGroup;
1198 mPolicies[aViolatedPolicyIndex]->getReportGroup(reportGroup);
1199
1200 // CSP Level 3 Reporting
1201 if (StaticPrefs::dom_reporting_enabled() && !reportGroup.IsEmpty()) {
1202 return SendReportsToEndpoints(reportGroup, aViolationEventInit);
1203 }
1204
1205 nsTArray<nsString> reportURIs;
1206 mPolicies[aViolatedPolicyIndex]->getReportURIs(reportURIs);
1207
1208 //[Deprecated] CSP Level 2 Reporting
1209 if (!reportURIs.IsEmpty()) {
1210 return SendReportsToURIs(reportURIs, aViolationEventInit);
1211 }
1212
1213 return NS_OK;
1214}
1215
1216nsresult nsCSPContext::SendReportsToEndpoints(
1217 nsAutoString& reportGroup,
1218 const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit) {
1219 nsCOMPtr<Document> doc = do_QueryReferent(mLoadingContext);
1220 if (!doc) {
1221 return NS_ERROR_FAILURE;
1222 }
1223 nsPIDOMWindowInner* window = doc->GetInnerWindow();
1224 if (NS_WARN_IF(!window)NS_warn_if_impl(!window, "!window", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1224)
) {
1225 return NS_ERROR_FAILURE;
1226 }
1227
1228 RefPtr<CSPViolationReportBody> body =
1229 new CSPViolationReportBody(window->AsGlobal(), aViolationEventInit);
1230
1231 ReportingUtils::Report(window->AsGlobal(), nsGkAtoms::cspViolation,
1232 reportGroup, aViolationEventInit.mDocumentURI, body);
1233 return NS_OK;
1234}
1235
1236nsresult nsCSPContext::SendReportsToURIs(
1237 const nsTArray<nsString>& reportURIs,
1238 const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit) {
1239 dom::CSPReport report;
1240
1241 // blocked-uri
1242 report.mCsp_report.mBlocked_uri = aViolationEventInit.mBlockedURI;
1243
1244 // document-uri
1245 report.mCsp_report.mDocument_uri = aViolationEventInit.mDocumentURI;
1246
1247 // original-policy
1248 report.mCsp_report.mOriginal_policy = aViolationEventInit.mOriginalPolicy;
1249
1250 // referrer
1251 report.mCsp_report.mReferrer = aViolationEventInit.mReferrer;
1252
1253 // effective-directive
1254 report.mCsp_report.mEffective_directive =
1255 aViolationEventInit.mEffectiveDirective;
1256
1257 // violated-directive
1258 report.mCsp_report.mViolated_directive =
1259 aViolationEventInit.mEffectiveDirective;
1260
1261 // disposition
1262 report.mCsp_report.mDisposition = aViolationEventInit.mDisposition;
1263
1264 // status-code
1265 report.mCsp_report.mStatus_code = aViolationEventInit.mStatusCode;
1266
1267 // source-file
1268 if (!aViolationEventInit.mSourceFile.IsEmpty()) {
1269 report.mCsp_report.mSource_file.Construct();
1270 CopyUTF16toUTF8(aViolationEventInit.mSourceFile,
1271 report.mCsp_report.mSource_file.Value());
1272 }
1273
1274 // script-sample
1275 if (!aViolationEventInit.mSample.IsEmpty()) {
1276 report.mCsp_report.mScript_sample.Construct();
1277 report.mCsp_report.mScript_sample.Value() = aViolationEventInit.mSample;
1278 }
1279
1280 // line-number
1281 if (aViolationEventInit.mLineNumber != 0) {
1282 report.mCsp_report.mLine_number.Construct();
1283 report.mCsp_report.mLine_number.Value() = aViolationEventInit.mLineNumber;
1284 }
1285
1286 if (aViolationEventInit.mColumnNumber != 0) {
1287 report.mCsp_report.mColumn_number.Construct();
1288 report.mCsp_report.mColumn_number.Value() =
1289 aViolationEventInit.mColumnNumber;
1290 }
1291
1292 nsString csp_report;
1293 if (!report.ToJSON(csp_report)) {
1294 return NS_ERROR_FAILURE;
1295 }
1296
1297 // ---------- Assembled, now send it to all the report URIs ----------- //
1298 nsCOMPtr<Document> doc = do_QueryReferent(mLoadingContext);
1299 nsCOMPtr<nsIURI> reportURI;
1300 nsCOMPtr<nsIChannel> reportChannel;
1301
1302 nsresult rv;
1303 for (uint32_t r = 0; r < reportURIs.Length(); r++) {
1304 nsAutoCString reportURICstring = NS_ConvertUTF16toUTF8(reportURIs[r]);
1305 // try to create a new uri from every report-uri string
1306 rv = NS_NewURI(getter_AddRefs(reportURI), reportURIs[r]);
1307 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1308 AutoTArray<nsString, 1> params = {reportURIs[r]};
1309 CSPCONTEXTLOG(("Could not create nsIURI for report URI %s",do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Could not create nsIURI for report URI %s"
, reportURICstring.get()); } } while (0)
1310 reportURICstring.get()))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Could not create nsIURI for report URI %s"
, reportURICstring.get()); } } while (0)
;
1311 logToConsole("triedToSendReport", params,
1312 NS_ConvertUTF16toUTF8(aViolationEventInit.mSourceFile),
1313 aViolationEventInit.mSample, aViolationEventInit.mLineNumber,
1314 aViolationEventInit.mColumnNumber,
1315 nsIScriptError::errorFlag);
1316 continue; // don't return yet, there may be more URIs
1317 }
1318
1319 // try to create a new channel for every report-uri
1320 if (doc) {
1321 rv =
1322 NS_NewChannel(getter_AddRefs(reportChannel), reportURI, doc,
1323 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
1324 nsIContentPolicy::TYPE_CSP_REPORT);
1325 } else {
1326 rv = NS_NewChannel(
1327 getter_AddRefs(reportChannel), reportURI, mLoadingPrincipal,
1328 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
1329 nsIContentPolicy::TYPE_CSP_REPORT);
1330 }
1331
1332 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1333 CSPCONTEXTLOG(("Could not create new channel for report URI %s",do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Could not create new channel for report URI %s"
, reportURICstring.get()); } } while (0)
1334 reportURICstring.get()))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Could not create new channel for report URI %s"
, reportURICstring.get()); } } while (0)
;
1335 continue; // don't return yet, there may be more URIs
1336 }
1337
1338 // log a warning to console if scheme is not http or https
1339 bool isHttpScheme =
1340 reportURI->SchemeIs("http") || reportURI->SchemeIs("https");
1341
1342 if (!isHttpScheme) {
1343 AutoTArray<nsString, 1> params = {reportURIs[r]};
1344 logToConsole("reportURInotHttpsOrHttp2", params,
1345 NS_ConvertUTF16toUTF8(aViolationEventInit.mSourceFile),
1346 aViolationEventInit.mSample, aViolationEventInit.mLineNumber,
1347 aViolationEventInit.mColumnNumber,
1348 nsIScriptError::errorFlag);
1349 continue;
1350 }
1351
1352 // make sure this is an anonymous request (no cookies) so in case the
1353 // policy URI is injected, it can't be abused for CSRF.
1354 nsLoadFlags flags;
1355 rv = reportChannel->GetLoadFlags(&flags);
1356 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1356); return rv; } } while (false)
;
1357 flags |= nsIRequest::LOAD_ANONYMOUS;
1358 flags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
1359 rv = reportChannel->SetLoadFlags(flags);
1360 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1360); return rv; } } while (false)
;
1361
1362 // we need to set an nsIChannelEventSink on the channel object
1363 // so we can tell it to not follow redirects when posting the reports
1364 RefPtr<CSPReportRedirectSink> reportSink = new CSPReportRedirectSink();
1365 if (doc && doc->GetDocShell()) {
1366 nsCOMPtr<nsINetworkInterceptController> interceptController =
1367 do_QueryInterface(doc->GetDocShell());
1368 reportSink->SetInterceptController(interceptController);
1369 }
1370 reportChannel->SetNotificationCallbacks(reportSink);
1371
1372 // apply the loadgroup taken by setRequestContextWithDocument. If there's
1373 // no loadgroup, AsyncOpen will fail on process-split necko (since the
1374 // channel cannot query the iBrowserChild).
1375 rv = reportChannel->SetLoadGroup(mCallingChannelLoadGroup);
1376 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1376); return rv; } } while (false)
;
1377
1378 // wire in the string input stream to send the report
1379 nsCOMPtr<nsIStringInputStream> sis(
1380 do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID"@mozilla.org/io/string-input-stream;1"));
1381 NS_ASSERTION(sis,do { if (!(sis)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "nsIStringInputStream is needed but not available to send CSP "
"violation reports", "sis", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1383); MOZ_PretendNoReturn(); } } while (0)
1382 "nsIStringInputStream is needed but not available to send CSP "do { if (!(sis)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "nsIStringInputStream is needed but not available to send CSP "
"violation reports", "sis", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1383); MOZ_PretendNoReturn(); } } while (0)
1383 "violation reports")do { if (!(sis)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "nsIStringInputStream is needed but not available to send CSP "
"violation reports", "sis", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1383); MOZ_PretendNoReturn(); } } while (0)
;
1384 rv = sis->SetUTF8Data(NS_ConvertUTF16toUTF8(csp_report));
1385 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1385); return rv; } } while (false)
;
1386
1387 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(reportChannel));
1388 if (!uploadChannel) {
1389 // It's possible the URI provided can't be uploaded to, in which case
1390 // we skip this one. We'll already have warned about a non-HTTP URI
1391 // earlier.
1392 continue;
1393 }
1394
1395 rv = uploadChannel->SetUploadStream(sis, "application/csp-report"_ns, -1);
1396 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1396); return rv; } } while (false)
;
1397
1398 // if this is an HTTP channel, set the request method to post
1399 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(reportChannel));
1400 if (httpChannel) {
1401 rv = httpChannel->SetRequestMethod("POST"_ns);
1402 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1402); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 1402; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1403 }
1404
1405 RefPtr<CSPViolationReportListener> listener =
1406 new CSPViolationReportListener();
1407 rv = reportChannel->AsyncOpen(listener);
1408
1409 // AsyncOpen should not fail, but could if there's no load group (like if
1410 // SetRequestContextWith{Document,Principal} is not given a channel). This
1411 // should fail quietly and not return an error since it's really ok if
1412 // reports don't go out, but it's good to log the error locally.
1413
1414 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1415 AutoTArray<nsString, 1> params = {reportURIs[r]};
1416 CSPCONTEXTLOG(("AsyncOpen failed for report URI %s",do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "AsyncOpen failed for report URI %s"
, NS_ConvertUTF16toUTF8(params[0]).get()); } } while (0)
1417 NS_ConvertUTF16toUTF8(params[0]).get()))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "AsyncOpen failed for report URI %s"
, NS_ConvertUTF16toUTF8(params[0]).get()); } } while (0)
;
1418 logToConsole("triedToSendReport", params,
1419 NS_ConvertUTF16toUTF8(aViolationEventInit.mSourceFile),
1420 aViolationEventInit.mSample, aViolationEventInit.mLineNumber,
1421 aViolationEventInit.mColumnNumber,
1422 nsIScriptError::errorFlag);
1423 } else {
1424 CSPCONTEXTLOG(do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Sent violation report to URI %s"
, reportURICstring.get()); } } while (0)
1425 ("Sent violation report to URI %s", reportURICstring.get()))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Sent violation report to URI %s"
, reportURICstring.get()); } } while (0)
;
1426 }
1427 }
1428 return NS_OK;
1429}
1430
1431nsresult nsCSPContext::FireViolationEvent(
1432 Element* aTriggeringElement, nsICSPEventListener* aCSPEventListener,
1433 const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit) {
1434 if (aCSPEventListener) {
1435 nsAutoString json;
1436 if (aViolationEventInit.ToJSON(json)) {
1437 aCSPEventListener->OnCSPViolationEvent(json);
1438 }
1439
1440 return NS_OK;
1441 }
1442
1443 // 1. If target is not null, and global is a Window, and target’s
1444 // shadow-including root is not global’s associated Document, set target to
1445 // null.
1446 RefPtr<EventTarget> eventTarget = aTriggeringElement;
1447
1448 nsCOMPtr<Document> doc = do_QueryReferent(mLoadingContext);
1449 if (doc && aTriggeringElement &&
1450 aTriggeringElement->GetComposedDoc() != doc) {
1451 eventTarget = nullptr;
1452 }
1453
1454 if (!eventTarget) {
1455 // If target is a Window, set target to target’s associated Document.
1456 eventTarget = doc;
1457 }
1458
1459 if (!eventTarget && mInnerWindowID && XRE_IsParentProcess()) {
1460 if (RefPtr<WindowGlobalParent> parent =
1461 WindowGlobalParent::GetByInnerWindowId(mInnerWindowID)) {
1462 nsAutoString json;
1463 if (aViolationEventInit.ToJSON(json)) {
1464 Unused << parent->SendDispatchSecurityPolicyViolation(json);
1465 }
1466 }
1467 return NS_OK;
1468 }
1469
1470 if (!eventTarget) {
1471 // If we are here, we are probably dealing with workers. Those are handled
1472 // via nsICSPEventListener. Nothing to do here.
1473 return NS_OK;
1474 }
1475
1476 RefPtr<mozilla::dom::Event> event =
1477 mozilla::dom::SecurityPolicyViolationEvent::Constructor(
1478 eventTarget, u"securitypolicyviolation"_ns, aViolationEventInit);
1479 event->SetTrusted(true);
1480
1481 ErrorResult rv;
1482 eventTarget->DispatchEvent(*event, rv);
1483 return rv.StealNSResult();
1484}
1485
1486/**
1487 * Dispatched from the main thread to send reports for one CSP violation.
1488 */
1489class CSPReportSenderRunnable final : public Runnable {
1490 public:
1491 CSPReportSenderRunnable(nsICSPEventListener* aCSPEventListener,
1492 CSPViolationData&& aCSPViolationData,
1493 nsIURI* aOriginalURI, bool aReportOnlyFlag,
1494 const nsAString& aViolatedDirectiveName,
1495 const nsAString& aViolatedDirectiveNameAndValue,
1496 const nsAString& aObserverSubject, bool aReportSample,
1497 nsCSPContext* aCSPContext)
1498 : mozilla::Runnable("CSPReportSenderRunnable"),
1499 mCSPEventListener(aCSPEventListener),
1500 mCSPViolationData(std::move(aCSPViolationData)),
1501 mOriginalURI(aOriginalURI),
1502 mReportOnlyFlag(aReportOnlyFlag),
1503 mReportSample(aReportSample),
1504 mViolatedDirectiveName(aViolatedDirectiveName),
1505 mViolatedDirectiveNameAndValue(aViolatedDirectiveNameAndValue),
1506 mCSPContext(aCSPContext) {
1507 NS_ASSERTION(!aViolatedDirectiveName.IsEmpty(),do { if (!(!aViolatedDirectiveName.IsEmpty())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Can not send reports without a violated directive"
, "!aViolatedDirectiveName.IsEmpty()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1508); MOZ_PretendNoReturn(); } } while (0)
1508 "Can not send reports without a violated directive")do { if (!(!aViolatedDirectiveName.IsEmpty())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Can not send reports without a violated directive"
, "!aViolatedDirectiveName.IsEmpty()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1508); MOZ_PretendNoReturn(); } } while (0)
;
1509 // the observer subject is an nsISupports: either an nsISupportsCString
1510 // from the arg passed in directly, or if that's empty, it's the blocked
1511 // source.
1512 if (aObserverSubject.IsEmpty() &&
1513 mCSPViolationData.mResource.is<nsCOMPtr<nsIURI>>()) {
1514 mObserverSubject = mCSPViolationData.mResource.as<nsCOMPtr<nsIURI>>();
1515 return;
1516 }
1517
1518 nsAutoCString subject;
1519 if (aObserverSubject.IsEmpty()) {
1520 BlockedContentSourceToString(
1521 mCSPViolationData.BlockedContentSourceOrUnknown(), subject);
1522 } else {
1523 CopyUTF16toUTF8(aObserverSubject, subject);
1524 }
1525
1526 nsCOMPtr<nsISupportsCString> supportscstr =
1527 do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID"@mozilla.org/supports-cstring;1");
1528 if (supportscstr) {
1529 supportscstr->SetData(subject);
1530 mObserverSubject = do_QueryInterface(supportscstr);
1531 }
1532 }
1533
1534 NS_IMETHODvirtual nsresult Run() override {
1535 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 1535; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1536
1537 // 0) prepare violation data
1538 mozilla::dom::SecurityPolicyViolationEventInit init;
1539
1540 nsAutoString effectiveDirective;
1541 effectiveDirective.AssignASCII(
1542 CSP_CSPDirectiveToString(mCSPViolationData.mEffectiveDirective));
1543
1544 nsresult rv = mCSPContext->GatherSecurityPolicyViolationEventData(
1545 mOriginalURI, effectiveDirective, mCSPViolationData, mReportSample,
1546 init);
1547 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1547); return rv; } } while (false)
;
1548
1549 // 1) notify observers
1550 nsCOMPtr<nsIObserverService> observerService =
1551 mozilla::services::GetObserverService();
1552 if (mObserverSubject && observerService) {
1553 rv = observerService->NotifyObservers(
1554 mObserverSubject, CSP_VIOLATION_TOPIC"csp-on-violate-policy", mViolatedDirectiveName.get());
1555 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1555); return rv; } } while (false)
;
1556 }
1557
1558 // 2) send reports for the policy that was violated
1559 mCSPContext->SendReports(init, mCSPViolationData.mViolatedPolicyIndex);
1560
1561 // 3) log to console (one per policy violation)
1562 ReportToConsole();
1563
1564 // 4) fire violation event
1565 // A frame-ancestors violation has occurred, but we should not dispatch
1566 // the violation event to a potentially cross-origin ancestor.
1567 if (!mViolatedDirectiveName.EqualsLiteral("frame-ancestors")) {
1568 mCSPContext->FireViolationEvent(mCSPViolationData.mElement,
1569 mCSPEventListener, init);
1570 }
1571
1572 return NS_OK;
1573 }
1574
1575 private:
1576 void ReportToConsole() const {
1577 NS_ConvertUTF8toUTF16 effectiveDirective(
1578 CSP_CSPDirectiveToString(mCSPViolationData.mEffectiveDirective));
1579
1580 const auto blockedContentSource =
1581 mCSPViolationData.BlockedContentSourceOrUnknown();
1582
1583 switch (blockedContentSource) {
1584 case CSPViolationData::BlockedContentSource::Inline: {
1585 const char* errorName = nullptr;
1586 if (mCSPViolationData.mEffectiveDirective ==
1587 CSPDirective::STYLE_SRC_ATTR_DIRECTIVE ||
1588 mCSPViolationData.mEffectiveDirective ==
1589 CSPDirective::STYLE_SRC_ELEM_DIRECTIVE) {
1590 errorName = mReportOnlyFlag ? "CSPROInlineStyleViolation"
1591 : "CSPInlineStyleViolation";
1592 } else if (mCSPViolationData.mEffectiveDirective ==
1593 CSPDirective::SCRIPT_SRC_ATTR_DIRECTIVE) {
1594 errorName = mReportOnlyFlag ? "CSPROEventHandlerScriptViolation"
1595 : "CSPEventHandlerScriptViolation";
1596 } else {
1597 MOZ_ASSERT(mCSPViolationData.mEffectiveDirective ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCSPViolationData.mEffectiveDirective == CSPDirective
::SCRIPT_SRC_ELEM_DIRECTIVE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCSPViolationData.mEffectiveDirective
== CSPDirective::SCRIPT_SRC_ELEM_DIRECTIVE))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mCSPViolationData.mEffectiveDirective == CSPDirective::SCRIPT_SRC_ELEM_DIRECTIVE"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCSPViolationData.mEffectiveDirective == CSPDirective::SCRIPT_SRC_ELEM_DIRECTIVE"
")"); do { *((volatile int*)__null) = 1598; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1598 CSPDirective::SCRIPT_SRC_ELEM_DIRECTIVE)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCSPViolationData.mEffectiveDirective == CSPDirective
::SCRIPT_SRC_ELEM_DIRECTIVE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCSPViolationData.mEffectiveDirective
== CSPDirective::SCRIPT_SRC_ELEM_DIRECTIVE))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mCSPViolationData.mEffectiveDirective == CSPDirective::SCRIPT_SRC_ELEM_DIRECTIVE"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCSPViolationData.mEffectiveDirective == CSPDirective::SCRIPT_SRC_ELEM_DIRECTIVE"
")"); do { *((volatile int*)__null) = 1598; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1599 errorName = mReportOnlyFlag ? "CSPROInlineScriptViolation"
1600 : "CSPInlineScriptViolation";
1601 }
1602
1603 AutoTArray<nsString, 2> params = {mViolatedDirectiveNameAndValue,
1604 effectiveDirective};
1605 mCSPContext->logToConsole(
1606 errorName, params, mCSPViolationData.mSourceFile,
1607 mCSPViolationData.mSample, mCSPViolationData.mLineNumber,
1608 mCSPViolationData.mColumnNumber, nsIScriptError::errorFlag);
1609 break;
1610 }
1611
1612 case CSPViolationData::BlockedContentSource::Eval: {
1613 AutoTArray<nsString, 2> params = {mViolatedDirectiveNameAndValue,
1614 effectiveDirective};
1615 mCSPContext->logToConsole(
1616 mReportOnlyFlag ? "CSPROEvalScriptViolation"
1617 : "CSPEvalScriptViolation",
1618 params, mCSPViolationData.mSourceFile, mCSPViolationData.mSample,
1619 mCSPViolationData.mLineNumber, mCSPViolationData.mColumnNumber,
1620 nsIScriptError::errorFlag);
1621 break;
1622 }
1623
1624 case CSPViolationData::BlockedContentSource::WasmEval: {
1625 AutoTArray<nsString, 2> params = {mViolatedDirectiveNameAndValue,
1626 effectiveDirective};
1627 mCSPContext->logToConsole(
1628 mReportOnlyFlag ? "CSPROWasmEvalScriptViolation"
1629 : "CSPWasmEvalScriptViolation",
1630 params, mCSPViolationData.mSourceFile, mCSPViolationData.mSample,
1631 mCSPViolationData.mLineNumber, mCSPViolationData.mColumnNumber,
1632 nsIScriptError::errorFlag);
1633 break;
1634 }
1635
1636 case CSPViolationData::BlockedContentSource::TrustedTypesPolicy: {
1637 AutoTArray<nsString, 1> params = {mViolatedDirectiveNameAndValue};
1638
1639 mCSPContext->logToConsole(
1640 mReportOnlyFlag ? "CSPROTrustedTypesPolicyViolation"
1641 : "CSPTrustedTypesPolicyViolation",
1642 params, mCSPViolationData.mSourceFile, mCSPViolationData.mSample,
1643 mCSPViolationData.mLineNumber, mCSPViolationData.mColumnNumber,
1644 nsIScriptError::errorFlag);
1645 break;
1646 }
1647
1648 case CSPViolationData::BlockedContentSource::TrustedTypesSink: {
1649 mCSPContext->logToConsole(
1650 mReportOnlyFlag ? "CSPROTrustedTypesSinkViolation"
1651 : "CSPTrustedTypesSinkViolation",
1652 {}, mCSPViolationData.mSourceFile, mCSPViolationData.mSample,
1653 mCSPViolationData.mLineNumber, mCSPViolationData.mColumnNumber,
1654 nsIScriptError::errorFlag);
1655 break;
1656 }
1657
1658 case CSPViolationData::BlockedContentSource::Self:
1659 case CSPViolationData::BlockedContentSource::Unknown: {
1660 nsAutoString source(u"<unknown>"_ns);
1661 if (mCSPViolationData.mResource.is<nsCOMPtr<nsIURI>>()) {
1662 nsAutoCString uri;
1663 auto blockedURI = mCSPViolationData.mResource.as<nsCOMPtr<nsIURI>>();
1664 blockedURI->GetSpec(uri);
1665
1666 if (blockedURI->SchemeIs("data") &&
1667 uri.Length() > nsCSPContext::ScriptSampleMaxLength()) {
1668 uri.Truncate(nsCSPContext::ScriptSampleMaxLength());
1669 uri.Append(
1670 NS_ConvertUTF16toUTF8(nsContentUtils::GetLocalizedEllipsis()));
1671 }
1672
1673 if (!uri.IsEmpty()) {
1674 CopyUTF8toUTF16(uri, source);
1675 }
1676 }
1677
1678 const char* errorName = nullptr;
1679 switch (mCSPViolationData.mEffectiveDirective) {
1680 case CSPDirective::STYLE_SRC_ELEM_DIRECTIVE:
1681 errorName =
1682 mReportOnlyFlag ? "CSPROStyleViolation" : "CSPStyleViolation";
1683 break;
1684 case CSPDirective::SCRIPT_SRC_ELEM_DIRECTIVE:
1685 errorName =
1686 mReportOnlyFlag ? "CSPROScriptViolation" : "CSPScriptViolation";
1687 break;
1688 case CSPDirective::WORKER_SRC_DIRECTIVE:
1689 errorName =
1690 mReportOnlyFlag ? "CSPROWorkerViolation" : "CSPWorkerViolation";
1691 break;
1692 default:
1693 errorName = mReportOnlyFlag ? "CSPROGenericViolation"
1694 : "CSPGenericViolation";
1695 }
1696
1697 AutoTArray<nsString, 3> params = {mViolatedDirectiveNameAndValue,
1698 source, effectiveDirective};
1699 mCSPContext->logToConsole(
1700 errorName, params, mCSPViolationData.mSourceFile,
1701 mCSPViolationData.mSample, mCSPViolationData.mLineNumber,
1702 mCSPViolationData.mColumnNumber, nsIScriptError::errorFlag);
1703 }
1704 }
1705 }
1706
1707 nsCOMPtr<nsICSPEventListener> mCSPEventListener;
1708 CSPViolationData mCSPViolationData;
1709 nsCOMPtr<nsIURI> mOriginalURI;
1710 bool mReportOnlyFlag;
1711 bool mReportSample;
1712 nsString mViolatedDirectiveName;
1713 nsString mViolatedDirectiveNameAndValue;
1714 nsCOMPtr<nsISupports> mObserverSubject;
1715 RefPtr<nsCSPContext> mCSPContext;
1716};
1717
1718nsresult nsCSPContext::AsyncReportViolation(
1719 nsICSPEventListener* aCSPEventListener,
1720 mozilla::dom::CSPViolationData&& aCSPViolationData, nsIURI* aOriginalURI,
1721 const nsAString& aViolatedDirectiveName,
1722 const nsAString& aViolatedDirectiveNameAndValue,
1723 const nsAString& aObserverSubject, bool aReportSample) {
1724 EnsureIPCPoliciesRead();
1725 NS_ENSURE_ARG_MAX(aCSPViolationData.mViolatedPolicyIndex,do { if ((__builtin_expect(!!(!((aCSPViolationData.mViolatedPolicyIndex
) <= mPolicies.Length() - 1)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "(aCSPViolationData.mViolatedPolicyIndex) <= mPolicies.Length() - 1"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1726); return NS_ERROR_INVALID_ARG; } } while (false)
1726 mPolicies.Length() - 1)do { if ((__builtin_expect(!!(!((aCSPViolationData.mViolatedPolicyIndex
) <= mPolicies.Length() - 1)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "(aCSPViolationData.mViolatedPolicyIndex) <= mPolicies.Length() - 1"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1726); return NS_ERROR_INVALID_ARG; } } while (false)
;
1727
1728 nsCOMPtr<nsIRunnable> task = new CSPReportSenderRunnable(
1729 aCSPEventListener, std::move(aCSPViolationData), aOriginalURI,
1730 mPolicies[aCSPViolationData.mViolatedPolicyIndex]->getReportOnlyFlag(),
1731 aViolatedDirectiveName, aViolatedDirectiveNameAndValue, aObserverSubject,
1732 aReportSample, this);
1733
1734 if (XRE_IsContentProcess()) {
1735 if (mEventTarget) {
1736 mEventTarget->Dispatch(task.forget(), NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1737 return NS_OK;
1738 }
1739 }
1740
1741 NS_DispatchToMainThread(task.forget());
1742 return NS_OK;
1743}
1744
1745/**
1746 * Based on the given loadinfo, determines if this CSP context allows the
1747 * ancestry.
1748 *
1749 * In order to determine the URI of the parent document (one causing the load
1750 * of this protected document), this function traverses all Browsing Contexts
1751 * until it reaches the top level browsing context.
1752 */
1753NS_IMETHODIMPnsresult
1754nsCSPContext::PermitsAncestry(nsILoadInfo* aLoadInfo,
1755 bool* outPermitsAncestry) {
1756 nsresult rv;
1757
1758 *outPermitsAncestry = true;
1759
1760 RefPtr<mozilla::dom::BrowsingContext> ctx;
1761 aLoadInfo->GetBrowsingContext(getter_AddRefs(ctx));
1762
1763 // extract the ancestry as an array
1764 nsCOMArray<nsIURI> ancestorsArray;
1765 nsCOMPtr<nsIURI> uriClone;
1766
1767 while (ctx) {
1768 nsCOMPtr<nsIPrincipal> currentPrincipal;
1769 // Generally permitsAncestry is consulted from within the
1770 // DocumentLoadListener in the parent process. For loads of type object
1771 // and embed it's called from the Document in the content process.
1772 // After Bug 1646899 we should be able to remove that branching code for
1773 // querying the currentURI.
1774 if (XRE_IsParentProcess()) {
1775 WindowGlobalParent* window = ctx->Canonical()->GetCurrentWindowGlobal();
1776 if (window) {
1777 // Using the URI of the Principal and not the document because e.g.
1778 // about:blank inherits the principal and hence the URI of the
1779 // document does not reflect the security context of the document.
1780 currentPrincipal = window->DocumentPrincipal();
1781 }
1782 } else if (nsPIDOMWindowOuter* windowOuter = ctx->GetDOMWindow()) {
1783 currentPrincipal = nsGlobalWindowOuter::Cast(windowOuter)->GetPrincipal();
1784 }
1785
1786 if (currentPrincipal) {
1787 nsCOMPtr<nsIURI> currentURI;
1788 auto* currentBasePrincipal = BasePrincipal::Cast(currentPrincipal);
1789 currentBasePrincipal->GetURI(getter_AddRefs(currentURI));
1790
1791 if (currentURI) {
1792 nsAutoCString spec;
1793 currentURI->GetSpec(spec);
1794 // delete the userpass from the URI.
1795 rv = NS_MutateURI(currentURI)
1796 .SetRef(""_ns)
1797 .SetUserPass(""_ns)
1798 .Finalize(uriClone);
1799
1800 // If setUserPass fails for some reason, just return a clone of the
1801 // current URI
1802 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1803 rv = NS_GetURIWithoutRef(currentURI, getter_AddRefs(uriClone));
1804 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1804); return rv; } } while (false)
;
1805 }
1806 ancestorsArray.AppendElement(uriClone);
1807 }
1808 }
1809 ctx = ctx->GetParent();
1810 }
1811
1812 nsAutoString violatedDirective;
1813
1814 // Now that we've got the ancestry chain in ancestorsArray, time to check
1815 // them against any CSP.
1816 // NOTE: the ancestors are not allowed to be sent cross origin; this is a
1817 // restriction not placed on subresource loads.
1818
1819 for (uint32_t a = 0; a < ancestorsArray.Length(); a++) {
1820 if (CSPCONTEXTLOGENABLED()(__builtin_expect(!!(mozilla::detail::log_test(GetCspContextLog
(), mozilla::LogLevel::Debug)), 0))
) {
1821 CSPCONTEXTLOG(("nsCSPContext::PermitsAncestry, checking ancestor: %s",do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::PermitsAncestry, checking ancestor: %s"
, ancestorsArray[a]->GetSpecOrDefault().get()); } } while (
0)
1822 ancestorsArray[a]->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::PermitsAncestry, checking ancestor: %s"
, ancestorsArray[a]->GetSpecOrDefault().get()); } } while (
0)
;
1823 }
1824 // omit the ancestor URI in violation reports if cross-origin as per spec
1825 // (it is a violation of the same-origin policy).
1826 bool okToSendAncestor =
1827 NS_SecurityCompareURIs(ancestorsArray[a], mSelfURI, true);
1828
1829 bool permits =
1830 permitsInternal(nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE,
1831 nullptr, // triggering element
1832 nullptr, // nsICSPEventListener
1833 nullptr, // nsILoadInfo
1834 ancestorsArray[a],
1835 nullptr, // no redirect here.
1836 true, // specific, do not use default-src
1837 true, // send violation reports
1838 okToSendAncestor);
1839 if (!permits) {
1840 *outPermitsAncestry = false;
1841 }
1842 }
1843 return NS_OK;
1844}
1845
1846NS_IMETHODIMPnsresult
1847nsCSPContext::Permits(Element* aTriggeringElement,
1848 nsICSPEventListener* aCSPEventListener, nsIURI* aURI,
1849 CSPDirective aDir, bool aSpecific,
1850 bool aSendViolationReports, bool* outPermits) {
1851 // Can't perform check without aURI
1852 if (aURI == nullptr) {
1853 return NS_ERROR_FAILURE;
1854 }
1855
1856 if (aURI->SchemeIs("resource")) {
1857 // XXX Ideally we would call SubjectToCSP() here but that would also
1858 // allowlist e.g. javascript: URIs which should not be allowlisted here.
1859 // As a hotfix we just allowlist pdf.js internals here explicitly.
1860 nsAutoCString uriSpec;
1861 aURI->GetSpec(uriSpec);
1862 if (StringBeginsWith(uriSpec, "resource://pdf.js/"_ns)) {
1863 *outPermits = true;
1864 return NS_OK;
1865 }
1866 }
1867
1868 *outPermits = permitsInternal(aDir, aTriggeringElement, aCSPEventListener,
1869 nullptr, // no nsILoadInfo
1870 aURI,
1871 nullptr, // no original (pre-redirect) URI
1872 aSpecific, aSendViolationReports,
1873 true); // send blocked URI in violation reports
1874
1875 if (CSPCONTEXTLOGENABLED()(__builtin_expect(!!(mozilla::detail::log_test(GetCspContextLog
(), mozilla::LogLevel::Debug)), 0))
) {
1876 CSPCONTEXTLOG(("nsCSPContext::Permits, aUri: %s, aDir: %s, isAllowed: %s",do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::Permits, aUri: %s, aDir: %s, isAllowed: %s"
, aURI->GetSpecOrDefault().get(), CSP_CSPDirectiveToString
(aDir), *outPermits ? "allow" : "deny"); } } while (0)
1877 aURI->GetSpecOrDefault().get(),do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::Permits, aUri: %s, aDir: %s, isAllowed: %s"
, aURI->GetSpecOrDefault().get(), CSP_CSPDirectiveToString
(aDir), *outPermits ? "allow" : "deny"); } } while (0)
1878 CSP_CSPDirectiveToString(aDir),do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::Permits, aUri: %s, aDir: %s, isAllowed: %s"
, aURI->GetSpecOrDefault().get(), CSP_CSPDirectiveToString
(aDir), *outPermits ? "allow" : "deny"); } } while (0)
1879 *outPermits ? "allow" : "deny"))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::Permits, aUri: %s, aDir: %s, isAllowed: %s"
, aURI->GetSpecOrDefault().get(), CSP_CSPDirectiveToString
(aDir), *outPermits ? "allow" : "deny"); } } while (0)
;
1880 }
1881
1882 return NS_OK;
1883}
1884
1885NS_IMETHODIMPnsresult
1886nsCSPContext::ToJSON(nsAString& outCSPinJSON) {
1887 outCSPinJSON.Truncate();
1888 dom::CSPPolicies jsonPolicies;
1889 jsonPolicies.mCsp_policies.Construct();
1890 EnsureIPCPoliciesRead();
1891
1892 for (uint32_t p = 0; p < mPolicies.Length(); p++) {
1893 dom::CSP jsonCSP;
1894 mPolicies[p]->toDomCSPStruct(jsonCSP);
1895 if (!jsonPolicies.mCsp_policies.Value().AppendElement(jsonCSP, fallible)) {
1896 return NS_ERROR_OUT_OF_MEMORY;
1897 }
1898 }
1899
1900 // convert the gathered information to JSON
1901 if (!jsonPolicies.ToJSON(outCSPinJSON)) {
1902 return NS_ERROR_FAILURE;
1903 }
1904 return NS_OK;
1905}
1906
1907NS_IMETHODIMPnsresult
1908nsCSPContext::GetCSPSandboxFlags(uint32_t* aOutSandboxFlags) {
1909 if (!aOutSandboxFlags) {
1910 return NS_ERROR_FAILURE;
1911 }
1912 *aOutSandboxFlags = SANDBOXED_NONE;
1913
1914 EnsureIPCPoliciesRead();
1915 for (uint32_t i = 0; i < mPolicies.Length(); i++) {
1916 uint32_t flags = mPolicies[i]->getSandboxFlags();
1917
1918 // current policy doesn't have sandbox flag, check next policy
1919 if (!flags) {
1920 continue;
1921 }
1922
1923 // current policy has sandbox flags, if the policy is in enforcement-mode
1924 // (i.e. not report-only) set these flags and check for policies with more
1925 // restrictions
1926 if (!mPolicies[i]->getReportOnlyFlag()) {
1927 *aOutSandboxFlags |= flags;
1928 } else {
1929 // sandbox directive is ignored in report-only mode, warn about it and
1930 // continue the loop checking for an enforcement policy.
1931 nsAutoString policy;
1932 mPolicies[i]->toString(policy);
1933
1934 CSPCONTEXTLOG(do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::GetCSPSandboxFlags, report only policy, ignoring "
"sandbox in: %s", NS_ConvertUTF16toUTF8(policy).get()); } } while
(0)
1935 ("nsCSPContext::GetCSPSandboxFlags, report only policy, ignoring "do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::GetCSPSandboxFlags, report only policy, ignoring "
"sandbox in: %s", NS_ConvertUTF16toUTF8(policy).get()); } } while
(0)
1936 "sandbox in: %s",do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::GetCSPSandboxFlags, report only policy, ignoring "
"sandbox in: %s", NS_ConvertUTF16toUTF8(policy).get()); } } while
(0)
1937 NS_ConvertUTF16toUTF8(policy).get()))do { const ::mozilla::LogModule* moz_real_module = GetCspContextLog
(); if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "nsCSPContext::GetCSPSandboxFlags, report only policy, ignoring "
"sandbox in: %s", NS_ConvertUTF16toUTF8(policy).get()); } } while
(0)
;
1938
1939 AutoTArray<nsString, 1> params = {policy};
1940 logToConsole("ignoringReportOnlyDirective", params, ""_ns, u""_ns, 0, 1,
1941 nsIScriptError::warningFlag);
1942 }
1943 }
1944
1945 return NS_OK;
1946}
1947
1948/* ========== CSPViolationReportListener implementation ========== */
1949
1950NS_IMPL_ISUPPORTS(CSPViolationReportListener, nsIStreamListener,MozExternalRefCountType CSPViolationReportListener::AddRef(void
) { static_assert(!std::is_destructible_v<CSPViolationReportListener
>, "Reference-counted class " "CSPViolationReportListener"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
1951; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CSPViolationReportListener" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("CSPViolationReportListener" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"CSPViolationReportListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CSPViolationReportListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1951; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CSPViolationReportListener" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"CSPViolationReportListener"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType CSPViolationReportListener::
Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 1951
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CSPViolationReportListener" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("CSPViolationReportListener" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"CSPViolationReportListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CSPViolationReportListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1951; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CSPViolationReportListener" " not thread-safe"
); const char* const nametmp = "CSPViolationReportListener"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult CSPViolationReportListener::QueryInterface
(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1951); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(3 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<CSPViolationReportListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((CSPViolationReportListener*)0x1000)) - reinterpret_cast
<char*>((CSPViolationReportListener*)0x1000))}, {&mozilla
::detail::kImplementedIID<CSPViolationReportListener, nsIRequestObserver
>, int32_t( reinterpret_cast<char*>(static_cast<nsIRequestObserver
*>((CSPViolationReportListener*)0x1000)) - reinterpret_cast
<char*>((CSPViolationReportListener*)0x1000))}, {&mozilla
::detail::kImplementedIID<CSPViolationReportListener, nsISupports
>, int32_t( reinterpret_cast<char*>(static_cast<nsISupports
*>((CSPViolationReportListener*)0x1000)) - reinterpret_cast
<char*>((CSPViolationReportListener*)0x1000))}, {&mozilla
::detail::kImplementedIID<CSPViolationReportListener, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIStreamListener*>((CSPViolationReportListener
*)0x1000))) - reinterpret_cast<char*>((CSPViolationReportListener
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
1951 nsIRequestObserver, nsISupports)MozExternalRefCountType CSPViolationReportListener::AddRef(void
) { static_assert(!std::is_destructible_v<CSPViolationReportListener
>, "Reference-counted class " "CSPViolationReportListener"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
1951; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CSPViolationReportListener" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("CSPViolationReportListener" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"CSPViolationReportListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CSPViolationReportListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1951; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CSPViolationReportListener" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"CSPViolationReportListener"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType CSPViolationReportListener::
Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 1951
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CSPViolationReportListener" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("CSPViolationReportListener" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"CSPViolationReportListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CSPViolationReportListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1951; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CSPViolationReportListener" " not thread-safe"
); const char* const nametmp = "CSPViolationReportListener"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult CSPViolationReportListener::QueryInterface
(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1951); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(3 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<CSPViolationReportListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((CSPViolationReportListener*)0x1000)) - reinterpret_cast
<char*>((CSPViolationReportListener*)0x1000))}, {&mozilla
::detail::kImplementedIID<CSPViolationReportListener, nsIRequestObserver
>, int32_t( reinterpret_cast<char*>(static_cast<nsIRequestObserver
*>((CSPViolationReportListener*)0x1000)) - reinterpret_cast
<char*>((CSPViolationReportListener*)0x1000))}, {&mozilla
::detail::kImplementedIID<CSPViolationReportListener, nsISupports
>, int32_t( reinterpret_cast<char*>(static_cast<nsISupports
*>((CSPViolationReportListener*)0x1000)) - reinterpret_cast
<char*>((CSPViolationReportListener*)0x1000))}, {&mozilla
::detail::kImplementedIID<CSPViolationReportListener, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIStreamListener*>((CSPViolationReportListener
*)0x1000))) - reinterpret_cast<char*>((CSPViolationReportListener
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
;
1952
1953CSPViolationReportListener::CSPViolationReportListener() = default;
1954
1955CSPViolationReportListener::~CSPViolationReportListener() = default;
1956
1957nsresult AppendSegmentToString(nsIInputStream* aInputStream, void* aClosure,
1958 const char* aRawSegment, uint32_t aToOffset,
1959 uint32_t aCount, uint32_t* outWrittenCount) {
1960 nsCString* decodedData = static_cast<nsCString*>(aClosure);
1961 decodedData->Append(aRawSegment, aCount);
1962 *outWrittenCount = aCount;
1963 return NS_OK;
1964}
1965
1966NS_IMETHODIMPnsresult
1967CSPViolationReportListener::OnDataAvailable(nsIRequest* aRequest,
1968 nsIInputStream* aInputStream,
1969 uint64_t aOffset, uint32_t aCount) {
1970 uint32_t read;
1971 nsCString decodedData;
1972 return aInputStream->ReadSegments(AppendSegmentToString, &decodedData, aCount,
1973 &read);
1974}
1975
1976NS_IMETHODIMPnsresult
1977CSPViolationReportListener::OnStopRequest(nsIRequest* aRequest,
1978 nsresult aStatus) {
1979 return NS_OK;
1980}
1981
1982NS_IMETHODIMPnsresult
1983CSPViolationReportListener::OnStartRequest(nsIRequest* aRequest) {
1984 return NS_OK;
1985}
1986
1987/* ========== CSPReportRedirectSink implementation ========== */
1988
1989NS_IMPL_ISUPPORTS(CSPReportRedirectSink, nsIChannelEventSink,MozExternalRefCountType CSPReportRedirectSink::AddRef(void) {
static_assert(!std::is_destructible_v<CSPReportRedirectSink
>, "Reference-counted class " "CSPReportRedirectSink" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
1990; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CSPReportRedirectSink" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("CSPReportRedirectSink" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"CSPReportRedirectSink\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CSPReportRedirectSink\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1990; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CSPReportRedirectSink" " not thread-safe");
nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("CSPReportRedirectSink"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
CSPReportRedirectSink::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 1990
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CSPReportRedirectSink" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("CSPReportRedirectSink" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"CSPReportRedirectSink\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CSPReportRedirectSink\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1990; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CSPReportRedirectSink" " not thread-safe");
const char* const nametmp = "CSPReportRedirectSink"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult CSPReportRedirectSink::QueryInterface(const
nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1990); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<CSPReportRedirectSink, nsIChannelEventSink
>, int32_t( reinterpret_cast<char*>(static_cast<nsIChannelEventSink
*>((CSPReportRedirectSink*)0x1000)) - reinterpret_cast<
char*>((CSPReportRedirectSink*)0x1000))}, {&mozilla::detail
::kImplementedIID<CSPReportRedirectSink, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((CSPReportRedirectSink*)0x1000)) - reinterpret_cast<
char*>((CSPReportRedirectSink*)0x1000))}, {&mozilla::detail
::kImplementedIID<CSPReportRedirectSink, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIChannelEventSink*>((CSPReportRedirectSink
*)0x1000))) - reinterpret_cast<char*>((CSPReportRedirectSink
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
1990 nsIInterfaceRequestor)MozExternalRefCountType CSPReportRedirectSink::AddRef(void) {
static_assert(!std::is_destructible_v<CSPReportRedirectSink
>, "Reference-counted class " "CSPReportRedirectSink" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
1990; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CSPReportRedirectSink" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("CSPReportRedirectSink" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"CSPReportRedirectSink\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CSPReportRedirectSink\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1990; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CSPReportRedirectSink" " not thread-safe");
nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("CSPReportRedirectSink"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
CSPReportRedirectSink::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 1990
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CSPReportRedirectSink" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("CSPReportRedirectSink" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"CSPReportRedirectSink\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CSPReportRedirectSink\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1990; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CSPReportRedirectSink" " not thread-safe");
const char* const nametmp = "CSPReportRedirectSink"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult CSPReportRedirectSink::QueryInterface(const
nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 1990); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<CSPReportRedirectSink, nsIChannelEventSink
>, int32_t( reinterpret_cast<char*>(static_cast<nsIChannelEventSink
*>((CSPReportRedirectSink*)0x1000)) - reinterpret_cast<
char*>((CSPReportRedirectSink*)0x1000))}, {&mozilla::detail
::kImplementedIID<CSPReportRedirectSink, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((CSPReportRedirectSink*)0x1000)) - reinterpret_cast<
char*>((CSPReportRedirectSink*)0x1000))}, {&mozilla::detail
::kImplementedIID<CSPReportRedirectSink, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIChannelEventSink*>((CSPReportRedirectSink
*)0x1000))) - reinterpret_cast<char*>((CSPReportRedirectSink
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
;
1991
1992CSPReportRedirectSink::CSPReportRedirectSink() = default;
1993
1994CSPReportRedirectSink::~CSPReportRedirectSink() = default;
1995
1996NS_IMETHODIMPnsresult
1997CSPReportRedirectSink::AsyncOnChannelRedirect(
1998 nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aRedirFlags,
1999 nsIAsyncVerifyRedirectCallback* aCallback) {
2000 if (aRedirFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
2001 aCallback->OnRedirectVerifyCallback(NS_OK);
2002 return NS_OK;
2003 }
2004
2005 // cancel the old channel so XHR failure callback happens
2006 nsresult rv = aOldChannel->Cancel(NS_ERROR_ABORT);
2007 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2007); return rv; } } while (false)
;
2008
2009 // notify an observer that we have blocked the report POST due to a
2010 // redirect, used in testing, do this async since we're in an async call now
2011 // to begin with
2012 nsCOMPtr<nsIURI> uri;
2013 rv = aOldChannel->GetURI(getter_AddRefs(uri));
2014 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2014); return rv; } } while (false)
;
2015
2016 nsCOMPtr<nsIObserverService> observerService =
2017 mozilla::services::GetObserverService();
2018 NS_ASSERTION(observerService,do { if (!(observerService)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Observer service required to log CSP violations", "observerService"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2019); MOZ_PretendNoReturn(); } } while (0)
2019 "Observer service required to log CSP violations")do { if (!(observerService)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Observer service required to log CSP violations", "observerService"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2019); MOZ_PretendNoReturn(); } } while (0)
;
2020 observerService->NotifyObservers(
2021 uri, CSP_VIOLATION_TOPIC"csp-on-violate-policy",
2022 u"denied redirect while sending violation report");
2023
2024 return NS_BINDING_REDIRECTED;
2025}
2026
2027NS_IMETHODIMPnsresult
2028CSPReportRedirectSink::GetInterface(const nsIID& aIID, void** aResult) {
2029 if (aIID.Equals(NS_GET_IID(nsINetworkInterceptController)(nsINetworkInterceptController::COMTypeInfo<nsINetworkInterceptController
, void>::kIID)
) &&
2030 mInterceptController) {
2031 nsCOMPtr<nsINetworkInterceptController> copy(mInterceptController);
2032 *aResult = copy.forget().take();
2033
2034 return NS_OK;
2035 }
2036
2037 return QueryInterface(aIID, aResult);
2038}
2039
2040void CSPReportRedirectSink::SetInterceptController(
2041 nsINetworkInterceptController* aInterceptController) {
2042 mInterceptController = aInterceptController;
2043}
2044
2045/* ===== nsISerializable implementation ====== */
2046
2047NS_IMETHODIMPnsresult
2048nsCSPContext::Read(nsIObjectInputStream* aStream) {
2049 nsresult rv;
2050 nsCOMPtr<nsISupports> supports;
2051
2052 rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
2053 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2053); return rv; } } while (false)
;
2054
2055 mSelfURI = do_QueryInterface(supports);
2056 MOZ_ASSERT(mSelfURI, "need a self URI to de-serialize")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSelfURI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSelfURI))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mSelfURI" " (" "need a self URI to de-serialize"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2056); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSelfURI" ") ("
"need a self URI to de-serialize" ")"); do { *((volatile int
*)__null) = 2056; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2057
2058 nsAutoCString JSON;
2059 rv = aStream->ReadCString(JSON);
2060 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2060); return rv; } } while (false)
;
2061
2062 nsCOMPtr<nsIPrincipal> principal = BasePrincipal::FromJSON(JSON);
2063 mLoadingPrincipal = principal;
2064 MOZ_ASSERT(mLoadingPrincipal, "need a loadingPrincipal to de-serialize")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadingPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadingPrincipal))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadingPrincipal"
" (" "need a loadingPrincipal to de-serialize" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadingPrincipal"
") (" "need a loadingPrincipal to de-serialize" ")"); do { *
((volatile int*)__null) = 2064; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
2065
2066 uint32_t numPolicies;
2067 rv = aStream->Read32(&numPolicies);
2068 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2068); return rv; } } while (false)
;
2069
2070 nsAutoString policyString;
2071
2072 while (numPolicies > 0) {
2073 numPolicies--;
2074
2075 rv = aStream->ReadString(policyString);
2076 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2076); return rv; } } while (false)
;
2077
2078 bool reportOnly = false;
2079 rv = aStream->ReadBoolean(&reportOnly);
2080 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2080); return rv; } } while (false)
;
2081
2082 bool deliveredViaMetaTag = false;
2083 rv = aStream->ReadBoolean(&deliveredViaMetaTag);
Value stored to 'rv' is never read
2084
2085 bool hasRequireTrustedTypesForDirective = false;
2086 rv = aStream->ReadBoolean(&hasRequireTrustedTypesForDirective);
2087
2088 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2088); return rv; } } while (false)
;
2089 AddIPCPolicy(mozilla::ipc::ContentSecurityPolicy(
2090 policyString, reportOnly, deliveredViaMetaTag,
2091 hasRequireTrustedTypesForDirective));
2092 }
2093
2094 return NS_OK;
2095}
2096
2097NS_IMETHODIMPnsresult
2098nsCSPContext::Write(nsIObjectOutputStream* aStream) {
2099 nsresult rv = NS_WriteOptionalCompoundObject(aStream, mSelfURI,
2100 NS_GET_IID(nsIURI)(nsIURI::COMTypeInfo<nsIURI, void>::kIID), true);
2101 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2101); return rv; } } while (false)
;
2102
2103 nsAutoCString JSON;
2104 BasePrincipal::Cast(mLoadingPrincipal)->ToJSON(JSON);
2105 rv = aStream->WriteStringZ(JSON.get());
2106 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp"
, 2106); return rv; } } while (false)
;
2107
2108 // Serialize all the policies.
2109 aStream->Write32(mPolicies.Length() + mIPCPolicies.Length());
2110
2111 nsAutoString polStr;
2112 for (uint32_t p = 0; p < mPolicies.Length(); p++) {
2113 polStr.Truncate();
2114 mPolicies[p]->toString(polStr);
2115 aStream->WriteWStringZ(polStr.get());
2116 aStream->WriteBoolean(mPolicies[p]->getReportOnlyFlag());
2117 aStream->WriteBoolean(mPolicies[p]->getDeliveredViaMetaTagFlag());
2118 aStream->WriteBoolean(mPolicies[p]->hasRequireTrustedTypesForDirective());
2119 }
2120 for (auto& policy : mIPCPolicies) {
2121 aStream->WriteWStringZ(policy.policy().get());
2122 aStream->WriteBoolean(policy.reportOnlyFlag());
2123 aStream->WriteBoolean(policy.deliveredViaMetaTagFlag());
2124 aStream->WriteBoolean(policy.hasRequireTrustedTypesForDirective());
2125 }
2126 return NS_OK;
2127}
2128
2129void nsCSPContext::AddIPCPolicy(const ContentSecurityPolicy& aPolicy) {
2130 mIPCPolicies.AppendElement(aPolicy);
2131 if (aPolicy.hasRequireTrustedTypesForDirective()) {
2132 if (mRequireTrustedTypesForDirectiveState !=
2133 RequireTrustedTypesForDirectiveState::ENFORCE) {
2134 mRequireTrustedTypesForDirectiveState =
2135 aPolicy.reportOnlyFlag()
2136 ? RequireTrustedTypesForDirectiveState::REPORT_ONLY
2137 : RequireTrustedTypesForDirectiveState::ENFORCE;
2138 }
2139 }
2140}
2141
2142void nsCSPContext::SerializePolicies(
2143 nsTArray<ContentSecurityPolicy>& aPolicies) {
2144 for (auto* policy : mPolicies) {
2145 nsAutoString policyString;
2146 policy->toString(policyString);
2147 aPolicies.AppendElement(
2148 ContentSecurityPolicy(policyString, policy->getReportOnlyFlag(),
2149 policy->getDeliveredViaMetaTagFlag(),
2150 policy->hasRequireTrustedTypesForDirective()));
2151 }
2152
2153 aPolicies.AppendElements(mIPCPolicies);
2154}