Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
Warning:line 518, 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_url-classifier0.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/toolkit/components/url-classifier -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/toolkit/components/url-classifier -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 GOOGLE_PROTOBUF_NO_RTTI -D GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER -D MOZ_SAFEBROWSING_DUMP_FAILED_UPDATES -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/toolkit/components/url-classifier -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/build -I /var/lib/jenkins/workspace/firefox-scan-build/xpcom/io -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/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_url-classifier0.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "chromium/safebrowsing.pb.h"
6#include "nsEscape.h"
7#include "nsString.h"
8#include "nsIURI.h"
9#include "nsIURIMutator.h"
10#include "nsIURL.h"
11#include "nsIXULRuntime.h"
12#include "nsUrlClassifierUtils.h"
13#include "nsTArray.h"
14#include "nsReadableUtils.h"
15#include "plbase64.h"
16#include "nsPrintfCString.h"
17#include "mozilla/ClearOnShutdown.h"
18#include "mozilla/Sprintf.h"
19#include "mozilla/StaticPtr.h"
20#include "mozilla/Mutex.h"
21#include "nsIRedirectHistoryEntry.h"
22#include "nsIHttpChannelInternal.h"
23#include "mozIThirdPartyUtil.h"
24#include "nsIDocShell.h"
25#include "mozilla/TextUtils.h"
26#include "mozilla/Preferences.h"
27#include "mozilla/Services.h"
28#include "mozilla/Telemetry.h"
29#include "nsNetUtil.h"
30#include "nsIHttpChannel.h"
31#include "nsIObserverService.h"
32#include "nsIPrefBranch.h"
33#include "nsIPrefService.h"
34#include "nsPIDOMWindow.h"
35#include "nsServiceManagerUtils.h"
36#include "nsThreadManager.h"
37#include "nsTHashSet.h"
38#include "Classifier.h"
39#include "Entries.h"
40#include "prprf.h"
41#include "prtime.h"
42
43#define DEFAULT_PROTOCOL_VERSION"2.2" "2.2"
44
45using namespace mozilla;
46using namespace mozilla::safebrowsing;
47
48static mozilla::StaticRefPtr<nsUrlClassifierUtils> gUrlClassifierUtils;
49
50static char int_to_hex_digit(int32_t i) {
51 NS_ASSERTION((i >= 0) && (i <= 15), "int too big in int_to_hex_digit")do { if (!((i >= 0) && (i <= 15))) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "int too big in int_to_hex_digit", "(i >= 0) && (i <= 15)"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 51); MOZ_PretendNoReturn(); } } while (0)
;
52 return static_cast<char>(((i < 10) ? (i + '0') : ((i - 10) + 'A')));
53}
54
55static bool IsDecimal(const nsACString& num) {
56 for (uint32_t i = 0; i < num.Length(); i++) {
57 if (!mozilla::IsAsciiDigit(num[i])) {
58 return false;
59 }
60 }
61
62 return true;
63}
64
65static bool IsHex(const nsACString& num) {
66 if (num.Length() < 3) {
67 return false;
68 }
69
70 if (num[0] != '0' || !(num[1] == 'x' || num[1] == 'X')) {
71 return false;
72 }
73
74 for (uint32_t i = 2; i < num.Length(); i++) {
75 if (!mozilla::IsAsciiHexDigit(num[i])) {
76 return false;
77 }
78 }
79
80 return true;
81}
82
83static bool IsOctal(const nsACString& num) {
84 if (num.Length() < 2) {
85 return false;
86 }
87
88 if (num[0] != '0') {
89 return false;
90 }
91
92 for (uint32_t i = 1; i < num.Length(); i++) {
93 if (!mozilla::IsAsciiDigit(num[i]) || num[i] == '8' || num[i] == '9') {
94 return false;
95 }
96 }
97
98 return true;
99}
100
101/////////////////////////////////////////////////////////////////
102// SafeBrowsing V4 related utits.
103
104namespace mozilla {
105namespace safebrowsing {
106
107static PlatformType GetPlatformType() {
108#if defined(ANDROID)
109 return ANDROID_PLATFORM;
110#elif defined(XP_MACOSX)
111 return OSX_PLATFORM;
112#elif defined(XP_LINUX1)
113 return LINUX_PLATFORM;
114#elif defined(XP_WIN)
115 return WINDOWS_PLATFORM;
116#else
117 // Default to Linux for other platforms (see bug 1362501).
118 return LINUX_PLATFORM;
119#endif
120}
121
122typedef FetchThreatListUpdatesRequest_ListUpdateRequest ListUpdateRequest;
123typedef FetchThreatListUpdatesRequest_ListUpdateRequest_Constraints Constraints;
124
125static void InitListUpdateRequest(ThreatType aThreatType,
126 const nsCString& aStateBase64,
127 ListUpdateRequest* aListUpdateRequest) {
128 aListUpdateRequest->set_threat_type(aThreatType);
129 PlatformType platform = GetPlatformType();
130#if defined(ANDROID)
131 // Temporary hack to fix bug 1441345.
132 if ((aThreatType == SOCIAL_ENGINEERING_PUBLIC) ||
133 (aThreatType == SOCIAL_ENGINEERING)) {
134 platform = LINUX_PLATFORM;
135 }
136#endif
137 aListUpdateRequest->set_platform_type(platform);
138 aListUpdateRequest->set_threat_entry_type(URL);
139
140 Constraints* contraints = new Constraints();
141 contraints->add_supported_compressions(RICE);
142 aListUpdateRequest->set_allocated_constraints(contraints);
143
144 // Only set non-empty state.
145 if (!aStateBase64.IsEmpty()) {
146 nsCString stateBinary;
147 nsresult rv = Base64Decode(aStateBase64, stateBinary);
148 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
149 aListUpdateRequest->set_state(stateBinary.get(), stateBinary.Length());
150 }
151 }
152}
153
154static ClientInfo* CreateClientInfo() {
155 ClientInfo* c = new ClientInfo();
156
157 nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID"@mozilla.org/preferences-service;1");
158
159 nsAutoCString clientId;
160 nsresult rv = prefBranch->GetCharPref("browser.safebrowsing.id", clientId);
161
162 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
163 clientId = "Firefox"; // Use "Firefox" as fallback.
164 }
165
166 c->set_client_id(clientId.get());
167
168 return c;
169}
170
171static bool IsAllowedOnCurrentPlatform(uint32_t aThreatType) {
172 PlatformType platform = GetPlatformType();
173
174 switch (aThreatType) {
175 case POTENTIALLY_HARMFUL_APPLICATION:
176 // Bug 1388582 - Google server would respond 404 error if the request
177 // contains PHA on non-mobile platform.
178 return ANDROID_PLATFORM == platform;
179 case MALICIOUS_BINARY:
180 case CSD_DOWNLOAD_WHITELIST:
181 // Bug 1392204 - 'goog-downloadwhite-proto' and 'goog-badbinurl-proto'
182 // are not available on android.
183 return ANDROID_PLATFORM != platform;
184 }
185 // We allow every threat type not listed in the switch cases.
186 return true;
187}
188
189} // end of namespace safebrowsing.
190} // end of namespace mozilla.
191
192// static
193already_AddRefed<nsUrlClassifierUtils>
194nsUrlClassifierUtils::GetXPCOMSingleton() {
195 if (gUrlClassifierUtils) {
196 return do_AddRef(gUrlClassifierUtils);
197 }
198
199 RefPtr<nsUrlClassifierUtils> utils = new nsUrlClassifierUtils();
200 if (NS_WARN_IF(NS_FAILED(utils->Init()))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(utils
->Init())), 0))), "NS_FAILED(utils->Init())", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 200)
) {
201 return nullptr;
202 }
203
204 // Note: This is cleared in the nsUrlClassifierUtils destructor.
205 gUrlClassifierUtils = utils.get();
206 ClearOnShutdown(&gUrlClassifierUtils);
207 return utils.forget();
208}
209
210// static
211nsUrlClassifierUtils* nsUrlClassifierUtils::GetInstance() {
212 if (!gUrlClassifierUtils) {
213 RefPtr<nsUrlClassifierUtils> utils = GetXPCOMSingleton();
214 }
215
216 return gUrlClassifierUtils;
217}
218
219nsUrlClassifierUtils::nsUrlClassifierUtils()
220 : mProviderDictLock("nsUrlClassifierUtils.mProviderDictLock") {}
221
222nsUrlClassifierUtils::~nsUrlClassifierUtils() {
223 if (gUrlClassifierUtils) {
224 MOZ_ASSERT(gUrlClassifierUtils == this)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gUrlClassifierUtils == this)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gUrlClassifierUtils == this)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("gUrlClassifierUtils == this"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "gUrlClassifierUtils == this"
")"); do { *((volatile int*)__null) = 224; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
225 gUrlClassifierUtils = nullptr;
226 }
227}
228
229nsresult nsUrlClassifierUtils::Init() {
230 // nsIUrlClassifierUtils is a thread-safe service so it's
231 // allowed to use on non-main threads. However, building
232 // the provider dictionary must be on the main thread.
233 // We forcefully load nsUrlClassifierUtils in
234 // nsUrlClassifierDBService::Init() to ensure we must
235 // now be on the main thread.
236 nsresult rv = ReadProvidersFromPrefs(mProviderDict);
237 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 237); return rv; } } while (false)
;
238
239 // Add an observer for shutdown
240 nsCOMPtr<nsIObserverService> observerService =
241 mozilla::services::GetObserverService();
242 if (!observerService) return NS_ERROR_FAILURE;
243
244 observerService->AddObserver(this, "xpcom-shutdown-threads", false);
245 mozilla::Preferences::AddStrongObserver(this, "browser.safebrowsing");
246
247 return NS_OK;
248}
249
250NS_IMPL_ISUPPORTS(nsUrlClassifierUtils, nsIUrlClassifierUtils, nsIObserver)MozExternalRefCountType nsUrlClassifierUtils::AddRef(void) { static_assert
(!std::is_destructible_v<nsUrlClassifierUtils>, "Reference-counted class "
"nsUrlClassifierUtils" " 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
250; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsUrlClassifierUtils" != nullptr)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!("nsUrlClassifierUtils" != nullptr))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("\"nsUrlClassifierUtils\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsUrlClassifierUtils\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 250; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsUrlClassifierUtils" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsUrlClassifierUtils"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsUrlClassifierUtils::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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 250
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsUrlClassifierUtils" != nullptr)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!("nsUrlClassifierUtils" != nullptr))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("\"nsUrlClassifierUtils\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsUrlClassifierUtils\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 250; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsUrlClassifierUtils" " not thread-safe"); const
char* const nametmp = "nsUrlClassifierUtils"; nsrefcnt count
= --mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (
count == 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult nsUrlClassifierUtils::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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 250); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsUrlClassifierUtils, nsIUrlClassifierUtils
>, int32_t( reinterpret_cast<char*>(static_cast<nsIUrlClassifierUtils
*>((nsUrlClassifierUtils*)0x1000)) - reinterpret_cast<char
*>((nsUrlClassifierUtils*)0x1000))}, {&mozilla::detail
::kImplementedIID<nsUrlClassifierUtils, nsIObserver>, int32_t
( reinterpret_cast<char*>(static_cast<nsIObserver*>
((nsUrlClassifierUtils*)0x1000)) - reinterpret_cast<char*>
((nsUrlClassifierUtils*)0x1000))}, {&mozilla::detail::kImplementedIID
<nsUrlClassifierUtils, nsISupports>, int32_t(reinterpret_cast
<char*>(static_cast<nsISupports*>( static_cast<
nsIUrlClassifierUtils*>((nsUrlClassifierUtils*)0x1000))) -
reinterpret_cast<char*>((nsUrlClassifierUtils*)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; }
251
252/////////////////////////////////////////////////////////////////////////////
253// nsIUrlClassifierUtils
254
255NS_IMETHODIMPnsresult
256nsUrlClassifierUtils::GetKeyForURI(nsIURI* uri, nsACString& _retval) {
257 nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(uri);
258 if (!innerURI) innerURI = uri;
259
260 nsAutoCString host;
261 innerURI->GetAsciiHost(host);
262
263 if (host.IsEmpty()) {
264 return NS_ERROR_MALFORMED_URI;
265 }
266
267 nsresult rv = CanonicalizeHostname(host, _retval);
268 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 268); return rv; } } while (false)
;
269
270 nsAutoCString path;
271 rv = innerURI->GetPathQueryRef(path);
272 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 272); return rv; } } while (false)
;
273
274 // Strip fragment and query because canonicalization only applies to path
275 int32_t ref = path.FindChar('#');
276 if (ref != kNotFound) {
277 path.SetLength(ref);
278 }
279
280 int32_t query = path.FindChar('?');
281 if (query != kNotFound) {
282 path.SetLength(query);
283 }
284
285 nsAutoCString temp;
286 rv = CanonicalizePath(path, temp);
287 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 287); return rv; } } while (false)
;
288
289 _retval.Append(temp);
290
291 if (query != kNotFound) {
292 nsAutoCString query;
293 rv = innerURI->GetQuery(query);
294 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 294); return rv; } } while (false)
;
295
296 // We have to canonicalize the query too based on
297 // https://developers.google.com/safe-browsing/v4/urls-hashing?hl=en#canonicalization
298 rv = CanonicalizeQuery(query, temp);
299 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 299); return rv; } } while (false)
;
300
301 _retval.Append(temp);
302 }
303
304 return NS_OK;
305}
306
307// We use "goog-*-proto" as the list name for v4, where "proto" indicates
308// it's updated (as well as hash completion) via protobuf.
309//
310// In the mozilla official build, we are allowed to use the
311// private phishing list (goog-phish-proto). See Bug 1288840.
312static const struct {
313 const char* mListName;
314 uint32_t mThreatType;
315} THREAT_TYPE_CONV_TABLE[] = {
316 {"goog-malware-proto", MALWARE_THREAT}, // 1
317 {"googpub-phish-proto", SOCIAL_ENGINEERING_PUBLIC}, // 2
318 {"goog-unwanted-proto", UNWANTED_SOFTWARE}, // 3
319 {"goog-harmful-proto", POTENTIALLY_HARMFUL_APPLICATION}, // 4
320 {"goog-phish-proto", SOCIAL_ENGINEERING}, // 5
321
322 // For application reputation
323 {"goog-badbinurl-proto", MALICIOUS_BINARY}, // 7
324 {"goog-downloadwhite-proto", CSD_DOWNLOAD_WHITELIST}, // 9
325
326 // For testing purpose.
327 {"moztest-phish-proto", SOCIAL_ENGINEERING_PUBLIC}, // 2
328 {"test-phish-proto", SOCIAL_ENGINEERING_PUBLIC}, // 2
329 {"moztest-unwanted-proto", UNWANTED_SOFTWARE}, // 3
330 {"test-unwanted-proto", UNWANTED_SOFTWARE}, // 3
331};
332
333NS_IMETHODIMPnsresult
334nsUrlClassifierUtils::ConvertThreatTypeToListNames(uint32_t aThreatType,
335 nsACString& aListNames) {
336 for (uint32_t i = 0; i < ArrayLength(THREAT_TYPE_CONV_TABLE); i++) {
337 if (aThreatType == THREAT_TYPE_CONV_TABLE[i].mThreatType) {
338 if (!aListNames.IsEmpty()) {
339 aListNames.AppendLiteral(",");
340 }
341 aListNames += THREAT_TYPE_CONV_TABLE[i].mListName;
342 }
343 }
344
345 return aListNames.IsEmpty() ? NS_ERROR_FAILURE : NS_OK;
346}
347
348NS_IMETHODIMPnsresult
349nsUrlClassifierUtils::ConvertListNameToThreatType(const nsACString& aListName,
350 uint32_t* aThreatType) {
351 for (uint32_t i = 0; i < ArrayLength(THREAT_TYPE_CONV_TABLE); i++) {
352 if (aListName.EqualsASCII(THREAT_TYPE_CONV_TABLE[i].mListName)) {
353 *aThreatType = THREAT_TYPE_CONV_TABLE[i].mThreatType;
354 return NS_OK;
355 }
356 }
357
358 return NS_ERROR_FAILURE;
359}
360
361NS_IMETHODIMPnsresult
362nsUrlClassifierUtils::GetProvider(const nsACString& aTableName,
363 nsACString& aProvider) {
364 MutexAutoLock lock(mProviderDictLock);
365 nsCString* provider = nullptr;
366
367 if (IsTestTable(aTableName)) {
368 aProvider = nsLiteralCString(TESTING_TABLE_PROVIDER_NAME"test");
369 } else if (mProviderDict.Get(aTableName, &provider)) {
370 aProvider = provider ? *provider : ""_ns;
371 } else {
372 aProvider.Truncate();
373 }
374 return NS_OK;
375}
376
377NS_IMETHODIMPnsresult
378nsUrlClassifierUtils::GetTelemetryProvider(const nsACString& aTableName,
379 nsACString& aProvider) {
380 GetProvider(aTableName, aProvider);
381 // Exceptionlist known providers to avoid reporting on private ones.
382 // An empty provider is treated as "other"
383 if (!"mozilla"_ns.Equals(aProvider) && !"google"_ns.Equals(aProvider) &&
384 !"google4"_ns.Equals(aProvider) && !"baidu"_ns.Equals(aProvider) &&
385 !"mozcn"_ns.Equals(aProvider) && !"yandex"_ns.Equals(aProvider) &&
386 !nsLiteralCString(TESTING_TABLE_PROVIDER_NAME"test").Equals(aProvider)) {
387 aProvider.AssignLiteral("other");
388 }
389
390 return NS_OK;
391}
392
393NS_IMETHODIMPnsresult
394nsUrlClassifierUtils::GetProtocolVersion(const nsACString& aProvider,
395 nsACString& aVersion) {
396 nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID"@mozilla.org/preferences-service;1");
397 if (prefBranch) {
398 nsPrintfCString prefName("browser.safebrowsing.provider.%s.pver",
399 nsCString(aProvider).get());
400 nsAutoCString version;
401 nsresult rv = prefBranch->GetCharPref(prefName.get(), version);
402
403 aVersion = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? version.get() : DEFAULT_PROTOCOL_VERSION"2.2";
404 } else {
405 aVersion = DEFAULT_PROTOCOL_VERSION"2.2";
406 }
407
408 return NS_OK;
409}
410
411NS_IMETHODIMPnsresult
412nsUrlClassifierUtils::MakeUpdateRequestV4(
413 const nsTArray<nsCString>& aListNames,
414 const nsTArray<nsCString>& aStatesBase64, nsACString& aRequest) {
415 using namespace mozilla::safebrowsing;
416
417 if (aListNames.Length() != aStatesBase64.Length()) {
418 return NS_ERROR_INVALID_ARG;
419 }
420
421 FetchThreatListUpdatesRequest r;
422 r.set_allocated_client(CreateClientInfo());
423
424 for (uint32_t i = 0; i < aListNames.Length(); i++) {
425 uint32_t threatType;
426 nsresult rv = ConvertListNameToThreatType(aListNames[i], &threatType);
427 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
428 continue; // Unknown list name.
429 }
430 if (!IsAllowedOnCurrentPlatform(threatType)) {
431 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Threat type %d (%s) is unsupported on current platform: %d"
, threatType, aListNames[i].get(), GetPlatformType()) .get(),
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 435)
432 nsPrintfCString(NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Threat type %d (%s) is unsupported on current platform: %d"
, threatType, aListNames[i].get(), GetPlatformType()) .get(),
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 435)
433 "Threat type %d (%s) is unsupported on current platform: %d",NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Threat type %d (%s) is unsupported on current platform: %d"
, threatType, aListNames[i].get(), GetPlatformType()) .get(),
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 435)
434 threatType, aListNames[i].get(), GetPlatformType())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Threat type %d (%s) is unsupported on current platform: %d"
, threatType, aListNames[i].get(), GetPlatformType()) .get(),
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 435)
435 .get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Threat type %d (%s) is unsupported on current platform: %d"
, threatType, aListNames[i].get(), GetPlatformType()) .get(),
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 435)
;
436 continue; // Some threat types are not available on some platforms.
437 }
438 auto lur = r.mutable_list_update_requests()->Add();
439 InitListUpdateRequest(static_cast<ThreatType>(threatType), aStatesBase64[i],
440 lur);
441 }
442
443 // Then serialize.
444 std::string s;
445 r.SerializeToString(&s);
446
447 nsCString out;
448 nsresult rv = Base64URLEncode(s.size(), (const uint8_t*)s.c_str(),
449 Base64URLEncodePaddingPolicy::Include, out);
450 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 450); return rv; } } while (false)
;
451
452 aRequest = out;
453
454 return NS_OK;
455}
456
457NS_IMETHODIMPnsresult
458nsUrlClassifierUtils::MakeFindFullHashRequestV4(
459 const nsTArray<nsCString>& aListNames,
460 const nsTArray<nsCString>& aListStatesBase64,
461 const nsTArray<nsCString>& aPrefixesBase64, nsACString& aRequest) {
462 if (aListNames.Length() != aListStatesBase64.Length()) {
463 return NS_ERROR_INVALID_ARG;
464 }
465
466 FindFullHashesRequest r;
467 r.set_allocated_client(CreateClientInfo());
468
469 nsresult rv;
470
471 //-------------------------------------------------------------------
472 // Set up FindFullHashesRequest.threat_info.
473 auto threatInfo = r.mutable_threat_info();
474
475 PlatformType platform = GetPlatformType();
476
477 // 1) Set threat types.
478 for (uint32_t i = 0; i < aListNames.Length(); i++) {
479 // Add threat types.
480 uint32_t threatType;
481 rv = ConvertListNameToThreatType(aListNames[i], &threatType);
482 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 482); return rv; } } while (false)
;
483 if (!IsAllowedOnCurrentPlatform(threatType)) {
484 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Threat type %d (%s) is unsupported on current platform: %d"
, threatType, aListNames[i].get(), GetPlatformType()) .get(),
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 488)
485 nsPrintfCString(NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Threat type %d (%s) is unsupported on current platform: %d"
, threatType, aListNames[i].get(), GetPlatformType()) .get(),
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 488)
486 "Threat type %d (%s) is unsupported on current platform: %d",NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Threat type %d (%s) is unsupported on current platform: %d"
, threatType, aListNames[i].get(), GetPlatformType()) .get(),
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 488)
487 threatType, aListNames[i].get(), GetPlatformType())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Threat type %d (%s) is unsupported on current platform: %d"
, threatType, aListNames[i].get(), GetPlatformType()) .get(),
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 488)
488 .get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Threat type %d (%s) is unsupported on current platform: %d"
, threatType, aListNames[i].get(), GetPlatformType()) .get(),
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 488)
;
489 continue;
490 }
491 threatInfo->add_threat_types((ThreatType)threatType);
492
493#if defined(ANDROID)
494 // Temporary hack to fix bug 1441345.
495 if (((ThreatType)threatType == SOCIAL_ENGINEERING_PUBLIC) ||
496 ((ThreatType)threatType == SOCIAL_ENGINEERING)) {
497 platform = LINUX_PLATFORM;
498 }
499#endif
500
501 // Add client states for index 'i' only when the threat type is available
502 // on current platform.
503 nsCString stateBinary;
504 rv = Base64Decode(aListStatesBase64[i], stateBinary);
505 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 505); return rv; } } while (false)
;
506 r.add_client_states(stateBinary.get(), stateBinary.Length());
507 }
508
509 // 2) Set platform type.
510 threatInfo->add_platform_types(platform);
511
512 // 3) Set threat entry type.
513 threatInfo->add_threat_entry_types(URL);
514
515 // 4) Set threat entries.
516 for (const nsCString& prefix : aPrefixesBase64) {
517 nsCString prefixBinary;
518 rv = Base64Decode(prefix, prefixBinary);
Value stored to 'rv' is never read
519 threatInfo->add_threat_entries()->set_hash(prefixBinary.get(),
520 prefixBinary.Length());
521 }
522 //-------------------------------------------------------------------
523
524 // Then serialize.
525 std::string s;
526 r.SerializeToString(&s);
527
528 nsCString out;
529 rv = Base64URLEncode(s.size(), (const uint8_t*)s.c_str(),
530 Base64URLEncodePaddingPolicy::Include, out);
531 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 531); return rv; } } while (false)
;
532
533 aRequest = out;
534
535 return NS_OK;
536}
537
538// Remove ref, query, userpass, anypart which may contain sensitive data
539static nsresult GetSpecWithoutSensitiveData(nsIURI* aUri, nsACString& aSpec) {
540 if (NS_WARN_IF(!aUri)NS_warn_if_impl(!aUri, "!aUri", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 540)
) {
541 return NS_ERROR_INVALID_ARG;
542 }
543
544 nsresult rv;
545 nsCOMPtr<nsIURL> url(do_QueryInterface(aUri));
546 if (url) {
547 nsCOMPtr<nsIURI> clone;
548 rv = NS_MutateURI(url)
549 .SetQuery(""_ns)
550 .SetRef(""_ns)
551 .SetUserPass(""_ns)
552 .Finalize(clone);
553 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 553); return rv; } } while (false)
;
554 rv = clone->GetAsciiSpec(aSpec);
555 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 555); return rv; } } while (false)
;
556 }
557 return NS_OK;
558}
559
560static nsresult AddThreatSourceFromChannel(ThreatHit& aHit,
561 nsIChannel* aChannel,
562 ThreatHit_ThreatSourceType aType) {
563 if (NS_WARN_IF(!aChannel)NS_warn_if_impl(!aChannel, "!aChannel", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 563)
) {
564 return NS_ERROR_INVALID_ARG;
565 }
566
567 nsresult rv;
568
569 auto matchingSource = aHit.add_resources();
570 matchingSource->set_type(aType);
571
572 nsCOMPtr<nsIURI> uri;
573 rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
574 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 574); return rv; } } while (false)
;
575
576 nsCString spec;
577 rv = GetSpecWithoutSensitiveData(uri, spec);
578 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 578); return rv; } } while (false)
;
579 matchingSource->set_url(spec.get());
580
581 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
582 if (httpChannel) {
583 nsCOMPtr<nsIReferrerInfo> referrerInfo = httpChannel->GetReferrerInfo();
584 if (referrerInfo) {
585 nsAutoCString referrerSpec;
586 nsCOMPtr<nsIURI> referrer = referrerInfo->GetComputedReferrer();
587 if (referrer) {
588 rv = GetSpecWithoutSensitiveData(referrer, referrerSpec);
589 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 589); return rv; } } while (false)
;
590 matchingSource->set_referrer(referrerSpec.get());
591 }
592 }
593 }
594
595 nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
596 do_QueryInterface(aChannel);
597 if (httpChannelInternal) {
598 nsCString remoteIp;
599 rv = httpChannelInternal->GetRemoteAddress(remoteIp);
600 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !remoteIp.IsEmpty()) {
601 matchingSource->set_remote_ip(remoteIp.get());
602 }
603 }
604 return NS_OK;
605}
606static nsresult AddThreatSourceFromRedirectEntry(
607 ThreatHit& aHit, nsIRedirectHistoryEntry* aRedirectEntry,
608 ThreatHit_ThreatSourceType aType) {
609 if (NS_WARN_IF(!aRedirectEntry)NS_warn_if_impl(!aRedirectEntry, "!aRedirectEntry", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 609)
) {
610 return NS_ERROR_INVALID_ARG;
611 }
612
613 nsresult rv;
614
615 nsCOMPtr<nsIPrincipal> principal;
616 rv = aRedirectEntry->GetPrincipal(getter_AddRefs(principal));
617 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 617); return rv; } } while (false)
;
618 nsCString spec;
619 rv = principal->GetExposableSpec(spec);
620 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 620); return rv; } } while (false)
;
621 auto source = aHit.add_resources();
622 source->set_url(spec.get());
623 source->set_type(aType);
624
625 nsCOMPtr<nsIURI> referrer;
626 rv = aRedirectEntry->GetReferrerURI(getter_AddRefs(referrer));
627 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && referrer) {
628 nsCString referrerSpec;
629 rv = GetSpecWithoutSensitiveData(referrer, referrerSpec);
630 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 630); return rv; } } while (false)
;
631 source->set_referrer(referrerSpec.get());
632 }
633
634 nsCString remoteIp;
635 rv = aRedirectEntry->GetRemoteAddress(remoteIp);
636 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !remoteIp.IsEmpty()) {
637 source->set_remote_ip(remoteIp.get());
638 }
639 return NS_OK;
640}
641
642// Add top level tab url and redirect threatsources to threatHit message
643static nsresult AddTabThreatSources(ThreatHit& aHit, nsIChannel* aChannel) {
644 if (NS_WARN_IF(!aChannel)NS_warn_if_impl(!aChannel, "!aChannel", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 644)
) {
645 return NS_ERROR_INVALID_ARG;
646 }
647
648 nsresult rv;
649 nsCOMPtr<mozIDOMWindowProxy> win;
650 nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
651 do_GetService(THIRDPARTYUTIL_CONTRACTID"@mozilla.org/thirdpartyutil;1", &rv);
652 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 652); return rv; } } while (false)
;
653
654 rv = thirdPartyUtil->GetTopWindowForChannel(aChannel, nullptr,
655 getter_AddRefs(win));
656 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 656); return rv; } } while (false)
;
657
658 auto* pwin = nsPIDOMWindowOuter::From(win);
659 nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
660 if (!docShell) {
661 return NS_OK;
662 }
663
664 nsCOMPtr<nsIChannel> topChannel;
665 docShell->GetCurrentDocumentChannel(getter_AddRefs(topChannel));
666 if (!topChannel) {
667 return NS_OK;
668 }
669
670 nsCOMPtr<nsIURI> uri;
671 rv = aChannel->GetURI(getter_AddRefs(uri));
672 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 672); return rv; } } while (false)
;
673
674 nsCOMPtr<nsIURI> topUri;
675 rv = topChannel->GetURI(getter_AddRefs(topUri));
676 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 676); return rv; } } while (false)
;
677
678 bool isTopUri = false;
679 rv = topUri->Equals(uri, &isTopUri);
680 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isTopUri) {
681 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
682 if (loadInfo->RedirectChain().Length()) {
683 AddThreatSourceFromRedirectEntry(aHit, loadInfo->RedirectChain()[0],
684 ThreatHit_ThreatSourceType_TAB_RESOURCE);
685 }
686 }
687
688 // Set top level tab_url threat source
689 rv = AddThreatSourceFromChannel(aHit, topChannel,
690 ThreatHit_ThreatSourceType_TAB_URL);
691 Unused << NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 691)
;
692
693 // Set tab_redirect threat sources if there's any
694 nsCOMPtr<nsILoadInfo> topLoadInfo = topChannel->LoadInfo();
695 nsIRedirectHistoryEntry* redirectEntry;
696 size_t length = topLoadInfo->RedirectChain().Length();
697 for (size_t i = 0; i < length; i++) {
698 redirectEntry = topLoadInfo->RedirectChain()[i];
699 AddThreatSourceFromRedirectEntry(aHit, redirectEntry,
700 ThreatHit_ThreatSourceType_TAB_REDIRECT);
701 }
702
703 return NS_OK;
704}
705
706NS_IMETHODIMPnsresult
707nsUrlClassifierUtils::MakeThreatHitReport(nsIChannel* aChannel,
708 const nsACString& aListName,
709 const nsACString& aHashBase64,
710 nsACString& aRequest) {
711 if (NS_WARN_IF(aListName.IsEmpty())NS_warn_if_impl(aListName.IsEmpty(), "aListName.IsEmpty()", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 711)
|| NS_WARN_IF(aHashBase64.IsEmpty())NS_warn_if_impl(aHashBase64.IsEmpty(), "aHashBase64.IsEmpty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 711)
||
712 NS_WARN_IF(!aChannel)NS_warn_if_impl(!aChannel, "!aChannel", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 712)
) {
713 return NS_ERROR_INVALID_ARG;
714 }
715
716 ThreatHit hit;
717 nsresult rv;
718
719 uint32_t threatType;
720 rv = ConvertListNameToThreatType(aListName, &threatType);
721 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 721); return rv; } } while (false)
;
722 hit.set_threat_type(static_cast<ThreatType>(threatType));
723
724 hit.set_platform_type(GetPlatformType());
725
726 nsCString hash;
727 rv = Base64Decode(aHashBase64, hash);
728 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || hash.Length() != COMPLETE_SIZE32) {
729 return NS_ERROR_FAILURE;
730 }
731
732 auto threatEntry = hit.mutable_entry();
733 threatEntry->set_hash(hash.get(), hash.Length());
734
735 // Set matching source
736 rv = AddThreatSourceFromChannel(hit, aChannel,
737 ThreatHit_ThreatSourceType_MATCHING_URL);
738 Unused << NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 738)
;
739 // Set tab url, tab resource url and redirect sources
740 rv = AddTabThreatSources(hit, aChannel);
741 Unused << NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 741)
;
742
743 hit.set_allocated_client_info(CreateClientInfo());
744
745 std::string s;
746 hit.SerializeToString(&s);
747
748 nsCString out;
749 rv = Base64URLEncode(s.size(), reinterpret_cast<const uint8_t*>(s.c_str()),
750 Base64URLEncodePaddingPolicy::Include, out);
751 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 751); return rv; } } while (false)
;
752
753 aRequest = out;
754
755 return NS_OK;
756}
757
758static uint32_t DurationToMs(const Duration& aDuration) {
759 // Seconds precision is good enough. Ignore nanoseconds like Chrome does.
760 return aDuration.seconds() * 1000;
761}
762
763NS_IMETHODIMPnsresult
764nsUrlClassifierUtils::ParseFindFullHashResponseV4(
765 const nsACString& aResponse,
766 nsIUrlClassifierParseFindFullHashCallback* aCallback) {
767 enum CompletionErrorType {
768 SUCCESS = 0,
769 PARSING_FAILURE = 1,
770 UNKNOWN_THREAT_TYPE = 2,
771 };
772
773 FindFullHashesResponse r;
774 if (!r.ParseFromArray(aResponse.BeginReading(), aResponse.Length())) {
775 NS_WARNING("Invalid response")NS_DebugBreak(NS_DEBUG_WARNING, "Invalid response", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 775)
;
776 Telemetry::Accumulate(Telemetry::URLCLASSIFIER_COMPLETION_ERROR,
777 PARSING_FAILURE);
778 return NS_ERROR_FAILURE;
779 }
780
781 bool hasUnknownThreatType = false;
782
783 for (auto& m : r.matches()) {
784 nsCString tableNames;
785 nsresult rv = ConvertThreatTypeToListNames(m.threat_type(), tableNames);
786 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
787 hasUnknownThreatType = true;
788 continue; // Ignore un-convertable threat type.
789 }
790 auto& hash = m.threat().hash();
791 auto cacheDurationSec = m.cache_duration().seconds();
792 aCallback->OnCompleteHashFound(
793 nsDependentCString(hash.c_str(), hash.length()), tableNames,
794 cacheDurationSec);
795 }
796
797 auto minWaitDuration = DurationToMs(r.minimum_wait_duration());
798 auto negCacheDurationSec = r.negative_cache_duration().seconds();
799
800 aCallback->OnResponseParsed(minWaitDuration, negCacheDurationSec);
801
802 Telemetry::Accumulate(Telemetry::URLCLASSIFIER_COMPLETION_ERROR,
803 hasUnknownThreatType ? UNKNOWN_THREAT_TYPE : SUCCESS);
804 return NS_OK;
805}
806
807//////////////////////////////////////////////////////////
808// nsIObserver
809
810NS_IMETHODIMPnsresult
811nsUrlClassifierUtils::Observe(nsISupports* aSubject, const char* aTopic,
812 const char16_t* aData) {
813 if (0 == strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID"nsPref:changed")) {
814 MutexAutoLock lock(mProviderDictLock);
815 return ReadProvidersFromPrefs(mProviderDict);
816 }
817
818 if (0 == strcmp(aTopic, "xpcom-shutdown-threads")) {
819 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID"@mozilla.org/preferences-service;1");
820 NS_ENSURE_TRUE(prefs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(prefs)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefs" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 820); return NS_ERROR_FAILURE; } } while (false)
;
821 return prefs->RemoveObserver("browser.safebrowsing", this);
822 }
823
824 return NS_ERROR_UNEXPECTED;
825}
826
827/////////////////////////////////////////////////////////////////////////////
828// non-interface methods
829
830nsresult nsUrlClassifierUtils::ReadProvidersFromPrefs(ProviderDictType& aDict) {
831 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()"
" (" "ReadProvidersFromPrefs must be on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "ReadProvidersFromPrefs must be on main thread" ")"); do
{ *((volatile int*)__null) = 832; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
832 "ReadProvidersFromPrefs must be on main thread")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()"
" (" "ReadProvidersFromPrefs must be on main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "ReadProvidersFromPrefs must be on main thread" ")"); do
{ *((volatile int*)__null) = 832; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
833
834 nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID"@mozilla.org/preferences-service;1");
835 NS_ENSURE_TRUE(prefs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(prefs)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefs" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 835); return NS_ERROR_FAILURE; } } while (false)
;
836 nsCOMPtr<nsIPrefBranch> prefBranch;
837 nsresult rv = prefs->GetBranch("browser.safebrowsing.provider.",
838 getter_AddRefs(prefBranch));
839 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 839); return rv; } } while (false)
;
840
841 // We've got a pref branch for "browser.safebrowsing.provider.".
842 // Enumerate all children prefs and parse providers.
843 nsTArray<nsCString> childArray;
844 rv = prefBranch->GetChildList("", childArray);
845 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/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp"
, 845); return rv; } } while (false)
;
846
847 // Collect providers from childArray.
848 nsTHashSet<nsCString> providers;
849 for (auto& child : childArray) {
850 auto dotPos = child.FindChar('.');
851 if (dotPos < 0) {
852 continue;
853 }
854
855 nsDependentCSubstring provider = Substring(child, 0, dotPos);
856
857 providers.Insert(provider);
858 }
859
860 // Now we have all providers. Check which one owns |aTableName|.
861 // e.g. The owning lists of provider "google" is defined in
862 // "browser.safebrowsing.provider.google.lists".
863 for (const auto& provider : providers) {
864 nsPrintfCString owninListsPref("%s.lists",
865 nsPromiseFlatCString{provider}.get());
866
867 nsAutoCString owningLists;
868 nsresult rv = prefBranch->GetCharPref(owninListsPref.get(), owningLists);
869 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
870 continue;
871 }
872
873 // We've got the owning lists (represented as string) of |provider|.
874 // Build the dictionary for the owning list and the current provider.
875 nsTArray<nsCString> tables;
876 Classifier::SplitTables(owningLists, tables);
877 for (auto tableName : tables) {
878 aDict.InsertOrUpdate(tableName, MakeUnique<nsCString>(provider));
879 }
880 }
881
882 return NS_OK;
883}
884
885nsresult nsUrlClassifierUtils::CanonicalizeHostname(const nsACString& hostname,
886 nsACString& _retval) {
887 nsAutoCString unescaped;
888 if (!NS_UnescapeURL(PromiseFlatCStringTPromiseFlatString<char>(hostname).get(),
889 PromiseFlatCStringTPromiseFlatString<char>(hostname).Length(), 0, unescaped)) {
890 unescaped.Assign(hostname);
891 }
892
893 nsAutoCString cleaned;
894 CleanupHostname(unescaped, cleaned);
895
896 nsAutoCString temp;
897 ParseIPAddress(cleaned, temp);
898 if (!temp.IsEmpty()) {
899 cleaned.Assign(temp);
900 }
901
902 ToLowerCase(cleaned);
903 SpecialEncode(cleaned, false, _retval);
904
905 return NS_OK;
906}
907
908nsresult nsUrlClassifierUtils::CanonicalizePath(const nsACString& path,
909 nsACString& _retval) {
910 _retval.Truncate();
911
912 nsAutoCString decodedPath(path);
913 nsAutoCString temp;
914 while (NS_UnescapeURL(decodedPath.get(), decodedPath.Length(), 0, temp)) {
915 decodedPath.Assign(temp);
916 temp.Truncate();
917 }
918
919 SpecialEncode(decodedPath, true, _retval);
920 // XXX: lowercase the path?
921
922 return NS_OK;
923}
924
925nsresult nsUrlClassifierUtils::CanonicalizeQuery(const nsACString& query,
926 nsACString& _retval) {
927 _retval.Truncate();
928 _retval.Append('?');
929
930 // Unescape the query
931 nsAutoCString unescaped;
932 if (!NS_UnescapeURL(PromiseFlatCStringTPromiseFlatString<char>(query).get(),
933 PromiseFlatCStringTPromiseFlatString<char>(query).Length(), 0, unescaped)) {
934 unescaped.Assign(query);
935 }
936
937 // slash folding does not apply to the query parameters, but we need to
938 // percent-escape all characters that are <= ASCII 32, >= 127, "#", or "%"
939 SpecialEncode(unescaped, false, _retval);
940
941 return NS_OK;
942}
943
944void nsUrlClassifierUtils::CleanupHostname(const nsACString& hostname,
945 nsACString& _retval) {
946 _retval.Truncate();
947
948 const char* curChar = hostname.BeginReading();
949 const char* end = hostname.EndReading();
950 char lastChar = '\0';
951 while (curChar != end) {
952 unsigned char c = static_cast<unsigned char>(*curChar);
953 if (c == '.' && (lastChar == '\0' || lastChar == '.')) {
954 // skip
955 } else {
956 _retval.Append(*curChar);
957 }
958 lastChar = c;
959 ++curChar;
960 }
961
962 // cut off trailing dots
963 while (_retval.Length() > 0 && _retval[_retval.Length() - 1] == '.') {
964 _retval.SetLength(_retval.Length() - 1);
965 }
966}
967
968void nsUrlClassifierUtils::ParseIPAddress(const nsACString& host,
969 nsACString& _retval) {
970 _retval.Truncate();
971 nsACString::const_iterator iter, end;
972 host.BeginReading(iter);
973 host.EndReading(end);
974
975 if (host.Length() <= 15) {
976 // The Windows resolver allows a 4-part dotted decimal IP address to
977 // have a space followed by any old rubbish, so long as the total length
978 // of the string doesn't get above 15 characters. So, "10.192.95.89 xy"
979 // is resolved to 10.192.95.89.
980 // If the string length is greater than 15 characters, e.g.
981 // "10.192.95.89 xy.wildcard.example.com", it will be resolved through
982 // DNS.
983
984 if (FindCharInReadable(' ', iter, end)) {
985 end = iter;
986 }
987 }
988
989 for (host.BeginReading(iter); iter != end; iter++) {
990 if (!(mozilla::IsAsciiHexDigit(*iter) || *iter == 'x' || *iter == 'X' ||
991 *iter == '.')) {
992 // not an IP
993 return;
994 }
995 }
996
997 host.BeginReading(iter);
998 nsTArray<nsCString> parts;
999 ParseString(PromiseFlatCStringTPromiseFlatString<char>(Substring(iter, end)), '.', parts);
1000 if (parts.Length() > 4) {
1001 return;
1002 }
1003
1004 // If any potentially-octal numbers (start with 0 but not hex) have
1005 // non-octal digits, no part of the ip can be in octal
1006 // XXX: this came from the old javascript implementation, is it really
1007 // supposed to be like this?
1008 bool allowOctal = true;
1009 uint32_t i;
1010
1011 for (i = 0; i < parts.Length(); i++) {
1012 const nsCString& part = parts[i];
1013 if (part[0] == '0') {
1014 for (uint32_t j = 1; j < part.Length(); j++) {
1015 if (part[j] == 'x') {
1016 break;
1017 }
1018 if (part[j] == '8' || part[j] == '9') {
1019 allowOctal = false;
1020 break;
1021 }
1022 }
1023 }
1024 }
1025
1026 for (i = 0; i < parts.Length(); i++) {
1027 nsAutoCString canonical;
1028
1029 if (i == parts.Length() - 1) {
1030 CanonicalNum(parts[i], 5 - parts.Length(), allowOctal, canonical);
1031 } else {
1032 CanonicalNum(parts[i], 1, allowOctal, canonical);
1033 }
1034
1035 if (canonical.IsEmpty()) {
1036 _retval.Truncate();
1037 return;
1038 }
1039
1040 if (_retval.IsEmpty()) {
1041 _retval.Assign(canonical);
1042 } else {
1043 _retval.Append('.');
1044 _retval.Append(canonical);
1045 }
1046 }
1047}
1048
1049void nsUrlClassifierUtils::CanonicalNum(const nsACString& num, uint32_t bytes,
1050 bool allowOctal, nsACString& _retval) {
1051 _retval.Truncate();
1052
1053 if (num.Length() < 1) {
1054 return;
1055 }
1056
1057 uint32_t val;
1058 if (allowOctal && IsOctal(num)) {
1059 if (PR_sscanf(PromiseFlatCStringTPromiseFlatString<char>(num).get(), "%o", &val) != 1) {
1060 return;
1061 }
1062 } else if (IsDecimal(num)) {
1063 if (PR_sscanf(PromiseFlatCStringTPromiseFlatString<char>(num).get(), "%u", &val) != 1) {
1064 return;
1065 }
1066 } else if (IsHex(num)) {
1067 if (PR_sscanf(PromiseFlatCStringTPromiseFlatString<char>(num).get(),
1068 num[1] == 'X' ? "0X%x" : "0x%x", &val) != 1) {
1069 return;
1070 }
1071 } else {
1072 return;
1073 }
1074
1075 while (bytes--) {
1076 char buf[20];
1077 SprintfLiteral(buf, "%u", val & 0xff);
1078 if (_retval.IsEmpty()) {
1079 _retval.Assign(buf);
1080 } else {
1081 _retval = nsDependentCString(buf) + "."_ns + _retval;
1082 }
1083 val >>= 8;
1084 }
1085}
1086
1087// This function will encode all "special" characters in typical url
1088// encoding, that is %hh where h is a valid hex digit. It will also fold
1089// any duplicated slashes.
1090bool nsUrlClassifierUtils::SpecialEncode(const nsACString& url,
1091 bool foldSlashes,
1092 nsACString& _retval) {
1093 bool changed = false;
1094 const char* curChar = url.BeginReading();
1095 const char* end = url.EndReading();
1096
1097 unsigned char lastChar = '\0';
1098 while (curChar != end) {
1099 unsigned char c = static_cast<unsigned char>(*curChar);
1100 if (ShouldURLEscape(c)) {
1101 _retval.Append('%');
1102 _retval.Append(int_to_hex_digit(c / 16));
1103 _retval.Append(int_to_hex_digit(c % 16));
1104
1105 changed = true;
1106 } else if (foldSlashes && (c == '/' && lastChar == '/')) {
1107 // skip
1108 } else {
1109 _retval.Append(*curChar);
1110 }
1111 lastChar = c;
1112 curChar++;
1113 }
1114 return changed;
1115}
1116
1117bool nsUrlClassifierUtils::ShouldURLEscape(const unsigned char c) const {
1118 return c <= 32 || c == '%' || c == '#' || c >= 127;
1119}
1120
1121// moztest- tables are built-in created in LookupCache, they contain hardcoded
1122// url entries in it. moztest tables don't support updates.
1123// static
1124bool nsUrlClassifierUtils::IsMozTestTable(const nsACString& aTableName) {
1125 return StringBeginsWith(aTableName, "moztest-"_ns);
1126}
1127
1128// test- tables are used by testcases and can add custom test entries
1129// through update API.
1130// static
1131bool nsUrlClassifierUtils::IsTestTable(const nsACString& aTableName) {
1132 return IsMozTestTable(aTableName) || StringBeginsWith(aTableName, "test"_ns);
1133}
1134
1135bool nsUrlClassifierUtils::IsInSafeMode() {
1136 static Maybe<bool> sIsInSafeMode;
1137
1138 if (!sIsInSafeMode.isSome()) {
1139 nsCOMPtr<nsIXULRuntime> appInfo =
1140 do_GetService("@mozilla.org/xre/runtime;1");
1141 if (appInfo) {
1142 bool inSafeMode = false;
1143 appInfo->GetInSafeMode(&inSafeMode);
1144 sIsInSafeMode.emplace(inSafeMode);
1145 }
1146 }
1147
1148 return sIsInSafeMode.value();
1149}