Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp
Warning:line 177, column 12
Value stored to 'rv' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_dom_reporting0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/reporting -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/reporting -resource-dir /usr/lib/llvm-19/lib/clang/19 -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 MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/dom/reporting -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/reporting -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/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-09-22-115206-3586786-1 -x c++ Unified_cpp_dom_reporting0.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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include <algorithm>
8
9#include "mozilla/JSONStringWriteFuncs.h"
10#include "mozilla/StaticPrefs_dom.h"
11#include "mozilla/dom/EndpointForReportChild.h"
12#include "mozilla/dom/Fetch.h"
13#include "mozilla/dom/Navigator.h"
14#include "mozilla/dom/Promise.h"
15#include "mozilla/dom/ReportBody.h"
16#include "mozilla/dom/ReportDeliver.h"
17#include "mozilla/dom/Request.h"
18#include "mozilla/dom/RequestBinding.h"
19#include "mozilla/dom/Response.h"
20#include "mozilla/dom/RootedDictionary.h"
21#include "mozilla/ipc/BackgroundChild.h"
22#include "mozilla/ipc/PBackgroundChild.h"
23#include "mozilla/ipc/PBackgroundSharedTypes.h"
24#include "nsGlobalWindowInner.h"
25#include "nsIGlobalObject.h"
26#include "nsIXPConnect.h"
27#include "nsNetUtil.h"
28#include "nsStringStream.h"
29
30namespace mozilla::dom {
31
32namespace {
33
34StaticRefPtr<ReportDeliver> gReportDeliver;
35
36// This is the same value as the default value of
37// dom.min_timeout_value, so it's not that random.
38constexpr double gMinReportAgeInMs = 4.0;
39
40class ReportFetchHandler final : public PromiseNativeHandler {
41 public:
42 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:
43
44 explicit ReportFetchHandler(
45 const nsTArray<ReportDeliver::ReportData>& aReportData)
46 : mReports(aReportData.Clone()) {}
47
48 void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
49 ErrorResult& aRv) override {
50 if (!gReportDeliver) {
51 return;
52 }
53
54 if (NS_WARN_IF(!aValue.isObject())NS_warn_if_impl(!aValue.isObject(), "!aValue.isObject()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 54)
) {
55 return;
56 }
57
58 JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
59 MOZ_ASSERT(obj)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(obj)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(obj))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("obj", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 59); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj" ")"); do
{ *((volatile int*)__null) = 59; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
60
61 {
62 Response* response = nullptr;
63 if (NS_WARN_IF(NS_FAILED(UNWRAP_OBJECT(Response, &obj, response)))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(mozilla
::dom::binding_detail::UnwrapObjectWithCrossOriginAsserts<
mozilla::dom::prototypes::id::Response, mozilla::dom::Response_Binding
::NativeType>(&obj, response))), 0))), "NS_FAILED(UNWRAP_OBJECT(Response, &obj, response))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 63)
) {
64 return;
65 }
66
67 if (response->Status() == 410) {
68 mozilla::ipc::PBackgroundChild* actorChild =
69 mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
70
71 for (const auto& report : mReports) {
72 mozilla::ipc::PrincipalInfo principalInfo;
73 nsresult rv =
74 PrincipalToPrincipalInfo(report.mPrincipal, &principalInfo);
75 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 75)
) {
76 continue;
77 }
78
79 actorChild->SendRemoveEndpoint(report.mGroupName, report.mEndpointURL,
80 principalInfo);
81 }
82 }
83 }
84 }
85
86 void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue,
87 ErrorResult& aRv) override {
88 if (gReportDeliver) {
89 for (auto& report : mReports) {
90 ++report.mFailures;
91 gReportDeliver->AppendReportData(report);
92 }
93 }
94 }
95
96 private:
97 ~ReportFetchHandler() = default;
98
99 nsTArray<ReportDeliver::ReportData> mReports;
100};
101
102NS_IMPL_ISUPPORTS0(ReportFetchHandler)MozExternalRefCountType ReportFetchHandler::AddRef(void) { static_assert
(!std::is_destructible_v<ReportFetchHandler>, "Reference-counted class "
"ReportFetchHandler" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
102; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("ReportFetchHandler" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("ReportFetchHandler" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"ReportFetchHandler\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ReportFetchHandler\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 102; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("ReportFetchHandler" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("ReportFetchHandler"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
ReportFetchHandler::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 102
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("ReportFetchHandler" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("ReportFetchHandler" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"ReportFetchHandler\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ReportFetchHandler\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 102; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("ReportFetchHandler" " not thread-safe"); const
char* const nametmp = "ReportFetchHandler"; nsrefcnt count =
--mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult ReportFetchHandler::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 102); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<ReportFetchHandler, nsISupports>, int32_t
( reinterpret_cast<char*>(static_cast<nsISupports*>
((ReportFetchHandler*)0x1000)) - reinterpret_cast<char*>
((ReportFetchHandler*)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; }
103
104class ReportJSONWriter final : public JSONWriter {
105 public:
106 explicit ReportJSONWriter(JSONStringWriteFunc<nsAutoCString>& aOutput)
107 : JSONWriter(aOutput) {}
108
109 void JSONProperty(const Span<const char>& aProperty,
110 const Span<const char>& aJSON) {
111 Separator();
112 PropertyNameAndColon(aProperty);
113 mWriter.Write(aJSON);
114 }
115};
116
117void SendReports(nsTArray<ReportDeliver::ReportData>& aReports,
118 const nsCString& aEndPointUrl, nsIPrincipal* aPrincipal) {
119 if (NS_WARN_IF(aReports.IsEmpty())NS_warn_if_impl(aReports.IsEmpty(), "aReports.IsEmpty()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 119)
) {
120 return;
121 }
122
123 nsIXPConnect* xpc = nsContentUtils::XPConnect();
124 MOZ_ASSERT(xpc, "This should never be null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(xpc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(xpc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("xpc" " (" "This should never be null!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 124); AnnotateMozCrashReason("MOZ_ASSERT" "(" "xpc" ") (" "This should never be null!"
")"); do { *((volatile int*)__null) = 124; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
125
126 nsCOMPtr<nsIGlobalObject> globalObject;
127 {
128 AutoJSAPI jsapi;
129 jsapi.Init();
130
131 JSContext* cx = jsapi.cx();
132 JS::Rooted<JSObject*> sandbox(cx);
133 nsresult rv = xpc->CreateSandbox(cx, aPrincipal, sandbox.address());
134 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 134)
) {
135 return;
136 }
137
138 // The JSContext is not in a realm, so CreateSandbox returned an unwrapped
139 // global.
140 MOZ_ASSERT(JS_IsGlobalObject(sandbox))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JS_IsGlobalObject(sandbox))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JS_IsGlobalObject(sandbox)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JS_IsGlobalObject(sandbox)"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 140); AnnotateMozCrashReason("MOZ_ASSERT" "(" "JS_IsGlobalObject(sandbox)"
")"); do { *((volatile int*)__null) = 140; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
141
142 globalObject = xpc::NativeGlobal(sandbox);
143 }
144
145 if (NS_WARN_IF(!globalObject)NS_warn_if_impl(!globalObject, "!globalObject", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 145)
) {
146 return;
147 }
148
149 // The body
150 JSONStringWriteFunc<nsAutoCString> body;
151 ReportJSONWriter w(body);
152
153 w.StartArrayElement();
154 for (const auto& report : aReports) {
155 MOZ_ASSERT(report.mPrincipal == aPrincipal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(report.mPrincipal == aPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(report.mPrincipal == aPrincipal
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"report.mPrincipal == aPrincipal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 155); AnnotateMozCrashReason("MOZ_ASSERT" "(" "report.mPrincipal == aPrincipal"
")"); do { *((volatile int*)__null) = 155; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
156 MOZ_ASSERT(report.mEndpointURL == aEndPointUrl)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(report.mEndpointURL == aEndPointUrl)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(report.mEndpointURL == aEndPointUrl
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"report.mEndpointURL == aEndPointUrl", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 156); AnnotateMozCrashReason("MOZ_ASSERT" "(" "report.mEndpointURL == aEndPointUrl"
")"); do { *((volatile int*)__null) = 156; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
157 w.StartObjectElement();
158 // It looks like in rare cases, TimeStamp::Now() may be the same
159 // as report.mCreationTime, so we introduce a constant number to
160 // make sure "age" is always not 0.
161 w.IntProperty(
162 "age",
163 std::max((TimeStamp::Now() - report.mCreationTime).ToMilliseconds(),
164 gMinReportAgeInMs));
165 w.StringProperty("type", NS_ConvertUTF16toUTF8(report.mType));
166 w.StringProperty("url", NS_ConvertUTF16toUTF8(report.mURL));
167 w.StringProperty("user_agent", NS_ConvertUTF16toUTF8(report.mUserAgent));
168 w.JSONProperty(MakeStringSpan("body"),
169 Span<const char>(report.mReportBodyJSON.Data(),
170 report.mReportBodyJSON.Length()));
171 w.EndObject();
172 }
173 w.EndArray();
174
175 // The body as stream
176 nsCOMPtr<nsIInputStream> streamBody;
177 nsresult rv =
Value stored to 'rv' during its initialization is never read
178 NS_NewCStringInputStream(getter_AddRefs(streamBody), body.StringCRef());
179
180 // Headers
181 IgnoredErrorResult error;
182 RefPtr<InternalHeaders> internalHeaders =
183 new InternalHeaders(HeadersGuardEnum::Request);
184 internalHeaders->Set("Content-Type"_ns, "application/reports+json"_ns, error);
185 if (NS_WARN_IF(error.Failed())NS_warn_if_impl(error.Failed(), "error.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 185)
) {
186 return;
187 }
188
189 // URL and fragments
190 nsCOMPtr<nsIURI> uri;
191 rv = NS_NewURI(getter_AddRefs(uri), aEndPointUrl);
192 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 192)
) {
193 return;
194 }
195
196 nsCOMPtr<nsIURI> uriClone;
197 rv = NS_GetURIWithoutRef(uri, getter_AddRefs(uriClone));
198 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 198)
) {
199 return;
200 }
201
202 nsAutoCString uriSpec;
203 rv = uriClone->GetSpec(uriSpec);
204 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 204)
) {
205 return;
206 }
207
208 nsAutoCString uriFragment;
209 rv = uri->GetRef(uriFragment);
210 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 210)
) {
211 return;
212 }
213
214 auto internalRequest = MakeSafeRefPtr<InternalRequest>(uriSpec, uriFragment);
215
216 internalRequest->SetMethod("POST"_ns);
217 internalRequest->SetBody(streamBody, body.StringCRef().Length());
218 internalRequest->SetHeaders(internalHeaders);
219 internalRequest->SetSkipServiceWorker();
220 // TODO: internalRequest->SetContentPolicyType(TYPE_REPORT);
221 internalRequest->SetMode(RequestMode::Cors);
222 internalRequest->SetCredentialsMode(RequestCredentials::Same_origin);
223
224 RefPtr<Request> request =
225 new Request(globalObject, std::move(internalRequest), nullptr);
226
227 RequestOrUTF8String fetchInput;
228 fetchInput.SetAsRequest() = request;
229
230 RootedDictionary<RequestInit> requestInit(RootingCx());
231 RefPtr<Promise> promise = FetchRequest(globalObject, fetchInput, requestInit,
232 CallerType::NonSystem, error);
233 if (error.Failed()) {
234 for (auto& report : aReports) {
235 ++report.mFailures;
236 if (gReportDeliver) {
237 gReportDeliver->AppendReportData(report);
238 }
239 }
240 return;
241 }
242
243 RefPtr<ReportFetchHandler> handler = new ReportFetchHandler(aReports);
244 promise->AppendNativeHandler(handler);
245}
246
247} // namespace
248
249/* static */
250void ReportDeliver::Record(nsPIDOMWindowInner* aWindow, const nsAString& aType,
251 const nsAString& aGroupName, const nsAString& aURL,
252 ReportBody* aBody) {
253 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 253; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
254 MOZ_ASSERT(aWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWindow))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWindow", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { *((volatile int*)__null) = 254; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
255 MOZ_ASSERT(aBody)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBody)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aBody))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aBody", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBody" ")");
do { *((volatile int*)__null) = 255; __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
;
256
257 JSONStringWriteFunc<nsAutoCString> reportBodyJSON;
258 ReportJSONWriter w(reportBodyJSON);
259
260 w.Start();
261 aBody->ToJSON(w);
262 w.End();
263
264 nsCOMPtr<nsIPrincipal> principal =
265 nsGlobalWindowInner::Cast(aWindow)->GetPrincipal();
266 if (NS_WARN_IF(!principal)NS_warn_if_impl(!principal, "!principal", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 266)
) {
267 return;
268 }
269
270 mozilla::ipc::PrincipalInfo principalInfo;
271 nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo);
272 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 272)
) {
273 return;
274 }
275
276 mozilla::ipc::PBackgroundChild* actorChild =
277 mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
278
279 PEndpointForReportChild* actor =
280 actorChild->SendPEndpointForReportConstructor(nsString(aGroupName),
281 principalInfo);
282 if (NS_WARN_IF(!actor)NS_warn_if_impl(!actor, "!actor", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 282)
) {
283 return;
284 }
285
286 ReportData data;
287 data.mType = aType;
288 data.mGroupName = aGroupName;
289 data.mURL = aURL;
290 data.mCreationTime = TimeStamp::Now();
291 data.mReportBodyJSON = std::move(reportBodyJSON).StringRRef();
292 data.mPrincipal = principal;
293 data.mFailures = 0;
294
295 Navigator* navigator = aWindow->Navigator();
296 MOZ_ASSERT(navigator)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(navigator)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(navigator))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("navigator", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "navigator" ")"
); do { *((volatile int*)__null) = 296; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
297
298 IgnoredErrorResult error;
299 navigator->GetUserAgent(data.mUserAgent, CallerType::NonSystem, error);
300 if (NS_WARN_IF(error.Failed())NS_warn_if_impl(error.Failed(), "error.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 300)
) {
301 return;
302 }
303
304 static_cast<EndpointForReportChild*>(actor)->Initialize(data);
305}
306
307/* static */
308void ReportDeliver::Fetch(const ReportData& aReportData) {
309 if (!gReportDeliver) {
310 RefPtr<ReportDeliver> rd = new ReportDeliver();
311
312 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
313 if (NS_WARN_IF(!obs)NS_warn_if_impl(!obs, "!obs", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 313)
) {
314 return;
315 }
316
317 obs->AddObserver(rd, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown", false);
318 gReportDeliver = rd;
319 }
320
321 gReportDeliver->AppendReportData(aReportData);
322}
323
324void ReportDeliver::AppendReportData(const ReportData& aReportData) {
325 if (aReportData.mFailures >
326 StaticPrefs::dom_reporting_delivering_maxFailures()) {
327 return;
328 }
329
330 if (NS_WARN_IF(!mReportQueue.AppendElement(aReportData, fallible))NS_warn_if_impl(!mReportQueue.AppendElement(aReportData, fallible
), "!mReportQueue.AppendElement(aReportData, fallible)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 330)
) {
331 return;
332 }
333
334 while (mReportQueue.Length() >
335 StaticPrefs::dom_reporting_delivering_maxReports()) {
336 mReportQueue.RemoveElementAt(0);
337 }
338
339 RefPtr<ReportDeliver> self{this};
340 nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
341 "ReportDeliver::CallNotify", [self]() { self->Notify(); });
342
343 NS_DispatchToCurrentThreadQueue(
344 runnable.forget(), StaticPrefs::dom_reporting_delivering_timeout() * 1000,
345 EventQueuePriority::Idle);
346}
347
348void ReportDeliver::Notify() {
349 nsTArray<ReportData> reports = std::move(mReportQueue);
350
351 // group reports by endpoint and nsIPrincipal
352 std::map<std::pair<nsCString, nsCOMPtr<nsIPrincipal>>, nsTArray<ReportData>>
353 reportsByPrincipal;
354 for (ReportData& report : reports) {
355 auto already_seen =
356 reportsByPrincipal.find({report.mEndpointURL, report.mPrincipal});
357 if (already_seen == reportsByPrincipal.end()) {
358 reportsByPrincipal.emplace(
359 std::make_pair(report.mEndpointURL, report.mPrincipal),
360 nsTArray<ReportData>({report}));
361 } else {
362 already_seen->second.AppendElement(report);
363 }
364 }
365
366 for (auto& iter : reportsByPrincipal) {
367 std::pair<nsCString, nsCOMPtr<nsIPrincipal>> key = iter.first;
368 nsTArray<ReportData>& value = iter.second;
369 nsCString url = key.first;
370 nsCOMPtr<nsIPrincipal> principal = key.second;
371 nsAutoCString u(url);
372 SendReports(value, url, principal);
373 }
374}
375
376NS_IMETHODIMPnsresult
377ReportDeliver::GetName(nsACString& aName) {
378 aName.AssignLiteral("ReportDeliver");
379 return NS_OK;
380}
381
382NS_IMETHODIMPnsresult
383ReportDeliver::Observe(nsISupports* aSubject, const char* aTopic,
384 const char16_t* aData) {
385 MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!strcmp(aTopic, "xpcom-shutdown"))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!strcmp(aTopic, "xpcom-shutdown"
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!strcmp(aTopic, \"xpcom-shutdown\")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 385); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!strcmp(aTopic, \"xpcom-shutdown\")"
")"); do { *((volatile int*)__null) = 385; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
386
387 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
388 if (NS_WARN_IF(!obs)NS_warn_if_impl(!obs, "!obs", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 388)
) {
389 return NS_OK;
390 }
391
392 obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown");
393
394 gReportDeliver = nullptr;
395 return NS_OK;
396}
397
398ReportDeliver::ReportDeliver() = default;
399
400ReportDeliver::~ReportDeliver() = default;
401
402NS_INTERFACE_MAP_BEGIN(ReportDeliver)nsresult ReportDeliver::QueryInterface(const nsIID& aIID,
void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 402); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
403 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<nsIObserver*>(this)); else
404 NS_INTERFACE_MAP_ENTRY(nsIObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIObserver>)) foundInterface = static_cast
<nsIObserver*>(this); else
405 NS_INTERFACE_MAP_ENTRY(nsINamed)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsINamed>)) foundInterface = static_cast
<nsINamed*>(this); else
406NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports
, void>::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::COMTypeInfo
<nsISupports, void>::kIID))))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 406); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 406; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
407
408NS_IMPL_ADDREF(ReportDeliver)MozExternalRefCountType ReportDeliver::AddRef(void) { static_assert
(!std::is_destructible_v<ReportDeliver>, "Reference-counted class "
"ReportDeliver" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
408; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("ReportDeliver" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("ReportDeliver" != nullptr))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"ReportDeliver\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ReportDeliver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 408; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("ReportDeliver" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("ReportDeliver"
), (uint32_t)(sizeof(*this))); return count; }
409NS_IMPL_RELEASE(ReportDeliver)MozExternalRefCountType ReportDeliver::Release(void) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 409); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 409
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("ReportDeliver" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("ReportDeliver" != nullptr))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"ReportDeliver\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/reporting/ReportDeliver.cpp"
, 409); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ReportDeliver\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 409; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("ReportDeliver" " not thread-safe"); const char
* const nametmp = "ReportDeliver"; nsrefcnt count = --mRefCnt
; NS_LogRelease((this), (count), (nametmp)); if (count == 0) {
mRefCnt = 1; delete (this); return 0; } return count; }
410
411} // namespace mozilla::dom