Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp
Warning:line 663, column 5
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_protocol_http4.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/protocol/http -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/protocol/http -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_APP_UA_NAME="" -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/netwerk/protocol/http -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/cookie -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/dns -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/ipc -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/socket/neqo_glue -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/url-classifier -I /var/lib/jenkins/workspace/firefox-scan-build/extensions/auth -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-07-27-022226-2793976-1 -x c++ Unified_cpp_protocol_http4.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "nsIThreadRetargetableStreamListener.h"
8#include "nsString.h"
9#include "mozilla/Assertions.h"
10#include "mozilla/Components.h"
11#include "mozilla/LinkedList.h"
12#include "mozilla/StaticPrefs_content.h"
13#include "mozilla/StoragePrincipalHelper.h"
14
15#include "nsCORSListenerProxy.h"
16#include "nsIChannel.h"
17#include "nsIHttpChannel.h"
18#include "HttpChannelChild.h"
19#include "nsIHttpChannelInternal.h"
20#include "nsError.h"
21#include "nsContentUtils.h"
22#include "nsNetUtil.h"
23#include "nsComponentManagerUtils.h"
24#include "nsIInterfaceRequestorUtils.h"
25#include "nsServiceManagerUtils.h"
26#include "nsMimeTypes.h"
27#include "nsStringStream.h"
28#include "nsGkAtoms.h"
29#include "nsWhitespaceTokenizer.h"
30#include "nsIChannelEventSink.h"
31#include "nsIAsyncVerifyRedirectCallback.h"
32#include "nsCharSeparatedTokenizer.h"
33#include "nsAsyncRedirectVerifyHelper.h"
34#include "nsClassHashtable.h"
35#include "nsHashKeys.h"
36#include "nsStreamUtils.h"
37#include "mozilla/Preferences.h"
38#include "nsIScriptError.h"
39#include "nsILoadGroup.h"
40#include "nsILoadContext.h"
41#include "nsIConsoleService.h"
42#include "nsINetworkInterceptController.h"
43#include "nsICorsPreflightCallback.h"
44#include "nsISupportsImpl.h"
45#include "nsHttpChannel.h"
46#include "mozilla/BasePrincipal.h"
47#include "mozilla/ExpandedPrincipal.h"
48#include "mozilla/LoadInfo.h"
49#include "mozilla/NullPrincipal.h"
50#include "nsIHttpHeaderVisitor.h"
51#include "nsQueryObject.h"
52#include "mozilla/StaticPrefs_network.h"
53#include "mozilla/StaticPrefs_dom.h"
54#include "mozilla/dom/nsHTTPSOnlyUtils.h"
55#include "mozilla/dom/ReferrerInfo.h"
56#include "mozilla/dom/RequestBinding.h"
57#include "mozilla/glean/GleanMetrics.h"
58#include <algorithm>
59
60using namespace mozilla;
61using namespace mozilla::net;
62
63#define PREFLIGHT_CACHE_SIZE100 100
64// 5 seconds is chosen to be compatible with Chromium.
65#define PREFLIGHT_DEFAULT_EXPIRY_SECONDS5 5
66
67static inline nsAutoString GetStatusCodeAsString(nsIHttpChannel* aHttp) {
68 nsAutoString result;
69 uint32_t code;
70 if (NS_SUCCEEDED(aHttp->GetResponseStatus(&code))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aHttp->GetResponseStatus
(&code))), 1)))
) {
71 result.AppendInt(code);
72 }
73 return result;
74}
75
76static void LogBlockedRequest(nsIRequest* aRequest, const char* aProperty,
77 const char16_t* aParam, uint32_t aBlockingReason,
78 nsIHttpChannel* aCreatingChannel,
79 bool aIsWarning = false) {
80 nsresult rv = NS_OK;
81
82 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
83
84 if (!aIsWarning) {
85 NS_SetRequestBlockingReason(channel, aBlockingReason);
86 }
87
88 nsCOMPtr<nsIURI> aUri;
89 channel->GetURI(getter_AddRefs(aUri));
90 nsAutoCString spec;
91 if (aUri) {
92 spec = aUri->GetSpecOrDefault();
93 }
94
95 // Generate the error message
96 nsAutoString blockedMessage;
97 AutoTArray<nsString, 2> params;
98 CopyUTF8toUTF16(spec, *params.AppendElement());
99 if (aParam) {
100 params.AppendElement(aParam);
101 }
102 NS_ConvertUTF8toUTF16 specUTF16(spec);
103 rv = nsContentUtils::FormatLocalizedString(
104 nsContentUtils::eSECURITY_PROPERTIES, aProperty, params, blockedMessage);
105
106 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
107 NS_WARNING("Failed to log blocked cross-site request (no formalizedStr")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to log blocked cross-site request (no formalizedStr"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 107)
;
108 return;
109 }
110
111 nsAutoString msg(blockedMessage.get());
112 nsDependentCString category(aProperty);
113
114 if (XRE_IsParentProcess()) {
115 if (aCreatingChannel) {
116 rv = aCreatingChannel->LogBlockedCORSRequest(msg, category, aIsWarning);
117 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
118 return;
119 }
120 }
121 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Failed to log blocked cross-site request to web console from "
"parent->child, falling back to browser console", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 123)
122 "Failed to log blocked cross-site request to web console from "NS_DebugBreak(NS_DEBUG_WARNING, "Failed to log blocked cross-site request to web console from "
"parent->child, falling back to browser console", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 123)
123 "parent->child, falling back to browser console")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to log blocked cross-site request to web console from "
"parent->child, falling back to browser console", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 123)
;
124 }
125
126 bool privateBrowsing = false;
127 if (aRequest) {
128 nsCOMPtr<nsILoadGroup> loadGroup;
129 rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup));
130 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 130); return; } } while (false)
;
131 privateBrowsing = nsContentUtils::IsInPrivateBrowsing(loadGroup);
132 }
133
134 bool fromChromeContext = false;
135 if (channel) {
136 nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
137 fromChromeContext = loadInfo->TriggeringPrincipal()->IsSystemPrincipal();
138 }
139
140 // we are passing aProperty as the category so we can link to the
141 // appropriate MDN docs depending on the specific error.
142 uint64_t innerWindowID = nsContentUtils::GetInnerWindowID(aRequest);
143 // The |innerWindowID| could be 0 if this request is created from script.
144 // We can always try top level content window id in this case,
145 // since the window id can lead to current top level window's web console.
146 if (!innerWindowID) {
147 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
148 if (httpChannel) {
149 Unused << httpChannel->GetTopLevelContentWindowId(&innerWindowID);
150 }
151 }
152 nsCORSListenerProxy::LogBlockedCORSRequest(innerWindowID, privateBrowsing,
153 fromChromeContext, msg, category,
154 aIsWarning);
155}
156
157//////////////////////////////////////////////////////////////////////////
158// Preflight cache
159
160class nsPreflightCache {
161 public:
162 struct TokenTime {
163 nsCString token;
164 TimeStamp expirationTime;
165 };
166
167 struct CacheEntry : public LinkedListElement<CacheEntry> {
168 explicit CacheEntry(nsCString& aKey, bool aPrivateBrowsing)
169 : mKey(aKey), mPrivateBrowsing(aPrivateBrowsing) {
170 MOZ_COUNT_CTOR(nsPreflightCache::CacheEntry)do { static_assert(std::is_class_v<nsPreflightCache::CacheEntry
>, "Token '" "nsPreflightCache::CacheEntry" "' is not a class type."
); static_assert(!std::is_base_of<nsISupports, nsPreflightCache
::CacheEntry>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "nsPreflightCache::CacheEntry"
, sizeof(*this)); } while (0)
;
171 }
172
173 ~CacheEntry() { MOZ_COUNT_DTOR(nsPreflightCache::CacheEntry)do { static_assert(std::is_class_v<nsPreflightCache::CacheEntry
>, "Token '" "nsPreflightCache::CacheEntry" "' is not a class type."
); static_assert(!std::is_base_of<nsISupports, nsPreflightCache
::CacheEntry>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "nsPreflightCache::CacheEntry"
, sizeof(*this)); } while (0)
; }
174
175 void PurgeExpired(TimeStamp now);
176 bool CheckRequest(const nsCString& aMethod,
177 const nsTArray<nsCString>& aHeaders);
178
179 nsCString mKey;
180 bool mPrivateBrowsing{false};
181 nsTArray<TokenTime> mMethods;
182 nsTArray<TokenTime> mHeaders;
183 };
184
185 MOZ_COUNTED_DEFAULT_CTOR(nsPreflightCache)nsPreflightCache() { do { static_assert(std::is_class_v<nsPreflightCache
>, "Token '" "nsPreflightCache" "' is not a class type.");
static_assert(!std::is_base_of<nsISupports, nsPreflightCache
>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "nsPreflightCache"
, sizeof(*this)); } while (0); }
186
187 ~nsPreflightCache() {
188 Clear();
189 MOZ_COUNT_DTOR(nsPreflightCache)do { static_assert(std::is_class_v<nsPreflightCache>, "Token '"
"nsPreflightCache" "' is not a class type."); static_assert(
!std::is_base_of<nsISupports, nsPreflightCache>::value,
"nsISupports classes don't need to call MOZ_COUNT_CTOR or " "MOZ_COUNT_DTOR"
);; NS_LogDtor((void*)this, "nsPreflightCache", sizeof(*this)
); } while (0)
;
190 }
191
192 bool Initialize() { return true; }
193
194 CacheEntry* GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal,
195 bool aWithCredentials,
196 const OriginAttributes& aOriginAttributes, bool aCreate);
197 void RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal,
198 const OriginAttributes& aOriginAttributes);
199 void PurgePrivateBrowsingEntries();
200
201 void Clear();
202
203 private:
204 nsClassHashtable<nsCStringHashKey, CacheEntry> mTable;
205 LinkedList<CacheEntry> mList;
206};
207
208// Will be initialized in EnsurePreflightCache.
209static nsPreflightCache* sPreflightCache = nullptr;
210
211static bool EnsurePreflightCache() {
212 if (sPreflightCache) return true;
213
214 UniquePtr<nsPreflightCache> newCache(new nsPreflightCache());
215
216 if (newCache->Initialize()) {
217 sPreflightCache = newCache.release();
218 return true;
219 }
220
221 return false;
222}
223
224void nsPreflightCache::PurgePrivateBrowsingEntries() {
225 for (auto iter = mTable.Iter(); !iter.Done(); iter.Next()) {
226 auto* entry = iter.UserData();
227 if (entry->mPrivateBrowsing) {
228 // last private browsing window closed, remove preflight cache entries
229 entry->removeFrom(sPreflightCache->mList);
230 iter.Remove();
231 }
232 }
233}
234
235void nsPreflightCache::CacheEntry::PurgeExpired(TimeStamp now) {
236 for (uint32_t i = 0, len = mMethods.Length(); i < len; ++i) {
237 if (now >= mMethods[i].expirationTime) {
238 mMethods.UnorderedRemoveElementAt(i);
239 --i; // Examine the element again, if necessary.
240 --len;
241 }
242 }
243 for (uint32_t i = 0, len = mHeaders.Length(); i < len; ++i) {
244 if (now >= mHeaders[i].expirationTime) {
245 mHeaders.UnorderedRemoveElementAt(i);
246 --i; // Examine the element again, if necessary.
247 --len;
248 }
249 }
250}
251
252bool nsPreflightCache::CacheEntry::CheckRequest(
253 const nsCString& aMethod, const nsTArray<nsCString>& aHeaders) {
254 PurgeExpired(TimeStamp::NowLoRes());
255
256 if (!aMethod.EqualsLiteral("GET") && !aMethod.EqualsLiteral("POST")) {
257 struct CheckToken {
258 bool Equals(const TokenTime& e, const nsCString& method) const {
259 return e.token.Equals(method);
260 }
261 };
262
263 if (!mMethods.Contains(aMethod, CheckToken())) {
264 return false;
265 }
266 }
267
268 struct CheckHeaderToken {
269 bool Equals(const TokenTime& e, const nsCString& header) const {
270 return e.token.Equals(header, nsCaseInsensitiveCStringComparator);
271 }
272 } checker;
273 for (uint32_t i = 0; i < aHeaders.Length(); ++i) {
274 if (!mHeaders.Contains(aHeaders[i], checker)) {
275 return false;
276 }
277 }
278
279 return true;
280}
281
282nsPreflightCache::CacheEntry* nsPreflightCache::GetEntry(
283 nsIURI* aURI, nsIPrincipal* aPrincipal, bool aWithCredentials,
284 const OriginAttributes& aOriginAttributes, bool aCreate) {
285 nsCString key;
286 if (NS_FAILED(aPrincipal->GetPrefLightCacheKey(aURI, aWithCredentials,((bool)(__builtin_expect(!!(NS_FAILED_impl(aPrincipal->GetPrefLightCacheKey
(aURI, aWithCredentials, aOriginAttributes, key))), 0)))
287 aOriginAttributes, key))((bool)(__builtin_expect(!!(NS_FAILED_impl(aPrincipal->GetPrefLightCacheKey
(aURI, aWithCredentials, aOriginAttributes, key))), 0)))
) {
288 NS_WARNING("Invalid cache key!")NS_DebugBreak(NS_DEBUG_WARNING, "Invalid cache key!", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 288)
;
289 return nullptr;
290 }
291
292 CacheEntry* existingEntry = nullptr;
293
294 if (mTable.Get(key, &existingEntry)) {
295 // Entry already existed so just return it. Also update the LRU list.
296
297 // Move to the head of the list.
298 existingEntry->removeFrom(mList);
299 mList.insertFront(existingEntry);
300
301 return existingEntry;
302 }
303
304 if (!aCreate) {
305 return nullptr;
306 }
307
308 // This is a new entry, allocate and insert into the table now so that any
309 // failures don't cause items to be removed from a full cache.
310 auto newEntry =
311 MakeUnique<CacheEntry>(key, aOriginAttributes.IsPrivateBrowsing());
312
313 NS_ASSERTION(mTable.Count() <= PREFLIGHT_CACHE_SIZE,do { if (!(mTable.Count() <= 100)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Something is borked, too many entries in the cache!", "mTable.Count() <= PREFLIGHT_CACHE_SIZE"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 314); MOZ_PretendNoReturn(); } } while (0)
314 "Something is borked, too many entries in the cache!")do { if (!(mTable.Count() <= 100)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Something is borked, too many entries in the cache!", "mTable.Count() <= PREFLIGHT_CACHE_SIZE"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 314); MOZ_PretendNoReturn(); } } while (0)
;
315
316 // Now enforce the max count.
317 if (mTable.Count() == PREFLIGHT_CACHE_SIZE100) {
318 // Try to kick out all the expired entries.
319 TimeStamp now = TimeStamp::NowLoRes();
320 for (auto iter = mTable.Iter(); !iter.Done(); iter.Next()) {
321 auto* entry = iter.UserData();
322 entry->PurgeExpired(now);
323
324 if (entry->mHeaders.IsEmpty() && entry->mMethods.IsEmpty()) {
325 // Expired, remove from the list as well as the hash table.
326 entry->removeFrom(sPreflightCache->mList);
327 iter.Remove();
328 }
329 }
330
331 // If that didn't remove anything then kick out the least recently used
332 // entry.
333 if (mTable.Count() == PREFLIGHT_CACHE_SIZE100) {
334 CacheEntry* lruEntry = static_cast<CacheEntry*>(mList.popLast());
335 MOZ_ASSERT(lruEntry)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lruEntry)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(lruEntry))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("lruEntry", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 335); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lruEntry" ")"
); do { *((volatile int*)__null) = 335; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
336
337 // This will delete 'lruEntry'.
338 mTable.Remove(lruEntry->mKey);
339
340 NS_ASSERTION(mTable.Count() == PREFLIGHT_CACHE_SIZE - 1,do { if (!(mTable.Count() == 100 - 1)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Somehow tried to remove an entry that was never added!", "mTable.Count() == PREFLIGHT_CACHE_SIZE - 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 341); MOZ_PretendNoReturn(); } } while (0)
341 "Somehow tried to remove an entry that was never added!")do { if (!(mTable.Count() == 100 - 1)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Somehow tried to remove an entry that was never added!", "mTable.Count() == PREFLIGHT_CACHE_SIZE - 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 341); MOZ_PretendNoReturn(); } } while (0)
;
342 }
343 }
344
345 auto* newEntryWeakRef = mTable.InsertOrUpdate(key, std::move(newEntry)).get();
346 mList.insertFront(newEntryWeakRef);
347
348 return newEntryWeakRef;
349}
350
351void nsPreflightCache::RemoveEntries(
352 nsIURI* aURI, nsIPrincipal* aPrincipal,
353 const OriginAttributes& aOriginAttributes) {
354 CacheEntry* entry;
355 nsCString key;
356 if (NS_SUCCEEDED(aPrincipal->GetPrefLightCacheKey(aURI, true,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->GetPrefLightCacheKey
(aURI, true, aOriginAttributes, key))), 1)))
357 aOriginAttributes, key))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->GetPrefLightCacheKey
(aURI, true, aOriginAttributes, key))), 1)))
&&
358 mTable.Get(key, &entry)) {
359 entry->removeFrom(mList);
360 mTable.Remove(key);
361 }
362
363 if (NS_SUCCEEDED(aPrincipal->GetPrefLightCacheKey(aURI, false,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->GetPrefLightCacheKey
(aURI, false, aOriginAttributes, key))), 1)))
364 aOriginAttributes, key))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->GetPrefLightCacheKey
(aURI, false, aOriginAttributes, key))), 1)))
&&
365 mTable.Get(key, &entry)) {
366 entry->removeFrom(mList);
367 mTable.Remove(key);
368 }
369}
370
371void nsPreflightCache::Clear() {
372 mList.clear();
373 mTable.Clear();
374}
375
376//////////////////////////////////////////////////////////////////////////
377// nsCORSListenerProxy
378
379NS_IMPL_ISUPPORTS(nsCORSListenerProxy, nsIStreamListener, nsIRequestObserver,MozExternalRefCountType nsCORSListenerProxy::AddRef(void) { static_assert
(!std::is_destructible_v<nsCORSListenerProxy>, "Reference-counted class "
"nsCORSListenerProxy" " 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
381; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCORSListenerProxy" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsCORSListenerProxy" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsCORSListenerProxy\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSListenerProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 381; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCORSListenerProxy" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsCORSListenerProxy"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsCORSListenerProxy::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 381
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCORSListenerProxy" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsCORSListenerProxy" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsCORSListenerProxy\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSListenerProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 381; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCORSListenerProxy" " not thread-safe"); const
char* const nametmp = "nsCORSListenerProxy"; nsrefcnt count =
--mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult nsCORSListenerProxy::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(5 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsCORSListenerProxy, nsIStreamListener>
, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsIRequestObserver>
, int32_t( reinterpret_cast<char*>(static_cast<nsIRequestObserver
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsIChannelEventSink>
, int32_t( reinterpret_cast<char*>(static_cast<nsIChannelEventSink
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsIThreadRetargetableStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIThreadRetargetableStreamListener
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIStreamListener*>((nsCORSListenerProxy*
)0x1000))) - reinterpret_cast<char*>((nsCORSListenerProxy
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
380 nsIChannelEventSink, nsIInterfaceRequestor,MozExternalRefCountType nsCORSListenerProxy::AddRef(void) { static_assert
(!std::is_destructible_v<nsCORSListenerProxy>, "Reference-counted class "
"nsCORSListenerProxy" " 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
381; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCORSListenerProxy" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsCORSListenerProxy" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsCORSListenerProxy\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSListenerProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 381; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCORSListenerProxy" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsCORSListenerProxy"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsCORSListenerProxy::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 381
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCORSListenerProxy" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsCORSListenerProxy" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsCORSListenerProxy\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSListenerProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 381; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCORSListenerProxy" " not thread-safe"); const
char* const nametmp = "nsCORSListenerProxy"; nsrefcnt count =
--mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult nsCORSListenerProxy::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(5 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsCORSListenerProxy, nsIStreamListener>
, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsIRequestObserver>
, int32_t( reinterpret_cast<char*>(static_cast<nsIRequestObserver
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsIChannelEventSink>
, int32_t( reinterpret_cast<char*>(static_cast<nsIChannelEventSink
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsIThreadRetargetableStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIThreadRetargetableStreamListener
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIStreamListener*>((nsCORSListenerProxy*
)0x1000))) - reinterpret_cast<char*>((nsCORSListenerProxy
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
381 nsIThreadRetargetableStreamListener)MozExternalRefCountType nsCORSListenerProxy::AddRef(void) { static_assert
(!std::is_destructible_v<nsCORSListenerProxy>, "Reference-counted class "
"nsCORSListenerProxy" " 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
381; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCORSListenerProxy" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsCORSListenerProxy" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsCORSListenerProxy\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSListenerProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 381; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCORSListenerProxy" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsCORSListenerProxy"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsCORSListenerProxy::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 381
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCORSListenerProxy" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsCORSListenerProxy" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsCORSListenerProxy\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSListenerProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 381; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCORSListenerProxy" " not thread-safe"); const
char* const nametmp = "nsCORSListenerProxy"; nsrefcnt count =
--mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult nsCORSListenerProxy::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 381); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(5 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsCORSListenerProxy, nsIStreamListener>
, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsIRequestObserver>
, int32_t( reinterpret_cast<char*>(static_cast<nsIRequestObserver
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsIChannelEventSink>
, int32_t( reinterpret_cast<char*>(static_cast<nsIChannelEventSink
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsIThreadRetargetableStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIThreadRetargetableStreamListener
*>((nsCORSListenerProxy*)0x1000)) - reinterpret_cast<char
*>((nsCORSListenerProxy*)0x1000))}, {&mozilla::detail::
kImplementedIID<nsCORSListenerProxy, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIStreamListener*>((nsCORSListenerProxy*
)0x1000))) - reinterpret_cast<char*>((nsCORSListenerProxy
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
382
383/* static */
384void nsCORSListenerProxy::Shutdown() {
385 delete sPreflightCache;
386 sPreflightCache = nullptr;
387}
388
389/* static */
390void nsCORSListenerProxy::ClearCache() {
391 if (!sPreflightCache) {
392 return;
393 }
394 sPreflightCache->Clear();
395}
396
397// static
398void nsCORSListenerProxy::ClearPrivateBrowsingCache() {
399 if (!sPreflightCache) {
400 return;
401 }
402 sPreflightCache->PurgePrivateBrowsingEntries();
403}
404
405// Usually, when using an expanded principal, there's no particularly good
406// origin to do the request with. However if the expanded principal only wraps
407// one principal, we can use that one instead.
408//
409// This is needed so that DevTools can still do CORS-enabled requests (since
410// DevTools uses a triggering principal expanding the node principal to bypass
411// CSP checks, see Element::CreateDevToolsPrincipal(), bug 1604562, and bug
412// 1391994).
413static nsIPrincipal* GetOriginHeaderPrincipal(nsIPrincipal* aPrincipal) {
414 while (aPrincipal && aPrincipal->GetIsExpandedPrincipal()) {
415 auto* ep = BasePrincipal::Cast(aPrincipal)->As<ExpandedPrincipal>();
416 if (ep->AllowList().Length() != 1) {
417 break;
418 }
419 aPrincipal = ep->AllowList()[0];
420 }
421 return aPrincipal;
422}
423
424nsCORSListenerProxy::nsCORSListenerProxy(nsIStreamListener* aOuter,
425 nsIPrincipal* aRequestingPrincipal,
426 bool aWithCredentials)
427 : mOuterListener(aOuter),
428 mRequestingPrincipal(aRequestingPrincipal),
429 mOriginHeaderPrincipal(GetOriginHeaderPrincipal(aRequestingPrincipal)),
430 mWithCredentials(aWithCredentials),
431 mRequestApproved(false),
432 mHasBeenCrossSite(false),
433#ifdef DEBUG1
434 mInited(false),
435#endif
436 mMutex("nsCORSListenerProxy") {
437}
438
439nsresult nsCORSListenerProxy::Init(nsIChannel* aChannel,
440 DataURIHandling aAllowDataURI) {
441 aChannel->GetNotificationCallbacks(
442 getter_AddRefs(mOuterNotificationCallbacks));
443 aChannel->SetNotificationCallbacks(this);
444
445 nsresult rv =
446 UpdateChannel(aChannel, aAllowDataURI, UpdateType::Default, false);
447 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
448 {
449 MutexAutoLock lock(mMutex);
450 mOuterListener = nullptr;
451 }
452 mRequestingPrincipal = nullptr;
453 mOriginHeaderPrincipal = nullptr;
454 mOuterNotificationCallbacks = nullptr;
455 mHttpChannel = nullptr;
456 }
457#ifdef DEBUG1
458 mInited = true;
459#endif
460 return rv;
461}
462
463NS_IMETHODIMPnsresult
464nsCORSListenerProxy::OnStartRequest(nsIRequest* aRequest) {
465 MOZ_ASSERT(mInited, "nsCORSListenerProxy has not been initialized properly")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInited)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInited))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mInited" " (" "nsCORSListenerProxy has not been initialized properly"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInited" ") ("
"nsCORSListenerProxy has not been initialized properly" ")")
; do { *((volatile int*)__null) = 465; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
466 nsresult rv = CheckRequestApproved(aRequest);
467 mRequestApproved = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
468 if (!mRequestApproved) {
469 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
470 if (channel) {
471 nsCOMPtr<nsIURI> uri;
472 NS_GetFinalChannelURI(channel, getter_AddRefs(uri));
473 if (uri) {
474 OriginAttributes attrs;
475 StoragePrincipalHelper::GetOriginAttributesForNetworkState(channel,
476 attrs);
477
478 if (sPreflightCache) {
479 // OK to use mRequestingPrincipal since preflights never get
480 // redirected.
481 sPreflightCache->RemoveEntries(uri, mRequestingPrincipal, attrs);
482 } else {
483 nsCOMPtr<nsIHttpChannelChild> httpChannelChild =
484 do_QueryInterface(channel);
485 if (httpChannelChild) {
486 rv = httpChannelChild->RemoveCorsPreflightCacheEntry(
487 uri, mRequestingPrincipal, attrs);
488 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
489 // Only warn here to ensure we fall through the request Cancel()
490 // and outer listener OnStartRequest() calls.
491 NS_WARNING("Failed to remove CORS preflight cache entry!")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to remove CORS preflight cache entry!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 491)
;
492 }
493 }
494 }
495 }
496 }
497
498 aRequest->Cancel(NS_ERROR_DOM_BAD_URI);
499 nsCOMPtr<nsIStreamListener> listener;
500 {
501 MutexAutoLock lock(mMutex);
502 listener = mOuterListener;
503 }
504 listener->OnStartRequest(aRequest);
505
506 // Reason for NS_ERROR_DOM_BAD_URI already logged in CheckRequestApproved()
507 return NS_ERROR_DOM_BAD_URI;
508 }
509
510 nsCOMPtr<nsIStreamListener> listener;
511 {
512 MutexAutoLock lock(mMutex);
513 listener = mOuterListener;
514 }
515 return listener->OnStartRequest(aRequest);
516}
517
518namespace {
519class CheckOriginHeader final : public nsIHttpHeaderVisitor {
520 public:
521 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
522
523 CheckOriginHeader() = default;
524
525 NS_IMETHODvirtual nsresult
526 VisitHeader(const nsACString& aHeader, const nsACString& aValue) override {
527 if (aHeader.EqualsLiteral("Access-Control-Allow-Origin")) {
528 mHeaderCount++;
529 }
530
531 if (mHeaderCount > 1) {
532 return NS_ERROR_DOM_BAD_URI;
533 }
534 return NS_OK;
535 }
536
537 private:
538 uint32_t mHeaderCount{0};
539
540 ~CheckOriginHeader() = default;
541};
542
543NS_IMPL_ISUPPORTS(CheckOriginHeader, nsIHttpHeaderVisitor)MozExternalRefCountType CheckOriginHeader::AddRef(void) { static_assert
(!std::is_destructible_v<CheckOriginHeader>, "Reference-counted class "
"CheckOriginHeader" " 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
543; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CheckOriginHeader" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("CheckOriginHeader" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"CheckOriginHeader\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CheckOriginHeader\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 543; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CheckOriginHeader" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("CheckOriginHeader"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
CheckOriginHeader::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 543
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CheckOriginHeader" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("CheckOriginHeader" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"CheckOriginHeader\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 543); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CheckOriginHeader\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 543; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CheckOriginHeader" " not thread-safe"); const
char* const nametmp = "CheckOriginHeader"; nsrefcnt count = --
mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult CheckOriginHeader::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 543); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<CheckOriginHeader, nsIHttpHeaderVisitor>
, int32_t( reinterpret_cast<char*>(static_cast<nsIHttpHeaderVisitor
*>((CheckOriginHeader*)0x1000)) - reinterpret_cast<char
*>((CheckOriginHeader*)0x1000))}, {&mozilla::detail::kImplementedIID
<CheckOriginHeader, nsISupports>, int32_t(reinterpret_cast
<char*>(static_cast<nsISupports*>( static_cast<
nsIHttpHeaderVisitor*>((CheckOriginHeader*)0x1000))) - reinterpret_cast
<char*>((CheckOriginHeader*)0x1000))}, { nullptr, 0 } }
; static_assert((sizeof(table) / sizeof(table[0])) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
544} // namespace
545
546nsresult nsCORSListenerProxy::CheckRequestApproved(nsIRequest* aRequest) {
547 // Check if this was actually a cross domain request
548 if (!mHasBeenCrossSite) {
549 return NS_OK;
550 }
551 nsCOMPtr<nsIHttpChannel> topChannel;
552 topChannel.swap(mHttpChannel);
553
554 if (StaticPrefs::content_cors_disable()) {
555 LogBlockedRequest(aRequest, "CORSDisabled", nullptr,
556 nsILoadInfo::BLOCKING_REASON_CORSDISABLED, topChannel);
557 return NS_ERROR_DOM_BAD_URI;
558 }
559
560 // Check if the request failed
561 nsresult status;
562 nsresult rv = aRequest->GetStatus(&status);
563 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
564 LogBlockedRequest(aRequest, "CORSDidNotSucceed2", nullptr,
565 nsILoadInfo::BLOCKING_REASON_CORSDIDNOTSUCCEED,
566 topChannel);
567 return rv;
568 }
569
570 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
571 if (NS_BINDING_ABORTED != status) {
572 // Don't want to log mere cancellation as an error.
573 LogBlockedRequest(aRequest, "CORSDidNotSucceed2", nullptr,
574 nsILoadInfo::BLOCKING_REASON_CORSDIDNOTSUCCEED,
575 topChannel);
576 }
577 return status;
578 }
579
580 // Test that things worked on a HTTP level
581 nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
582 if (!http) {
583 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
584 nsCOMPtr<nsIURI> uri;
585 NS_GetFinalChannelURI(channel, getter_AddRefs(uri));
586 if (uri && uri->SchemeIs("moz-extension")) {
587 // moz-extension:-URLs do not support CORS, but can universally be read
588 // if an extension lists the resource in web_accessible_resources.
589 // Access will be checked in UpdateChannel.
590 return NS_OK;
591 }
592 LogBlockedRequest(aRequest, "CORSRequestNotHttp", nullptr,
593 nsILoadInfo::BLOCKING_REASON_CORSREQUESTNOTHTTP,
594 topChannel);
595 return NS_ERROR_DOM_BAD_URI;
596 }
597
598 nsCOMPtr<nsILoadInfo> loadInfo = http->LoadInfo();
599 if (loadInfo->GetServiceWorkerTaintingSynthesized()) {
600 // For synthesized responses, we don't need to perform any checks.
601 // Note: This would be unsafe if we ever changed our behavior to allow
602 // service workers to intercept CORS preflights.
603 return NS_OK;
604 }
605
606 // Check the Access-Control-Allow-Origin header
607 RefPtr<CheckOriginHeader> visitor = new CheckOriginHeader();
608 nsAutoCString allowedOriginHeader;
609
610 // check for duplicate headers
611 rv = http->VisitOriginalResponseHeaders(visitor);
612 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
613 LogBlockedRequest(
614 aRequest, "CORSMultipleAllowOriginNotAllowed", nullptr,
615 nsILoadInfo::BLOCKING_REASON_CORSMULTIPLEALLOWORIGINNOTALLOWED,
616 topChannel);
617 return rv;
618 }
619
620 rv = http->GetResponseHeader("Access-Control-Allow-Origin"_ns,
621 allowedOriginHeader);
622 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
623 auto statusCode = GetStatusCodeAsString(http);
624 LogBlockedRequest(aRequest, "CORSMissingAllowOrigin2", statusCode.get(),
625 nsILoadInfo::BLOCKING_REASON_CORSMISSINGALLOWORIGIN,
626 topChannel);
627 return rv;
628 }
629
630 // Bug 1210985 - Explicitly point out the error that the credential is
631 // not supported if the allowing origin is '*'. Note that this check
632 // has to be done before the condition
633 //
634 // >> if (mWithCredentials || !allowedOriginHeader.EqualsLiteral("*"))
635 //
636 // below since "if (A && B)" is included in "if (A || !B)".
637 //
638 if (mWithCredentials && allowedOriginHeader.EqualsLiteral("*")) {
639 LogBlockedRequest(aRequest, "CORSNotSupportingCredentials", nullptr,
640 nsILoadInfo::BLOCKING_REASON_CORSNOTSUPPORTINGCREDENTIALS,
641 topChannel);
642 return NS_ERROR_DOM_BAD_URI;
643 }
644
645 if (mWithCredentials || !allowedOriginHeader.EqualsLiteral("*")) {
646 MOZ_ASSERT(!mOriginHeaderPrincipal->GetIsExpandedPrincipal())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mOriginHeaderPrincipal->GetIsExpandedPrincipal()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mOriginHeaderPrincipal->GetIsExpandedPrincipal()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mOriginHeaderPrincipal->GetIsExpandedPrincipal()", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 646); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mOriginHeaderPrincipal->GetIsExpandedPrincipal()"
")"); do { *((volatile int*)__null) = 646; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
647 nsAutoCString origin;
648 mOriginHeaderPrincipal->GetWebExposedOriginSerialization(origin);
649
650 if (!allowedOriginHeader.Equals(origin)) {
651 LogBlockedRequest(
652 aRequest, "CORSAllowOriginNotMatchingOrigin",
653 NS_ConvertUTF8toUTF16(allowedOriginHeader).get(),
654 nsILoadInfo::BLOCKING_REASON_CORSALLOWORIGINNOTMATCHINGORIGIN,
655 topChannel);
656 return NS_ERROR_DOM_BAD_URI;
657 }
658 }
659
660 // Check Access-Control-Allow-Credentials header
661 if (mWithCredentials) {
662 nsAutoCString allowCredentialsHeader;
663 rv = http->GetResponseHeader("Access-Control-Allow-Credentials"_ns,
Value stored to 'rv' is never read
664 allowCredentialsHeader);
665
666 if (!allowCredentialsHeader.EqualsLiteral("true")) {
667 LogBlockedRequest(
668 aRequest, "CORSMissingAllowCredentials", nullptr,
669 nsILoadInfo::BLOCKING_REASON_CORSMISSINGALLOWCREDENTIALS, topChannel);
670 return NS_ERROR_DOM_BAD_URI;
671 }
672 }
673
674 return NS_OK;
675}
676
677NS_IMETHODIMPnsresult
678nsCORSListenerProxy::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
679 MOZ_ASSERT(mInited, "nsCORSListenerProxy has not been initialized properly")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInited)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInited))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mInited" " (" "nsCORSListenerProxy has not been initialized properly"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInited" ") ("
"nsCORSListenerProxy has not been initialized properly" ")")
; do { *((volatile int*)__null) = 679; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
680 nsCOMPtr<nsIStreamListener> listener;
681 {
682 MutexAutoLock lock(mMutex);
683 listener = std::move(mOuterListener);
684 }
685 nsresult rv = listener->OnStopRequest(aRequest, aStatusCode);
686 mOuterNotificationCallbacks = nullptr;
687 mHttpChannel = nullptr;
688 return rv;
689}
690
691NS_IMETHODIMPnsresult
692nsCORSListenerProxy::OnDataAvailable(nsIRequest* aRequest,
693 nsIInputStream* aInputStream,
694 uint64_t aOffset, uint32_t aCount) {
695 // NB: This can be called on any thread! But we're guaranteed that it is
696 // called between OnStartRequest and OnStopRequest, so we don't need to worry
697 // about races.
698
699 MOZ_ASSERT(mInited, "nsCORSListenerProxy has not been initialized properly")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInited)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInited))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mInited" " (" "nsCORSListenerProxy has not been initialized properly"
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInited" ") ("
"nsCORSListenerProxy has not been initialized properly" ")")
; do { *((volatile int*)__null) = 699; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
700 if (!mRequestApproved) {
701 // Reason for NS_ERROR_DOM_BAD_URI already logged in CheckRequestApproved()
702 return NS_ERROR_DOM_BAD_URI;
703 }
704 nsCOMPtr<nsIStreamListener> listener;
705 {
706 MutexAutoLock lock(mMutex);
707 listener = mOuterListener;
708 }
709 return listener->OnDataAvailable(aRequest, aInputStream, aOffset, aCount);
710}
711
712NS_IMETHODIMPnsresult
713nsCORSListenerProxy::OnDataFinished(nsresult aStatus) {
714 nsCOMPtr<nsIStreamListener> listener;
715 {
716 MutexAutoLock lock(mMutex);
717 listener = mOuterListener;
718 }
719 if (!listener) {
720 return NS_ERROR_FAILURE;
721 }
722 nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
723 do_QueryInterface(listener);
724 if (retargetableListener) {
725 return retargetableListener->OnDataFinished(aStatus);
726 }
727
728 return NS_OK;
729}
730
731void nsCORSListenerProxy::SetInterceptController(
732 nsINetworkInterceptController* aInterceptController) {
733 mInterceptController = aInterceptController;
734}
735
736NS_IMETHODIMPnsresult
737nsCORSListenerProxy::GetInterface(const nsIID& aIID, void** aResult) {
738 if (aIID.Equals(NS_GET_IID(nsIChannelEventSink)(nsIChannelEventSink::COMTypeInfo<nsIChannelEventSink, void
>::kIID)
)) {
739 *aResult = static_cast<nsIChannelEventSink*>(this);
740 NS_ADDREF_THIS()AddRef();
741
742 return NS_OK;
743 }
744
745 if (aIID.Equals(NS_GET_IID(nsINetworkInterceptController)(nsINetworkInterceptController::COMTypeInfo<nsINetworkInterceptController
, void>::kIID)
) &&
746 mInterceptController) {
747 nsCOMPtr<nsINetworkInterceptController> copy(mInterceptController);
748 *aResult = copy.forget().take();
749
750 return NS_OK;
751 }
752
753 return mOuterNotificationCallbacks
754 ? mOuterNotificationCallbacks->GetInterface(aIID, aResult)
755 : NS_ERROR_NO_INTERFACE;
756}
757
758NS_IMETHODIMPnsresult
759nsCORSListenerProxy::AsyncOnChannelRedirect(
760 nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags,
761 nsIAsyncVerifyRedirectCallback* aCb) {
762 nsresult rv;
763 if (NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags) ||
764 NS_IsHSTSUpgradeRedirect(aOldChannel, aNewChannel, aFlags)) {
765 // Internal redirects still need to be updated in order to maintain
766 // the correct headers. We use DataURIHandling::Allow, since unallowed
767 // data URIs should have been blocked before we got to the internal
768 // redirect.
769 rv = UpdateChannel(aNewChannel, DataURIHandling::Allow,
770 UpdateType::InternalOrHSTSRedirect, false);
771 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
772 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsCORSListenerProxy::AsyncOnChannelRedirect: "
"internal redirect UpdateChannel() returned failure", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 774)
773 "nsCORSListenerProxy::AsyncOnChannelRedirect: "NS_DebugBreak(NS_DEBUG_WARNING, "nsCORSListenerProxy::AsyncOnChannelRedirect: "
"internal redirect UpdateChannel() returned failure", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 774)
774 "internal redirect UpdateChannel() returned failure")NS_DebugBreak(NS_DEBUG_WARNING, "nsCORSListenerProxy::AsyncOnChannelRedirect: "
"internal redirect UpdateChannel() returned failure", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 774)
;
775 aOldChannel->Cancel(rv);
776 return rv;
777 }
778 } else {
779 mIsRedirect = true;
780 // A real, external redirect. Perform CORS checking on new URL.
781 rv = CheckRequestApproved(aOldChannel);
782 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
783 nsCOMPtr<nsIURI> oldURI;
784 NS_GetFinalChannelURI(aOldChannel, getter_AddRefs(oldURI));
785 if (oldURI) {
786 OriginAttributes attrs;
787 StoragePrincipalHelper::GetOriginAttributesForNetworkState(aOldChannel,
788 attrs);
789 if (sPreflightCache) {
790 // OK to use mRequestingPrincipal since preflights never get
791 // redirected.
792 sPreflightCache->RemoveEntries(oldURI, mRequestingPrincipal, attrs);
793 } else {
794 nsCOMPtr<nsIHttpChannelChild> httpChannelChild =
795 do_QueryInterface(aOldChannel);
796 if (httpChannelChild) {
797 rv = httpChannelChild->RemoveCorsPreflightCacheEntry(
798 oldURI, mRequestingPrincipal, attrs);
799 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
800 // Only warn here to ensure we call the channel Cancel() below
801 NS_WARNING("Failed to remove CORS preflight cache entry!")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to remove CORS preflight cache entry!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 801)
;
802 }
803 }
804 }
805 }
806 aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
807 // Reason for NS_ERROR_DOM_BAD_URI already logged in
808 // CheckRequestApproved()
809 return NS_ERROR_DOM_BAD_URI;
810 }
811
812 if (mHasBeenCrossSite) {
813 // Once we've been cross-site, cross-origin redirects reset our source
814 // origin. Note that we need to call GetChannelURIPrincipal() because
815 // we are looking for the principal that is actually being loaded and not
816 // the principal that initiated the load.
817 nsCOMPtr<nsIPrincipal> oldChannelPrincipal;
818 nsContentUtils::GetSecurityManager()->GetChannelURIPrincipal(
819 aOldChannel, getter_AddRefs(oldChannelPrincipal));
820 nsCOMPtr<nsIPrincipal> newChannelPrincipal;
821 nsContentUtils::GetSecurityManager()->GetChannelURIPrincipal(
822 aNewChannel, getter_AddRefs(newChannelPrincipal));
823 if (!oldChannelPrincipal || !newChannelPrincipal) {
824 rv = NS_ERROR_OUT_OF_MEMORY;
825 }
826
827 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
828 aOldChannel->Cancel(rv);
829 return rv;
830 }
831
832 if (!oldChannelPrincipal->Equals(newChannelPrincipal)) {
833 // Spec says to set our source origin to a unique origin.
834 mOriginHeaderPrincipal =
835 NullPrincipal::CreateWithInheritedAttributes(oldChannelPrincipal);
836 }
837 }
838
839 bool rewriteToGET = false;
840 // We need to strip auth header from preflight request for
841 // cross-origin redirects.
842 // See Bug 1874132
843 bool stripAuthHeader =
844 NS_ShouldRemoveAuthHeaderOnRedirect(aOldChannel, aNewChannel, aFlags);
845
846 nsCOMPtr<nsIHttpChannel> oldHttpChannel = do_QueryInterface(aOldChannel);
847 if (oldHttpChannel) {
848 nsAutoCString method;
849 Unused << oldHttpChannel->GetRequestMethod(method);
850 Unused << oldHttpChannel->ShouldStripRequestBodyHeader(method,
851 &rewriteToGET);
852 }
853
854 rv = UpdateChannel(
855 aNewChannel, DataURIHandling::Disallow,
856 rewriteToGET ? UpdateType::StripRequestBodyHeader : UpdateType::Default,
857 stripAuthHeader);
858 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
859 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsCORSListenerProxy::AsyncOnChannelRedirect: "
"UpdateChannel() returned failure", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 861)
860 "nsCORSListenerProxy::AsyncOnChannelRedirect: "NS_DebugBreak(NS_DEBUG_WARNING, "nsCORSListenerProxy::AsyncOnChannelRedirect: "
"UpdateChannel() returned failure", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 861)
861 "UpdateChannel() returned failure")NS_DebugBreak(NS_DEBUG_WARNING, "nsCORSListenerProxy::AsyncOnChannelRedirect: "
"UpdateChannel() returned failure", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 861)
;
862 aOldChannel->Cancel(rv);
863 return rv;
864 }
865 }
866
867 nsCOMPtr<nsIChannelEventSink> outer =
868 do_GetInterface(mOuterNotificationCallbacks);
869 if (outer) {
870 return outer->AsyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags, aCb);
871 }
872
873 aCb->OnRedirectVerifyCallback(NS_OK);
874
875 return NS_OK;
876}
877
878NS_IMETHODIMPnsresult
879nsCORSListenerProxy::CheckListenerChain() {
880 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 880); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 880; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
881
882 nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener;
883 {
884 MutexAutoLock lock(mMutex);
885 retargetableListener = do_QueryInterface(mOuterListener);
886 }
887 if (!retargetableListener) {
888 return NS_ERROR_NO_INTERFACE;
889 }
890
891 return retargetableListener->CheckListenerChain();
892}
893
894// Please note that the CSP directive 'upgrade-insecure-requests' and the
895// HTTPS-Only Mode are relying on the promise that channels get updated from
896// http: to https: before the channel fetches any data from the netwerk. Such
897// channels should not be blocked by CORS and marked as cross origin requests.
898// E.g.: toplevel page: https://www.example.com loads
899// xhr: http://www.example.com/foo which gets updated to
900// https://www.example.com/foo
901// In such a case we should bail out of CORS and rely on the promise that
902// nsHttpChannel::Connect() upgrades the request from http to https.
903bool CheckInsecureUpgradePreventsCORS(nsIPrincipal* aRequestingPrincipal,
904 nsIChannel* aChannel) {
905 nsCOMPtr<nsIURI> channelURI;
906 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
907 NS_ENSURE_SUCCESS(rv, false)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", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 907); return false; } } while (false)
;
908
909 // upgrade insecure requests is only applicable to http requests
910 if (!channelURI->SchemeIs("http")) {
911 return false;
912 }
913
914 nsCOMPtr<nsIURI> originalURI;
915 rv = aChannel->GetOriginalURI(getter_AddRefs(originalURI));
916 NS_ENSURE_SUCCESS(rv, false)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", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 916); return false; } } while (false)
;
917
918 nsAutoCString principalHost, channelHost, origChannelHost;
919
920 // if we can not query a host from the uri, there is nothing to do
921 if (NS_FAILED(aRequestingPrincipal->GetAsciiHost(principalHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aRequestingPrincipal
->GetAsciiHost(principalHost))), 0)))
||
922 NS_FAILED(channelURI->GetAsciiHost(channelHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(channelURI->GetAsciiHost
(channelHost))), 0)))
||
923 NS_FAILED(originalURI->GetAsciiHost(origChannelHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(originalURI->GetAsciiHost
(origChannelHost))), 0)))
) {
924 return false;
925 }
926
927 // if the hosts do not match, there is nothing to do
928 if (!principalHost.EqualsIgnoreCase(channelHost.get())) {
929 return false;
930 }
931
932 // also check that uri matches the one of the originalURI
933 if (!channelHost.EqualsIgnoreCase(origChannelHost.get())) {
934 return false;
935 }
936
937 return true;
938}
939
940nsresult nsCORSListenerProxy::UpdateChannel(nsIChannel* aChannel,
941 DataURIHandling aAllowDataURI,
942 UpdateType aUpdateType,
943 bool aStripAuthHeader) {
944 MOZ_ASSERT_IF(aUpdateType == UpdateType::InternalOrHSTSRedirect,do { if (aUpdateType == UpdateType::InternalOrHSTSRedirect) {
do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aStripAuthHeader)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aStripAuthHeader))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!aStripAuthHeader"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 945); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aStripAuthHeader"
")"); do { *((volatile int*)__null) = 945; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
945 !aStripAuthHeader)do { if (aUpdateType == UpdateType::InternalOrHSTSRedirect) {
do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aStripAuthHeader)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aStripAuthHeader))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!aStripAuthHeader"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 945); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aStripAuthHeader"
")"); do { *((volatile int*)__null) = 945; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
946 nsCOMPtr<nsIURI> uri, originalURI;
947 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
948 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 948); return rv; } } while (false)
;
949 rv = aChannel->GetOriginalURI(getter_AddRefs(originalURI));
950 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 950); return rv; } } while (false)
;
951
952 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
953
954 // Introduced for DevTools in order to allow overriding some requests
955 // with the content of data: URIs.
956 if (loadInfo->GetAllowInsecureRedirectToDataURI() && uri->SchemeIs("data")) {
957 return NS_OK;
958 }
959
960 // exempt data URIs from the same origin check.
961 if (aAllowDataURI == DataURIHandling::Allow && originalURI == uri) {
962 if (uri->SchemeIs("data")) {
963 return NS_OK;
964 }
965 if (loadInfo->GetAboutBlankInherits() && NS_IsAboutBlank(uri)) {
966 return NS_OK;
967 }
968 }
969
970 // Set CORS attributes on channel so that intercepted requests get correct
971 // values. We have to do this here because the CheckMayLoad checks may lead
972 // to early return. We can't be sure this is an http channel though, so we
973 // can't return early on failure.
974 nsCOMPtr<nsIHttpChannelInternal> internal = do_QueryInterface(aChannel);
975 if (internal) {
976 rv = internal->SetRequestMode(dom::RequestMode::Cors);
977 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 977); return rv; } } while (false)
;
978 rv = internal->SetCorsIncludeCredentials(mWithCredentials);
979 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 979); return rv; } } while (false)
;
980 }
981
982 // TODO: Bug 1353683
983 // consider calling SetBlockedRequest in nsCORSListenerProxy::UpdateChannel
984 //
985 // Check that the uri is ok to load
986 uint32_t flags = loadInfo->CheckLoadURIFlags();
987 rv = nsContentUtils::GetSecurityManager()->CheckLoadURIWithPrincipal(
988 mRequestingPrincipal, uri, flags, loadInfo->GetInnerWindowID());
989 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 989); return rv; } } while (false)
;
990
991 if (originalURI != uri) {
992 rv = nsContentUtils::GetSecurityManager()->CheckLoadURIWithPrincipal(
993 mRequestingPrincipal, originalURI, flags, loadInfo->GetInnerWindowID());
994 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 994); return rv; } } while (false)
;
995 }
996
997 if (uri->SchemeIs("moz-extension")) {
998 // moz-extension:-URLs do not support CORS, but can universally be read
999 // if an extension lists the resource in web_accessible_resources.
1000 // This is enforced via the CheckLoadURIWithPrincipal call above:
1001 // moz-extension resources have the URI_DANGEROUS_TO_LOAD flag, unless
1002 // listed in web_accessible_resources.
1003 return NS_OK;
1004 }
1005
1006 if (!mHasBeenCrossSite &&
1007 NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(uri, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestingPrincipal
->CheckMayLoad(uri, false))), 1)))
&&
1008 (originalURI == uri ||
1009 NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(originalURI, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestingPrincipal
->CheckMayLoad(originalURI, false))), 1)))
)) {
1010 return NS_OK;
1011 }
1012
1013 // If the CSP directive 'upgrade-insecure-requests' is used or the HTTPS-Only
1014 // Mode is enabled then we should not incorrectly require CORS if the only
1015 // difference of a subresource request and the main page is the scheme. e.g.
1016 // toplevel page: https://www.example.com loads
1017 // xhr: http://www.example.com/somefoo,
1018 // then the xhr request will be upgraded to https before it fetches any data
1019 // from the netwerk, hence we shouldn't require CORS in that specific case.
1020 if (CheckInsecureUpgradePreventsCORS(mRequestingPrincipal, aChannel)) {
1021 // Check if https-only mode upgrades this later anyway
1022 nsCOMPtr<nsILoadInfo> loadinfo = aChannel->LoadInfo();
1023 if (nsHTTPSOnlyUtils::IsSafeToAcceptCORSOrMixedContent(loadinfo)) {
1024 return NS_OK;
1025 }
1026 // Check if 'upgrade-insecure-requests' is used
1027 if (loadInfo->GetUpgradeInsecureRequests() ||
1028 loadInfo->GetBrowserUpgradeInsecureRequests()) {
1029 return NS_OK;
1030 }
1031 }
1032
1033 // Check if we need to do a preflight, and if so set one up. This must be
1034 // called once we know that the request is going, or has gone, cross-origin.
1035 rv = CheckPreflightNeeded(aChannel, aUpdateType, aStripAuthHeader);
1036 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1036); return rv; } } while (false)
;
1037
1038 // It's a cross site load
1039 mHasBeenCrossSite = true;
1040
1041 if (mIsRedirect) {
1042 // https://fetch.spec.whatwg.org/#http-redirect-fetch
1043 // Step 9. If request’s mode is "cors", locationURL includes credentials,
1044 // and request’s origin is not same origin with locationURL’s origin,
1045 // then return a network error.
1046
1047 nsAutoCString userpass;
1048 uri->GetUserPass(userpass);
1049 NS_ENSURE_TRUE(userpass.IsEmpty(), NS_ERROR_DOM_BAD_URI)do { if ((__builtin_expect(!!(!(userpass.IsEmpty())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "userpass.IsEmpty()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1049); return NS_ERROR_DOM_BAD_URI; } } while (false)
;
1050 }
1051
1052 // If we have an expanded principal here, we'll reject the CORS request,
1053 // because we can't send a useful Origin header which is required for CORS.
1054 if (nsContentUtils::IsExpandedPrincipal(mOriginHeaderPrincipal)) {
1055 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
1056 LogBlockedRequest(aChannel, "CORSOriginHeaderNotAdded", nullptr,
1057 nsILoadInfo::BLOCKING_REASON_CORSORIGINHEADERNOTADDED,
1058 httpChannel);
1059 return NS_ERROR_DOM_BAD_URI;
1060 }
1061
1062 // Add the Origin header
1063 nsAutoCString origin;
1064 rv = mOriginHeaderPrincipal->GetWebExposedOriginSerialization(origin);
1065 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1065); return rv; } } while (false)
;
1066
1067 nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aChannel);
1068 NS_ENSURE_TRUE(http, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(http)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "http" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1068); return NS_ERROR_FAILURE; } } while (false)
;
1069
1070 // hide the Origin header when requesting from .onion and requesting CORS
1071 if (StaticPrefs::network_http_referer_hideOnionSource()) {
1072 if (mOriginHeaderPrincipal->GetIsOnion()) {
1073 origin.AssignLiteral("null");
1074 }
1075 }
1076
1077 rv = http->SetRequestHeader(net::nsHttp::Origin.val(), origin, false);
1078 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1078); return rv; } } while (false)
;
1079
1080 // Make cookie-less if needed. We don't need to do anything here if the
1081 // channel was opened with AsyncOpen, since then AsyncOpen will take
1082 // care of the cookie policy for us.
1083 if (!mWithCredentials) {
1084 nsLoadFlags flags;
1085 rv = http->GetLoadFlags(&flags);
1086 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1086); return rv; } } while (false)
;
1087
1088 flags |= nsIRequest::LOAD_ANONYMOUS;
1089 if (StaticPrefs::network_cors_preflight_allow_client_cert()) {
1090 flags |= nsIRequest::LOAD_ANONYMOUS_ALLOW_CLIENT_CERT;
1091 }
1092 rv = http->SetLoadFlags(flags);
1093 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1093); return rv; } } while (false)
;
1094 }
1095
1096 mHttpChannel = http;
1097
1098 return NS_OK;
1099}
1100
1101nsresult nsCORSListenerProxy::CheckPreflightNeeded(nsIChannel* aChannel,
1102 UpdateType aUpdateType,
1103 bool aStripAuthHeader) {
1104 // If this caller isn't using AsyncOpen, or if this *is* a preflight channel,
1105 // then we shouldn't initiate preflight for this channel.
1106 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
1107 if (loadInfo->GetSecurityMode() !=
1108 nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT ||
1109 loadInfo->GetIsPreflight()) {
1110 return NS_OK;
1111 }
1112
1113 bool doPreflight = loadInfo->GetForcePreflight();
1114
1115 nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aChannel);
1116 if (!http) {
1117 // Note: A preflight is not needed for moz-extension:-requests either, but
1118 // there is already a check for that in the caller of CheckPreflightNeeded,
1119 // in UpdateChannel.
1120 LogBlockedRequest(aChannel, "CORSRequestNotHttp", nullptr,
1121 nsILoadInfo::BLOCKING_REASON_CORSREQUESTNOTHTTP,
1122 mHttpChannel);
1123 return NS_ERROR_DOM_BAD_URI;
1124 }
1125
1126 nsAutoCString method;
1127 Unused << http->GetRequestMethod(method);
1128 if (!method.LowerCaseEqualsLiteral("get") &&
1129 !method.LowerCaseEqualsLiteral("post") &&
1130 !method.LowerCaseEqualsLiteral("head")) {
1131 doPreflight = true;
1132 }
1133
1134 // Avoid copying the array here
1135 const nsTArray<nsCString>& loadInfoHeaders = loadInfo->CorsUnsafeHeaders();
1136 if (!loadInfoHeaders.IsEmpty()) {
1137 doPreflight = true;
1138 }
1139
1140 // Add Content-Type header if needed
1141 nsTArray<nsCString> headers;
1142 nsAutoCString contentTypeHeader;
1143 nsresult rv = http->GetRequestHeader("Content-Type"_ns, contentTypeHeader);
1144 // GetRequestHeader return an error if the header is not set. Don't add
1145 // "content-type" to the list if that's the case.
1146 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) &&
1147 !nsContentUtils::IsAllowedNonCorsContentType(contentTypeHeader) &&
1148 !loadInfoHeaders.Contains("content-type"_ns,
1149 nsCaseInsensitiveCStringArrayComparator())) {
1150 headers.AppendElements(loadInfoHeaders);
1151 headers.AppendElement("content-type"_ns);
1152 doPreflight = true;
1153 }
1154
1155 if (!doPreflight) {
1156 return NS_OK;
1157 }
1158
1159 nsCOMPtr<nsIHttpChannelInternal> internal = do_QueryInterface(http);
1160 if (!internal) {
1161 auto statusCode = GetStatusCodeAsString(http);
1162 LogBlockedRequest(aChannel, "CORSDidNotSucceed2", statusCode.get(),
1163 nsILoadInfo::BLOCKING_REASON_CORSDIDNOTSUCCEED,
1164 mHttpChannel);
1165 return NS_ERROR_DOM_BAD_URI;
1166 }
1167
1168 internal->SetCorsPreflightParameters(
1169 headers.IsEmpty() ? loadInfoHeaders : headers,
1170 aUpdateType == UpdateType::StripRequestBodyHeader, aStripAuthHeader);
1171
1172 return NS_OK;
1173}
1174
1175//////////////////////////////////////////////////////////////////////////
1176// Preflight proxy
1177
1178// Class used as streamlistener and notification callback when
1179// doing the initial OPTIONS request for a CORS check
1180class nsCORSPreflightListener final : public nsIStreamListener,
1181 public nsIInterfaceRequestor,
1182 public nsIChannelEventSink {
1183 public:
1184 nsCORSPreflightListener(nsIPrincipal* aReferrerPrincipal,
1185 nsICorsPreflightCallback* aCallback,
1186 nsILoadContext* aLoadContext, bool aWithCredentials,
1187 const nsCString& aPreflightMethod,
1188 const nsTArray<nsCString>& aPreflightHeaders)
1189 : mPreflightMethod(aPreflightMethod),
1190 mPreflightHeaders(aPreflightHeaders.Clone()),
1191 mReferrerPrincipal(aReferrerPrincipal),
1192 mCallback(aCallback),
1193 mLoadContext(aLoadContext),
1194 mWithCredentials(aWithCredentials) {}
1195
1196 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
1197 NS_DECL_NSISTREAMLISTENERvirtual nsresult OnDataAvailable(nsIRequest *aRequest, nsIInputStream
*aInputStream, uint64_t aOffset, uint32_t aCount) override;
1198 NS_DECL_NSIREQUESTOBSERVERvirtual nsresult OnStartRequest(nsIRequest *aRequest) override
; virtual nsresult OnStopRequest(nsIRequest *aRequest, nsresult
aStatusCode) override;
1199 NS_DECL_NSIINTERFACEREQUESTORvirtual nsresult GetInterface(const nsIID & uuid, void * *
result) override;
1200 NS_DECL_NSICHANNELEVENTSINKvirtual nsresult AsyncOnChannelRedirect(nsIChannel *oldChannel
, nsIChannel *newChannel, uint32_t flags, nsIAsyncVerifyRedirectCallback
*callback) override;
1201
1202 nsresult CheckPreflightRequestApproved(nsIRequest* aRequest);
1203
1204 private:
1205 ~nsCORSPreflightListener() = default;
1206
1207 void AddResultToCache(nsIRequest* aRequest);
1208
1209 nsCString mPreflightMethod;
1210 nsTArray<nsCString> mPreflightHeaders;
1211 nsCOMPtr<nsIPrincipal> mReferrerPrincipal;
1212 nsCOMPtr<nsICorsPreflightCallback> mCallback;
1213 nsCOMPtr<nsILoadContext> mLoadContext;
1214 bool mWithCredentials;
1215};
1216
1217NS_IMPL_ISUPPORTS(nsCORSPreflightListener, nsIStreamListener,MozExternalRefCountType nsCORSPreflightListener::AddRef(void)
{ static_assert(!std::is_destructible_v<nsCORSPreflightListener
>, "Reference-counted class " "nsCORSPreflightListener" " 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
1219; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCORSPreflightListener" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsCORSPreflightListener" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsCORSPreflightListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSPreflightListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1219; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCORSPreflightListener" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsCORSPreflightListener"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType nsCORSPreflightListener::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 1219
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCORSPreflightListener" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsCORSPreflightListener" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsCORSPreflightListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSPreflightListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1219; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCORSPreflightListener" " not thread-safe"
); const char* const nametmp = "nsCORSPreflightListener"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult nsCORSPreflightListener::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(4 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsCORSPreflightListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((nsCORSPreflightListener*)0x1000)) - reinterpret_cast<
char*>((nsCORSPreflightListener*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsCORSPreflightListener, nsIRequestObserver
>, int32_t( reinterpret_cast<char*>(static_cast<nsIRequestObserver
*>((nsCORSPreflightListener*)0x1000)) - reinterpret_cast<
char*>((nsCORSPreflightListener*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsCORSPreflightListener, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((nsCORSPreflightListener*)0x1000)) - reinterpret_cast<
char*>((nsCORSPreflightListener*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsCORSPreflightListener, nsIChannelEventSink
>, int32_t( reinterpret_cast<char*>(static_cast<nsIChannelEventSink
*>((nsCORSPreflightListener*)0x1000)) - reinterpret_cast<
char*>((nsCORSPreflightListener*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsCORSPreflightListener, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIStreamListener*>((nsCORSPreflightListener
*)0x1000))) - reinterpret_cast<char*>((nsCORSPreflightListener
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
1218 nsIRequestObserver, nsIInterfaceRequestor,MozExternalRefCountType nsCORSPreflightListener::AddRef(void)
{ static_assert(!std::is_destructible_v<nsCORSPreflightListener
>, "Reference-counted class " "nsCORSPreflightListener" " 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
1219; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCORSPreflightListener" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsCORSPreflightListener" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsCORSPreflightListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSPreflightListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1219; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCORSPreflightListener" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsCORSPreflightListener"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType nsCORSPreflightListener::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 1219
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCORSPreflightListener" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsCORSPreflightListener" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsCORSPreflightListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSPreflightListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1219; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCORSPreflightListener" " not thread-safe"
); const char* const nametmp = "nsCORSPreflightListener"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult nsCORSPreflightListener::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(4 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsCORSPreflightListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((nsCORSPreflightListener*)0x1000)) - reinterpret_cast<
char*>((nsCORSPreflightListener*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsCORSPreflightListener, nsIRequestObserver
>, int32_t( reinterpret_cast<char*>(static_cast<nsIRequestObserver
*>((nsCORSPreflightListener*)0x1000)) - reinterpret_cast<
char*>((nsCORSPreflightListener*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsCORSPreflightListener, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((nsCORSPreflightListener*)0x1000)) - reinterpret_cast<
char*>((nsCORSPreflightListener*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsCORSPreflightListener, nsIChannelEventSink
>, int32_t( reinterpret_cast<char*>(static_cast<nsIChannelEventSink
*>((nsCORSPreflightListener*)0x1000)) - reinterpret_cast<
char*>((nsCORSPreflightListener*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsCORSPreflightListener, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIStreamListener*>((nsCORSPreflightListener
*)0x1000))) - reinterpret_cast<char*>((nsCORSPreflightListener
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
1219 nsIChannelEventSink)MozExternalRefCountType nsCORSPreflightListener::AddRef(void)
{ static_assert(!std::is_destructible_v<nsCORSPreflightListener
>, "Reference-counted class " "nsCORSPreflightListener" " 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
1219; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCORSPreflightListener" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsCORSPreflightListener" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsCORSPreflightListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSPreflightListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1219; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCORSPreflightListener" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsCORSPreflightListener"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType nsCORSPreflightListener::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 1219
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsCORSPreflightListener" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsCORSPreflightListener" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"nsCORSPreflightListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSPreflightListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 1219; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsCORSPreflightListener" " not thread-safe"
); const char* const nametmp = "nsCORSPreflightListener"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult nsCORSPreflightListener::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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1219); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(4 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsCORSPreflightListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((nsCORSPreflightListener*)0x1000)) - reinterpret_cast<
char*>((nsCORSPreflightListener*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsCORSPreflightListener, nsIRequestObserver
>, int32_t( reinterpret_cast<char*>(static_cast<nsIRequestObserver
*>((nsCORSPreflightListener*)0x1000)) - reinterpret_cast<
char*>((nsCORSPreflightListener*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsCORSPreflightListener, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((nsCORSPreflightListener*)0x1000)) - reinterpret_cast<
char*>((nsCORSPreflightListener*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsCORSPreflightListener, nsIChannelEventSink
>, int32_t( reinterpret_cast<char*>(static_cast<nsIChannelEventSink
*>((nsCORSPreflightListener*)0x1000)) - reinterpret_cast<
char*>((nsCORSPreflightListener*)0x1000))}, {&mozilla::
detail::kImplementedIID<nsCORSPreflightListener, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIStreamListener*>((nsCORSPreflightListener
*)0x1000))) - reinterpret_cast<char*>((nsCORSPreflightListener
*)0x1000))}, { nullptr, 0 } } ; static_assert((sizeof(table) /
sizeof(table[0])) > 1, "need at least 1 interface"); rv =
NS_TableDrivenQI(static_cast<void*>(this), aIID, aInstancePtr
, table); return rv; }
1220
1221void nsCORSPreflightListener::AddResultToCache(nsIRequest* aRequest) {
1222 nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
1223 NS_ASSERTION(http, "Request was not http")do { if (!(http)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Request was not http"
, "http", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1223); MOZ_PretendNoReturn(); } } while (0)
;
1224
1225 // The "Access-Control-Max-Age" header should return an age in seconds.
1226 nsAutoCString headerVal;
1227 uint32_t age = 0;
1228 Unused << http->GetResponseHeader("Access-Control-Max-Age"_ns, headerVal);
1229 if (headerVal.IsEmpty()) {
1230 age = PREFLIGHT_DEFAULT_EXPIRY_SECONDS5;
1231 } else {
1232 // Sanitize the string. We only allow 'delta-seconds' as specified by
1233 // http://dev.w3.org/2006/waf/access-control (digits 0-9 with no leading or
1234 // trailing non-whitespace characters).
1235 nsACString::const_char_iterator iter, end;
1236 headerVal.BeginReading(iter);
1237 headerVal.EndReading(end);
1238 while (iter != end) {
1239 if (*iter < '0' || *iter > '9') {
1240 return;
1241 }
1242 age = age * 10 + (*iter - '0');
1243 // Cap at 24 hours. This also avoids overflow
1244 age = std::min(age, 86400U);
1245 ++iter;
1246 }
1247 }
1248
1249 if (!age || !EnsurePreflightCache()) {
1250 return;
1251 }
1252
1253 // String seems fine, go ahead and cache.
1254 // Note that we have already checked that these headers follow the correct
1255 // syntax.
1256
1257 nsCOMPtr<nsIURI> uri;
1258 NS_GetFinalChannelURI(http, getter_AddRefs(uri));
1259
1260 TimeStamp expirationTime =
1261 TimeStamp::NowLoRes() + TimeDuration::FromSeconds(age);
1262
1263 OriginAttributes attrs;
1264 StoragePrincipalHelper::GetOriginAttributesForNetworkState(http, attrs);
1265
1266 nsPreflightCache::CacheEntry* entry = sPreflightCache->GetEntry(
1267 uri, mReferrerPrincipal, mWithCredentials, attrs, true);
1268 if (!entry) {
1269 return;
1270 }
1271
1272 // The "Access-Control-Allow-Methods" header contains a comma separated
1273 // list of method names.
1274 Unused << http->GetResponseHeader("Access-Control-Allow-Methods"_ns,
1275 headerVal);
1276
1277 for (const nsACString& method :
1278 nsCCharSeparatedTokenizer(headerVal, ',').ToRange()) {
1279 if (method.IsEmpty()) {
1280 continue;
1281 }
1282 uint32_t i;
1283 for (i = 0; i < entry->mMethods.Length(); ++i) {
1284 if (entry->mMethods[i].token.Equals(method)) {
1285 entry->mMethods[i].expirationTime = expirationTime;
1286 break;
1287 }
1288 }
1289 if (i == entry->mMethods.Length()) {
1290 nsPreflightCache::TokenTime* newMethod = entry->mMethods.AppendElement();
1291 if (!newMethod) {
1292 return;
1293 }
1294
1295 newMethod->token = method;
1296 newMethod->expirationTime = expirationTime;
1297 }
1298 }
1299
1300 // The "Access-Control-Allow-Headers" header contains a comma separated
1301 // list of method names.
1302 Unused << http->GetResponseHeader("Access-Control-Allow-Headers"_ns,
1303 headerVal);
1304
1305 for (const nsACString& header :
1306 nsCCharSeparatedTokenizer(headerVal, ',').ToRange()) {
1307 if (header.IsEmpty()) {
1308 continue;
1309 }
1310 uint32_t i;
1311 for (i = 0; i < entry->mHeaders.Length(); ++i) {
1312 if (entry->mHeaders[i].token.Equals(header)) {
1313 entry->mHeaders[i].expirationTime = expirationTime;
1314 break;
1315 }
1316 }
1317 if (i == entry->mHeaders.Length()) {
1318 nsPreflightCache::TokenTime* newHeader = entry->mHeaders.AppendElement();
1319 if (!newHeader) {
1320 return;
1321 }
1322
1323 newHeader->token = header;
1324 newHeader->expirationTime = expirationTime;
1325 }
1326 }
1327}
1328
1329NS_IMETHODIMPnsresult
1330nsCORSPreflightListener::OnStartRequest(nsIRequest* aRequest) {
1331#ifdef DEBUG1
1332 {
1333 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
1334 nsCOMPtr<nsILoadInfo> loadInfo = channel ? channel->LoadInfo() : nullptr;
1335 MOZ_ASSERT(!loadInfo || !loadInfo->GetServiceWorkerTaintingSynthesized())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!loadInfo || !loadInfo->GetServiceWorkerTaintingSynthesized
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!loadInfo || !loadInfo->GetServiceWorkerTaintingSynthesized
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!loadInfo || !loadInfo->GetServiceWorkerTaintingSynthesized()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1335); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!loadInfo || !loadInfo->GetServiceWorkerTaintingSynthesized()"
")"); do { *((volatile int*)__null) = 1335; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1336 }
1337#endif
1338
1339 nsresult rv = CheckPreflightRequestApproved(aRequest);
1340
1341 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1342 // Everything worked, try to cache and then fire off the actual request.
1343 AddResultToCache(aRequest);
1344
1345 mCallback->OnPreflightSucceeded();
1346 } else {
1347 mCallback->OnPreflightFailed(rv);
1348 }
1349
1350 return rv;
1351}
1352
1353NS_IMETHODIMPnsresult
1354nsCORSPreflightListener::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) {
1355 mCallback = nullptr;
1356 return NS_OK;
1357}
1358
1359/** nsIStreamListener methods **/
1360
1361NS_IMETHODIMPnsresult
1362nsCORSPreflightListener::OnDataAvailable(nsIRequest* aRequest,
1363 nsIInputStream* inStr,
1364 uint64_t sourceOffset,
1365 uint32_t count) {
1366 uint32_t totalRead;
1367 return inStr->ReadSegments(NS_DiscardSegment, nullptr, count, &totalRead);
1368}
1369
1370NS_IMETHODIMPnsresult
1371nsCORSPreflightListener::AsyncOnChannelRedirect(
1372 nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags,
1373 nsIAsyncVerifyRedirectCallback* callback) {
1374 // Only internal redirects allowed for now.
1375 if (!NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags) &&
1376 !NS_IsHSTSUpgradeRedirect(aOldChannel, aNewChannel, aFlags)) {
1377 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel);
1378 LogBlockedRequest(
1379 aOldChannel, "CORSExternalRedirectNotAllowed", nullptr,
1380 nsILoadInfo::BLOCKING_REASON_CORSEXTERNALREDIRECTNOTALLOWED,
1381 httpChannel);
1382 return NS_ERROR_DOM_BAD_URI;
1383 }
1384
1385 callback->OnRedirectVerifyCallback(NS_OK);
1386 return NS_OK;
1387}
1388
1389nsresult nsCORSPreflightListener::CheckPreflightRequestApproved(
1390 nsIRequest* aRequest) {
1391 nsresult status;
1392 nsresult rv = aRequest->GetStatus(&status);
1393 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1393); return rv; } } while (false)
;
1394 NS_ENSURE_SUCCESS(status, status)do { nsresult __rv = status; 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", "status", "status", static_cast<
uint32_t>(__rv), name ? " (" : "", name ? name : "", name ?
")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1394); return status; } } while (false)
;
1395
1396 // Test that things worked on a HTTP level
1397 nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
1398 nsCOMPtr<nsIHttpChannelInternal> internal = do_QueryInterface(aRequest);
1399 NS_ENSURE_STATE(internal)do { if ((__builtin_expect(!!(!(internal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "internal" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1399); return NS_ERROR_UNEXPECTED; } } while (false)
;
1400 nsCOMPtr<nsIHttpChannel> parentHttpChannel = do_QueryInterface(mCallback);
1401
1402 bool succeedded;
1403 rv = http->GetRequestSucceeded(&succeedded);
1404 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !succeedded) {
1405 auto statusCode = GetStatusCodeAsString(http);
1406 LogBlockedRequest(aRequest, "CORSPreflightDidNotSucceed3", statusCode.get(),
1407 nsILoadInfo::BLOCKING_REASON_CORSPREFLIGHTDIDNOTSUCCEED,
1408 parentHttpChannel);
1409 return NS_ERROR_DOM_BAD_URI;
1410 }
1411
1412 nsAutoCString headerVal;
1413 // The "Access-Control-Allow-Methods" header contains a comma separated
1414 // list of method names.
1415 Unused << http->GetResponseHeader("Access-Control-Allow-Methods"_ns,
1416 headerVal);
1417 bool foundMethod = mPreflightMethod.EqualsLiteral("GET") ||
1418 mPreflightMethod.EqualsLiteral("HEAD") ||
1419 mPreflightMethod.EqualsLiteral("POST");
1420 for (const nsACString& method :
1421 nsCCharSeparatedTokenizer(headerVal, ',').ToRange()) {
1422 if (method.IsEmpty()) {
1423 continue;
1424 }
1425 if (!NS_IsValidHTTPToken(method)) {
1426 LogBlockedRequest(aRequest, "CORSInvalidAllowMethod",
1427 NS_ConvertUTF8toUTF16(method).get(),
1428 nsILoadInfo::BLOCKING_REASON_CORSINVALIDALLOWMETHOD,
1429 parentHttpChannel);
1430 return NS_ERROR_DOM_BAD_URI;
1431 }
1432
1433 if (method.EqualsLiteral("*") && !mWithCredentials) {
1434 foundMethod = true;
1435 } else {
1436 foundMethod |= mPreflightMethod.Equals(method);
1437 }
1438 }
1439 if (!foundMethod) {
1440 LogBlockedRequest(aRequest, "CORSMethodNotFound", nullptr,
1441 nsILoadInfo::BLOCKING_REASON_CORSMETHODNOTFOUND,
1442 parentHttpChannel);
1443 return NS_ERROR_DOM_BAD_URI;
1444 }
1445
1446 // The "Access-Control-Allow-Headers" header contains a comma separated
1447 // list of header names.
1448 Unused << http->GetResponseHeader("Access-Control-Allow-Headers"_ns,
1449 headerVal);
1450 nsTArray<nsCString> headers;
1451 bool wildcard = false;
1452 bool hasAuthorizationHeader = false;
1453 for (const nsACString& header :
1454 nsCCharSeparatedTokenizer(headerVal, ',').ToRange()) {
1455 if (header.IsEmpty()) {
1456 continue;
1457 }
1458 if (!NS_IsValidHTTPToken(header)) {
1459 LogBlockedRequest(aRequest, "CORSInvalidAllowHeader",
1460 NS_ConvertUTF8toUTF16(header).get(),
1461 nsILoadInfo::BLOCKING_REASON_CORSINVALIDALLOWHEADER,
1462 parentHttpChannel);
1463 return NS_ERROR_DOM_BAD_URI;
1464 }
1465 if (header.EqualsLiteral("*") && !mWithCredentials) {
1466 wildcard = true;
1467 } else {
1468 headers.AppendElement(header);
1469 }
1470
1471 if (header.LowerCaseEqualsASCII("authorization")) {
1472 hasAuthorizationHeader = true;
1473 }
1474 }
1475
1476 bool authorizationInPreflightHeaders = false;
1477 bool authorizationCoveredByWildcard = false;
1478 for (uint32_t i = 0; i < mPreflightHeaders.Length(); ++i) {
1479 // Cache the result of the authorization header.
1480 bool isAuthorization =
1481 mPreflightHeaders[i].LowerCaseEqualsASCII("authorization");
1482 if (wildcard) {
1483 if (!isAuthorization) {
1484 continue;
1485 } else {
1486 authorizationInPreflightHeaders = true;
1487 if (StaticPrefs::
1488 network_cors_preflight_authorization_covered_by_wildcard() &&
1489 !hasAuthorizationHeader) {
1490 // When `Access-Control-Allow-Headers` is `*` and there is no
1491 // `Authorization` header listed, we send a deprecation warning to the
1492 // console.
1493 LogBlockedRequest(aRequest, "CORSAllowHeaderFromPreflightDeprecation",
1494 nullptr, 0, parentHttpChannel, true);
1495 glean::network::cors_authorization_header
1496 .Get("covered_by_wildcard"_ns)
1497 .Add(1);
1498 authorizationCoveredByWildcard = true;
1499 continue;
1500 }
1501 }
1502 }
1503
1504 const auto& comparator = nsCaseInsensitiveCStringArrayComparator();
1505 if (!headers.Contains(mPreflightHeaders[i], comparator)) {
1506 LogBlockedRequest(
1507 aRequest, "CORSMissingAllowHeaderFromPreflight2",
1508 NS_ConvertUTF8toUTF16(mPreflightHeaders[i]).get(),
1509 nsILoadInfo::BLOCKING_REASON_CORSMISSINGALLOWHEADERFROMPREFLIGHT,
1510 parentHttpChannel);
1511 if (isAuthorization) {
1512 glean::network::cors_authorization_header.Get("disallowed"_ns).Add(1);
1513 }
1514 return NS_ERROR_DOM_BAD_URI;
1515 }
1516 }
1517
1518 if (authorizationInPreflightHeaders && !authorizationCoveredByWildcard) {
1519 glean::network::cors_authorization_header.Get("allowed"_ns).Add(1);
1520 }
1521
1522 return NS_OK;
1523}
1524
1525NS_IMETHODIMPnsresult
1526nsCORSPreflightListener::GetInterface(const nsIID& aIID, void** aResult) {
1527 if (aIID.Equals(NS_GET_IID(nsILoadContext)(nsILoadContext::COMTypeInfo<nsILoadContext, void>::kIID
)
) && mLoadContext) {
1528 nsCOMPtr<nsILoadContext> copy = mLoadContext;
1529 copy.forget(aResult);
1530 return NS_OK;
1531 }
1532
1533 return QueryInterface(aIID, aResult);
1534}
1535
1536void nsCORSListenerProxy::RemoveFromCorsPreflightCache(
1537 nsIURI* aURI, nsIPrincipal* aRequestingPrincipal,
1538 const OriginAttributes& aOriginAttributes) {
1539 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { *((volatile int*)__null) = 1539; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1540 if (sPreflightCache) {
1541 sPreflightCache->RemoveEntries(aURI, aRequestingPrincipal,
1542 aOriginAttributes);
1543 }
1544}
1545
1546// static
1547nsresult nsCORSListenerProxy::StartCORSPreflight(
1548 nsIChannel* aRequestChannel, nsICorsPreflightCallback* aCallback,
1549 nsTArray<nsCString>& aUnsafeHeaders, nsIChannel** aPreflightChannel) {
1550 *aPreflightChannel = nullptr;
1551
1552 if (StaticPrefs::content_cors_disable()) {
1553 nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequestChannel);
1554 LogBlockedRequest(aRequestChannel, "CORSDisabled", nullptr,
1555 nsILoadInfo::BLOCKING_REASON_CORSDISABLED, http);
1556 return NS_ERROR_DOM_BAD_URI;
1557 }
1558
1559 nsAutoCString method;
1560 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequestChannel));
1561 NS_ENSURE_TRUE(httpChannel, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(httpChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "httpChannel" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1561); return NS_ERROR_UNEXPECTED; } } while (false)
;
1562 Unused << httpChannel->GetRequestMethod(method);
1563
1564 nsCOMPtr<nsIURI> uri;
1565 nsresult rv = NS_GetFinalChannelURI(aRequestChannel, getter_AddRefs(uri));
1566 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1566); return rv; } } while (false)
;
1567
1568 nsCOMPtr<nsILoadInfo> originalLoadInfo = aRequestChannel->LoadInfo();
1569 MOZ_ASSERT(originalLoadInfo->GetSecurityMode() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(originalLoadInfo->GetSecurityMode() == nsILoadInfo
::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(originalLoadInfo->GetSecurityMode
() == nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("originalLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT"
" (" "how did we end up here?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1571); AnnotateMozCrashReason("MOZ_ASSERT" "(" "originalLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT"
") (" "how did we end up here?" ")"); do { *((volatile int*)
__null) = 1571; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1570 nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(originalLoadInfo->GetSecurityMode() == nsILoadInfo
::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(originalLoadInfo->GetSecurityMode
() == nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("originalLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT"
" (" "how did we end up here?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1571); AnnotateMozCrashReason("MOZ_ASSERT" "(" "originalLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT"
") (" "how did we end up here?" ")"); do { *((volatile int*)
__null) = 1571; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1571 "how did we end up here?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(originalLoadInfo->GetSecurityMode() == nsILoadInfo
::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(originalLoadInfo->GetSecurityMode
() == nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("originalLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT"
" (" "how did we end up here?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1571); AnnotateMozCrashReason("MOZ_ASSERT" "(" "originalLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT"
") (" "how did we end up here?" ")"); do { *((volatile int*)
__null) = 1571; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1572
1573 nsCOMPtr<nsIPrincipal> principal = originalLoadInfo->GetLoadingPrincipal();
1574 MOZ_ASSERT(principal && originalLoadInfo->GetExternalContentPolicyType() !=do { static_assert( mozilla::detail::AssertionConditionType<
decltype(principal && originalLoadInfo->GetExternalContentPolicyType
() != ExtContentPolicy::TYPE_DOCUMENT)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(principal && originalLoadInfo
->GetExternalContentPolicyType() != ExtContentPolicy::TYPE_DOCUMENT
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"principal && originalLoadInfo->GetExternalContentPolicyType() != ExtContentPolicy::TYPE_DOCUMENT"
" (" "Should not do CORS loads for top-level loads, so a " "loadingPrincipal should always exist."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "principal && originalLoadInfo->GetExternalContentPolicyType() != ExtContentPolicy::TYPE_DOCUMENT"
") (" "Should not do CORS loads for top-level loads, so a " "loadingPrincipal should always exist."
")"); do { *((volatile int*)__null) = 1577; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1575 ExtContentPolicy::TYPE_DOCUMENT,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(principal && originalLoadInfo->GetExternalContentPolicyType
() != ExtContentPolicy::TYPE_DOCUMENT)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(principal && originalLoadInfo
->GetExternalContentPolicyType() != ExtContentPolicy::TYPE_DOCUMENT
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"principal && originalLoadInfo->GetExternalContentPolicyType() != ExtContentPolicy::TYPE_DOCUMENT"
" (" "Should not do CORS loads for top-level loads, so a " "loadingPrincipal should always exist."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "principal && originalLoadInfo->GetExternalContentPolicyType() != ExtContentPolicy::TYPE_DOCUMENT"
") (" "Should not do CORS loads for top-level loads, so a " "loadingPrincipal should always exist."
")"); do { *((volatile int*)__null) = 1577; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1576 "Should not do CORS loads for top-level loads, so a "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(principal && originalLoadInfo->GetExternalContentPolicyType
() != ExtContentPolicy::TYPE_DOCUMENT)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(principal && originalLoadInfo
->GetExternalContentPolicyType() != ExtContentPolicy::TYPE_DOCUMENT
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"principal && originalLoadInfo->GetExternalContentPolicyType() != ExtContentPolicy::TYPE_DOCUMENT"
" (" "Should not do CORS loads for top-level loads, so a " "loadingPrincipal should always exist."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "principal && originalLoadInfo->GetExternalContentPolicyType() != ExtContentPolicy::TYPE_DOCUMENT"
") (" "Should not do CORS loads for top-level loads, so a " "loadingPrincipal should always exist."
")"); do { *((volatile int*)__null) = 1577; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1577 "loadingPrincipal should always exist.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(principal && originalLoadInfo->GetExternalContentPolicyType
() != ExtContentPolicy::TYPE_DOCUMENT)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(principal && originalLoadInfo
->GetExternalContentPolicyType() != ExtContentPolicy::TYPE_DOCUMENT
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"principal && originalLoadInfo->GetExternalContentPolicyType() != ExtContentPolicy::TYPE_DOCUMENT"
" (" "Should not do CORS loads for top-level loads, so a " "loadingPrincipal should always exist."
")", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "principal && originalLoadInfo->GetExternalContentPolicyType() != ExtContentPolicy::TYPE_DOCUMENT"
") (" "Should not do CORS loads for top-level loads, so a " "loadingPrincipal should always exist."
")"); do { *((volatile int*)__null) = 1577; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1578 bool withCredentials =
1579 originalLoadInfo->GetCookiePolicy() == nsILoadInfo::SEC_COOKIES_INCLUDE;
1580
1581 nsPreflightCache::CacheEntry* entry = nullptr;
1582
1583 nsLoadFlags loadFlags;
1584 rv = aRequestChannel->GetLoadFlags(&loadFlags);
1585 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1585); return rv; } } while (false)
;
1586
1587 // Disable preflight cache if devtools says so or on other force reloads
1588 bool disableCache = (loadFlags & nsIRequest::LOAD_BYPASS_CACHE);
1589
1590 if (sPreflightCache && !disableCache) {
1591 OriginAttributes attrs;
1592 StoragePrincipalHelper::GetOriginAttributesForNetworkState(aRequestChannel,
1593 attrs);
1594 entry = sPreflightCache->GetEntry(uri, principal, withCredentials, attrs,
1595 false);
1596 }
1597
1598 if (entry && entry->CheckRequest(method, aUnsafeHeaders)) {
1599 aCallback->OnPreflightSucceeded();
1600 return NS_OK;
1601 }
1602
1603 // Either it wasn't cached or the cached result has expired. Build a
1604 // channel for the OPTIONS request.
1605
1606 nsCOMPtr<nsILoadInfo> loadInfo =
1607 static_cast<mozilla::net::LoadInfo*>(originalLoadInfo.get())
1608 ->CloneForNewRequest();
1609 static_cast<mozilla::net::LoadInfo*>(loadInfo.get())->SetIsPreflight();
1610
1611 nsCOMPtr<nsILoadGroup> loadGroup;
1612 rv = aRequestChannel->GetLoadGroup(getter_AddRefs(loadGroup));
1613 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1613); return rv; } } while (false)
;
1614
1615 // We want to give the preflight channel's notification callbacks the same
1616 // load context as the original channel's notification callbacks had. We
1617 // don't worry about a load context provided via the loadgroup here, since
1618 // they have the same loadgroup.
1619 nsCOMPtr<nsIInterfaceRequestor> callbacks;
1620 rv = aRequestChannel->GetNotificationCallbacks(getter_AddRefs(callbacks));
1621 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1621); return rv; } } while (false)
;
1622 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
1623
1624 // Preflight requests should never be intercepted by service workers and
1625 // are always anonymous.
1626 // NOTE: We ignore CORS checks on synthesized responses (see the CORS
1627 // preflights, then we need to extend the GetResponseSynthesized() check in
1628 // nsCORSListenerProxy::CheckRequestApproved()). If we change our behavior
1629 // here and allow service workers to intercept CORS preflights, then that
1630 // check won't be safe any more.
1631 loadFlags |=
1632 nsIChannel::LOAD_BYPASS_SERVICE_WORKER | nsIRequest::LOAD_ANONYMOUS;
1633
1634 if (StaticPrefs::network_cors_preflight_allow_client_cert()) {
1635 loadFlags |= nsIRequest::LOAD_ANONYMOUS_ALLOW_CLIENT_CERT;
1636 }
1637
1638 nsCOMPtr<nsIChannel> preflightChannel;
1639 rv = NS_NewChannelInternal(getter_AddRefs(preflightChannel), uri, loadInfo,
1640 nullptr, // PerformanceStorage
1641 loadGroup,
1642 nullptr, // aCallbacks
1643 loadFlags);
1644 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1644); return rv; } } while (false)
;
1645
1646 // Set method and headers
1647 nsCOMPtr<nsIHttpChannel> preHttp = do_QueryInterface(preflightChannel);
1648 NS_ASSERTION(preHttp, "Failed to QI to nsIHttpChannel!")do { if (!(preHttp)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to QI to nsIHttpChannel!"
, "preHttp", "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1648); MOZ_PretendNoReturn(); } } while (0)
;
1649
1650 rv = preHttp->SetRequestMethod("OPTIONS"_ns);
1651 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1651); return rv; } } while (false)
;
1652
1653 rv = preHttp->SetRequestHeader("Access-Control-Request-Method"_ns, method,
1654 false);
1655 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1655); return rv; } } while (false)
;
1656
1657 // Set the CORS preflight channel's warning reporter to be the same as the
1658 // requesting channel so that all log messages are able to be reported through
1659 // the warning reporter.
1660 RefPtr<nsHttpChannel> reqCh = do_QueryObject(aRequestChannel);
1661 RefPtr<nsHttpChannel> preCh = do_QueryObject(preHttp);
1662 if (preCh && reqCh) { // there are other implementers of nsIHttpChannel
1663 preCh->SetWarningReporter(reqCh->GetWarningReporter());
1664 }
1665
1666 nsTArray<nsCString> preflightHeaders;
1667 if (!aUnsafeHeaders.IsEmpty()) {
1668 for (uint32_t i = 0; i < aUnsafeHeaders.Length(); ++i) {
1669 preflightHeaders.AppendElement();
1670 ToLowerCase(aUnsafeHeaders[i], preflightHeaders[i]);
1671 }
1672 preflightHeaders.Sort();
1673 nsAutoCString headers;
1674 for (uint32_t i = 0; i < preflightHeaders.Length(); ++i) {
1675 if (i != 0) {
1676 headers += ',';
1677 }
1678 headers += preflightHeaders[i];
1679 }
1680 rv = preHttp->SetRequestHeader("Access-Control-Request-Headers"_ns, headers,
1681 false);
1682 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1682); return rv; } } while (false)
;
1683 }
1684
1685 // Set up listener which will start the original channel
1686 RefPtr<nsCORSPreflightListener> preflightListener =
1687 new nsCORSPreflightListener(principal, aCallback, loadContext,
1688 withCredentials, method, preflightHeaders);
1689
1690 rv = preflightChannel->SetNotificationCallbacks(preflightListener);
1691 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1691); return rv; } } while (false)
;
1692
1693 if (preCh && reqCh) {
1694 // Per https://fetch.spec.whatwg.org/#cors-preflight-fetch step 1, the
1695 // request's referrer and referrer policy should match the original request.
1696 nsCOMPtr<nsIReferrerInfo> referrerInfo;
1697 rv = reqCh->GetReferrerInfo(getter_AddRefs(referrerInfo));
1698 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1698); return rv; } } while (false)
;
1699 if (referrerInfo) {
1700 nsCOMPtr<nsIReferrerInfo> newReferrerInfo =
1701 static_cast<dom::ReferrerInfo*>(referrerInfo.get())->Clone();
1702 rv = preCh->SetReferrerInfo(newReferrerInfo);
1703 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1703); return rv; } } while (false)
;
1704 }
1705 }
1706
1707 // Start preflight
1708 rv = preflightChannel->AsyncOpen(preflightListener);
1709 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/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1709); return rv; } } while (false)
;
1710
1711 // Return newly created preflight channel
1712 preflightChannel.forget(aPreflightChannel);
1713
1714 return NS_OK;
1715}
1716
1717// static
1718void nsCORSListenerProxy::LogBlockedCORSRequest(
1719 uint64_t aInnerWindowID, bool aPrivateBrowsing, bool aFromChromeContext,
1720 const nsAString& aMessage, const nsACString& aCategory, bool aIsWarning) {
1721 nsresult rv = NS_OK;
1722
1723 // Build the error object and log it to the console
1724 nsCOMPtr<nsIConsoleService> console(
1725 mozilla::components::Console::Service(&rv));
1726 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1727 NS_WARNING("Failed to log blocked cross-site request (no console)")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to log blocked cross-site request (no console)"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1727)
;
1728 return;
1729 }
1730
1731 nsCOMPtr<nsIScriptError> scriptError =
1732 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1", &rv);
1733 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1734 NS_WARNING("Failed to log blocked cross-site request (no scriptError)")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to log blocked cross-site request (no scriptError)"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1734)
;
1735 return;
1736 }
1737
1738 uint32_t errorFlag =
1739 aIsWarning ? nsIScriptError::warningFlag : nsIScriptError::errorFlag;
1740
1741 // query innerWindowID and log to web console, otherwise log to
1742 // the error to the browser console.
1743 if (aInnerWindowID > 0) {
1744 rv = scriptError->InitWithSanitizedSource(aMessage,
1745 u""_ns, // sourceName
1746 u""_ns, // sourceLine
1747 0, // lineNumber
1748 0, // columnNumber
1749 errorFlag, aCategory,
1750 aInnerWindowID);
1751 } else {
1752 rv = scriptError->Init(aMessage,
1753 u""_ns, // sourceName
1754 u""_ns, // sourceLine
1755 0, // lineNumber
1756 0, // columnNumber
1757 errorFlag, aCategory, aPrivateBrowsing,
1758 aFromChromeContext); // From chrome context
1759 }
1760 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1761 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Failed to log blocked cross-site request (scriptError init failed)"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1762)
1762 "Failed to log blocked cross-site request (scriptError init failed)")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to log blocked cross-site request (scriptError init failed)"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp"
, 1762)
;
1763 return;
1764 }
1765 console->LogMessage(scriptError);
1766}