File: | var/lib/jenkins/workspace/firefox-scan-build/dom/security/nsCSPContext.cpp |
Warning: | line 2083, column 5 Value stored to 'rv' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
62 | using namespace mozilla; |
63 | using namespace mozilla::dom; |
64 | using namespace mozilla::ipc; |
65 | |
66 | static 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 | |
76 | static 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 | */ |
91 | static 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 | |
108 | static 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 | |
141 | NS_IMETHODIMPnsresult |
142 | nsCSPContext::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 | |
193 | bool 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 | |
251 | NS_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 | |
253 | NS_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 | |
255 | nsCSPContext::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 | |
264 | nsCSPContext::~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 */ |
272 | bool 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 | |
305 | nsresult 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 | |
336 | NS_IMETHODIMPnsresult |
337 | nsCSPContext::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 | |
357 | NS_IMETHODIMPnsresult |
358 | nsCSPContext::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 | |
368 | const nsCSPPolicy* nsCSPContext::GetPolicy(uint32_t aIndex) { |
369 | EnsureIPCPoliciesRead(); |
370 | if (aIndex >= mPolicies.Length()) { |
371 | return nullptr; |
372 | } |
373 | return mPolicies[aIndex]; |
374 | } |
375 | |
376 | NS_IMETHODIMPnsresult |
377 | nsCSPContext::GetPolicyCount(uint32_t* outPolicyCount) { |
378 | EnsureIPCPoliciesRead(); |
379 | *outPolicyCount = mPolicies.Length(); |
380 | return NS_OK; |
381 | } |
382 | |
383 | NS_IMETHODIMPnsresult |
384 | nsCSPContext::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 | |
398 | NS_IMETHODIMPnsresult |
399 | nsCSPContext::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 | |
413 | NS_IMETHODIMPnsresult |
414 | nsCSPContext::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 | |
428 | NS_IMETHODIMPnsresult |
429 | nsCSPContext::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 | |
491 | NS_IMETHODIMPnsresult |
492 | nsCSPContext::GetRequireTrustedTypesForDirectiveState( |
493 | RequireTrustedTypesForDirectiveState* |
494 | aRequireTrustedTypesForDirectiveState) { |
495 | *aRequireTrustedTypesForDirectiveState = |
496 | mRequireTrustedTypesForDirectiveState; |
497 | return NS_OK; |
498 | } |
499 | |
500 | NS_IMETHODIMPnsresult |
501 | nsCSPContext::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 | |
520 | NS_IMETHODIMPnsresult |
521 | nsCSPContext::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 |
545 | void 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 | |
604 | NS_IMETHODIMPnsresult |
605 | nsCSPContext::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 | */ |
742 | NS_IMETHODIMPnsresult |
743 | nsCSPContext::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 | |
789 | void 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 | |
812 | NS_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 | |
826 | NS_IMETHODIMPnsresult |
827 | nsCSPContext::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 | |
849 | NS_IMETHODIMPnsresult |
850 | nsCSPContext::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 | |
872 | nsIPrincipal* nsCSPContext::GetRequestPrincipal() { return mLoadingPrincipal; } |
873 | |
874 | nsIURI* nsCSPContext::GetSelfURI() { return mSelfURI; } |
875 | |
876 | NS_IMETHODIMPnsresult |
877 | nsCSPContext::GetReferrer(nsACString& outReferrer) { |
878 | outReferrer.Assign(mReferrer); |
879 | return NS_OK; |
880 | } |
881 | |
882 | uint64_t nsCSPContext::GetInnerWindowID() { return mInnerWindowID; } |
883 | |
884 | bool nsCSPContext::GetSkipAllowInlineStyleCheck() { |
885 | return mSkipAllowInlineStyleCheck; |
886 | } |
887 | |
888 | void nsCSPContext::SetSkipAllowInlineStyleCheck( |
889 | bool aSkipAllowInlineStyleCheck) { |
890 | mSkipAllowInlineStyleCheck = aSkipAllowInlineStyleCheck; |
891 | } |
892 | |
893 | NS_IMETHODIMPnsresult |
894 | nsCSPContext::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 | |
906 | struct 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 | |
916 | void 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 | |
938 | void 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 | */ |
996 | void 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 | |
1034 | nsresult 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 | |
1146 | bool 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 | |
1187 | nsresult 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 | |
1216 | nsresult 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 | |
1236 | nsresult 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 | |
1431 | nsresult 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 | */ |
1489 | class 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 | |
1718 | nsresult 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 | */ |
1753 | NS_IMETHODIMPnsresult |
1754 | nsCSPContext::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 | |
1846 | NS_IMETHODIMPnsresult |
1847 | nsCSPContext::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 | |
1885 | NS_IMETHODIMPnsresult |
1886 | nsCSPContext::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 | |
1907 | NS_IMETHODIMPnsresult |
1908 | nsCSPContext::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 | |
1950 | NS_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 | |
1953 | CSPViolationReportListener::CSPViolationReportListener() = default; |
1954 | |
1955 | CSPViolationReportListener::~CSPViolationReportListener() = default; |
1956 | |
1957 | nsresult 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 | |
1966 | NS_IMETHODIMPnsresult |
1967 | CSPViolationReportListener::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 | |
1976 | NS_IMETHODIMPnsresult |
1977 | CSPViolationReportListener::OnStopRequest(nsIRequest* aRequest, |
1978 | nsresult aStatus) { |
1979 | return NS_OK; |
1980 | } |
1981 | |
1982 | NS_IMETHODIMPnsresult |
1983 | CSPViolationReportListener::OnStartRequest(nsIRequest* aRequest) { |
1984 | return NS_OK; |
1985 | } |
1986 | |
1987 | /* ========== CSPReportRedirectSink implementation ========== */ |
1988 | |
1989 | NS_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 | |
1992 | CSPReportRedirectSink::CSPReportRedirectSink() = default; |
1993 | |
1994 | CSPReportRedirectSink::~CSPReportRedirectSink() = default; |
1995 | |
1996 | NS_IMETHODIMPnsresult |
1997 | CSPReportRedirectSink::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 | |
2027 | NS_IMETHODIMPnsresult |
2028 | CSPReportRedirectSink::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 | |
2040 | void CSPReportRedirectSink::SetInterceptController( |
2041 | nsINetworkInterceptController* aInterceptController) { |
2042 | mInterceptController = aInterceptController; |
2043 | } |
2044 | |
2045 | /* ===== nsISerializable implementation ====== */ |
2046 | |
2047 | NS_IMETHODIMPnsresult |
2048 | nsCSPContext::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 | |
2097 | NS_IMETHODIMPnsresult |
2098 | nsCSPContext::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 | |
2129 | void 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 | |
2142 | void 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 | } |