Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/http/nsCORSListenerProxy.cpp
Warning:line 662, 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_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -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/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../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-05-16-034744-15991-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/LinkedList.h"
11#include "mozilla/StaticPrefs_content.h"
12#include "mozilla/StoragePrincipalHelper.h"
13
14#include "nsCORSListenerProxy.h"
15#include "nsIChannel.h"
16#include "nsIHttpChannel.h"
17#include "HttpChannelChild.h"
18#include "nsIHttpChannelInternal.h"
19#include "nsError.h"
20#include "nsContentUtils.h"
21#include "nsNetUtil.h"
22#include "nsComponentManagerUtils.h"
23#include "nsIInterfaceRequestorUtils.h"
24#include "nsServiceManagerUtils.h"
25#include "nsMimeTypes.h"
26#include "nsStringStream.h"
27#include "nsGkAtoms.h"
28#include "nsWhitespaceTokenizer.h"
29#include "nsIChannelEventSink.h"
30#include "nsIAsyncVerifyRedirectCallback.h"
31#include "nsCharSeparatedTokenizer.h"
32#include "nsAsyncRedirectVerifyHelper.h"
33#include "nsClassHashtable.h"
34#include "nsHashKeys.h"
35#include "nsStreamUtils.h"
36#include "mozilla/Preferences.h"
37#include "nsIScriptError.h"
38#include "nsILoadGroup.h"
39#include "nsILoadContext.h"
40#include "nsIConsoleService.h"
41#include "nsINetworkInterceptController.h"
42#include "nsICorsPreflightCallback.h"
43#include "nsISupportsImpl.h"
44#include "nsHttpChannel.h"
45#include "mozilla/BasePrincipal.h"
46#include "mozilla/ExpandedPrincipal.h"
47#include "mozilla/LoadInfo.h"
48#include "mozilla/NullPrincipal.h"
49#include "nsIHttpHeaderVisitor.h"
50#include "nsQueryObject.h"
51#include "mozilla/StaticPrefs_network.h"
52#include "mozilla/StaticPrefs_dom.h"
53#include "mozilla/dom/nsHTTPSOnlyUtils.h"
54#include "mozilla/dom/ReferrerInfo.h"
55#include "mozilla/dom/RequestBinding.h"
56#include "mozilla/glean/GleanMetrics.h"
57#include <algorithm>
58
59using namespace mozilla;
60using namespace mozilla::net;
61
62#define PREFLIGHT_CACHE_SIZE100 100
63// 5 seconds is chosen to be compatible with Chromium.
64#define PREFLIGHT_DEFAULT_EXPIRY_SECONDS5 5
65
66static inline nsAutoString GetStatusCodeAsString(nsIHttpChannel* aHttp) {
67 nsAutoString result;
68 uint32_t code;
69 if (NS_SUCCEEDED(aHttp->GetResponseStatus(&code))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aHttp->GetResponseStatus
(&code))), 1)))
) {
70 result.AppendInt(code);
71 }
72 return result;
73}
74
75static void LogBlockedRequest(nsIRequest* aRequest, const char* aProperty,
76 const char16_t* aParam, uint32_t aBlockingReason,
77 nsIHttpChannel* aCreatingChannel,
78 bool aIsWarning = false) {
79 nsresult rv = NS_OK;
80
81 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
82
83 if (!aIsWarning) {
84 NS_SetRequestBlockingReason(channel, aBlockingReason);
85 }
86
87 nsCOMPtr<nsIURI> aUri;
88 channel->GetURI(getter_AddRefs(aUri));
89 nsAutoCString spec;
90 if (aUri) {
91 spec = aUri->GetSpecOrDefault();
92 }
93
94 // Generate the error message
95 nsAutoString blockedMessage;
96 AutoTArray<nsString, 2> params;
97 CopyUTF8toUTF16(spec, *params.AppendElement());
98 if (aParam) {
99 params.AppendElement(aParam);
100 }
101 NS_ConvertUTF8toUTF16 specUTF16(spec);
102 rv = nsContentUtils::FormatLocalizedString(
103 nsContentUtils::eSECURITY_PROPERTIES, aProperty, params, blockedMessage);
104
105 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
106 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"
, 106)
;
107 return;
108 }
109
110 nsAutoString msg(blockedMessage.get());
111 nsDependentCString category(aProperty);
112
113 if (XRE_IsParentProcess()) {
114 if (aCreatingChannel) {
115 rv = aCreatingChannel->LogBlockedCORSRequest(msg, category, aIsWarning);
116 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
117 return;
118 }
119 }
120 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"
, 122)
121 "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"
, 122)
122 "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"
, 122)
;
123 }
124
125 bool privateBrowsing = false;
126 if (aRequest) {
127 nsCOMPtr<nsILoadGroup> loadGroup;
128 rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup));
129 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"
, 129); return; } } while (false)
;
130 privateBrowsing = nsContentUtils::IsInPrivateBrowsing(loadGroup);
131 }
132
133 bool fromChromeContext = false;
134 if (channel) {
135 nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
136 fromChromeContext = loadInfo->TriggeringPrincipal()->IsSystemPrincipal();
137 }
138
139 // we are passing aProperty as the category so we can link to the
140 // appropriate MDN docs depending on the specific error.
141 uint64_t innerWindowID = nsContentUtils::GetInnerWindowID(aRequest);
142 // The |innerWindowID| could be 0 if this request is created from script.
143 // We can always try top level content window id in this case,
144 // since the window id can lead to current top level window's web console.
145 if (!innerWindowID) {
146 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
147 if (httpChannel) {
148 Unused << httpChannel->GetTopLevelContentWindowId(&innerWindowID);
149 }
150 }
151 nsCORSListenerProxy::LogBlockedCORSRequest(innerWindowID, privateBrowsing,
152 fromChromeContext, msg, category,
153 aIsWarning);
154}
155
156//////////////////////////////////////////////////////////////////////////
157// Preflight cache
158
159class nsPreflightCache {
160 public:
161 struct TokenTime {
162 nsCString token;
163 TimeStamp expirationTime;
164 };
165
166 struct CacheEntry : public LinkedListElement<CacheEntry> {
167 explicit CacheEntry(nsCString& aKey, bool aPrivateBrowsing)
168 : mKey(aKey), mPrivateBrowsing(aPrivateBrowsing) {
169 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)
;
170 }
171
172 ~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)
; }
173
174 void PurgeExpired(TimeStamp now);
175 bool CheckRequest(const nsCString& aMethod,
176 const nsTArray<nsCString>& aHeaders);
177
178 nsCString mKey;
179 bool mPrivateBrowsing{false};
180 nsTArray<TokenTime> mMethods;
181 nsTArray<TokenTime> mHeaders;
182 };
183
184 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); }
185
186 ~nsPreflightCache() {
187 Clear();
188 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)
;
189 }
190
191 bool Initialize() { return true; }
192
193 CacheEntry* GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal,
194 bool aWithCredentials,
195 const OriginAttributes& aOriginAttributes, bool aCreate);
196 void RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal,
197 const OriginAttributes& aOriginAttributes);
198 void PurgePrivateBrowsingEntries();
199
200 void Clear();
201
202 private:
203 nsClassHashtable<nsCStringHashKey, CacheEntry> mTable;
204 LinkedList<CacheEntry> mList;
205};
206
207// Will be initialized in EnsurePreflightCache.
208static nsPreflightCache* sPreflightCache = nullptr;
209
210static bool EnsurePreflightCache() {
211 if (sPreflightCache) return true;
212
213 UniquePtr<nsPreflightCache> newCache(new nsPreflightCache());
214
215 if (newCache->Initialize()) {
216 sPreflightCache = newCache.release();
217 return true;
218 }
219
220 return false;
221}
222
223void nsPreflightCache::PurgePrivateBrowsingEntries() {
224 for (auto iter = mTable.Iter(); !iter.Done(); iter.Next()) {
225 auto* entry = iter.UserData();
226 if (entry->mPrivateBrowsing) {
227 // last private browsing window closed, remove preflight cache entries
228 entry->removeFrom(sPreflightCache->mList);
229 iter.Remove();
230 }
231 }
232}
233
234void nsPreflightCache::CacheEntry::PurgeExpired(TimeStamp now) {
235 for (uint32_t i = 0, len = mMethods.Length(); i < len; ++i) {
236 if (now >= mMethods[i].expirationTime) {
237 mMethods.UnorderedRemoveElementAt(i);
238 --i; // Examine the element again, if necessary.
239 --len;
240 }
241 }
242 for (uint32_t i = 0, len = mHeaders.Length(); i < len; ++i) {
243 if (now >= mHeaders[i].expirationTime) {
244 mHeaders.UnorderedRemoveElementAt(i);
245 --i; // Examine the element again, if necessary.
246 --len;
247 }
248 }
249}
250
251bool nsPreflightCache::CacheEntry::CheckRequest(
252 const nsCString& aMethod, const nsTArray<nsCString>& aHeaders) {
253 PurgeExpired(TimeStamp::NowLoRes());
254
255 if (!aMethod.EqualsLiteral("GET") && !aMethod.EqualsLiteral("POST")) {
256 struct CheckToken {
257 bool Equals(const TokenTime& e, const nsCString& method) const {
258 return e.token.Equals(method);
259 }
260 };
261
262 if (!mMethods.Contains(aMethod, CheckToken())) {
263 return false;
264 }
265 }
266
267 struct CheckHeaderToken {
268 bool Equals(const TokenTime& e, const nsCString& header) const {
269 return e.token.Equals(header, nsCaseInsensitiveCStringComparator);
270 }
271 } checker;
272 for (uint32_t i = 0; i < aHeaders.Length(); ++i) {
273 if (!mHeaders.Contains(aHeaders[i], checker)) {
274 return false;
275 }
276 }
277
278 return true;
279}
280
281nsPreflightCache::CacheEntry* nsPreflightCache::GetEntry(
282 nsIURI* aURI, nsIPrincipal* aPrincipal, bool aWithCredentials,
283 const OriginAttributes& aOriginAttributes, bool aCreate) {
284 nsCString key;
285 if (NS_FAILED(aPrincipal->GetPrefLightCacheKey(aURI, aWithCredentials,((bool)(__builtin_expect(!!(NS_FAILED_impl(aPrincipal->GetPrefLightCacheKey
(aURI, aWithCredentials, aOriginAttributes, key))), 0)))
286 aOriginAttributes, key))((bool)(__builtin_expect(!!(NS_FAILED_impl(aPrincipal->GetPrefLightCacheKey
(aURI, aWithCredentials, aOriginAttributes, key))), 0)))
) {
287 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"
, 287)
;
288 return nullptr;
289 }
290
291 CacheEntry* existingEntry = nullptr;
292
293 if (mTable.Get(key, &existingEntry)) {
294 // Entry already existed so just return it. Also update the LRU list.
295
296 // Move to the head of the list.
297 existingEntry->removeFrom(mList);
298 mList.insertFront(existingEntry);
299
300 return existingEntry;
301 }
302
303 if (!aCreate) {
304 return nullptr;
305 }
306
307 // This is a new entry, allocate and insert into the table now so that any
308 // failures don't cause items to be removed from a full cache.
309 auto newEntry =
310 MakeUnique<CacheEntry>(key, aOriginAttributes.mPrivateBrowsingId != 0);
311
312 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"
, 313); MOZ_PretendNoReturn(); } } while (0)
313 "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"
, 313); MOZ_PretendNoReturn(); } } while (0)
;
314
315 // Now enforce the max count.
316 if (mTable.Count() == PREFLIGHT_CACHE_SIZE100) {
317 // Try to kick out all the expired entries.
318 TimeStamp now = TimeStamp::NowLoRes();
319 for (auto iter = mTable.Iter(); !iter.Done(); iter.Next()) {
320 auto* entry = iter.UserData();
321 entry->PurgeExpired(now);
322
323 if (entry->mHeaders.IsEmpty() && entry->mMethods.IsEmpty()) {
324 // Expired, remove from the list as well as the hash table.
325 entry->removeFrom(sPreflightCache->mList);
326 iter.Remove();
327 }
328 }
329
330 // If that didn't remove anything then kick out the least recently used
331 // entry.
332 if (mTable.Count() == PREFLIGHT_CACHE_SIZE100) {
333 CacheEntry* lruEntry = static_cast<CacheEntry*>(mList.popLast());
334 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"
, 334); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lruEntry" ")"
); do { *((volatile int*)__null) = 334; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
335
336 // This will delete 'lruEntry'.
337 mTable.Remove(lruEntry->mKey);
338
339 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"
, 340); MOZ_PretendNoReturn(); } } while (0)
340 "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"
, 340); MOZ_PretendNoReturn(); } } while (0)
;
341 }
342 }
343
344 auto* newEntryWeakRef = mTable.InsertOrUpdate(key, std::move(newEntry)).get();
345 mList.insertFront(newEntryWeakRef);
346
347 return newEntryWeakRef;
348}
349
350void nsPreflightCache::RemoveEntries(
351 nsIURI* aURI, nsIPrincipal* aPrincipal,
352 const OriginAttributes& aOriginAttributes) {
353 CacheEntry* entry;
354 nsCString key;
355 if (NS_SUCCEEDED(aPrincipal->GetPrefLightCacheKey(aURI, true,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->GetPrefLightCacheKey
(aURI, true, aOriginAttributes, key))), 1)))
356 aOriginAttributes, key))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->GetPrefLightCacheKey
(aURI, true, aOriginAttributes, key))), 1)))
&&
357 mTable.Get(key, &entry)) {
358 entry->removeFrom(mList);
359 mTable.Remove(key);
360 }
361
362 if (NS_SUCCEEDED(aPrincipal->GetPrefLightCacheKey(aURI, false,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->GetPrefLightCacheKey
(aURI, false, aOriginAttributes, key))), 1)))
363 aOriginAttributes, key))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->GetPrefLightCacheKey
(aURI, false, aOriginAttributes, key))), 1)))
&&
364 mTable.Get(key, &entry)) {
365 entry->removeFrom(mList);
366 mTable.Remove(key);
367 }
368}
369
370void nsPreflightCache::Clear() {
371 mList.clear();
372 mTable.Clear();
373}
374
375//////////////////////////////////////////////////////////////////////////
376// nsCORSListenerProxy
377
378NS_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"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
380; __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"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSListenerProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 380; __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"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 380
; __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"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSListenerProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 380; __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"
, 380); 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; }
379 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"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
380; __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"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSListenerProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 380; __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"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 380
; __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"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSListenerProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 380; __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"
, 380); 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 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"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
380; __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"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSListenerProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 380; __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"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 380
; __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"
, 380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsCORSListenerProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 380; __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"
, 380); 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
382/* static */
383void nsCORSListenerProxy::Shutdown() {
384 delete sPreflightCache;
385 sPreflightCache = nullptr;
386}
387
388/* static */
389void nsCORSListenerProxy::ClearCache() {
390 if (!sPreflightCache) {
391 return;
392 }
393 sPreflightCache->Clear();
394}
395
396// static
397void nsCORSListenerProxy::ClearPrivateBrowsingCache() {
398 if (!sPreflightCache) {
399 return;
400 }
401 sPreflightCache->PurgePrivateBrowsingEntries();
402}
403
404// Usually, when using an expanded principal, there's no particularly good
405// origin to do the request with. However if the expanded principal only wraps
406// one principal, we can use that one instead.
407//
408// This is needed so that DevTools can still do CORS-enabled requests (since
409// DevTools uses a triggering principal expanding the node principal to bypass
410// CSP checks, see Element::CreateDevToolsPrincipal(), bug 1604562, and bug
411// 1391994).
412static nsIPrincipal* GetOriginHeaderPrincipal(nsIPrincipal* aPrincipal) {
413 while (aPrincipal && aPrincipal->GetIsExpandedPrincipal()) {
414 auto* ep = BasePrincipal::Cast(aPrincipal)->As<ExpandedPrincipal>();
415 if (ep->AllowList().Length() != 1) {
416 break;
417 }
418 aPrincipal = ep->AllowList()[0];
419 }
420 return aPrincipal;
421}
422
423nsCORSListenerProxy::nsCORSListenerProxy(nsIStreamListener* aOuter,
424 nsIPrincipal* aRequestingPrincipal,
425 bool aWithCredentials)
426 : mOuterListener(aOuter),
427 mRequestingPrincipal(aRequestingPrincipal),
428 mOriginHeaderPrincipal(GetOriginHeaderPrincipal(aRequestingPrincipal)),
429 mWithCredentials(aWithCredentials),
430 mRequestApproved(false),
431 mHasBeenCrossSite(false),
432#ifdef DEBUG1
433 mInited(false),
434#endif
435 mMutex("nsCORSListenerProxy") {
436}
437
438nsresult nsCORSListenerProxy::Init(nsIChannel* aChannel,
439 DataURIHandling aAllowDataURI) {
440 aChannel->GetNotificationCallbacks(
441 getter_AddRefs(mOuterNotificationCallbacks));
442 aChannel->SetNotificationCallbacks(this);
443
444 nsresult rv =
445 UpdateChannel(aChannel, aAllowDataURI, UpdateType::Default, false);
446 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
447 {
448 MutexAutoLock lock(mMutex);
449 mOuterListener = nullptr;
450 }
451 mRequestingPrincipal = nullptr;
452 mOriginHeaderPrincipal = nullptr;
453 mOuterNotificationCallbacks = nullptr;
454 mHttpChannel = nullptr;
455 }
456#ifdef DEBUG1
457 mInited = true;
458#endif
459 return rv;
460}
461
462NS_IMETHODIMPnsresult
463nsCORSListenerProxy::OnStartRequest(nsIRequest* aRequest) {
464 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"
, 464); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInited" ") ("
"nsCORSListenerProxy has not been initialized properly" ")")
; do { *((volatile int*)__null) = 464; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
465 nsresult rv = CheckRequestApproved(aRequest);
466 mRequestApproved = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
467 if (!mRequestApproved) {
468 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
469 if (channel) {
470 nsCOMPtr<nsIURI> uri;
471 NS_GetFinalChannelURI(channel, getter_AddRefs(uri));
472 if (uri) {
473 OriginAttributes attrs;
474 StoragePrincipalHelper::GetOriginAttributesForNetworkState(channel,
475 attrs);
476
477 if (sPreflightCache) {
478 // OK to use mRequestingPrincipal since preflights never get
479 // redirected.
480 sPreflightCache->RemoveEntries(uri, mRequestingPrincipal, attrs);
481 } else {
482 nsCOMPtr<nsIHttpChannelChild> httpChannelChild =
483 do_QueryInterface(channel);
484 if (httpChannelChild) {
485 rv = httpChannelChild->RemoveCorsPreflightCacheEntry(
486 uri, mRequestingPrincipal, attrs);
487 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
488 // Only warn here to ensure we fall through the request Cancel()
489 // and outer listener OnStartRequest() calls.
490 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"
, 490)
;
491 }
492 }
493 }
494 }
495 }
496
497 aRequest->Cancel(NS_ERROR_DOM_BAD_URI);
498 nsCOMPtr<nsIStreamListener> listener;
499 {
500 MutexAutoLock lock(mMutex);
501 listener = mOuterListener;
502 }
503 listener->OnStartRequest(aRequest);
504
505 // Reason for NS_ERROR_DOM_BAD_URI already logged in CheckRequestApproved()
506 return NS_ERROR_DOM_BAD_URI;
507 }
508
509 nsCOMPtr<nsIStreamListener> listener;
510 {
511 MutexAutoLock lock(mMutex);
512 listener = mOuterListener;
513 }
514 return listener->OnStartRequest(aRequest);
515}
516
517namespace {
518class CheckOriginHeader final : public nsIHttpHeaderVisitor {
519 public:
520 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:
521
522 CheckOriginHeader() = default;
523
524 NS_IMETHODvirtual nsresult
525 VisitHeader(const nsACString& aHeader, const nsACString& aValue) override {
526 if (aHeader.EqualsLiteral("Access-Control-Allow-Origin")) {
527 mHeaderCount++;
528 }
529
530 if (mHeaderCount > 1) {
531 return NS_ERROR_DOM_BAD_URI;
532 }
533 return NS_OK;
534 }
535
536 private:
537 uint32_t mHeaderCount{0};
538
539 ~CheckOriginHeader() = default;
540};
541
542NS_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"
, 542); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
542; __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"
, 542); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CheckOriginHeader\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 542; __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"
, 542); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 542
; __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"
, 542); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CheckOriginHeader\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 542; __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"
, 542); 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; }
543} // namespace
544
545nsresult nsCORSListenerProxy::CheckRequestApproved(nsIRequest* aRequest) {
546 // Check if this was actually a cross domain request
547 if (!mHasBeenCrossSite) {
548 return NS_OK;
549 }
550 nsCOMPtr<nsIHttpChannel> topChannel;
551 topChannel.swap(mHttpChannel);
552
553 if (StaticPrefs::content_cors_disable()) {
554 LogBlockedRequest(aRequest, "CORSDisabled", nullptr,
555 nsILoadInfo::BLOCKING_REASON_CORSDISABLED, topChannel);
556 return NS_ERROR_DOM_BAD_URI;
557 }
558
559 // Check if the request failed
560 nsresult status;
561 nsresult rv = aRequest->GetStatus(&status);
562 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
563 LogBlockedRequest(aRequest, "CORSDidNotSucceed2", nullptr,
564 nsILoadInfo::BLOCKING_REASON_CORSDIDNOTSUCCEED,
565 topChannel);
566 return rv;
567 }
568
569 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
570 if (NS_BINDING_ABORTED != status) {
571 // Don't want to log mere cancellation as an error.
572 LogBlockedRequest(aRequest, "CORSDidNotSucceed2", nullptr,
573 nsILoadInfo::BLOCKING_REASON_CORSDIDNOTSUCCEED,
574 topChannel);
575 }
576 return status;
577 }
578
579 // Test that things worked on a HTTP level
580 nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
581 if (!http) {
582 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
583 nsCOMPtr<nsIURI> uri;
584 NS_GetFinalChannelURI(channel, getter_AddRefs(uri));
585 if (uri && uri->SchemeIs("moz-extension")) {
586 // moz-extension:-URLs do not support CORS, but can universally be read
587 // if an extension lists the resource in web_accessible_resources.
588 // Access will be checked in UpdateChannel.
589 return NS_OK;
590 }
591 LogBlockedRequest(aRequest, "CORSRequestNotHttp", nullptr,
592 nsILoadInfo::BLOCKING_REASON_CORSREQUESTNOTHTTP,
593 topChannel);
594 return NS_ERROR_DOM_BAD_URI;
595 }
596
597 nsCOMPtr<nsILoadInfo> loadInfo = http->LoadInfo();
598 if (loadInfo->GetServiceWorkerTaintingSynthesized()) {
599 // For synthesized responses, we don't need to perform any checks.
600 // Note: This would be unsafe if we ever changed our behavior to allow
601 // service workers to intercept CORS preflights.
602 return NS_OK;
603 }
604
605 // Check the Access-Control-Allow-Origin header
606 RefPtr<CheckOriginHeader> visitor = new CheckOriginHeader();
607 nsAutoCString allowedOriginHeader;
608
609 // check for duplicate headers
610 rv = http->VisitOriginalResponseHeaders(visitor);
611 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
612 LogBlockedRequest(
613 aRequest, "CORSMultipleAllowOriginNotAllowed", nullptr,
614 nsILoadInfo::BLOCKING_REASON_CORSMULTIPLEALLOWORIGINNOTALLOWED,
615 topChannel);
616 return rv;
617 }
618
619 rv = http->GetResponseHeader("Access-Control-Allow-Origin"_ns,
620 allowedOriginHeader);
621 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
622 auto statusCode = GetStatusCodeAsString(http);
623 LogBlockedRequest(aRequest, "CORSMissingAllowOrigin2", statusCode.get(),
624 nsILoadInfo::BLOCKING_REASON_CORSMISSINGALLOWORIGIN,
625 topChannel);
626 return rv;
627 }
628
629 // Bug 1210985 - Explicitly point out the error that the credential is
630 // not supported if the allowing origin is '*'. Note that this check
631 // has to be done before the condition
632 //
633 // >> if (mWithCredentials || !allowedOriginHeader.EqualsLiteral("*"))
634 //
635 // below since "if (A && B)" is included in "if (A || !B)".
636 //
637 if (mWithCredentials && allowedOriginHeader.EqualsLiteral("*")) {
638 LogBlockedRequest(aRequest, "CORSNotSupportingCredentials", nullptr,
639 nsILoadInfo::BLOCKING_REASON_CORSNOTSUPPORTINGCREDENTIALS,
640 topChannel);
641 return NS_ERROR_DOM_BAD_URI;
642 }
643
644 if (mWithCredentials || !allowedOriginHeader.EqualsLiteral("*")) {
645 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"
, 645); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mOriginHeaderPrincipal->GetIsExpandedPrincipal()"
")"); do { *((volatile int*)__null) = 645; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
646 nsAutoCString origin;
647 mOriginHeaderPrincipal->GetWebExposedOriginSerialization(origin);
648
649 if (!allowedOriginHeader.Equals(origin)) {
650 LogBlockedRequest(
651 aRequest, "CORSAllowOriginNotMatchingOrigin",
652 NS_ConvertUTF8toUTF16(allowedOriginHeader).get(),
653 nsILoadInfo::BLOCKING_REASON_CORSALLOWORIGINNOTMATCHINGORIGIN,
654 topChannel);
655 return NS_ERROR_DOM_BAD_URI;
656 }
657 }
658
659 // Check Access-Control-Allow-Credentials header
660 if (mWithCredentials) {
661 nsAutoCString allowCredentialsHeader;
662 rv = http->GetResponseHeader("Access-Control-Allow-Credentials"_ns,
Value stored to 'rv' is never read
663 allowCredentialsHeader);
664
665 if (!allowCredentialsHeader.EqualsLiteral("true")) {
666 LogBlockedRequest(
667 aRequest, "CORSMissingAllowCredentials", nullptr,
668 nsILoadInfo::BLOCKING_REASON_CORSMISSINGALLOWCREDENTIALS, topChannel);
669 return NS_ERROR_DOM_BAD_URI;
670 }
671 }
672
673 return NS_OK;
674}
675
676NS_IMETHODIMPnsresult
677nsCORSListenerProxy::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
678 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"
, 678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInited" ") ("
"nsCORSListenerProxy has not been initialized properly" ")")
; do { *((volatile int*)__null) = 678; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
679 nsCOMPtr<nsIStreamListener> listener;
680 {
681 MutexAutoLock lock(mMutex);
682 listener = std::move(mOuterListener);
683 }
684 nsresult rv = listener->OnStopRequest(aRequest, aStatusCode);
685 mOuterNotificationCallbacks = nullptr;
686 mHttpChannel = nullptr;
687 return rv;
688}
689
690NS_IMETHODIMPnsresult
691nsCORSListenerProxy::OnDataAvailable(nsIRequest* aRequest,
692 nsIInputStream* aInputStream,
693 uint64_t aOffset, uint32_t aCount) {
694 // NB: This can be called on any thread! But we're guaranteed that it is
695 // called between OnStartRequest and OnStopRequest, so we don't need to worry
696 // about races.
697
698 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"
, 698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInited" ") ("
"nsCORSListenerProxy has not been initialized properly" ")")
; do { *((volatile int*)__null) = 698; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
699 if (!mRequestApproved) {
700 // Reason for NS_ERROR_DOM_BAD_URI already logged in CheckRequestApproved()
701 return NS_ERROR_DOM_BAD_URI;
702 }
703 nsCOMPtr<nsIStreamListener> listener;
704 {
705 MutexAutoLock lock(mMutex);
706 listener = mOuterListener;
707 }
708 return listener->OnDataAvailable(aRequest, aInputStream, aOffset, aCount);
709}
710
711NS_IMETHODIMPnsresult
712nsCORSListenerProxy::OnDataFinished(nsresult aStatus) {
713 nsCOMPtr<nsIStreamListener> listener;
714 {
715 MutexAutoLock lock(mMutex);
716 listener = mOuterListener;
717 }
718 if (!listener) {
719 return NS_ERROR_FAILURE;
720 }
721 nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
722 do_QueryInterface(listener);
723 if (retargetableListener) {
724 return retargetableListener->OnDataFinished(aStatus);
725 }
726
727 return NS_OK;
728}
729
730void nsCORSListenerProxy::SetInterceptController(
731 nsINetworkInterceptController* aInterceptController) {
732 mInterceptController = aInterceptController;
733}
734
735NS_IMETHODIMPnsresult
736nsCORSListenerProxy::GetInterface(const nsIID& aIID, void** aResult) {
737 if (aIID.Equals(NS_GET_IID(nsIChannelEventSink)(nsIChannelEventSink::COMTypeInfo<nsIChannelEventSink, void
>::kIID)
)) {
738 *aResult = static_cast<nsIChannelEventSink*>(this);
739 NS_ADDREF_THIS()AddRef();
740
741 return NS_OK;
742 }
743
744 if (aIID.Equals(NS_GET_IID(nsINetworkInterceptController)(nsINetworkInterceptController::COMTypeInfo<nsINetworkInterceptController
, void>::kIID)
) &&
745 mInterceptController) {
746 nsCOMPtr<nsINetworkInterceptController> copy(mInterceptController);
747 *aResult = copy.forget().take();
748
749 return NS_OK;
750 }
751
752 return mOuterNotificationCallbacks
753 ? mOuterNotificationCallbacks->GetInterface(aIID, aResult)
754 : NS_ERROR_NO_INTERFACE;
755}
756
757NS_IMETHODIMPnsresult
758nsCORSListenerProxy::AsyncOnChannelRedirect(
759 nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags,
760 nsIAsyncVerifyRedirectCallback* aCb) {
761 nsresult rv;
762 if (NS_IsInternalSameURIRedirect(aOldChannel, aNewChannel, aFlags) ||
763 NS_IsHSTSUpgradeRedirect(aOldChannel, aNewChannel, aFlags)) {
764 // Internal redirects still need to be updated in order to maintain
765 // the correct headers. We use DataURIHandling::Allow, since unallowed
766 // data URIs should have been blocked before we got to the internal
767 // redirect.
768 rv = UpdateChannel(aNewChannel, DataURIHandling::Allow,
769 UpdateType::InternalOrHSTSRedirect, false);
770 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
771 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"
, 773)
772 "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"
, 773)
773 "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"
, 773)
;
774 aOldChannel->Cancel(rv);
775 return rv;
776 }
777 } else {
778 mIsRedirect = true;
779 // A real, external redirect. Perform CORS checking on new URL.
780 rv = CheckRequestApproved(aOldChannel);
781 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
782 nsCOMPtr<nsIURI> oldURI;
783 NS_GetFinalChannelURI(aOldChannel, getter_AddRefs(oldURI));
784 if (oldURI) {
785 OriginAttributes attrs;
786 StoragePrincipalHelper::GetOriginAttributesForNetworkState(aOldChannel,
787 attrs);
788 if (sPreflightCache) {
789 // OK to use mRequestingPrincipal since preflights never get
790 // redirected.
791 sPreflightCache->RemoveEntries(oldURI, mRequestingPrincipal, attrs);
792 } else {
793 nsCOMPtr<nsIHttpChannelChild> httpChannelChild =
794 do_QueryInterface(aOldChannel);
795 if (httpChannelChild) {
796 rv = httpChannelChild->RemoveCorsPreflightCacheEntry(
797 oldURI, mRequestingPrincipal, attrs);
798 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
799 // Only warn here to ensure we call the channel Cancel() below
800 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"
, 800)
;
801 }
802 }
803 }
804 }
805 aOldChannel->Cancel(NS_ERROR_DOM_BAD_URI);
806 // Reason for NS_ERROR_DOM_BAD_URI already logged in
807 // CheckRequestApproved()
808 return NS_ERROR_DOM_BAD_URI;
809 }
810
811 if (mHasBeenCrossSite) {
812 // Once we've been cross-site, cross-origin redirects reset our source
813 // origin. Note that we need to call GetChannelURIPrincipal() because
814 // we are looking for the principal that is actually being loaded and not
815 // the principal that initiated the load.
816 nsCOMPtr<nsIPrincipal> oldChannelPrincipal;
817 nsContentUtils::GetSecurityManager()->GetChannelURIPrincipal(
818 aOldChannel, getter_AddRefs(oldChannelPrincipal));
819 nsCOMPtr<nsIPrincipal> newChannelPrincipal;
820 nsContentUtils::GetSecurityManager()->GetChannelURIPrincipal(
821 aNewChannel, getter_AddRefs(newChannelPrincipal));
822 if (!oldChannelPrincipal || !newChannelPrincipal) {
823 rv = NS_ERROR_OUT_OF_MEMORY;
824 }
825
826 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
827 aOldChannel->Cancel(rv);
828 return rv;
829 }
830
831 if (!oldChannelPrincipal->Equals(newChannelPrincipal)) {
832 // Spec says to set our source origin to a unique origin.
833 mOriginHeaderPrincipal =
834 NullPrincipal::CreateWithInheritedAttributes(oldChannelPrincipal);
835 }
836 }
837
838 bool rewriteToGET = false;
839 // We need to strip auth header from preflight request for
840 // cross-origin redirects.
841 // See Bug 1874132
842 bool stripAuthHeader =
843 StaticPrefs::network_fetch_redirect_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 || StaticPrefs::network_cors_preflight_block_userpass_uri()) {
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 do_GetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &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}