Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/net/OpaqueResponseUtils.h
Warning:line 179, column 5
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_dom_fetch0.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=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/fetch -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/fetch -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/dom/fetch -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/fetch -I /root/firefox-clang/dom/base -I /root/firefox-clang/netwerk/base -I /root/firefox-clang/netwerk/protocol/data -I /root/firefox-clang/netwerk/protocol/http -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/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-21/lib/clang/21/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=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-27-100320-3286336-1 -x c++ Unified_cpp_dom_fetch0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set sw=2 ts=8 et tw=80 : */
3
4/* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8#ifndef mozilla_net_OpaqueResponseUtils_h
9#define mozilla_net_OpaqueResponseUtils_h
10
11#include "ipc/EnumSerializer.h"
12#include "mozilla/TimeStamp.h"
13#include "nsIContentPolicy.h"
14#include "nsIEncodedChannel.h"
15#include "nsIStreamListener.h"
16#include "nsUnknownDecoder.h"
17#include "nsMimeTypes.h"
18#include "nsIHttpChannel.h"
19
20#include "mozilla/Variant.h"
21#include "mozilla/Logging.h"
22#include "mozilla/glean/NetwerkProtocolHttpMetrics.h"
23
24#include "nsCOMPtr.h"
25#include "nsString.h"
26#include "nsTArray.h"
27
28class nsIContentSniffer;
29
30namespace mozilla::dom {
31class JSValidatorParent;
32}
33
34namespace mozilla::ipc {
35class Shmem;
36}
37
38namespace mozilla::net {
39
40class HttpBaseChannel;
41class nsHttpResponseHead;
42
43enum class OpaqueResponseBlockedReason : uint32_t {
44 ALLOWED_SAFE_LISTED,
45 ALLOWED_SAFE_LISTED_SPEC_BREAKING,
46 BLOCKED_BLOCKLISTED_NEVER_SNIFFED,
47 BLOCKED_206_AND_BLOCKLISTED,
48 BLOCKED_NOSNIFF_AND_EITHER_BLOCKLISTED_OR_TEXTPLAIN,
49 BLOCKED_SHOULD_SNIFF
50};
51
52using OpaqueResponseBlockedTelemetryReason = glean::orb::BlockReasonLabel;
53
54enum class OpaqueResponse { Block, Allow, SniffCompressed, Sniff };
55
56OpaqueResponseBlockedReason GetOpaqueResponseBlockedReason(
57 const nsACString& aContentType, uint16_t aStatus, bool aNoSniff);
58
59OpaqueResponseBlockedReason GetOpaqueResponseBlockedReason(
60 nsHttpResponseHead& aResponseHead);
61
62// Returns a tuple of (rangeStart, rangeEnd, rangeTotal) from the input range
63// header string if succeed.
64Result<std::tuple<int64_t, int64_t, int64_t>, nsresult>
65ParseContentRangeHeaderString(const nsAutoCString& aRangeStr);
66
67bool IsFirstPartialResponse(nsHttpResponseHead& aResponseHead);
68
69LogModule* GetORBLog();
70
71// Helper class to filter data for opaque responses destined for `Window.fetch`.
72// See https://fetch.spec.whatwg.org/#concept-filtered-response-opaque.
73class OpaqueResponseFilter final : public nsIStreamListener {
74 public:
75 NS_DECL_THREADSAFE_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::true_type; protected
: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; nsAutoOwningThread
_mOwningThread; public:
76 NS_DECL_NSIREQUESTOBSERVERvirtual nsresult OnStartRequest(nsIRequest *aRequest) override
; virtual nsresult OnStopRequest(nsIRequest *aRequest, nsresult
aStatusCode) override;
77 NS_DECL_NSISTREAMLISTENERvirtual nsresult OnDataAvailable(nsIRequest *aRequest, nsIInputStream
*aInputStream, uint64_t aOffset, uint32_t aCount) override;
;
78
79 explicit OpaqueResponseFilter(nsIStreamListener* aNext);
80
81 private:
82 virtual ~OpaqueResponseFilter() = default;
83
84 nsCOMPtr<nsIStreamListener> mNext;
85};
86
87class OpaqueResponseBlocker final : public nsIStreamListener {
88 enum class State { Sniffing, Allowed, Blocked };
89
90 public:
91 NS_DECL_THREADSAFE_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::true_type; protected
: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; nsAutoOwningThread
_mOwningThread; public:
92 NS_DECL_NSIREQUESTOBSERVERvirtual nsresult OnStartRequest(nsIRequest *aRequest) override
; virtual nsresult OnStopRequest(nsIRequest *aRequest, nsresult
aStatusCode) override;
93 NS_DECL_NSISTREAMLISTENERvirtual nsresult OnDataAvailable(nsIRequest *aRequest, nsIInputStream
*aInputStream, uint64_t aOffset, uint32_t aCount) override;
;
94
95 OpaqueResponseBlocker(nsIStreamListener* aNext, HttpBaseChannel* aChannel,
96 const nsCString& aContentType, bool aNoSniff);
97
98 bool IsSniffing() const;
99 void AllowResponse();
100 void BlockResponse(HttpBaseChannel* aChannel, nsresult aStatus);
101 void FilterResponse();
102
103 nsresult EnsureOpaqueResponseIsAllowedAfterSniff(nsIRequest* aRequest);
104
105 OpaqueResponse EnsureOpaqueResponseIsAllowedAfterJavaScriptValidation(
106 HttpBaseChannel* aChannel, bool aAllow);
107
108 // The four possible results for validation. `JavaScript` and `JSON` are
109 // self-explanatory. `JavaScript` is the only successful result, in the sense
110 // that it will allow the opaque response, whereas `JSON` will block. `Other`
111 // is the case where validation fails, because the response is neither
112 // `JavaScript` nor `JSON`, but the framework itself works as intended.
113 // `Failure` implies that something has gone wrong, such as allocation, etc.
114 enum class ValidatorResult : uint32_t { JavaScript, JSON, Other, Failure };
115
116 private:
117 virtual ~OpaqueResponseBlocker() = default;
118
119 nsresult ValidateJavaScript(HttpBaseChannel* aChannel, nsIURI* aURI,
120 nsILoadInfo* aLoadInfo);
121
122 void ResolveAndProcessData(HttpBaseChannel* aChannel, bool aAllowed,
123 Maybe<mozilla::ipc::Shmem>& aSharedData);
124
125 void MaybeRunOnStopRequest(HttpBaseChannel* aChannel);
126
127 nsCOMPtr<nsIStreamListener> mNext;
128
129 const nsCString mContentType;
130 const bool mNoSniff;
131 bool mShouldFilter = false;
132
133 State mState = State::Sniffing;
134 nsresult mStatus = NS_OK;
135
136 TimeStamp mStartOfJavaScriptValidation;
137
138 RefPtr<dom::JSValidatorParent> mJSValidator;
139
140 Maybe<nsresult> mPendingOnStopRequestStatus{Nothing()};
141};
142
143class nsCompressedAudioVideoImageDetector : public nsUnknownDecoder {
144 const std::function<void(void*, const uint8_t*, uint32_t)> mCallback;
145
146 public:
147 nsCompressedAudioVideoImageDetector(
148 nsIStreamListener* aListener,
149 std::function<void(void*, const uint8_t*, uint32_t)>&& aCallback)
150 : nsUnknownDecoder(aListener), mCallback(aCallback) {}
151
152 protected:
153 virtual void DetermineContentType(nsIRequest* aRequest) override {
154 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
155 if (!httpChannel) {
156 return;
157 }
158
159 const char* testData = mBuffer;
160 uint32_t testDataLen = mBufferLen;
161 // Check if data are compressed.
162 nsAutoCString decodedData;
163
164 // ConvertEncodedData is always called only on a single thread for each
165 // instance of an object.
166 nsresult rv = ConvertEncodedData(aRequest, mBuffer, mBufferLen);
167 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
168 MutexAutoLock lock(mMutex);
169 decodedData = mDecodedData;
170 }
171 if (!decodedData.IsEmpty()) {
172 testData = decodedData.get();
173 testDataLen = std::min<uint32_t>(decodedData.Length(), 512u);
174 }
175
176 mCallback(httpChannel, (const uint8_t*)testData, testDataLen);
177
178 nsAutoCString contentType;
179 rv = httpChannel->GetContentType(contentType);
Value stored to 'rv' is never read
180
181 MutexAutoLock lock(mMutex);
182 if (!contentType.IsEmpty()) {
183 mContentType = contentType;
184 } else {
185 mContentType = UNKNOWN_CONTENT_TYPE"application/x-unknown-content-type";
186 }
187
188 nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(httpChannel);
189 if (encodedChannel) {
190 encodedChannel->SetHasContentDecompressed(true);
191 }
192 }
193};
194} // namespace mozilla::net
195
196namespace IPC {
197template <>
198struct ParamTraits<mozilla::net::OpaqueResponseBlocker::ValidatorResult>
199 : public ContiguousEnumSerializerInclusive<
200 mozilla::net::OpaqueResponseBlocker::ValidatorResult,
201 mozilla::net::OpaqueResponseBlocker::ValidatorResult::JavaScript,
202 mozilla::net::OpaqueResponseBlocker::ValidatorResult::Failure> {};
203} // namespace IPC
204
205#endif // mozilla_net_OpaqueResponseUtils_h