File: | var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/url-classifier/Classifier.cpp |
Warning: | line 551, column 3 Value stored to 'rv' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 |
26 | extern 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 | |
44 | namespace mozilla { |
45 | namespace safebrowsing { |
46 | |
47 | bool Classifier::OnUpdateThread() const { |
48 | bool onthread = false; |
49 | if (mUpdateThread) { |
50 | mUpdateThread->IsOnCurrentThread(&onthread); |
51 | } |
52 | return onthread; |
53 | } |
54 | |
55 | void 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 | |
71 | nsresult 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 | |
125 | Classifier::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 | |
136 | Classifier::~Classifier() { |
137 | if (mUpdateThread) { |
138 | mUpdateThread->Shutdown(); |
139 | mUpdateThread = nullptr; |
140 | } |
141 | |
142 | Close(); |
143 | } |
144 | |
145 | nsresult 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 | |
185 | nsresult 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 |
212 | nsresult 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 | |
261 | nsresult 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 | |
303 | void 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 | |
310 | void 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 | |
348 | void 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. |
374 | void 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. |
416 | void 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 | |
460 | nsresult 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 | |
519 | static 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)); |
551 | rv = tempDirectory->AppendNative(tempDirName); |
Value stored to 'rv' is never read | |
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 | |
583 | void 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 | |
597 | void 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 | |
623 | void 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 | |
651 | nsresult 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 | |
690 | void 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 | |
705 | nsresult 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 | |
806 | void 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 | |
822 | nsresult 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 | |
915 | nsresult 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 | |
935 | nsresult 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 | |
954 | void 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 | |
964 | void Classifier::DropStores() { |
965 | // See the comment in Classifier::Close() before adding anything here. |
966 | mLookupCaches.Clear(); |
967 | } |
968 | |
969 | nsresult 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 | |
1009 | nsresult 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 | |
1030 | nsresult 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 | |
1066 | nsresult Classifier::ActiveTables(nsTArray<nsCString>& aTables) const { |
1067 | aTables = mActiveTablesCache.Clone(); |
1068 | return NS_OK; |
1069 | } |
1070 | |
1071 | nsresult 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 | |
1086 | already_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 | |
1100 | nsresult 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 | |
1131 | nsresult 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 | */ |
1163 | nsresult 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 | |
1215 | nsresult 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 | |
1238 | nsresult 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 | |
1270 | bool 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 | |
1296 | nsCString 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 | */ |
1311 | nsresult 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 | |
1421 | nsresult 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 | |
1528 | nsresult 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 | |
1567 | RefPtr<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 | |
1644 | nsresult 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 | |
1714 | nsresult 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 | |
1773 | nsresult 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 | |
1825 | bool Classifier::ShouldAbort() const { |
1826 | return mIsClosed || nsUrlClassifierDBService::ShutdownHasStarted() || |
1827 | (mUpdateInterrupted && mUpdateThread->IsOnCurrentThread()); |
1828 | } |
1829 | |
1830 | } // namespace safebrowsing |
1831 | } // namespace mozilla |