| 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 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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 | |
| 45 | using namespace mozilla; |
| 46 | using namespace mozilla::safebrowsing; |
| 47 | |
| 48 | static mozilla::StaticRefPtr<nsUrlClassifierUtils> gUrlClassifierUtils; |
| 49 | |
| 50 | static 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 | |
| 55 | static 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 | |
| 65 | static 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 | |
| 83 | static 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 | |
| 104 | namespace mozilla { |
| 105 | namespace safebrowsing { |
| 106 | |
| 107 | static 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 | |
| 122 | typedef FetchThreatListUpdatesRequest_ListUpdateRequest ListUpdateRequest; |
| 123 | typedef FetchThreatListUpdatesRequest_ListUpdateRequest_Constraints Constraints; |
| 124 | |
| 125 | static 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 | |
| 154 | static 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 | |
| 171 | static 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 |
| 193 | already_AddRefed<nsUrlClassifierUtils> |
| 194 | nsUrlClassifierUtils::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 |
| 211 | nsUrlClassifierUtils* nsUrlClassifierUtils::GetInstance() { |
| 212 | if (!gUrlClassifierUtils) { |
| 213 | RefPtr<nsUrlClassifierUtils> utils = GetXPCOMSingleton(); |
| 214 | } |
| 215 | |
| 216 | return gUrlClassifierUtils; |
| 217 | } |
| 218 | |
| 219 | nsUrlClassifierUtils::nsUrlClassifierUtils() |
| 220 | : mProviderDictLock("nsUrlClassifierUtils.mProviderDictLock") {} |
| 221 | |
| 222 | nsUrlClassifierUtils::~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 | |
| 229 | nsresult 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 | |
| 250 | NS_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(std::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast <void*>(this), aIID, aInstancePtr, table); return rv; } |
| 251 | |
| 252 | ///////////////////////////////////////////////////////////////////////////// |
| 253 | // nsIUrlClassifierUtils |
| 254 | |
| 255 | NS_IMETHODIMPnsresult |
| 256 | nsUrlClassifierUtils::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. |
| 312 | static 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 | |
| 333 | NS_IMETHODIMPnsresult |
| 334 | nsUrlClassifierUtils::ConvertThreatTypeToListNames(uint32_t aThreatType, |
| 335 | nsACString& aListNames) { |
| 336 | for (uint32_t i = 0; i < std::size(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 | |
| 348 | NS_IMETHODIMPnsresult |
| 349 | nsUrlClassifierUtils::ConvertListNameToThreatType(const nsACString& aListName, |
| 350 | uint32_t* aThreatType) { |
| 351 | for (uint32_t i = 0; i < std::size(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 | |
| 361 | NS_IMETHODIMPnsresult |
| 362 | nsUrlClassifierUtils::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 | |
| 377 | NS_IMETHODIMPnsresult |
| 378 | nsUrlClassifierUtils::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 | |
| 393 | NS_IMETHODIMPnsresult |
| 394 | nsUrlClassifierUtils::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 | |
| 411 | NS_IMETHODIMPnsresult |
| 412 | nsUrlClassifierUtils::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 | |
| 457 | NS_IMETHODIMPnsresult |
| 458 | nsUrlClassifierUtils::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 |
| 539 | static 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 | |
| 560 | static 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 | } |
| 606 | static 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 |
| 643 | static 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 | |
| 706 | NS_IMETHODIMPnsresult |
| 707 | nsUrlClassifierUtils::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 | |
| 758 | static uint32_t DurationToMs(const Duration& aDuration) { |
| 759 | // Seconds precision is good enough. Ignore nanoseconds like Chrome does. |
| 760 | return aDuration.seconds() * 1000; |
| 761 | } |
| 762 | |
| 763 | NS_IMETHODIMPnsresult |
| 764 | nsUrlClassifierUtils::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 | |
| 810 | NS_IMETHODIMPnsresult |
| 811 | nsUrlClassifierUtils::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 | |
| 830 | nsresult 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 | |
| 885 | nsresult 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 | |
| 908 | nsresult 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 | |
| 925 | nsresult 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 | |
| 944 | void 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 | |
| 968 | void 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 | |
| 1049 | void 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. |
| 1090 | bool 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 | |
| 1117 | bool 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 |
| 1124 | bool 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 |
| 1131 | bool nsUrlClassifierUtils::IsTestTable(const nsACString& aTableName) { |
| 1132 | return IsMozTestTable(aTableName) || StringBeginsWith(aTableName, "test"_ns); |
| 1133 | } |
| 1134 | |
| 1135 | bool 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 | } |