Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp
Warning:line 550, column 3
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-19/lib/clang/19 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D 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 MOZ_SUPPORT_LEAKCHECKING -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/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-09-22-115206-3586786-1 -x c++ Unified_cpp_url-classifier0.cpp
1//* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6#include "Classifier.h"
7#include "LookupCacheV4.h"
8#include "nsIFile.h"
9#include "nsNetCID.h"
10#include "nsPrintfCString.h"
11#include "nsThreadUtils.h"
12#include "mozilla/Components.h"
13#include "mozilla/EndianUtils.h"
14#include "mozilla/Telemetry.h"
15#include "mozilla/IntegerPrintfMacros.h"
16#include "mozilla/LazyIdleThread.h"
17#include "mozilla/Logging.h"
18#include "mozilla/SyncRunnable.h"
19#include "mozilla/Base64.h"
20#include "mozilla/Unused.h"
21#include "mozilla/UniquePtr.h"
22#include "nsUrlClassifierDBService.h"
23#include "nsUrlClassifierUtils.h"
24
25// MOZ_LOG=UrlClassifierDbService:5
26extern mozilla::LazyLogModule gUrlClassifierDbServiceLog;
27#define LOG(args)do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
args); } } while (0)
\
28 MOZ_LOG(gUrlClassifierDbServiceLog, mozilla::LogLevel::Debug, args)do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
args); } } while (0)
29#define LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(gUrlClassifierDbServiceLog
, mozilla::LogLevel::Debug)), 0))
\
30 MOZ_LOG_TEST(gUrlClassifierDbServiceLog, mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gUrlClassifierDbServiceLog
, mozilla::LogLevel::Debug)), 0))
31
32#define STORE_DIRECTORY"safebrowsing"_ns "safebrowsing"_ns
33#define TO_DELETE_DIR_SUFFIX"-to_delete"_ns "-to_delete"_ns
34#define BACKUP_DIR_SUFFIX"-backup"_ns "-backup"_ns
35#define UPDATING_DIR_SUFFIX"-updating"_ns "-updating"_ns
36
37#define V4_METADATA_SUFFIX".metadata"_ns ".metadata"_ns
38#define V2_METADATA_SUFFIX".sbstore"_ns ".sbstore"_ns
39
40// The amount of time, in milliseconds, that our IO thread will stay alive after
41// the last event it processes.
42#define DEFAULT_THREAD_TIMEOUT_MS5000 5000
43
44namespace mozilla {
45namespace safebrowsing {
46
47bool Classifier::OnUpdateThread() const {
48 bool onthread = false;
49 if (mUpdateThread) {
50 mUpdateThread->IsOnCurrentThread(&onthread);
51 }
52 return onthread;
53}
54
55void Classifier::SplitTables(const nsACString& str,
56 nsTArray<nsCString>& tables) {
57 tables.Clear();
58
59 for (const auto& table : str.Split(',')) {
60 if (!table.IsEmpty()) {
61 tables.AppendElement(table);
62 }
63 }
64
65 // Remove duplicates
66 tables.Sort();
67 const auto newEnd = std::unique(tables.begin(), tables.end());
68 tables.TruncateLength(std::distance(tables.begin(), newEnd));
69}
70
71nsresult Classifier::GetPrivateStoreDirectory(
72 nsIFile* aRootStoreDirectory, const nsACString& aTableName,
73 const nsACString& aProvider, nsIFile** aPrivateStoreDirectory) {
74 NS_ENSURE_ARG_POINTER(aPrivateStoreDirectory)do { if ((__builtin_expect(!!(!(aPrivateStoreDirectory)), 0))
) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPrivateStoreDirectory"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 74); return NS_ERROR_INVALID_POINTER; } } while (false)
;
75
76 if (!StringEndsWith(aTableName, "-proto"_ns)) {
77 // Only V4 table names (ends with '-proto') would be stored
78 // to per-provider sub-directory.
79 nsCOMPtr<nsIFile>(aRootStoreDirectory).forget(aPrivateStoreDirectory);
80 return NS_OK;
81 }
82
83 if (aProvider.IsEmpty()) {
84 // When failing to get provider, just store in the root folder.
85 nsCOMPtr<nsIFile>(aRootStoreDirectory).forget(aPrivateStoreDirectory);
86 return NS_OK;
87 }
88
89 nsCOMPtr<nsIFile> providerDirectory;
90
91 // Clone first since we are gonna create a new directory.
92 nsresult rv = aRootStoreDirectory->Clone(getter_AddRefs(providerDirectory));
93 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/Classifier.cpp"
, 93); return rv; } } while (false)
;
94
95 // Append the provider name to the root store directory.
96 rv = providerDirectory->AppendNative(aProvider);
97 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/Classifier.cpp"
, 97); return rv; } } while (false)
;
98
99 // Ensure existence of the provider directory.
100 bool dirExists;
101 rv = providerDirectory->Exists(&dirExists);
102 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/Classifier.cpp"
, 102); return rv; } } while (false)
;
103
104 if (!dirExists) {
105 LOG(("Creating private directory for %s", nsCString(aTableName).get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Creating private directory for %s"
, nsCString(aTableName).get()); } } while (0)
;
106 rv = providerDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755);
107 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/Classifier.cpp"
, 107); return rv; } } while (false)
;
108 providerDirectory.forget(aPrivateStoreDirectory);
109 return rv;
110 }
111
112 // Store directory exists. Check if it's a directory.
113 bool isDir;
114 rv = providerDirectory->IsDirectory(&isDir);
115 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/Classifier.cpp"
, 115); return rv; } } while (false)
;
116 if (!isDir) {
117 return NS_ERROR_FILE_DESTINATION_NOT_DIR;
118 }
119
120 providerDirectory.forget(aPrivateStoreDirectory);
121
122 return NS_OK;
123}
124
125Classifier::Classifier()
126 : mIsTableRequestResultOutdated(true),
127 mAsyncUpdateInProgress(false),
128 mUpdateInterrupted(true),
129 mIsClosed(false) {
130 // Make a lazy thread for any IO
131 mUpdateThread =
132 new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS5000, "Classifier Update",
133 LazyIdleThread::ShutdownMethod::ManualShutdown);
134}
135
136Classifier::~Classifier() {
137 if (mUpdateThread) {
138 mUpdateThread->Shutdown();
139 mUpdateThread = nullptr;
140 }
141
142 Close();
143}
144
145nsresult Classifier::SetupPathNames() {
146 // Get the root directory where to store all the databases.
147 nsresult rv = mCacheDirectory->Clone(getter_AddRefs(mRootStoreDirectory));
148 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/Classifier.cpp"
, 148); return rv; } } while (false)
;
149
150 rv = mRootStoreDirectory->AppendNative(STORE_DIRECTORY"safebrowsing"_ns);
151 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/Classifier.cpp"
, 151); return rv; } } while (false)
;
152
153 // Make sure LookupCaches (which are persistent and survive updates)
154 // are reading/writing in the right place. We will be moving their
155 // files "underneath" them during backup/restore.
156 for (uint32_t i = 0; i < mLookupCaches.Length(); i++) {
157 mLookupCaches[i]->UpdateRootDirHandle(mRootStoreDirectory);
158 }
159
160 // Directory where to move a backup before an update.
161 rv = mCacheDirectory->Clone(getter_AddRefs(mBackupDirectory));
162 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/Classifier.cpp"
, 162); return rv; } } while (false)
;
163
164 rv = mBackupDirectory->AppendNative(STORE_DIRECTORY"safebrowsing"_ns + BACKUP_DIR_SUFFIX"-backup"_ns);
165 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/Classifier.cpp"
, 165); return rv; } } while (false)
;
166
167 // Directory where to be working on the update.
168 rv = mCacheDirectory->Clone(getter_AddRefs(mUpdatingDirectory));
169 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/Classifier.cpp"
, 169); return rv; } } while (false)
;
170
171 rv = mUpdatingDirectory->AppendNative(STORE_DIRECTORY"safebrowsing"_ns + UPDATING_DIR_SUFFIX"-updating"_ns);
172 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/Classifier.cpp"
, 172); return rv; } } while (false)
;
173
174 // Directory where to move the backup so we can atomically
175 // delete (really move) it.
176 rv = mCacheDirectory->Clone(getter_AddRefs(mToDeleteDirectory));
177 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/Classifier.cpp"
, 177); return rv; } } while (false)
;
178
179 rv = mToDeleteDirectory->AppendNative(STORE_DIRECTORY"safebrowsing"_ns + TO_DELETE_DIR_SUFFIX"-to_delete"_ns);
180 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/Classifier.cpp"
, 180); return rv; } } while (false)
;
181
182 return NS_OK;
183}
184
185nsresult Classifier::CreateStoreDirectory() {
186 if (ShouldAbort()) {
187 return NS_OK; // nothing to do, the classifier is done
188 }
189
190 // Ensure the safebrowsing directory exists.
191 bool storeExists;
192 nsresult rv = mRootStoreDirectory->Exists(&storeExists);
193 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/Classifier.cpp"
, 193); return rv; } } while (false)
;
194
195 if (!storeExists) {
196 rv = mRootStoreDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755);
197 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/Classifier.cpp"
, 197); return rv; } } while (false)
;
198 } else {
199 bool storeIsDir;
200 rv = mRootStoreDirectory->IsDirectory(&storeIsDir);
201 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/Classifier.cpp"
, 201); return rv; } } while (false)
;
202 if (!storeIsDir) return NS_ERROR_FILE_DESTINATION_NOT_DIR;
203 }
204
205 return NS_OK;
206}
207
208// Testing entries are created directly in LookupCache instead of
209// created via update(Bug 1531354). We can remove unused testing
210// files from profile.
211// TODO: See Bug 723153 to clear old safebrowsing store
212nsresult Classifier::ClearLegacyFiles() {
213 if (ShouldAbort()) {
214 return NS_OK; // nothing to do, the classifier is done
215 }
216
217 nsTArray<nsLiteralCString> tables = {
218 "test-phish-simple"_ns, "test-malware-simple"_ns,
219 "test-unwanted-simple"_ns, "test-harmful-simple"_ns,
220 "test-track-simple"_ns, "test-trackwhite-simple"_ns,
221 "test-block-simple"_ns,
222 };
223
224 const auto fnFindAndRemove = [](nsIFile* aRootDirectory,
225 const nsACString& aFileName) {
226 nsCOMPtr<nsIFile> file;
227 nsresult rv = aRootDirectory->Clone(getter_AddRefs(file));
228 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
229 return false;
230 }
231
232 rv = file->AppendNative(aFileName);
233 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
234 return false;
235 }
236
237 bool exists;
238 rv = file->Exists(&exists);
239 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !exists) {
240 return false;
241 }
242
243 rv = file->Remove(false);
244 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
245 return false;
246 }
247
248 return true;
249 };
250
251 for (const auto& table : tables) {
252 // Remove both .sbstore and .vlpse if .sbstore exists
253 if (fnFindAndRemove(mRootStoreDirectory, table + ".sbstore"_ns)) {
254 fnFindAndRemove(mRootStoreDirectory, table + ".vlpset"_ns);
255 }
256 }
257
258 return NS_OK;
259}
260
261nsresult Classifier::Open(nsIFile& aCacheDirectory) {
262 // Remember the Local profile directory.
263 nsresult rv = aCacheDirectory.Clone(getter_AddRefs(mCacheDirectory));
264 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/Classifier.cpp"
, 264); return rv; } } while (false)
;
265
266 // Create the handles to the update and backup directories.
267 rv = SetupPathNames();
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/Classifier.cpp"
, 268); return rv; } } while (false)
;
269
270 // Clean up any to-delete directories that haven't been deleted yet.
271 // This is still required for backward compatibility.
272 rv = CleanToDelete();
273 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/Classifier.cpp"
, 273); return rv; } } while (false)
;
274
275 // If we met a crash during the previous update, "safebrowsing-updating"
276 // directory will exist and let's remove it.
277 rv = mUpdatingDirectory->Remove(true);
278 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
279 // If the "safebrowsing-updating" exists, it implies a crash occurred
280 // in the previous update.
281 LOG(("We may have hit a crash in the previous update."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "We may have hit a crash in the previous update."
); } } while (0)
;
282 }
283
284 // Check whether we have an incomplete update and recover from the
285 // backup if so.
286 rv = RecoverBackups();
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/Classifier.cpp"
, 287); return rv; } } while (false)
;
288
289 // Make sure the main store directory exists.
290 rv = CreateStoreDirectory();
291 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/Classifier.cpp"
, 291); return rv; } } while (false)
;
292
293 rv = ClearLegacyFiles();
294 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/Classifier.cpp"
, 294)
;
295
296 // Build the list of know urlclassifier lists
297 // XXX: Disk IO potentially on the main thread during startup
298 RegenActiveTables();
299
300 return NS_OK;
301}
302
303void Classifier::Close() {
304 // Close will be called by PreShutdown, so it is important to note that
305 // things put here should not affect an ongoing update thread.
306 mIsClosed = true;
307 DropStores();
308}
309
310void Classifier::Reset() {
311 MOZ_ASSERT(!OnUpdateThread(), "Reset() MUST NOT be called on update thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "Reset() MUST NOT be called on update thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "Reset() MUST NOT be called on update thread" ")"); do
{ *((volatile int*)__null) = 311; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
312
313 LOG(("Reset() is called so we interrupt the update."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Reset() is called so we interrupt the update."
); } } while (0)
;
314 mUpdateInterrupted = true;
315
316 // We don't pass the ref counted object 'Classifier' to resetFunc because we
317 // don't want to release 'Classifier in the update thread, which triggers an
318 // assertion when LazyIdelUpdate thread is not created and removed by the same
319 // thread (worker thread). Since |resetFuc| is a synchronous call, we can just
320 // pass the reference of Classifier because Classifier's life cycle is
321 // guarantee longer than |resetFunc|.
322 auto resetFunc = [&] {
323 if (this->mIsClosed) {
324 return; // too late to reset, bail
325 }
326 this->DropStores();
327
328 this->mRootStoreDirectory->Remove(true);
329 this->mBackupDirectory->Remove(true);
330 this->mUpdatingDirectory->Remove(true);
331 this->mToDeleteDirectory->Remove(true);
332
333 this->CreateStoreDirectory();
334 this->RegenActiveTables();
335 };
336
337 if (!mUpdateThread) {
338 LOG(("Async update has been disabled. Just Reset() on worker thread."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Async update has been disabled. Just Reset() on worker thread."
); } } while (0)
;
339 resetFunc();
340 return;
341 }
342
343 nsCOMPtr<nsIRunnable> r =
344 NS_NewRunnableFunction("safebrowsing::Classifier::Reset", resetFunc);
345 SyncRunnable::DispatchToThread(mUpdateThread, r);
346}
347
348void Classifier::ResetTables(ClearType aType,
349 const nsTArray<nsCString>& aTables) {
350 for (uint32_t i = 0; i < aTables.Length(); i++) {
351 LOG(("Resetting table: %s", aTables[i].get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Resetting table: %s"
, aTables[i].get()); } } while (0)
;
352 RefPtr<LookupCache> cache = GetLookupCache(aTables[i]);
353 if (cache) {
354 // Remove any cached Completes for this table if clear type is Clear_Cache
355 if (aType == Clear_Cache) {
356 cache->ClearCache();
357 } else {
358 cache->ClearAll();
359 }
360 }
361 }
362
363 // Clear on-disk database if clear type is Clear_All
364 if (aType == Clear_All) {
365 DeleteTables(mRootStoreDirectory, aTables);
366
367 RegenActiveTables();
368 }
369}
370
371// |DeleteTables| is used by |GetLookupCache| to remove on-disk data when
372// we detect prefix file corruption. So make sure not to call |GetLookupCache|
373// again in this function to avoid infinite loop.
374void Classifier::DeleteTables(nsIFile* aDirectory,
375 const nsTArray<nsCString>& aTables) {
376 nsCOMPtr<nsIDirectoryEnumerator> entries;
377 nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
378 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 378); return; } } while (false)
;
379
380 nsCOMPtr<nsIFile> file;
381 while (NS_SUCCEEDED(rv = entries->GetNextFile(getter_AddRefs(file)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv = entries->
GetNextFile(getter_AddRefs(file)))), 1)))
&&
382 file) {
383 // If |file| is a directory, recurse to find its entries as well.
384 bool isDirectory;
385 if (NS_FAILED(file->IsDirectory(&isDirectory))((bool)(__builtin_expect(!!(NS_FAILED_impl(file->IsDirectory
(&isDirectory))), 0)))
) {
386 continue;
387 }
388 if (isDirectory) {
389 DeleteTables(file, aTables);
390 continue;
391 }
392
393 nsCString leafName;
394 rv = file->GetNativeLeafName(leafName);
395 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 395); return; } } while (false)
;
396
397 // Remove file extension if there's one.
398 int32_t dotPosition = leafName.RFind(".");
399 if (dotPosition >= 0) {
400 leafName.Truncate(dotPosition);
401 }
402
403 if (!leafName.IsEmpty() && aTables.Contains(leafName)) {
404 if (NS_FAILED(file->Remove(false))((bool)(__builtin_expect(!!(NS_FAILED_impl(file->Remove(false
))), 0)))
) {
405 NS_WARNING(nsPrintfCString("Fail to remove file %s from the disk",NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Fail to remove file %s from the disk"
, leafName.get()) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 407)
406 leafName.get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Fail to remove file %s from the disk"
, leafName.get()) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 407)
407 .get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString("Fail to remove file %s from the disk"
, leafName.get()) .get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 407)
;
408 }
409 }
410 }
411 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 411); return; } } while (false)
;
412}
413
414// This function is I/O intensive. It should only be called before applying
415// an update.
416void Classifier::TableRequest(nsACString& aResult) {
417 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()"
" (" "TableRequest must be called on the classifier worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 418); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "TableRequest must be called on the classifier worker thread."
")"); do { *((volatile int*)__null) = 418; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
418 "TableRequest must be called on the classifier worker 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()"
" (" "TableRequest must be called on the classifier worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 418); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "TableRequest must be called on the classifier worker thread."
")"); do { *((volatile int*)__null) = 418; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
419
420 // This function and all disk I/O are guaranteed to occur
421 // on the same thread so we don't need to add a lock around.
422 if (!mIsTableRequestResultOutdated) {
423 aResult = mTableRequestResult;
424 return;
425 }
426
427 // We reset tables failed to load here; not just tables are corrupted.
428 // It is because this is a safer way to ensure Safe Browsing databases
429 // can be recovered from any bad situations.
430 nsTArray<nsCString> failedTables;
431
432 // Load meta data from *.sbstore files in the root directory.
433 // Specifically for v4 tables.
434 nsCString v2Metadata;
435 nsresult rv = LoadHashStore(mRootStoreDirectory, v2Metadata, failedTables);
436 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
437 aResult.Append(v2Metadata);
438 }
439
440 // Load meta data from *.metadata files in the root directory.
441 // Specifically for v4 tables.
442 nsCString v4Metadata;
443 rv = LoadMetadata(mRootStoreDirectory, v4Metadata, failedTables);
444 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
445 aResult.Append(v4Metadata);
446 }
447
448 // Clear data for tables that we failed to open, a full update should
449 // be requested for those tables.
450 if (failedTables.Length() != 0) {
451 LOG(("Reset tables failed to open before applying an update"))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Reset tables failed to open before applying an update"
); } } while (0)
;
452 ResetTables(Clear_All, failedTables);
453 }
454
455 // Update the TableRequest result in-memory cache.
456 mTableRequestResult = aResult;
457 mIsTableRequestResultOutdated = false;
458}
459
460nsresult Classifier::CheckURIFragments(
461 const nsTArray<nsCString>& aSpecFragments, const nsACString& aTable,
462 LookupResultArray& aResults) {
463 // A URL can form up to 30 different fragments
464 MOZ_ASSERT(aSpecFragments.Length() != 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSpecFragments.Length() != 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSpecFragments.Length() != 0
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aSpecFragments.Length() != 0", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 464); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSpecFragments.Length() != 0"
")"); do { *((volatile int*)__null) = 464; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
465 MOZ_ASSERT(aSpecFragments.Length() <=do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSpecFragments.Length() <= (5 * (4 + 2)))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aSpecFragments.Length() <= (5 * (4 + 2))))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aSpecFragments.Length() <= (5 * (4 + 2))"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSpecFragments.Length() <= (5 * (4 + 2))"
")"); do { *((volatile int*)__null) = 466; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
466 (MAX_HOST_COMPONENTS * (MAX_PATH_COMPONENTS + 2)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSpecFragments.Length() <= (5 * (4 + 2)))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aSpecFragments.Length() <= (5 * (4 + 2))))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aSpecFragments.Length() <= (5 * (4 + 2))"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSpecFragments.Length() <= (5 * (4 + 2))"
")"); do { *((volatile int*)__null) = 466; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
467
468 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(gUrlClassifierDbServiceLog
, mozilla::LogLevel::Debug)), 0))
) {
469 uint32_t urlIdx = 0;
470 for (uint32_t i = 1; i < aSpecFragments.Length(); i++) {
471 if (aSpecFragments[urlIdx].Length() < aSpecFragments[i].Length()) {
472 urlIdx = i;
473 }
474 }
475 LOG(("Checking table %s, URL is %s", aTable.BeginReading(),do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Checking table %s, URL is %s"
, aTable.BeginReading(), aSpecFragments[urlIdx].get()); } } while
(0)
476 aSpecFragments[urlIdx].get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Checking table %s, URL is %s"
, aTable.BeginReading(), aSpecFragments[urlIdx].get()); } } while
(0)
;
477 }
478
479 RefPtr<LookupCache> cache = GetLookupCache(aTable);
480 if (NS_WARN_IF(!cache)NS_warn_if_impl(!cache, "!cache", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 480)
) {
481 return NS_ERROR_FAILURE;
482 }
483
484 // Now check each lookup fragment against the entries in the DB.
485 for (uint32_t i = 0; i < aSpecFragments.Length(); i++) {
486 Completion lookupHash;
487 lookupHash.FromPlaintext(aSpecFragments[i]);
488
489 bool has, confirmed;
490 uint32_t matchLength;
491
492 nsresult rv = cache->Has(lookupHash, &has, &matchLength, &confirmed);
493 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/Classifier.cpp"
, 493); return rv; } } while (false)
;
494
495 if (has) {
496 RefPtr<LookupResult> result = new LookupResult;
497 aResults.AppendElement(result);
498
499 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(gUrlClassifierDbServiceLog
, mozilla::LogLevel::Debug)), 0))
) {
500 nsAutoCString checking;
501 lookupHash.ToHexString(checking);
502 LOG(("Found a result in fragment %s, hash %s (%X)",do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Found a result in fragment %s, hash %s (%X)"
, aSpecFragments[i].get(), checking.get(), lookupHash.ToUint32
()); } } while (0)
503 aSpecFragments[i].get(), checking.get(), lookupHash.ToUint32()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Found a result in fragment %s, hash %s (%X)"
, aSpecFragments[i].get(), checking.get(), lookupHash.ToUint32
()); } } while (0)
;
504 LOG(("Result %s, match %d-bytes prefix",do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Result %s, match %d-bytes prefix"
, confirmed ? "confirmed." : "Not confirmed.", matchLength); }
} while (0)
505 confirmed ? "confirmed." : "Not confirmed.", matchLength))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Result %s, match %d-bytes prefix"
, confirmed ? "confirmed." : "Not confirmed.", matchLength); }
} while (0)
;
506 }
507
508 result->hash.complete = lookupHash;
509 result->mConfirmed = confirmed;
510 result->mTableName.Assign(cache->TableName());
511 result->mPartialHashLength = confirmed ? COMPLETE_SIZE32 : matchLength;
512 result->mProtocolV2 = LookupCache::Cast<LookupCacheV2>(cache);
513 }
514 }
515
516 return NS_OK;
517}
518
519static nsresult SwapDirectoryContent(nsIFile* aDir1, nsIFile* aDir2,
520 nsIFile* aParentDir, nsIFile* aTempDir) {
521 // Pre-condition: |aDir1| and |aDir2| are directory and their parent
522 // are both |aParentDir|.
523 //
524 // Post-condition: The locations where aDir1 and aDir2 point to will not
525 // change but their contents will be exchanged. If we failed
526 // to swap their content, everything will be rolled back.
527
528 nsAutoCString tempDirName;
529 aTempDir->GetNativeLeafName(tempDirName);
530
531 nsresult rv;
532
533 nsAutoCString dirName1, dirName2;
534 aDir1->GetNativeLeafName(dirName1);
535 aDir2->GetNativeLeafName(dirName2);
536
537 LOG(("Swapping directories %s and %s...", dirName1.get(), dirName2.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Swapping directories %s and %s..."
, dirName1.get(), dirName2.get()); } } while (0)
;
538
539 // 1. Rename "dirName1" to "temp"
540 rv = aDir1->RenameToNative(nullptr, tempDirName);
541 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
542 LOG(("Unable to rename %s to %s", dirName1.get(), tempDirName.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Unable to rename %s to %s"
, dirName1.get(), tempDirName.get()); } } while (0)
;
543 return rv; // Nothing to roll back.
544 }
545
546 // 1.1. Create a handle for temp directory. This is required since
547 // |nsIFile.rename| will not change the location where the
548 // object points to.
549 nsCOMPtr<nsIFile> tempDirectory;
550 rv = aParentDir->Clone(getter_AddRefs(tempDirectory));
Value stored to 'rv' is never read
551 rv = tempDirectory->AppendNative(tempDirName);
552
553 // 2. Rename "dirName2" to "dirName1".
554 rv = aDir2->RenameToNative(nullptr, dirName1);
555 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
556 LOG(("Failed to rename %s to %s. Rename temp directory back to %s",do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to rename %s to %s. Rename temp directory back to %s"
, dirName2.get(), dirName1.get(), dirName1.get()); } } while (
0)
557 dirName2.get(), dirName1.get(), dirName1.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to rename %s to %s. Rename temp directory back to %s"
, dirName2.get(), dirName1.get(), dirName1.get()); } } while (
0)
;
558 nsresult rbrv = tempDirectory->RenameToNative(nullptr, dirName1);
559 NS_ENSURE_SUCCESS(rbrv, rbrv)do { nsresult __rv = rbrv; 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", "rbrv", "rbrv", 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/Classifier.cpp"
, 559); return rbrv; } } while (false)
;
560 return rv;
561 }
562
563 // 3. Rename "temp" to "dirName2".
564 rv = tempDirectory->RenameToNative(nullptr, dirName2);
565 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
566 LOG(("Failed to rename temp directory to %s. ", dirName2.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to rename temp directory to %s. "
, dirName2.get()); } } while (0)
;
567 // We've done (1) renaming "dir1 to temp" and
568 // (2) renaming "dir2 to dir1"
569 // so the rollback is
570 // (1) renaming "dir1 to dir2" and
571 // (2) renaming "temp to dir1"
572 nsresult rbrv; // rollback result
573 rbrv = aDir1->RenameToNative(nullptr, dirName2);
574 NS_ENSURE_SUCCESS(rbrv, rbrv)do { nsresult __rv = rbrv; 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", "rbrv", "rbrv", 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/Classifier.cpp"
, 574); return rbrv; } } while (false)
;
575 rbrv = tempDirectory->RenameToNative(nullptr, dirName1);
576 NS_ENSURE_SUCCESS(rbrv, rbrv)do { nsresult __rv = rbrv; 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", "rbrv", "rbrv", 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/Classifier.cpp"
, 576); return rbrv; } } while (false)
;
577 return rv;
578 }
579
580 return rv;
581}
582
583void Classifier::RemoveUpdateIntermediaries() {
584 // Remove old LookupCaches.
585 mNewLookupCaches.Clear();
586
587 // Remove the "old" directory. (despite its looking-new name)
588 if (NS_FAILED(mUpdatingDirectory->Remove(true))((bool)(__builtin_expect(!!(NS_FAILED_impl(mUpdatingDirectory
->Remove(true))), 0)))
) {
589 // If the directory is locked from removal for some reason,
590 // we will fail here and it doesn't matter until the next
591 // update. (the next udpate will fail due to the removable
592 // "safebrowsing-udpating" directory.)
593 LOG(("Failed to remove updating directory."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to remove updating directory."
); } } while (0)
;
594 }
595}
596
597void Classifier::CopyAndInvalidateFullHashCache() {
598 MOZ_ASSERT(!OnUpdateThread(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "CopyAndInvalidateFullHashCache cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "CopyAndInvalidateFullHashCache cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")"); do { *((volatile int*)__null) = 601; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
599 "CopyAndInvalidateFullHashCache cannot be called on update thread "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "CopyAndInvalidateFullHashCache cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "CopyAndInvalidateFullHashCache cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")"); do { *((volatile int*)__null) = 601; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
600 "since it mutates mLookupCaches which is only safe on "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "CopyAndInvalidateFullHashCache cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "CopyAndInvalidateFullHashCache cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")"); do { *((volatile int*)__null) = 601; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
601 "worker thread.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "CopyAndInvalidateFullHashCache cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "CopyAndInvalidateFullHashCache cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")"); do { *((volatile int*)__null) = 601; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
602
603 // New lookup caches are built from disk, data likes cache which is
604 // generated online won't exist. We have to manually copy cache from
605 // old LookupCache to new LookupCache.
606 for (auto& newCache : mNewLookupCaches) {
607 for (auto& oldCache : mLookupCaches) {
608 if (oldCache->TableName() == newCache->TableName()) {
609 newCache->CopyFullHashCache(oldCache);
610 break;
611 }
612 }
613 }
614
615 // Clear cache when update.
616 // Invalidate cache entries in CopyAndInvalidateFullHashCache because only
617 // at this point we will have cache data in LookupCache.
618 for (auto& newCache : mNewLookupCaches) {
619 newCache->InvalidateExpiredCacheEntries();
620 }
621}
622
623void Classifier::MergeNewLookupCaches() {
624 MOZ_ASSERT(!OnUpdateThread(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "MergeNewLookupCaches cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "MergeNewLookupCaches cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")"); do { *((volatile int*)__null) = 627; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
625 "MergeNewLookupCaches cannot be called on update thread "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "MergeNewLookupCaches cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "MergeNewLookupCaches cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")"); do { *((volatile int*)__null) = 627; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
626 "since it mutates mLookupCaches which is only safe on "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "MergeNewLookupCaches cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "MergeNewLookupCaches cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")"); do { *((volatile int*)__null) = 627; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
627 "worker thread.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "MergeNewLookupCaches cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "MergeNewLookupCaches cannot be called on update thread "
"since it mutates mLookupCaches which is only safe on " "worker thread."
")"); do { *((volatile int*)__null) = 627; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
628
629 for (auto& newCache : mNewLookupCaches) {
630 // For each element in mNewLookCaches, it will be swapped with
631 // - An old cache in mLookupCache with the same table name or
632 // - nullptr (mLookupCache will be expaned) otherwise.
633 size_t swapIndex = 0;
634 for (; swapIndex < mLookupCaches.Length(); swapIndex++) {
635 if (mLookupCaches[swapIndex]->TableName() == newCache->TableName()) {
636 break;
637 }
638 }
639 if (swapIndex == mLookupCaches.Length()) {
640 mLookupCaches.AppendElement(nullptr);
641 }
642
643 std::swap(mLookupCaches[swapIndex], newCache);
644 mLookupCaches[swapIndex]->UpdateRootDirHandle(mRootStoreDirectory);
645 }
646
647 // At this point, mNewLookupCaches's length remains the same but
648 // will contain either old cache (override) or nullptr (append).
649}
650
651nsresult Classifier::SwapInNewTablesAndCleanup() {
652 nsresult rv;
653
654 // Step 1. Swap in on-disk tables. The idea of using "safebrowsing-backup"
655 // as the intermediary directory is we can get databases recovered if
656 // crash occurred in any step of the swap. (We will recover from
657 // "safebrowsing-backup" in OpenDb().)
658 rv = SwapDirectoryContent(mUpdatingDirectory, // contains new tables
659 mRootStoreDirectory, // contains old tables
660 mCacheDirectory, // common parent dir
661 mBackupDirectory); // intermediary dir for swap
662 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
663 LOG(("Failed to swap in on-disk tables."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to swap in on-disk tables."
); } } while (0)
;
664 RemoveUpdateIntermediaries();
665 return rv;
666 }
667
668 // Step 2. Merge mNewLookupCaches into mLookupCaches. The outdated
669 // LookupCaches will be stored in mNewLookupCaches and be cleaned
670 // up later.
671 MergeNewLookupCaches();
672
673 // Step 3. Re-generate active tables based on on-disk tables.
674 rv = RegenActiveTables();
675 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
676 LOG(("Failed to re-generate active tables!"))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to re-generate active tables!"
); } } while (0)
;
677 }
678
679 // Step 4. Clean up intermediaries for update.
680 RemoveUpdateIntermediaries();
681
682 // Step 5. Invalidate cached tableRequest request.
683 mIsTableRequestResultOutdated = true;
684
685 LOG(("Done swap in updated tables."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Done swap in updated tables."
); } } while (0)
;
686
687 return rv;
688}
689
690void Classifier::FlushAndDisableAsyncUpdate() {
691 LOG(("Classifier::FlushAndDisableAsyncUpdate [%p, %p]", this,do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Classifier::FlushAndDisableAsyncUpdate [%p, %p]"
, this, mUpdateThread.get()); } } while (0)
692 mUpdateThread.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Classifier::FlushAndDisableAsyncUpdate [%p, %p]"
, this, mUpdateThread.get()); } } while (0)
;
693
694 if (!mUpdateThread) {
695 LOG(("Async update has been disabled."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Async update has been disabled."
); } } while (0)
;
696 return;
697 }
698
699 mUpdateThread->Shutdown();
700 mUpdateThread = nullptr;
701 mPendingUpdates.Clear();
702 mAsyncUpdateInProgress = false;
703}
704
705nsresult Classifier::AsyncApplyUpdates(const TableUpdateArray& aUpdates,
706 const AsyncUpdateCallback& aCallback) {
707 LOG(("Classifier::AsyncApplyUpdates"))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Classifier::AsyncApplyUpdates"
); } } while (0)
;
708
709 if (!mUpdateThread) {
710 LOG(("Async update has already been disabled."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Async update has already been disabled."
); } } while (0)
;
711 return NS_ERROR_FAILURE;
712 }
713
714 if (mAsyncUpdateInProgress) {
715 mPendingUpdates.AppendElement(NS_NewRunnableFunction(
716 "safebrowsing::Classifier::AsyncApplyUpdates",
717 [self = RefPtr{this}, aUpdates = aUpdates.Clone(),
718 aCallback]() mutable {
719 nsresult rv = self->AsyncApplyUpdates(aUpdates, aCallback);
720
721 // Calling the callback if we got an failure here to notify update
722 // observers.
723 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
724 aCallback(rv);
725 }
726 }));
727 return NS_OK;
728 }
729
730 // Caller thread | Update thread
731 // --------------------------------------------------------
732 // | ApplyUpdatesBackground
733 // (processing other task) | (bg-update done. ping back to caller
734 // thread) (processing other task) | idle... ApplyUpdatesForeground |
735 // callback |
736
737 MOZ_ASSERT(mNewLookupCaches.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mNewLookupCaches.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mNewLookupCaches.IsEmpty()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mNewLookupCaches.IsEmpty()"
" (" "There should be no leftovers from a previous update." ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 738); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mNewLookupCaches.IsEmpty()"
") (" "There should be no leftovers from a previous update."
")"); do { *((volatile int*)__null) = 738; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
738 "There should be no leftovers from a previous update.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mNewLookupCaches.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mNewLookupCaches.IsEmpty()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mNewLookupCaches.IsEmpty()"
" (" "There should be no leftovers from a previous update." ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 738); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mNewLookupCaches.IsEmpty()"
") (" "There should be no leftovers from a previous update."
")"); do { *((volatile int*)__null) = 738; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
739
740 mAsyncUpdateInProgress = true;
741 mUpdateInterrupted = false;
742 nsresult rv =
743 mRootStoreDirectory->Clone(getter_AddRefs(mRootStoreDirectoryForUpdate));
744 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
745 LOG(("Failed to clone mRootStoreDirectory for update."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to clone mRootStoreDirectory for update."
); } } while (0)
;
746 return rv;
747 }
748
749 nsCOMPtr<nsIThread> callerThread = NS_GetCurrentThread();
750 MOZ_ASSERT(!OnUpdateThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
")"); do { *((volatile int*)__null) = 750; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
751
752 RefPtr<Classifier> self = this;
753 nsCOMPtr<nsIRunnable> bgRunnable = NS_NewRunnableFunction(
754 "safebrowsing::Classifier::AsyncApplyUpdates",
755 [self, aUpdates = aUpdates.Clone(), aCallback, callerThread]() mutable {
756 MOZ_ASSERT(self->OnUpdateThread(), "MUST be on update thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(self->OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(self->OnUpdateThread())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("self->OnUpdateThread()"
" (" "MUST be on update thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->OnUpdateThread()"
") (" "MUST be on update thread" ")"); do { *((volatile int*
)__null) = 756; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
757
758 nsresult bgRv;
759 nsTArray<nsCString> failedTableNames;
760
761 TableUpdateArray updates;
762
763 // Make a copy of the array since we'll be removing entries as
764 // we process them on the background thread.
765 if (updates.AppendElements(std::move(aUpdates), fallible)) {
766 LOG(("Step 1. ApplyUpdatesBackground on update thread."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Step 1. ApplyUpdatesBackground on update thread."
); } } while (0)
;
767 bgRv = self->ApplyUpdatesBackground(updates, failedTableNames);
768 } else {
769 LOG(do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Step 1. Not enough memory to run ApplyUpdatesBackground on "
"update thread."); } } while (0)
770 ("Step 1. Not enough memory to run ApplyUpdatesBackground on "do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Step 1. Not enough memory to run ApplyUpdatesBackground on "
"update thread."); } } while (0)
771 "update thread."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Step 1. Not enough memory to run ApplyUpdatesBackground on "
"update thread."); } } while (0)
;
772 bgRv = NS_ERROR_OUT_OF_MEMORY;
773 }
774
775 // Classifier is created in the worker thread and it has to be released
776 // in the worker thread(because of the constrain that LazyIdelThread has
777 // to be created and released in the same thread). We transfer the
778 // ownership to the caller thread here to gurantee that we don't release
779 // it in the udpate thread.
780 nsCOMPtr<nsIRunnable> fgRunnable = NS_NewRunnableFunction(
781 "safebrowsing::Classifier::AsyncApplyUpdates",
782 [self = std::move(self), aCallback, bgRv,
783 failedTableNames = std::move(failedTableNames),
784 callerThread]() mutable {
785 RefPtr<Classifier> classifier = std::move(self);
786
787 MOZ_ASSERT(NS_GetCurrentThread() == callerThread,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_GetCurrentThread() == callerThread)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(NS_GetCurrentThread() == callerThread))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("NS_GetCurrentThread() == callerThread"
" (" "MUST be on caller thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_GetCurrentThread() == callerThread"
") (" "MUST be on caller thread" ")"); do { *((volatile int*
)__null) = 788; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
788 "MUST be on caller thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_GetCurrentThread() == callerThread)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(NS_GetCurrentThread() == callerThread))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("NS_GetCurrentThread() == callerThread"
" (" "MUST be on caller thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_GetCurrentThread() == callerThread"
") (" "MUST be on caller thread" ")"); do { *((volatile int*
)__null) = 788; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
789
790 LOG(("Step 2. ApplyUpdatesForeground on caller thread"))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Step 2. ApplyUpdatesForeground on caller thread"
); } } while (0)
;
791 nsresult rv =
792 classifier->ApplyUpdatesForeground(bgRv, failedTableNames);
793
794 LOG(("Step 3. Updates applied! Fire callback."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Step 3. Updates applied! Fire callback."
); } } while (0)
;
795 aCallback(rv);
796
797 classifier->AsyncUpdateFinished();
798 });
799
800 callerThread->Dispatch(fgRunnable, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
801 });
802
803 return mUpdateThread->Dispatch(bgRunnable, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
804}
805
806void Classifier::AsyncUpdateFinished() {
807 MOZ_ASSERT(!OnUpdateThread(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "AsyncUpdateFinished() MUST NOT be called on update thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 808); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "AsyncUpdateFinished() MUST NOT be called on update thread"
")"); do { *((volatile int*)__null) = 808; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
808 "AsyncUpdateFinished() MUST NOT be called on update thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "AsyncUpdateFinished() MUST NOT be called on update thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 808); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "AsyncUpdateFinished() MUST NOT be called on update thread"
")"); do { *((volatile int*)__null) = 808; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
809 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()"
" (" "AsyncUpdateFinished() must be called on the worker thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "AsyncUpdateFinished() must be called on the worker thread"
")"); do { *((volatile int*)__null) = 810; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
810 "AsyncUpdateFinished() must be called on the worker 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()"
" (" "AsyncUpdateFinished() must be called on the worker thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "AsyncUpdateFinished() must be called on the worker thread"
")"); do { *((volatile int*)__null) = 810; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
811
812 mAsyncUpdateInProgress = false;
813
814 // If there are pending updates, run the first one.
815 if (!mPendingUpdates.IsEmpty()) {
816 auto& runnable = mPendingUpdates.ElementAt(0);
817 runnable->Run();
818 mPendingUpdates.RemoveElementAt(0);
819 }
820}
821
822nsresult Classifier::ApplyUpdatesBackground(
823 TableUpdateArray& aUpdates, nsTArray<nsCString>& aFailedTableNames) {
824 // |mUpdateInterrupted| is guaranteed to have been unset.
825 // If |mUpdateInterrupted| is set at any point, Reset() must have
826 // been called then we need to interrupt the update process.
827 // We only add checkpoints for non-trivial tasks.
828
829 if (aUpdates.IsEmpty()) {
830 return NS_OK;
831 }
832
833 nsUrlClassifierUtils* urlUtil = nsUrlClassifierUtils::GetInstance();
834 if (NS_WARN_IF(!urlUtil)NS_warn_if_impl(!urlUtil, "!urlUtil", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 834)
) {
835 return NS_ERROR_FAILURE;
836 }
837
838 nsCString provider;
839 // Assume all TableUpdate objects should have the same provider.
840 urlUtil->GetTelemetryProvider(aUpdates[0]->TableName(), provider);
841
842 Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_CL_KEYED_UPDATE_TIME>
843 keyedTimer(provider);
844
845 PRIntervalTime clockStart = 0;
846 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(gUrlClassifierDbServiceLog
, mozilla::LogLevel::Debug)), 0))
) {
847 clockStart = PR_IntervalNow();
848 }
849
850 nsresult rv;
851
852 // Check point 1: Copying files takes time so we check ShouldAbort()
853 // inside CopyInUseDirForUpdate().
854 rv = CopyInUseDirForUpdate(); // i.e. mUpdatingDirectory will be setup.
855 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
856 LOG(("Failed to copy in-use directory for update."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to copy in-use directory for update."
); } } while (0)
;
857 return (rv == NS_ERROR_ABORT) ? NS_OK : rv;
858 }
859
860 LOG(("Applying %zu table updates.", aUpdates.Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Applying %zu table updates."
, aUpdates.Length()); } } while (0)
;
861
862 for (uint32_t i = 0; i < aUpdates.Length(); i++) {
863 RefPtr<const TableUpdate> update = aUpdates[i];
864 if (!update) {
865 // Previous UpdateHashStore() may have consumed this update..
866 continue;
867 }
868
869 // Run all updates for one table
870 nsAutoCString updateTable(update->TableName());
871
872 // Check point 2: Processing downloaded data takes time.
873 if (ShouldAbort()) {
874 LOG(("Update is interrupted. Stop building new tables."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Update is interrupted. Stop building new tables."
); } } while (0)
;
875 return NS_OK;
876 }
877
878 // Will update the mirrored in-memory and on-disk databases.
879 if (TableUpdate::Cast<TableUpdateV2>(update)) {
880 rv = UpdateHashStore(aUpdates, updateTable);
881 } else {
882 rv = UpdateTableV4(aUpdates, updateTable);
883 }
884
885 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 885)
) {
886 LOG(("Failed to update table: %s", updateTable.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to update table: %s"
, updateTable.get()); } } while (0)
;
887 // We don't quit the updating process immediately when we discover
888 // a failure. Instead, we continue to apply updates to the
889 // remaining tables to find other tables which may also fail to
890 // apply an update. This help us reset all the corrupted tables
891 // within a single update.
892 // Note that changes that result from successful updates don't take
893 // effect after the updating process is finished. This is because
894 // when an error occurs during the updating process, we ignore all
895 // changes that have happened during the udpating process.
896 aFailedTableNames.AppendElement(updateTable);
897 continue;
898 }
899 }
900
901 if (!aFailedTableNames.IsEmpty()) {
902 RemoveUpdateIntermediaries();
903 return NS_ERROR_FAILURE;
904 }
905
906 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(gUrlClassifierDbServiceLog
, mozilla::LogLevel::Debug)), 0))
) {
907 PRIntervalTime clockEnd = PR_IntervalNow();
908 LOG(("update took %dms\n",do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "update took %dms\n"
, PR_IntervalToMilliseconds(clockEnd - clockStart)); } } while
(0)
909 PR_IntervalToMilliseconds(clockEnd - clockStart)))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "update took %dms\n"
, PR_IntervalToMilliseconds(clockEnd - clockStart)); } } while
(0)
;
910 }
911
912 return rv;
913}
914
915nsresult Classifier::ApplyUpdatesForeground(
916 nsresult aBackgroundRv, const nsTArray<nsCString>& aFailedTableNames) {
917 if (ShouldAbort()) {
918 LOG(("Update is interrupted! Just remove update intermediaries."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Update is interrupted! Just remove update intermediaries."
); } } while (0)
;
919 RemoveUpdateIntermediaries();
920 return NS_OK;
921 }
922 if (NS_SUCCEEDED(aBackgroundRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aBackgroundRv)), 1
)))
) {
923 // Copy and Invalidate fullhash cache here because this call requires
924 // mLookupCaches which is only available on work-thread
925 CopyAndInvalidateFullHashCache();
926
927 return SwapInNewTablesAndCleanup();
928 }
929 if (NS_ERROR_OUT_OF_MEMORY != aBackgroundRv) {
930 ResetTables(Clear_All, aFailedTableNames);
931 }
932 return aBackgroundRv;
933}
934
935nsresult Classifier::ApplyFullHashes(ConstTableUpdateArray& aUpdates) {
936 MOZ_ASSERT(!OnUpdateThread(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "ApplyFullHashes() MUST NOT be called on update thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 937); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "ApplyFullHashes() MUST NOT be called on update thread"
")"); do { *((volatile int*)__null) = 937; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
937 "ApplyFullHashes() MUST NOT be called on update thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!OnUpdateThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!OnUpdateThread()"
" (" "ApplyFullHashes() MUST NOT be called on update thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 937); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!OnUpdateThread()"
") (" "ApplyFullHashes() MUST NOT be called on update thread"
")"); do { *((volatile int*)__null) = 937; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
938 MOZ_ASSERT(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()"
" (" "ApplyFullHashes() must be called on the classifier worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "ApplyFullHashes() must be called on the classifier worker thread."
")"); do { *((volatile int*)__null) = 940; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
939 !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()"
" (" "ApplyFullHashes() must be called on the classifier worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "ApplyFullHashes() must be called on the classifier worker thread."
")"); do { *((volatile int*)__null) = 940; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
940 "ApplyFullHashes() must be called on the classifier worker 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()"
" (" "ApplyFullHashes() must be called on the classifier worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "ApplyFullHashes() must be called on the classifier worker thread."
")"); do { *((volatile int*)__null) = 940; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
941
942 LOG(("Applying %zu table gethashes.", aUpdates.Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Applying %zu table gethashes."
, aUpdates.Length()); } } while (0)
;
943
944 for (uint32_t i = 0; i < aUpdates.Length(); i++) {
945 nsresult rv = UpdateCache(aUpdates[i]);
946 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/Classifier.cpp"
, 946); return rv; } } while (false)
;
947
948 aUpdates[i] = nullptr;
949 }
950
951 return NS_OK;
952}
953
954void Classifier::GetCacheInfo(const nsACString& aTable,
955 nsIUrlClassifierCacheInfo** aCache) {
956 RefPtr<const LookupCache> lookupCache = GetLookupCache(aTable);
957 if (!lookupCache) {
958 return;
959 }
960
961 lookupCache->GetCacheInfo(aCache);
962}
963
964void Classifier::DropStores() {
965 // See the comment in Classifier::Close() before adding anything here.
966 mLookupCaches.Clear();
967}
968
969nsresult Classifier::RegenActiveTables() {
970 if (ShouldAbort()) {
971 return NS_OK; // nothing to do, the classifier is done
972 }
973
974 mActiveTablesCache.Clear();
975
976 // The extension of V2 and V4 prefix files is .vlpset
977 // We still check .pset here for legacy load.
978 nsTArray<nsCString> exts = {".vlpset"_ns, ".pset"_ns};
979 nsTArray<nsCString> foundTables;
980 nsresult rv = ScanStoreDir(mRootStoreDirectory, exts, foundTables);
981 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/Classifier.cpp"
, 981)
;
982
983 // We don't have test tables on disk, add Moz built-in entries here
984 rv = AddMozEntries(foundTables);
985 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/Classifier.cpp"
, 985)
;
986
987 for (const auto& table : foundTables) {
988 RefPtr<const LookupCache> lookupCache = GetLookupCache(table);
989 if (!lookupCache) {
990 LOG(("Inactive table (no cache): %s", table.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Inactive table (no cache): %s"
, table.get()); } } while (0)
;
991 continue;
992 }
993
994 if (!lookupCache->IsPrimed()) {
995 LOG(("Inactive table (cache not primed): %s", table.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Inactive table (cache not primed): %s"
, table.get()); } } while (0)
;
996 continue;
997 }
998
999 LOG(("Active %s table: %s",do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Active %s table: %s"
, LookupCache::Cast<const LookupCacheV4>(lookupCache) ?
"v4" : "v2", table.get()); } } while (0)
1000 LookupCache::Cast<const LookupCacheV4>(lookupCache) ? "v4" : "v2",do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Active %s table: %s"
, LookupCache::Cast<const LookupCacheV4>(lookupCache) ?
"v4" : "v2", table.get()); } } while (0)
1001 table.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Active %s table: %s"
, LookupCache::Cast<const LookupCacheV4>(lookupCache) ?
"v4" : "v2", table.get()); } } while (0)
;
1002
1003 mActiveTablesCache.AppendElement(table);
1004 }
1005
1006 return NS_OK;
1007}
1008
1009nsresult Classifier::AddMozEntries(nsTArray<nsCString>& aTables) {
1010 nsTArray<nsLiteralCString> tables = {
1011 "moztest-phish-simple"_ns, "moztest-malware-simple"_ns,
1012 "moztest-unwanted-simple"_ns, "moztest-harmful-simple"_ns,
1013 "moztest-track-simple"_ns, "moztest-trackwhite-simple"_ns,
1014 "moztest-block-simple"_ns,
1015 };
1016
1017 for (const auto& table : tables) {
1018 RefPtr<LookupCache> c = GetLookupCache(table, false);
1019 RefPtr<LookupCacheV2> lookupCache = LookupCache::Cast<LookupCacheV2>(c);
1020 if (!lookupCache || lookupCache->IsPrimed()) {
1021 continue;
1022 }
1023
1024 aTables.AppendElement(table);
1025 }
1026
1027 return NS_OK;
1028}
1029
1030nsresult Classifier::ScanStoreDir(nsIFile* aDirectory,
1031 const nsTArray<nsCString>& aExtensions,
1032 nsTArray<nsCString>& aTables) {
1033 nsCOMPtr<nsIDirectoryEnumerator> entries;
1034 nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
1035 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/Classifier.cpp"
, 1035); return rv; } } while (false)
;
1036
1037 nsCOMPtr<nsIFile> file;
1038 while (NS_SUCCEEDED(rv = entries->GetNextFile(getter_AddRefs(file)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv = entries->
GetNextFile(getter_AddRefs(file)))), 1)))
&&
1039 file) {
1040 // If |file| is a directory, recurse to find its entries as well.
1041 bool isDirectory;
1042 if (NS_FAILED(file->IsDirectory(&isDirectory))((bool)(__builtin_expect(!!(NS_FAILED_impl(file->IsDirectory
(&isDirectory))), 0)))
) {
1043 continue;
1044 }
1045 if (isDirectory) {
1046 ScanStoreDir(file, aExtensions, aTables);
1047 continue;
1048 }
1049
1050 nsAutoCString leafName;
1051 rv = file->GetNativeLeafName(leafName);
1052 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/Classifier.cpp"
, 1052); return rv; } } while (false)
;
1053
1054 for (const auto& ext : aExtensions) {
1055 if (StringEndsWith(leafName, ext)) {
1056 aTables.AppendElement(
1057 Substring(leafName, 0, leafName.Length() - strlen(ext.get())));
1058 break;
1059 }
1060 }
1061 }
1062
1063 return NS_OK;
1064}
1065
1066nsresult Classifier::ActiveTables(nsTArray<nsCString>& aTables) const {
1067 aTables = mActiveTablesCache.Clone();
1068 return NS_OK;
1069}
1070
1071nsresult Classifier::CleanToDelete() {
1072 bool exists;
1073 nsresult rv = mToDeleteDirectory->Exists(&exists);
1074 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/Classifier.cpp"
, 1074); return rv; } } while (false)
;
1075
1076 if (exists) {
1077 rv = mToDeleteDirectory->Remove(true);
1078 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1078); return rv; } } while (false)
;
1079 }
1080
1081 return NS_OK;
1082}
1083
1084#ifdef MOZ_SAFEBROWSING_DUMP_FAILED_UPDATES1
1085
1086already_AddRefed<nsIFile> Classifier::GetFailedUpdateDirectroy() {
1087 nsCString failedUpdatekDirName = STORE_DIRECTORY"safebrowsing"_ns + nsCString("-failedupdate");
1088
1089 nsCOMPtr<nsIFile> failedUpdatekDirectory;
1090 if (NS_FAILED(((bool)(__builtin_expect(!!(NS_FAILED_impl(mCacheDirectory->
Clone(getter_AddRefs(failedUpdatekDirectory)))), 0)))
1091 mCacheDirectory->Clone(getter_AddRefs(failedUpdatekDirectory)))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCacheDirectory->
Clone(getter_AddRefs(failedUpdatekDirectory)))), 0)))
||
1092 NS_FAILED(failedUpdatekDirectory->AppendNative(failedUpdatekDirName))((bool)(__builtin_expect(!!(NS_FAILED_impl(failedUpdatekDirectory
->AppendNative(failedUpdatekDirName))), 0)))
) {
1093 LOG(("Failed to init failedUpdatekDirectory."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to init failedUpdatekDirectory."
); } } while (0)
;
1094 return nullptr;
1095 }
1096
1097 return failedUpdatekDirectory.forget();
1098}
1099
1100nsresult Classifier::DumpRawTableUpdates(const nsACString& aRawUpdates) {
1101 LOG(("Dumping raw table updates..."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Dumping raw table updates..."
); } } while (0)
;
1102
1103 DumpFailedUpdate();
1104
1105 nsCOMPtr<nsIFile> failedUpdatekDirectory = GetFailedUpdateDirectroy();
1106
1107 // Create tableupdate.bin and dump raw table update data.
1108 nsCOMPtr<nsIFile> rawTableUpdatesFile;
1109 nsCOMPtr<nsIOutputStream> outputStream;
1110 if (NS_FAILED(((bool)(__builtin_expect(!!(NS_FAILED_impl(failedUpdatekDirectory
->Clone(getter_AddRefs(rawTableUpdatesFile)))), 0)))
1111 failedUpdatekDirectory->Clone(getter_AddRefs(rawTableUpdatesFile)))((bool)(__builtin_expect(!!(NS_FAILED_impl(failedUpdatekDirectory
->Clone(getter_AddRefs(rawTableUpdatesFile)))), 0)))
||
1112 NS_FAILED(((bool)(__builtin_expect(!!(NS_FAILED_impl(rawTableUpdatesFile
->AppendNative(nsCString("tableupdates.bin")))), 0)))
1113 rawTableUpdatesFile->AppendNative(nsCString("tableupdates.bin")))((bool)(__builtin_expect(!!(NS_FAILED_impl(rawTableUpdatesFile
->AppendNative(nsCString("tableupdates.bin")))), 0)))
||
1114 NS_FAILED(NS_NewLocalFileOutputStream(((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_NewLocalFileOutputStream
( getter_AddRefs(outputStream), rawTableUpdatesFile, 0x02 | 0x20
| 0x08))), 0)))
1115 getter_AddRefs(outputStream), rawTableUpdatesFile,((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_NewLocalFileOutputStream
( getter_AddRefs(outputStream), rawTableUpdatesFile, 0x02 | 0x20
| 0x08))), 0)))
1116 PR_WRONLY | PR_TRUNCATE | PR_CREATE_FILE))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_NewLocalFileOutputStream
( getter_AddRefs(outputStream), rawTableUpdatesFile, 0x02 | 0x20
| 0x08))), 0)))
) {
1117 LOG(("Failed to create file to dump raw table updates."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to create file to dump raw table updates."
); } } while (0)
;
1118 return NS_ERROR_FAILURE;
1119 }
1120
1121 // Write out the data.
1122 uint32_t written;
1123 nsresult rv = outputStream->Write(aRawUpdates.BeginReading(),
1124 aRawUpdates.Length(), &written);
1125 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/Classifier.cpp"
, 1125); return rv; } } while (false)
;
1126 NS_ENSURE_TRUE(written == aRawUpdates.Length(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(written == aRawUpdates.Length
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"written == aRawUpdates.Length()" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1126); return NS_ERROR_FAILURE; } } while (false)
;
1127
1128 return rv;
1129}
1130
1131nsresult Classifier::DumpFailedUpdate() {
1132 LOG(("Dumping failed update..."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Dumping failed update..."
); } } while (0)
;
1133
1134 nsCOMPtr<nsIFile> failedUpdatekDirectory = GetFailedUpdateDirectroy();
1135
1136 // Remove the "failed update" directory no matter it exists or not.
1137 // Failure is fine because the directory may not exist.
1138 failedUpdatekDirectory->Remove(true);
1139
1140 nsCString failedUpdatekDirName;
1141 nsresult rv = failedUpdatekDirectory->GetNativeLeafName(failedUpdatekDirName);
1142 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/Classifier.cpp"
, 1142); return rv; } } while (false)
;
1143
1144 // Copy the in-use directory to a clean "failed update" directory.
1145 nsCOMPtr<nsIFile> inUseDirectory;
1146 if (NS_FAILED(mRootStoreDirectory->Clone(getter_AddRefs(inUseDirectory)))((bool)(__builtin_expect(!!(NS_FAILED_impl(mRootStoreDirectory
->Clone(getter_AddRefs(inUseDirectory)))), 0)))
||
1147 NS_FAILED(inUseDirectory->CopyToNative(nullptr, failedUpdatekDirName))((bool)(__builtin_expect(!!(NS_FAILED_impl(inUseDirectory->
CopyToNative(nullptr, failedUpdatekDirName))), 0)))
) {
1148 LOG(("Failed to move in-use to the \"failed update\" directory %s",do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to move in-use to the \"failed update\" directory %s"
, failedUpdatekDirName.get()); } } while (0)
1149 failedUpdatekDirName.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to move in-use to the \"failed update\" directory %s"
, failedUpdatekDirName.get()); } } while (0)
;
1150 return NS_ERROR_FAILURE;
1151 }
1152
1153 return rv;
1154}
1155
1156#endif // MOZ_SAFEBROWSING_DUMP_FAILED_UPDATES
1157
1158/**
1159 * This function copies the files one by one to the destination folder.
1160 * Before copying a file, it checks ::ShouldAbort and returns
1161 * NS_ERROR_ABORT if the flag is set.
1162 */
1163nsresult Classifier::CopyDirectoryInterruptible(nsCOMPtr<nsIFile>& aDestDir,
1164 nsCOMPtr<nsIFile>& aSourceDir) {
1165 nsCOMPtr<nsIDirectoryEnumerator> entries;
1166 nsresult rv = aSourceDir->GetDirectoryEntries(getter_AddRefs(entries));
1167 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/Classifier.cpp"
, 1167); return rv; } } while (false)
;
1168 MOZ_ASSERT(entries)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(entries)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(entries))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("entries", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1168); AnnotateMozCrashReason("MOZ_ASSERT" "(" "entries" ")"
); do { *((volatile int*)__null) = 1168; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1169
1170 nsCOMPtr<nsIFile> source;
1171 while (NS_SUCCEEDED(rv = entries->GetNextFile(getter_AddRefs(source)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv = entries->
GetNextFile(getter_AddRefs(source)))), 1)))
&&
1172 source) {
1173 if (ShouldAbort()) {
1174 LOG(("Update is interrupted. Aborting the directory copy"))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Update is interrupted. Aborting the directory copy"
); } } while (0)
;
1175 return NS_ERROR_ABORT;
1176 }
1177
1178 bool isDirectory;
1179 rv = source->IsDirectory(&isDirectory);
1180 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/Classifier.cpp"
, 1180); return rv; } } while (false)
;
1181
1182 if (isDirectory) {
1183 // If it is a directory, recursively copy the files inside the directory.
1184 nsAutoCString leaf;
1185 source->GetNativeLeafName(leaf);
1186 MOZ_ASSERT(!leaf.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!leaf.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!leaf.IsEmpty()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!leaf.IsEmpty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1186); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!leaf.IsEmpty()"
")"); do { *((volatile int*)__null) = 1186; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1187
1188 nsCOMPtr<nsIFile> dest;
1189 aDestDir->Clone(getter_AddRefs(dest));
1190 dest->AppendNative(leaf);
1191 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/Classifier.cpp"
, 1191); return rv; } } while (false)
;
1192
1193 rv = CopyDirectoryInterruptible(dest, source);
1194 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/Classifier.cpp"
, 1194); return rv; } } while (false)
;
1195 } else {
1196 rv = source->CopyToNative(aDestDir, ""_ns);
1197 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/Classifier.cpp"
, 1197); return rv; } } while (false)
;
1198 }
1199 }
1200
1201 // If the destination directory doesn't exist in the end, it means that the
1202 // source directory is empty, we should copy the directory here.
1203 bool exist;
1204 rv = aDestDir->Exists(&exist);
1205 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/Classifier.cpp"
, 1205); return rv; } } while (false)
;
1206
1207 if (!exist) {
1208 rv = aDestDir->Create(nsIFile::DIRECTORY_TYPE, 0755);
1209 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/Classifier.cpp"
, 1209); return rv; } } while (false)
;
1210 }
1211
1212 return NS_OK;
1213}
1214
1215nsresult Classifier::CopyInUseDirForUpdate() {
1216 LOG(("Copy in-use directory content for update."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Copy in-use directory content for update."
); } } while (0)
;
1217 if (ShouldAbort()) {
1218 return NS_ERROR_UC_UPDATE_SHUTDOWNING;
1219 }
1220
1221 // We copy everything from in-use directory to a temporary directory
1222 // for updating.
1223
1224 // Remove the destination directory first (just in case) the do the copy.
1225 mUpdatingDirectory->Remove(true);
1226 if (!mRootStoreDirectoryForUpdate) {
1227 LOG(("mRootStoreDirectoryForUpdate is null."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "mRootStoreDirectoryForUpdate is null."
); } } while (0)
;
1228 return NS_ERROR_NULL_POINTER;
1229 }
1230
1231 nsresult rv = CopyDirectoryInterruptible(mUpdatingDirectory,
1232 mRootStoreDirectoryForUpdate);
1233 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/Classifier.cpp"
, 1233); return rv; } } while (false)
;
1234
1235 return NS_OK;
1236}
1237
1238nsresult Classifier::RecoverBackups() {
1239 bool backupExists;
1240 nsresult rv = mBackupDirectory->Exists(&backupExists);
1241 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/Classifier.cpp"
, 1241); return rv; } } while (false)
;
1242
1243 if (backupExists) {
1244 // Remove the safebrowsing dir if it exists
1245 nsCString storeDirName;
1246 rv = mRootStoreDirectory->GetNativeLeafName(storeDirName);
1247 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/Classifier.cpp"
, 1247); return rv; } } while (false)
;
1248
1249 bool storeExists;
1250 rv = mRootStoreDirectory->Exists(&storeExists);
1251 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/Classifier.cpp"
, 1251); return rv; } } while (false)
;
1252
1253 if (storeExists) {
1254 rv = mRootStoreDirectory->Remove(true);
1255 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/Classifier.cpp"
, 1255); return rv; } } while (false)
;
1256 }
1257
1258 // Move the backup to the store location
1259 rv = mBackupDirectory->MoveToNative(nullptr, storeDirName);
1260 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/Classifier.cpp"
, 1260); return rv; } } while (false)
;
1261
1262 // mBackupDirectory now points to storeDir, fix up.
1263 rv = SetupPathNames();
1264 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/Classifier.cpp"
, 1264); return rv; } } while (false)
;
1265 }
1266
1267 return NS_OK;
1268}
1269
1270bool Classifier::CheckValidUpdate(TableUpdateArray& aUpdates,
1271 const nsACString& aTable) {
1272 // take the quick exit if there is no valid update for us
1273 // (common case)
1274 uint32_t validupdates = 0;
1275
1276 for (uint32_t i = 0; i < aUpdates.Length(); i++) {
1277 RefPtr<const TableUpdate> update = aUpdates[i];
1278 if (!update || !update->TableName().Equals(aTable)) {
1279 continue;
1280 }
1281 if (update->Empty()) {
1282 aUpdates[i] = nullptr;
1283 continue;
1284 }
1285 validupdates++;
1286 }
1287
1288 if (!validupdates) {
1289 // This can happen if the update was only valid for one table.
1290 return false;
1291 }
1292
1293 return true;
1294}
1295
1296nsCString Classifier::GetProvider(const nsACString& aTableName) {
1297 nsUrlClassifierUtils* urlUtil = nsUrlClassifierUtils::GetInstance();
1298 if (NS_WARN_IF(!urlUtil)NS_warn_if_impl(!urlUtil, "!urlUtil", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1298)
) {
1299 return ""_ns;
1300 }
1301
1302 nsCString provider;
1303 nsresult rv = urlUtil->GetProvider(aTableName, provider);
1304
1305 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? provider : ""_ns;
1306}
1307
1308/*
1309 * This will consume+delete updates from the passed nsTArray.
1310 */
1311nsresult Classifier::UpdateHashStore(TableUpdateArray& aUpdates,
1312 const nsACString& aTable) {
1313 if (ShouldAbort()) {
1314 return NS_ERROR_UC_UPDATE_SHUTDOWNING;
1315 }
1316
1317 LOG(("Classifier::UpdateHashStore(%s)", PromiseFlatCString(aTable).get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Classifier::UpdateHashStore(%s)"
, TPromiseFlatString<char>(aTable).get()); } } while (0
)
;
1318
1319 // moztest- tables don't support update because they are directly created
1320 // in LookupCache. To test updates, use tables begin with "test-" instead.
1321 // Also, recommend using 'test-' tables while writing testcases because
1322 // it is more like the real world scenario.
1323 MOZ_ASSERT(!nsUrlClassifierUtils::IsMozTestTable(aTable))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!nsUrlClassifierUtils::IsMozTestTable(aTable))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!nsUrlClassifierUtils::IsMozTestTable(aTable)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!nsUrlClassifierUtils::IsMozTestTable(aTable)"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nsUrlClassifierUtils::IsMozTestTable(aTable)"
")"); do { *((volatile int*)__null) = 1323; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1324
1325 HashStore store(aTable, GetProvider(aTable), mUpdatingDirectory);
1326
1327 if (!CheckValidUpdate(aUpdates, store.TableName())) {
1328 return NS_OK;
1329 }
1330
1331 nsresult rv = store.Open();
1332 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1332)
) {
1333 return rv;
1334 }
1335
1336 rv = store.BeginUpdate();
1337 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/Classifier.cpp"
, 1337); return rv; } } while (false)
;
1338
1339 // Read the part of the store that is (only) in the cache
1340 RefPtr<LookupCacheV2> lookupCacheV2;
1341 {
1342 RefPtr<LookupCache> lookupCache =
1343 GetLookupCacheForUpdate(store.TableName());
1344 if (lookupCache) {
1345 lookupCacheV2 = LookupCache::Cast<LookupCacheV2>(lookupCache);
1346 }
1347 }
1348 if (!lookupCacheV2) {
1349 return NS_ERROR_UC_UPDATE_TABLE_NOT_FOUND;
1350 }
1351
1352 FallibleTArray<uint32_t> AddPrefixHashes;
1353 FallibleTArray<nsCString> AddCompletesHashes;
1354 rv = lookupCacheV2->GetPrefixes(AddPrefixHashes, AddCompletesHashes);
1355 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/Classifier.cpp"
, 1355); return rv; } } while (false)
;
1356
1357 rv = store.AugmentAdds(AddPrefixHashes, AddCompletesHashes);
1358 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/Classifier.cpp"
, 1358); return rv; } } while (false)
;
1359
1360 AddPrefixHashes.Clear();
1361 AddCompletesHashes.Clear();
1362
1363 uint32_t applied = 0;
1364
1365 for (uint32_t i = 0; i < aUpdates.Length(); i++) {
1366 RefPtr<TableUpdate> update = aUpdates[i];
1367 if (!update || !update->TableName().Equals(store.TableName())) {
1368 continue;
1369 }
1370
1371 RefPtr<TableUpdateV2> updateV2 = TableUpdate::Cast<TableUpdateV2>(update);
1372 NS_ENSURE_TRUE(updateV2, NS_ERROR_UC_UPDATE_UNEXPECTED_VERSION)do { if ((__builtin_expect(!!(!(updateV2)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "updateV2" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1372); return NS_ERROR_UC_UPDATE_UNEXPECTED_VERSION; } } while
(false)
;
1373
1374 rv = store.ApplyUpdate(updateV2);
1375 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/Classifier.cpp"
, 1375); return rv; } } while (false)
;
1376
1377 applied++;
1378
1379 LOG(("Applied update to table %s:", store.TableName().get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Applied update to table %s:"
, store.TableName().get()); } } while (0)
;
1380 LOG((" %d add chunks", updateV2->AddChunks().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %d add chunks"
, updateV2->AddChunks().Length()); } } while (0)
;
1381 LOG((" %zu add prefixes", updateV2->AddPrefixes().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %zu add prefixes"
, updateV2->AddPrefixes().Length()); } } while (0)
;
1382 LOG((" %zu add completions", updateV2->AddCompletes().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %zu add completions"
, updateV2->AddCompletes().Length()); } } while (0)
;
1383 LOG((" %d sub chunks", updateV2->SubChunks().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %d sub chunks"
, updateV2->SubChunks().Length()); } } while (0)
;
1384 LOG((" %zu sub prefixes", updateV2->SubPrefixes().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %zu sub prefixes"
, updateV2->SubPrefixes().Length()); } } while (0)
;
1385 LOG((" %zu sub completions", updateV2->SubCompletes().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %zu sub completions"
, updateV2->SubCompletes().Length()); } } while (0)
;
1386 LOG((" %d add expirations", updateV2->AddExpirations().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %d add expirations"
, updateV2->AddExpirations().Length()); } } while (0)
;
1387 LOG((" %d sub expirations", updateV2->SubExpirations().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %d sub expirations"
, updateV2->SubExpirations().Length()); } } while (0)
;
1388
1389 aUpdates[i] = nullptr;
1390 }
1391
1392 LOG(("Applied %d update(s) to %s.", applied, store.TableName().get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Applied %d update(s) to %s."
, applied, store.TableName().get()); } } while (0)
;
1393
1394 rv = store.Rebuild();
1395 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/Classifier.cpp"
, 1395); return rv; } } while (false)
;
1396
1397 LOG(("Table %s now has:", store.TableName().get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Table %s now has:"
, store.TableName().get()); } } while (0)
;
1398 LOG((" %d add chunks", store.AddChunks().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %d add chunks"
, store.AddChunks().Length()); } } while (0)
;
1399 LOG((" %zu add prefixes", store.AddPrefixes().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %zu add prefixes"
, store.AddPrefixes().Length()); } } while (0)
;
1400 LOG((" %zu add completions", store.AddCompletes().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %zu add completions"
, store.AddCompletes().Length()); } } while (0)
;
1401 LOG((" %d sub chunks", store.SubChunks().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %d sub chunks"
, store.SubChunks().Length()); } } while (0)
;
1402 LOG((" %zu sub prefixes", store.SubPrefixes().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %zu sub prefixes"
, store.SubPrefixes().Length()); } } while (0)
;
1403 LOG((" %zu sub completions", store.SubCompletes().Length()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, " %zu sub completions"
, store.SubCompletes().Length()); } } while (0)
;
1404
1405 rv = store.WriteFile();
1406 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/Classifier.cpp"
, 1406); return rv; } } while (false)
;
1407
1408 // At this point the store is updated and written out to disk, but
1409 // the data is still in memory. Build our quick-lookup table here.
1410 rv = lookupCacheV2->Build(store.AddPrefixes(), store.AddCompletes());
1411 NS_ENSURE_SUCCESS(rv, NS_ERROR_UC_UPDATE_BUILD_PREFIX_FAILURE)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", "NS_ERROR_UC_UPDATE_BUILD_PREFIX_FAILURE"
, 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/Classifier.cpp"
, 1411); return NS_ERROR_UC_UPDATE_BUILD_PREFIX_FAILURE; } } while
(false)
;
1412
1413 rv = lookupCacheV2->WriteFile();
1414 NS_ENSURE_SUCCESS(rv, NS_ERROR_UC_UPDATE_FAIL_TO_WRITE_DISK)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", "NS_ERROR_UC_UPDATE_FAIL_TO_WRITE_DISK"
, 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/Classifier.cpp"
, 1414); return NS_ERROR_UC_UPDATE_FAIL_TO_WRITE_DISK; } } while
(false)
;
1415
1416 LOG(("Successfully updated %s", store.TableName().get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Successfully updated %s"
, store.TableName().get()); } } while (0)
;
1417
1418 return NS_OK;
1419}
1420
1421nsresult Classifier::UpdateTableV4(TableUpdateArray& aUpdates,
1422 const nsACString& aTable) {
1423 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()"
" (" "UpdateTableV4 must be called on the classifier worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "UpdateTableV4 must be called on the classifier worker thread."
")"); do { *((volatile int*)__null) = 1424; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1424 "UpdateTableV4 must be called on the classifier worker 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()"
" (" "UpdateTableV4 must be called on the classifier worker thread."
")", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "UpdateTableV4 must be called on the classifier worker thread."
")"); do { *((volatile int*)__null) = 1424; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1425 if (ShouldAbort()) {
1426 return NS_ERROR_UC_UPDATE_SHUTDOWNING;
1427 }
1428
1429 // moztest- tables don't support update, see comment in UpdateHashStore.
1430 MOZ_ASSERT(!nsUrlClassifierUtils::IsMozTestTable(aTable))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!nsUrlClassifierUtils::IsMozTestTable(aTable))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!nsUrlClassifierUtils::IsMozTestTable(aTable)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!nsUrlClassifierUtils::IsMozTestTable(aTable)"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1430); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nsUrlClassifierUtils::IsMozTestTable(aTable)"
")"); do { *((volatile int*)__null) = 1430; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1431
1432 LOG(("Classifier::UpdateTableV4(%s)", PromiseFlatCString(aTable).get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Classifier::UpdateTableV4(%s)"
, TPromiseFlatString<char>(aTable).get()); } } while (0
)
;
1433
1434 if (!CheckValidUpdate(aUpdates, aTable)) {
1435 return NS_OK;
1436 }
1437
1438 RefPtr<LookupCacheV4> lookupCacheV4;
1439 {
1440 RefPtr<LookupCache> lookupCache = GetLookupCacheForUpdate(aTable);
1441 if (lookupCache) {
1442 lookupCacheV4 = LookupCache::Cast<LookupCacheV4>(lookupCache);
1443 }
1444 }
1445 if (!lookupCacheV4) {
1446 return NS_ERROR_UC_UPDATE_TABLE_NOT_FOUND;
1447 }
1448
1449 nsresult rv = NS_OK;
1450
1451 // If there are multiple updates for the same table, prefixes1 & prefixes2
1452 // will act as input and output in turn to reduce memory copy overhead.
1453 PrefixStringMap prefixes1, prefixes2;
1454 PrefixStringMap* input = &prefixes1;
1455 PrefixStringMap* output = &prefixes2;
1456
1457 RefPtr<const TableUpdateV4> lastAppliedUpdate = nullptr;
1458 for (uint32_t i = 0; i < aUpdates.Length(); i++) {
1459 RefPtr<TableUpdate> update = aUpdates[i];
1460 if (!update || !update->TableName().Equals(aTable)) {
1461 continue;
1462 }
1463
1464 RefPtr<TableUpdateV4> updateV4 = TableUpdate::Cast<TableUpdateV4>(update);
1465 NS_ENSURE_TRUE(updateV4, NS_ERROR_UC_UPDATE_UNEXPECTED_VERSION)do { if ((__builtin_expect(!!(!(updateV4)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "updateV4" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1465); return NS_ERROR_UC_UPDATE_UNEXPECTED_VERSION; } } while
(false)
;
1466
1467 if (updateV4->IsFullUpdate()) {
1468 input->Clear();
1469 output->Clear();
1470 rv = lookupCacheV4->ApplyUpdate(updateV4, *input, *output);
1471 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1472 return rv;
1473 }
1474 } else {
1475 // If both prefix sets are empty, this means we are doing a partial update
1476 // without a prior full/partial update in the loop. In this case we should
1477 // get prefixes from the lookup cache first.
1478 if (prefixes1.IsEmpty() && prefixes2.IsEmpty()) {
1479 lookupCacheV4->GetPrefixes(prefixes1);
1480
1481 // Bug 1911932: Temporary move the ApplyUpdate call here to verify the
1482 // issue.
1483 rv = lookupCacheV4->ApplyUpdate(updateV4, *input, *output);
1484 } else {
1485 MOZ_ASSERT(prefixes1.IsEmpty() ^ prefixes2.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prefixes1.IsEmpty() ^ prefixes2.IsEmpty())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(prefixes1.IsEmpty() ^ prefixes2.IsEmpty()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("prefixes1.IsEmpty() ^ prefixes2.IsEmpty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1485); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prefixes1.IsEmpty() ^ prefixes2.IsEmpty()"
")"); do { *((volatile int*)__null) = 1485; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1486
1487 // When there are multiple partial updates, input should always point
1488 // to the non-empty prefix set(filled by previous full/partial update).
1489 // output should always point to the empty prefix set.
1490 input = prefixes1.IsEmpty() ? &prefixes2 : &prefixes1;
1491 output = prefixes1.IsEmpty() ? &prefixes1 : &prefixes2;
1492
1493 // Bug 1911932: Temporary move the ApplyUpdate call here to verify the
1494 // issue.
1495 rv = lookupCacheV4->ApplyUpdate(updateV4, *input, *output);
1496 }
1497
1498 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1499 return rv;
1500 }
1501
1502 input->Clear();
1503 }
1504
1505 // Keep track of the last applied update.
1506 lastAppliedUpdate = updateV4;
1507
1508 aUpdates[i] = nullptr;
1509 }
1510
1511 rv = lookupCacheV4->Build(*output);
1512 NS_ENSURE_SUCCESS(rv, NS_ERROR_UC_UPDATE_BUILD_PREFIX_FAILURE)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", "NS_ERROR_UC_UPDATE_BUILD_PREFIX_FAILURE"
, 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/Classifier.cpp"
, 1512); return NS_ERROR_UC_UPDATE_BUILD_PREFIX_FAILURE; } } while
(false)
;
1513
1514 rv = lookupCacheV4->WriteFile();
1515 NS_ENSURE_SUCCESS(rv, NS_ERROR_UC_UPDATE_FAIL_TO_WRITE_DISK)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", "NS_ERROR_UC_UPDATE_FAIL_TO_WRITE_DISK"
, 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/Classifier.cpp"
, 1515); return NS_ERROR_UC_UPDATE_FAIL_TO_WRITE_DISK; } } while
(false)
;
1516
1517 if (lastAppliedUpdate) {
1518 LOG(("Write meta data of the last applied update."))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Write meta data of the last applied update."
); } } while (0)
;
1519 rv = lookupCacheV4->WriteMetadata(lastAppliedUpdate);
1520 NS_ENSURE_SUCCESS(rv, NS_ERROR_UC_UPDATE_FAIL_TO_WRITE_DISK)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", "NS_ERROR_UC_UPDATE_FAIL_TO_WRITE_DISK"
, 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/Classifier.cpp"
, 1520); return NS_ERROR_UC_UPDATE_FAIL_TO_WRITE_DISK; } } while
(false)
;
1521 }
1522
1523 LOG(("Successfully updated %s\n", PromiseFlatCString(aTable).get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Successfully updated %s\n"
, TPromiseFlatString<char>(aTable).get()); } } while (0
)
;
1524
1525 return NS_OK;
1526}
1527
1528nsresult Classifier::UpdateCache(RefPtr<const TableUpdate> aUpdate) {
1529 if (!aUpdate) {
1530 return NS_OK;
1531 }
1532
1533 nsAutoCString table(aUpdate->TableName());
1534 LOG(("Classifier::UpdateCache(%s)", table.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Classifier::UpdateCache(%s)"
, table.get()); } } while (0)
;
1535
1536 RefPtr<LookupCache> lookupCache = GetLookupCache(table);
1537 if (!lookupCache) {
1538 return NS_ERROR_FAILURE;
1539 }
1540
1541 RefPtr<LookupCacheV2> lookupV2 =
1542 LookupCache::Cast<LookupCacheV2>(lookupCache);
1543 if (lookupV2) {
1544 RefPtr<const TableUpdateV2> updateV2 =
1545 TableUpdate::Cast<TableUpdateV2>(aUpdate);
1546 lookupV2->AddGethashResultToCache(updateV2->AddCompletes(),
1547 updateV2->MissPrefixes());
1548 } else {
1549 RefPtr<LookupCacheV4> lookupV4 =
1550 LookupCache::Cast<LookupCacheV4>(lookupCache);
1551 if (!lookupV4) {
1552 return NS_ERROR_FAILURE;
1553 }
1554
1555 RefPtr<const TableUpdateV4> updateV4 =
1556 TableUpdate::Cast<TableUpdateV4>(aUpdate);
1557 lookupV4->AddFullHashResponseToCache(updateV4->FullHashResponse());
1558 }
1559
1560#if defined(DEBUG1)
1561 lookupCache->DumpCache();
1562#endif
1563
1564 return NS_OK;
1565}
1566
1567RefPtr<LookupCache> Classifier::GetLookupCache(const nsACString& aTable,
1568 bool aForUpdate) {
1569 // GetLookupCache(aForUpdate==true) can only be called on update thread.
1570 MOZ_ASSERT_IF(aForUpdate, OnUpdateThread())do { if (aForUpdate) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(OnUpdateThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(OnUpdateThread()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("OnUpdateThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1570); AnnotateMozCrashReason("MOZ_ASSERT" "(" "OnUpdateThread()"
")"); do { *((volatile int*)__null) = 1570; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1571
1572 LookupCacheArray& lookupCaches =
1573 aForUpdate ? mNewLookupCaches : mLookupCaches;
1574 auto& rootStoreDirectory =
1575 aForUpdate ? mUpdatingDirectory : mRootStoreDirectory;
1576
1577 for (auto c : lookupCaches) {
1578 if (c->TableName().Equals(aTable)) {
1579 return c;
1580 }
1581 }
1582
1583 // We don't want to create lookupcache when shutdown is already happening.
1584 if (ShouldAbort()) {
1585 return nullptr;
1586 }
1587
1588 // TODO : Bug 1302600, It would be better if we have a more general non-main
1589 // thread method to convert table name to protocol version. Currently
1590 // we can only know this by checking if the table name ends with
1591 // '-proto'.
1592 RefPtr<LookupCache> cache;
1593 nsCString provider = GetProvider(aTable);
1594
1595 // Google requests SafeBrowsing related feature should only be enabled when
1596 // the databases are update-to-date. Since we disable Safe Browsing update in
1597 // Safe Mode, ignore tables provided by Google to ensure we don't show
1598 // outdated warnings.
1599 if (nsUrlClassifierUtils::IsInSafeMode()) {
1600 if (provider.EqualsASCII("google") || provider.EqualsASCII("google4")) {
1601 return nullptr;
1602 }
1603 }
1604
1605 if (StringEndsWith(aTable, "-proto"_ns)) {
1606 cache = new LookupCacheV4(aTable, provider, rootStoreDirectory);
1607 } else {
1608 cache = new LookupCacheV2(aTable, provider, rootStoreDirectory);
1609 }
1610
1611 nsresult rv = cache->Init();
1612 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1613 return nullptr;
1614 }
1615 rv = cache->Open();
1616 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1617 lookupCaches.AppendElement(cache);
1618 return cache;
1619 }
1620
1621 // At this point we failed to open LookupCache.
1622 //
1623 // GetLookupCache for update and for other usage will run on update thread
1624 // and worker thread respectively (Bug 1339760). Removing stuff only in
1625 // their own realms potentially increases the concurrency.
1626
1627 if (aForUpdate) {
1628 // Remove intermediaries no matter if it's due to file corruption or not.
1629 RemoveUpdateIntermediaries();
1630 return nullptr;
1631 }
1632
1633 // Non-update case.
1634 if (rv == NS_ERROR_FILE_CORRUPTED) {
1635 // Remove all the on-disk data when the table's prefix file is corrupted.
1636 LOG(("Failed to get prefixes from file for table %s, delete on-disk data!",do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to get prefixes from file for table %s, delete on-disk data!"
, aTable.BeginReading()); } } while (0)
1637 aTable.BeginReading()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to get prefixes from file for table %s, delete on-disk data!"
, aTable.BeginReading()); } } while (0)
;
1638
1639 DeleteTables(mRootStoreDirectory, nsTArray<nsCString>{nsCString(aTable)});
1640 }
1641 return nullptr;
1642}
1643
1644nsresult Classifier::ReadNoiseEntries(const Prefix& aPrefix,
1645 const nsACString& aTableName,
1646 uint32_t aCount,
1647 PrefixArray& aNoiseEntries) {
1648 RefPtr<LookupCache> cache = GetLookupCache(aTableName);
1649 if (!cache) {
1650 return NS_ERROR_FAILURE;
1651 }
1652
1653 RefPtr<LookupCacheV2> cacheV2 = LookupCache::Cast<LookupCacheV2>(cache);
1654 RefPtr<LookupCacheV4> cacheV4 = LookupCache::Cast<LookupCacheV4>(cache);
1655 MOZ_ASSERT_IF(cacheV2, !cacheV4)do { if (cacheV2) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!cacheV4)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!cacheV4))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!cacheV4", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!cacheV4" ")"
); do { *((volatile int*)__null) = 1655; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1656
1657 if (cache->PrefixLength() == 0) {
1658 NS_WARNING("Could not find prefix in PrefixSet during noise lookup")NS_DebugBreak(NS_DEBUG_WARNING, "Could not find prefix in PrefixSet during noise lookup"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1658)
;
1659 return NS_ERROR_FAILURE;
1660 }
1661
1662 // We do not want to simply pick random prefixes, because this would allow
1663 // averaging out the noise by analysing the traffic from Firefox users.
1664 // Instead, we ensure the 'noise' is the same for the same prefix by seeding
1665 // the random number generator with the prefix. We prefer not to use rand()
1666 // which isn't thread safe, and the reseeding of which could trip up other
1667 // parts othe code that expect actual random numbers.
1668 // Here we use a simple LCG (Linear Congruential Generator) to generate
1669 // random numbers. We seed the LCG with the prefix we are generating noise
1670 // for.
1671 // http://en.wikipedia.org/wiki/Linear_congruential_generator
1672
1673 uint32_t m = cache->PrefixLength();
1674 uint32_t a = aCount % m;
1675 uint32_t idx = aPrefix.ToUint32() % m;
1676
1677 for (size_t i = 0; i < aCount; i++) {
1678 idx = (a * idx + a) % m;
1679
1680 uint32_t hash;
1681
1682 nsresult rv;
1683 if (cacheV2) {
1684 rv = cacheV2->GetPrefixByIndex(idx, &hash);
1685 } else {
1686 // We don't add noises for variable length prefix because of simplicity,
1687 // so we will only get fixed length prefix (4 bytes).
1688 rv = cacheV4->GetFixedLengthPrefixByIndex(idx, &hash);
1689 }
1690
1691 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1692 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Could not find the target prefix in PrefixSet during noise lookup"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1693)
1693 "Could not find the target prefix in PrefixSet during noise lookup")NS_DebugBreak(NS_DEBUG_WARNING, "Could not find the target prefix in PrefixSet during noise lookup"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1693)
;
1694 return NS_ERROR_FAILURE;
1695 }
1696
1697 Prefix newPrefix;
1698 // In the case V4 little endian, we did swapping endian when converting from
1699 // char* to int, should revert endian to make sure we will send hex string
1700 // correctly See https://bugzilla.mozilla.org/show_bug.cgi?id=1283007#c23
1701 if (!cacheV2 && !bool(MOZ_BIG_ENDIAN()0)) {
1702 hash = NativeEndian::swapFromBigEndian(hash);
1703 }
1704
1705 newPrefix.FromUint32(hash);
1706 if (newPrefix != aPrefix) {
1707 aNoiseEntries.AppendElement(newPrefix);
1708 }
1709 }
1710
1711 return NS_OK;
1712}
1713
1714nsresult Classifier::LoadHashStore(nsIFile* aDirectory, nsACString& aResult,
1715 nsTArray<nsCString>& aFailedTableNames) {
1716 nsTArray<nsCString> tables;
1717 nsTArray<nsCString> exts = {V2_METADATA_SUFFIX".sbstore"_ns};
1718
1719 nsresult rv = ScanStoreDir(mRootStoreDirectory, exts, tables);
1720 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1720)
) {
1721 return rv;
1722 }
1723
1724 for (const auto& table : tables) {
1725 HashStore store(table, GetProvider(table), mRootStoreDirectory);
1726
1727 nsresult rv = store.Open();
1728 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !GetLookupCache(table)) {
1729 // TableRequest is called right before applying an update.
1730 // If we cannot retrieve metadata for a given table or we fail to
1731 // load the prefixes for a table, reset the table to esnure we
1732 // apply a full update to the table.
1733 LOG(("Failed to get metadata for v2 table %s", table.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to get metadata for v2 table %s"
, table.get()); } } while (0)
;
1734 aFailedTableNames.AppendElement(table);
1735 continue;
1736 }
1737
1738 ChunkSet& adds = store.AddChunks();
1739 ChunkSet& subs = store.SubChunks();
1740
1741 // Open HashStore will always succeed even that is not a v2 table.
1742 // So exception tables without add and sub chunks.
1743 if (adds.Length() == 0 && subs.Length() == 0) {
1744 continue;
1745 }
1746
1747 aResult.Append(store.TableName());
1748 aResult.Append(';');
1749
1750 if (adds.Length() > 0) {
1751 aResult.AppendLiteral("a:");
1752 nsAutoCString addList;
1753 adds.Serialize(addList);
1754 aResult.Append(addList);
1755 }
1756
1757 if (subs.Length() > 0) {
1758 if (adds.Length() > 0) {
1759 aResult.Append(':');
1760 }
1761 aResult.AppendLiteral("s:");
1762 nsAutoCString subList;
1763 subs.Serialize(subList);
1764 aResult.Append(subList);
1765 }
1766
1767 aResult.Append('\n');
1768 }
1769
1770 return rv;
1771}
1772
1773nsresult Classifier::LoadMetadata(nsIFile* aDirectory, nsACString& aResult,
1774 nsTArray<nsCString>& aFailedTableNames) {
1775 nsTArray<nsCString> tables;
1776 nsTArray<nsCString> exts = {V4_METADATA_SUFFIX".metadata"_ns};
1777
1778 nsresult rv = ScanStoreDir(mRootStoreDirectory, exts, tables);
1779 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1779)
) {
1780 return rv;
1781 }
1782
1783 for (const auto& table : tables) {
1784 RefPtr<LookupCache> c = GetLookupCache(table);
1785 RefPtr<LookupCacheV4> lookupCacheV4 = LookupCache::Cast<LookupCacheV4>(c);
1786
1787 if (!lookupCacheV4) {
1788 aFailedTableNames.AppendElement(table);
1789 continue;
1790 }
1791
1792 nsCString state, sha256;
1793 rv = lookupCacheV4->LoadMetadata(state, sha256);
1794 Telemetry::Accumulate(Telemetry::URLCLASSIFIER_VLPS_METADATA_CORRUPT,
1795 rv == NS_ERROR_FILE_CORRUPTED);
1796 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1797 LOG(("Failed to get metadata for v4 table %s", table.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Failed to get metadata for v4 table %s"
, table.get()); } } while (0)
;
1798 aFailedTableNames.AppendElement(table);
1799 continue;
1800 }
1801
1802 // The state might include '\n' so that we have to encode.
1803 nsAutoCString stateBase64;
1804 rv = Base64Encode(state, stateBase64);
1805 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1805)
) {
1806 return rv;
1807 }
1808
1809 nsAutoCString checksumBase64;
1810 rv = Base64Encode(sha256, checksumBase64);
1811 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp"
, 1811)
) {
1812 return rv;
1813 }
1814
1815 LOG(("Appending state '%s' and checksum '%s' for table %s",do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Appending state '%s' and checksum '%s' for table %s"
, stateBase64.get(), checksumBase64.get(), table.get()); } } while
(0)
1816 stateBase64.get(), checksumBase64.get(), table.get()))do { const ::mozilla::LogModule* moz_real_module = gUrlClassifierDbServiceLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "Appending state '%s' and checksum '%s' for table %s"
, stateBase64.get(), checksumBase64.get(), table.get()); } } while
(0)
;
1817
1818 aResult.AppendPrintf("%s;%s:%s\n", table.get(), stateBase64.get(),
1819 checksumBase64.get());
1820 }
1821
1822 return rv;
1823}
1824
1825bool Classifier::ShouldAbort() const {
1826 return mIsClosed || nsUrlClassifierDBService::ShutdownHasStarted() ||
1827 (mUpdateInterrupted && mUpdateThread->IsOnCurrentThread());
1828}
1829
1830} // namespace safebrowsing
1831} // namespace mozilla