Bug Summary

File:root/firefox-clang/storage/mozStorageConnection.cpp
Warning:line 1704, column 5
Value stored to 'srv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name mozStorageConnection.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/storage -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/storage -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_SQLITE_PERSIST_AUXILIARY_FILES=1 -D MOZ_SQLITE_VEC0_EXT=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/storage -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/storage -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -I /root/firefox-clang/dom/base -I /root/firefox-clang/third_party/sqlite3/ext -I /root/firefox-clang/third_party/sqlite3/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ /root/firefox-clang/storage/mozStorageConnection.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "BaseVFS.h"
6#include "ErrorList.h"
7#include "ScopedNSSTypes.h"
8#include "nsNetUtil.h"
9#include "nsError.h"
10#include "nsLocalFile.h"
11#include "nsThreadUtils.h"
12#include "nsIFile.h"
13#include "nsIFileURL.h"
14#include "nsIXPConnect.h"
15#include "mozilla/AppShutdown.h"
16#include "mozilla/CheckedInt.h"
17#include "mozilla/glean/StorageMetrics.h"
18#include "mozilla/Telemetry.h"
19#include "mozilla/Mutex.h"
20#include "mozilla/CondVar.h"
21#include "mozilla/Attributes.h"
22#include "mozilla/ErrorNames.h"
23#include "mozilla/dom/quota/QuotaObject.h"
24#include "mozilla/ScopeExit.h"
25#include "mozilla/storage/SQLiteEncryption.h"
26#include "mozilla/SpinEventLoopUntil.h"
27#include "mozilla/StaticPrefs_security.h"
28#include "mozilla/StaticPrefs_storage.h"
29
30#include "mozIStorageCompletionCallback.h"
31#include "mozIStorageFunction.h"
32
33#include "mozStorageAsyncStatementExecution.h"
34#include "mozStorageSQLFunctions.h"
35#include "mozStorageConnection.h"
36#include "mozStorageService.h"
37#include "mozStorageStatement.h"
38#include "mozStorageAsyncStatement.h"
39#include "mozStorageArgValueArray.h"
40#include "mozStoragePrivateHelpers.h"
41#include "mozStorageStatementData.h"
42#include "ObfuscatingVFS.h"
43#include "QuotaVFS.h"
44#include "StorageBaseStatementInternal.h"
45#include "mozilla/storage/StoragePathUtil.h"
46#include "mozilla/intl/AppCollator.h"
47#include "FileSystemModule.h"
48#include "mozStorageHelper.h"
49
50#include "mozilla/Assertions.h"
51#include "mozilla/Logging.h"
52#include "mozilla/Printf.h"
53#include "mozilla/ProfilerLabels.h"
54#include "mozilla/RefPtr.h"
55#include "nsComponentManagerUtils.h"
56#include "nsProxyRelease.h"
57#include "nsStringFwd.h"
58#include "nsURLHelper.h"
59
60#define MIN_AVAILABLE_BYTES_PER_CHUNKED_GROWTH524288000 524288000 // 500 MiB
61
62// Maximum size of the pages cache per connection.
63#define MAX_CACHE_SIZE_KIBIBYTES2048 2048 // 2 MiB
64
65mozilla::LazyLogModule gStorageLog("mozStorage");
66
67// Checks that the protected code is running on the main-thread only if the
68// connection was also opened on it.
69#ifdef DEBUG1
70# define CHECK_MAINTHREAD_ABUSE()do { do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 70)
; } } while (false); } while (0)
\
71 do { \
72 NS_WARNING_ASSERTION( \do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 76)
; } } while (false)
73 eventTargetOpenedOn == GetMainThreadSerialEventTarget() || \do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 76)
; } } while (false)
74 !NS_IsMainThread(), \do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 76)
; } } while (false)
75 "Using Storage synchronous API on main-thread, but " \do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 76)
; } } while (false)
76 "the connection was opened on another thread.")do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 76)
; } } while (false)
; \
77 } while (0)
78#else
79# define CHECK_MAINTHREAD_ABUSE()do { do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 79)
; } } while (false); } while (0)
\
80 do { /* Nothing */ \
81 } while (0)
82#endif
83
84namespace mozilla::storage {
85
86using mozilla::dom::quota::QuotaObject;
87
88namespace {
89
90int nsresultToSQLiteResult(nsresult aXPCOMResultCode) {
91 if (NS_SUCCEEDED(aXPCOMResultCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aXPCOMResultCode)
), 1)))
) {
92 return SQLITE_OK0;
93 }
94
95 switch (aXPCOMResultCode) {
96 case NS_ERROR_FILE_CORRUPTED:
97 return SQLITE_CORRUPT11;
98 case NS_ERROR_FILE_ACCESS_DENIED:
99 return SQLITE_CANTOPEN14;
100 case NS_ERROR_STORAGE_BUSY:
101 return SQLITE_BUSY5;
102 case NS_ERROR_FILE_IS_LOCKED:
103 return SQLITE_LOCKED6;
104 case NS_ERROR_FILE_READ_ONLY:
105 return SQLITE_READONLY8;
106 case NS_ERROR_STORAGE_IOERR:
107 return SQLITE_IOERR10;
108 case NS_ERROR_FILE_NO_DEVICE_SPACE:
109 return SQLITE_FULL13;
110 case NS_ERROR_OUT_OF_MEMORY:
111 return SQLITE_NOMEM7;
112 case NS_ERROR_UNEXPECTED:
113 return SQLITE_MISUSE21;
114 case NS_ERROR_ABORT:
115 return SQLITE_ABORT4;
116 case NS_ERROR_STORAGE_CONSTRAINT:
117 return SQLITE_CONSTRAINT19;
118 default:
119 return SQLITE_ERROR1;
120 }
121
122 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Must return in switch above!")do { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Must return in switch above!" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 122); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Must return in switch above!" ")"
); do { MOZ_CrashSequence(__null, 122); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); __builtin_unreachable
(); } while (false)
;
123}
124
125////////////////////////////////////////////////////////////////////////////////
126//// Variant Specialization Functions (variantToSQLiteT)
127
128int sqlite3_T_int(sqlite3_context* aCtx, int aValue) {
129 ::sqlite3_result_int(aCtx, aValue);
130 return SQLITE_OK0;
131}
132
133int sqlite3_T_int64(sqlite3_context* aCtx, sqlite3_int64 aValue) {
134 ::sqlite3_result_int64(aCtx, aValue);
135 return SQLITE_OK0;
136}
137
138int sqlite3_T_double(sqlite3_context* aCtx, double aValue) {
139 ::sqlite3_result_double(aCtx, aValue);
140 return SQLITE_OK0;
141}
142
143int sqlite3_T_text(sqlite3_context* aCtx, const nsCString& aValue) {
144 CheckedInt<int32_t> length(aValue.Length());
145 if (!length.isValid()) {
146 return SQLITE_MISUSE21;
147 }
148 ::sqlite3_result_text(aCtx, aValue.get(), length.value(), SQLITE_TRANSIENT((sqlite3_destructor_type)-1));
149 return SQLITE_OK0;
150}
151
152int sqlite3_T_text16(sqlite3_context* aCtx, const nsString& aValue) {
153 CheckedInt<int32_t> n_bytes =
154 CheckedInt<int32_t>(aValue.Length()) * sizeof(char16_t);
155 if (!n_bytes.isValid()) {
156 return SQLITE_MISUSE21;
157 }
158 ::sqlite3_result_text16(aCtx, aValue.get(), n_bytes.value(),
159 SQLITE_TRANSIENT((sqlite3_destructor_type)-1));
160 return SQLITE_OK0;
161}
162
163int sqlite3_T_null(sqlite3_context* aCtx) {
164 ::sqlite3_result_null(aCtx);
165 return SQLITE_OK0;
166}
167
168int sqlite3_T_blob(sqlite3_context* aCtx, const void* aData, int aSize) {
169 ::sqlite3_result_blob(aCtx, aData, aSize, free);
170 return SQLITE_OK0;
171}
172
173int sqlite3_T_array(sqlite3_context* aCtx, const void* aData, int aSize,
174 int aType) {
175 // Not supported for now.
176 return SQLITE_MISUSE21;
177}
178
179#include "variantToSQLiteT_impl.h"
180
181////////////////////////////////////////////////////////////////////////////////
182//// Modules
183
184struct Module {
185 const char* name;
186 int (*registerFunc)(sqlite3*, const char*);
187};
188
189Module gModules[] = {{"filesystem", RegisterFileSystemModule}};
190
191////////////////////////////////////////////////////////////////////////////////
192//// Local Functions
193
194int tracefunc(unsigned aReason, void* aClosure, void* aP, void* aX) {
195 switch (aReason) {
196 case SQLITE_TRACE_STMT0x01: {
197 // aP is a pointer to the prepared statement.
198 sqlite3_stmt* stmt = static_cast<sqlite3_stmt*>(aP);
199 // aX is a pointer to a string containing the unexpanded SQL or a comment,
200 // starting with "--"" in case of a trigger.
201 char* expanded = static_cast<char*>(aX);
202 // Simulate what sqlite_trace was doing.
203 if (!::strncmp(expanded, "--", 2)) {
204 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_STMT on %p: '%s'", aClosure, expanded
); } } while (0)
205 ("TRACE_STMT on %p: '%s'", aClosure, expanded))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_STMT on %p: '%s'", aClosure, expanded
); } } while (0)
;
206 } else {
207 char* sql = ::sqlite3_expanded_sql(stmt);
208 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_STMT on %p: '%s'", aClosure, sql); }
} while (0)
209 ("TRACE_STMT on %p: '%s'", aClosure, sql))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_STMT on %p: '%s'", aClosure, sql); }
} while (0)
;
210 ::sqlite3_free(sql);
211 }
212 break;
213 }
214 case SQLITE_TRACE_PROFILE0x02: {
215 // aX is pointer to a 64bit integer containing nanoseconds it took to
216 // execute the last command.
217 sqlite_int64 time = *(static_cast<sqlite_int64*>(aX)) / 1000000;
218 if (time > 0) {
219 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_TIME on %p: %lldms", aClosure, time
); } } while (0)
220 ("TRACE_TIME on %p: %lldms", aClosure, time))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_TIME on %p: %lldms", aClosure, time
); } } while (0)
;
221 }
222 break;
223 }
224 }
225 return 0;
226}
227
228void basicFunctionHelper(sqlite3_context* aCtx, int aArgc,
229 sqlite3_value** aArgv) {
230 void* userData = ::sqlite3_user_data(aCtx);
231
232 mozIStorageFunction* func = static_cast<mozIStorageFunction*>(userData);
233
234 RefPtr<ArgValueArray> arguments(new ArgValueArray(aArgc, aArgv));
235 if (!arguments) return;
236
237 nsCOMPtr<nsIVariant> result;
238 nsresult rv = func->OnFunctionCall(arguments, getter_AddRefs(result));
239 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
240 nsAutoCString errorMessage;
241 GetErrorName(rv, errorMessage);
242 errorMessage.InsertLiteral("User function returned ", 0);
243 errorMessage.Append('!');
244
245 NS_WARNING(errorMessage.get())NS_DebugBreak(NS_DEBUG_WARNING, errorMessage.get(), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 245)
;
246
247 ::sqlite3_result_error(aCtx, errorMessage.get(), -1);
248 ::sqlite3_result_error_code(aCtx, nsresultToSQLiteResult(rv));
249 return;
250 }
251 int retcode = variantToSQLiteT(aCtx, result);
252 if (retcode != SQLITE_OK0) {
253 NS_WARNING("User function returned invalid data type!")NS_DebugBreak(NS_DEBUG_WARNING, "User function returned invalid data type!"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 253)
;
254 ::sqlite3_result_error(aCtx, "User function returned invalid data type",
255 -1);
256 }
257}
258
259using mozilla::storage::PreparePathForURI;
260
261nsresult ExtractURIPathAndQuery(const char* aURI, nsCString& aPath,
262 nsCString& aQuery) {
263 if (strncmp(aURI, "file:", 5) != 0) {
264 aPath.Assign(aURI);
265 aQuery.Truncate();
266 return NS_OK;
267 }
268
269 nsCOMPtr<nsIURI> uri;
270 nsresult rv = NS_NewURI(getter_AddRefs(uri), nsDependentCString(aURI));
271 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 271); return rv; } } while (false)
;
272
273 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(uri, &rv);
274 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 274); return rv; } } while (false)
;
275
276 nsCOMPtr<nsIFile> file;
277 rv = fileURL->GetFile(getter_AddRefs(file));
278 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 278); return rv; } } while (false)
;
279
280 nsAutoString path;
281 rv = file->GetPath(path);
282 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 282); return rv; } } while (false)
;
283
284 aPath = NS_ConvertUTF16toUTF8(path);
285
286 rv = uri->GetQuery(aQuery);
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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 287); return rv; } } while (false)
;
288 return NS_OK;
289}
290
291void BuildFileURIWithKey(const nsACString& aEscapedPath,
292 const nsACString& aQuery, const nsACString& aDBKey,
293 nsACString& aURI) {
294 aURI.AssignLiteral("file:");
295 aURI.Append(aEscapedPath);
296 if (aQuery.IsEmpty()) {
297 aURI.AppendLiteral("?key=");
298 } else {
299 aURI.AppendLiteral("?");
300 aURI.Append(aQuery);
301 aURI.AppendLiteral("&key=");
302 }
303 aURI.Append(aDBKey);
304}
305
306RefPtr<QuotaObject> GetQuotaObject(sqlite3_file* aFile, bool obfuscatingVFS) {
307 return obfuscatingVFS
308 ? mozilla::storage::obfsvfs::GetQuotaObjectForFile(aFile)
309 : mozilla::storage::quotavfs::GetQuotaObjectForFile(aFile);
310}
311
312/**
313 * This code is heavily based on the sample at:
314 * http://www.sqlite.org/unlock_notify.html
315 */
316class UnlockNotification {
317 public:
318 UnlockNotification()
319 : mMutex("UnlockNotification mMutex"),
320 mCondVar(mMutex, "UnlockNotification condVar"),
321 mSignaled(false) {}
322
323 void Wait() {
324 MutexAutoLock lock(mMutex);
325 while (!mSignaled) {
326 (void)mCondVar.Wait();
327 }
328 }
329
330 void Signal() {
331 MutexAutoLock lock(mMutex);
332 mSignaled = true;
333 (void)mCondVar.Notify();
334 }
335
336 private:
337 Mutex mMutex MOZ_UNANNOTATED;
338 CondVar mCondVar;
339 bool mSignaled;
340};
341
342void UnlockNotifyCallback(void** aArgs, int aArgsSize) {
343 for (int i = 0; i < aArgsSize; i++) {
344 UnlockNotification* notification =
345 static_cast<UnlockNotification*>(aArgs[i]);
346 notification->Signal();
347 }
348}
349
350int WaitForUnlockNotify(sqlite3* aDatabase) {
351 UnlockNotification notification;
352 int srv =
353 ::sqlite3_unlock_notify(aDatabase, UnlockNotifyCallback, &notification);
354 MOZ_ASSERT(srv == SQLITE_LOCKED || srv == SQLITE_OK)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv == 6 || srv == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv == 6 || srv == 0))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("srv == 6 || srv == 0"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 354
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv == 6 || srv == 0"
")"); do { MOZ_CrashSequence(__null, 354); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
355 if (srv == SQLITE_OK0) {
356 notification.Wait();
357 }
358
359 return srv;
360}
361
362////////////////////////////////////////////////////////////////////////////////
363//// Local Classes
364
365class AsyncCloseConnection final : public Runnable {
366 public:
367 AsyncCloseConnection(Connection* aConnection, sqlite3* aNativeConnection,
368 nsIRunnable* aCallbackEvent)
369 : Runnable("storage::AsyncCloseConnection"),
370 mConnection(aConnection),
371 mNativeConnection(aNativeConnection),
372 mCallbackEvent(aCallbackEvent) {}
373
374 NS_IMETHODvirtual nsresult Run() override {
375 // Make sure we don't dispatch to the current thread.
376 MOZ_ASSERT(!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 376
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 376); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
377
378 nsCOMPtr<nsIRunnable> event =
379 NewRunnableMethod("storage::Connection::shutdownAsyncThread",
380 mConnection, &Connection::shutdownAsyncThread);
381 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(event))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(NS_DispatchToMainThread(event))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(NS_DispatchToMainThread(event))"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 381
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(NS_DispatchToMainThread(event))"
")"); do { MOZ_CrashSequence(__null, 381); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
382
383 // Internal close.
384 (void)mConnection->internalClose(mNativeConnection);
385
386 // Callback
387 if (mCallbackEvent) {
388 nsCOMPtr<nsIThread> thread;
389 (void)NS_GetMainThread(getter_AddRefs(thread));
390 (void)thread->Dispatch(mCallbackEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
391 }
392
393 return NS_OK;
394 }
395
396 ~AsyncCloseConnection() override {
397 NS_ReleaseOnMainThread("AsyncCloseConnection::mConnection",
398 mConnection.forget());
399 NS_ReleaseOnMainThread("AsyncCloseConnection::mCallbackEvent",
400 mCallbackEvent.forget());
401 }
402
403 private:
404 RefPtr<Connection> mConnection;
405 sqlite3* mNativeConnection;
406 nsCOMPtr<nsIRunnable> mCallbackEvent;
407};
408
409/**
410 * An event used to initialize the clone of a connection.
411 *
412 * Must be executed on the clone's async execution thread.
413 */
414class AsyncInitializeClone final : public Runnable {
415 public:
416 /**
417 * @param aConnection The connection being cloned.
418 * @param aClone The clone.
419 * @param aReadOnly If |true|, the clone is read only.
420 * @param aCallback A callback to trigger once initialization
421 * is complete. This event will be called on
422 * aClone->eventTargetOpenedOn.
423 */
424 AsyncInitializeClone(Connection* aConnection, Connection* aClone,
425 const bool aReadOnly,
426 mozIStorageCompletionCallback* aCallback)
427 : Runnable("storage::AsyncInitializeClone"),
428 mConnection(aConnection),
429 mClone(aClone),
430 mReadOnly(aReadOnly),
431 mCallback(aCallback) {
432 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()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 432
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 432); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
433 }
434
435 NS_IMETHODvirtual nsresult Run() override {
436 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()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 436
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 436); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
437 nsresult rv = mConnection->initializeClone(mClone, mReadOnly);
438 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
439 return Dispatch(rv, nullptr);
440 }
441 return Dispatch(NS_OK,
442 NS_ISUPPORTS_CAST(mozIStorageAsyncConnection*, mClone)static_cast<nsISupports*>(static_cast<mozIStorageAsyncConnection
*>(mClone))
);
443 }
444
445 private:
446 nsresult Dispatch(nsresult aResult, nsISupports* aValue) {
447 auto event =
448 MakeRefPtr<CallbackComplete>(aResult, aValue, mCallback.forget());
449 return mClone->eventTargetOpenedOn->Dispatch(event, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
450 }
451
452 ~AsyncInitializeClone() override {
453 nsCOMPtr<nsIThread> thread;
454 DebugOnly<nsresult> rv = NS_GetMainThread(getter_AddRefs(thread));
455 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 455); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 455); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
456
457 // Handle ambiguous nsISupports inheritance.
458 NS_ProxyRelease("AsyncInitializeClone::mConnection", thread,
459 mConnection.forget());
460 NS_ProxyRelease("AsyncInitializeClone::mClone", thread, mClone.forget());
461
462 // Generally, the callback will be released by CallbackComplete.
463 // However, if for some reason Run() is not executed, we still
464 // need to ensure that it is released here.
465 NS_ProxyRelease("AsyncInitializeClone::mCallback", thread,
466 mCallback.forget());
467 }
468
469 RefPtr<Connection> mConnection;
470 RefPtr<Connection> mClone;
471 const bool mReadOnly;
472 nsCOMPtr<mozIStorageCompletionCallback> mCallback;
473};
474
475/**
476 * A listener for async connection closing.
477 */
478class CloseListener final : public mozIStorageCompletionCallback {
479 public:
480 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
481 CloseListener() : mClosed(false) {}
482
483 NS_IMETHODvirtual nsresult Complete(nsresult, nsISupports*) override {
484 mClosed = true;
485 return NS_OK;
486 }
487
488 bool mClosed;
489
490 private:
491 ~CloseListener() = default;
492};
493
494NS_IMPL_ISUPPORTS(CloseListener, mozIStorageCompletionCallback)MozExternalRefCountType CloseListener::AddRef(void) { static_assert
(!std::is_destructible_v<CloseListener>, "Reference-counted class "
"CloseListener" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 494
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CloseListener" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("CloseListener" != nullptr))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"CloseListener\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CloseListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 494); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("CloseListener" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("CloseListener"), (uint32_t)
(sizeof(*this))); return count; } MozExternalRefCountType CloseListener
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 494
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CloseListener" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("CloseListener" != nullptr))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"CloseListener\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CloseListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 494); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("CloseListener" " not thread-safe"); const char* const nametmp
= "CloseListener"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult CloseListener::
QueryInterface(const nsIID& aIID, void** aInstancePtr) { do
{ if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 494); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<CloseListener, mozIStorageCompletionCallback
>, int32_t( reinterpret_cast<char*>(static_cast<mozIStorageCompletionCallback
*>((CloseListener*)0x1000)) - reinterpret_cast<char*>
((CloseListener*)0x1000))}, {&mozilla::detail::kImplementedIID
<CloseListener, nsISupports>, int32_t(reinterpret_cast<
char*>(static_cast<nsISupports*>( static_cast<mozIStorageCompletionCallback
*>((CloseListener*)0x1000))) - reinterpret_cast<char*>
((CloseListener*)0x1000))}, { nullptr, 0 } } ; static_assert(
std::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
495
496class AsyncVacuumEvent final : public Runnable {
497 public:
498 AsyncVacuumEvent(Connection* aConnection,
499 mozIStorageCompletionCallback* aCallback,
500 bool aUseIncremental, int32_t aSetPageSize)
501 : Runnable("storage::AsyncVacuum"),
502 mConnection(aConnection),
503 mCallback(aCallback),
504 mUseIncremental(aUseIncremental),
505 mSetPageSize(aSetPageSize),
506 mStatus(NS_ERROR_UNEXPECTED) {}
507
508 NS_IMETHODvirtual nsresult Run() override {
509 // This is initially dispatched to the helper thread, then re-dispatched
510 // to the opener thread, where it will callback.
511 if (IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn)) {
512 // Send the completion event.
513 if (mCallback) {
514 (void)mCallback->Complete(mStatus, nullptr);
515 }
516 return NS_OK;
517 }
518
519 // Ensure to invoke the callback regardless of errors.
520 auto guard = MakeScopeExit([&]() {
521 mConnection->mIsStatementOnHelperThreadInterruptible = false;
522 (void)mConnection->eventTargetOpenedOn->Dispatch(this,
523 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
524 });
525
526 // Get list of attached databases.
527 nsCOMPtr<mozIStorageStatement> stmt;
528 nsresult rv = mConnection->CreateStatement(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ "
529 "PRAGMA database_list"_ns,
530 getter_AddRefs(stmt));
531 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 531); return rv; } } while (false)
;
532 // We must accumulate names and loop through them later, otherwise VACUUM
533 // will see an ongoing statement and bail out.
534 nsTArray<nsCString> schemaNames;
535 bool hasResult = false;
536 while (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
537 nsAutoCString name;
538 rv = stmt->GetUTF8String(1, name);
539 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !name.EqualsLiteral("temp")) {
540 schemaNames.AppendElement(name);
541 }
542 }
543 mStatus = NS_OK;
544 // Mark this vacuum as an interruptible operation, so it can be interrupted
545 // if the connection closes during shutdown.
546 mConnection->mIsStatementOnHelperThreadInterruptible = true;
547 for (const nsCString& schemaName : schemaNames) {
548 rv = this->Vacuum(schemaName);
549 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
550 // This is sub-optimal since it's only keeping the last error reason,
551 // but it will do for now.
552 mStatus = rv;
553 }
554 }
555 return mStatus;
556 }
557
558 nsresult Vacuum(const nsACString& aSchemaName) {
559 // Abort if we're in shutdown.
560 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
561 return NS_ERROR_ABORT;
562 }
563 int32_t removablePages = mConnection->RemovablePagesInFreeList(aSchemaName);
564 if (!removablePages) {
565 // There's no empty pages to remove, so skip this vacuum for now.
566 return NS_OK;
567 }
568 nsresult rv;
569 bool needsFullVacuum = true;
570
571 if (mSetPageSize) {
572 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA ");
573 query.Append(aSchemaName);
574 query.AppendLiteral(".page_size = ");
575 query.AppendInt(mSetPageSize);
576 nsCOMPtr<mozIStorageStatement> stmt;
577 rv = mConnection->ExecuteSimpleSQL(query);
578 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 578); return rv; } } while (false)
;
579 }
580
581 // Check auto_vacuum.
582 {
583 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA ");
584 query.Append(aSchemaName);
585 query.AppendLiteral(".auto_vacuum");
586 nsCOMPtr<mozIStorageStatement> stmt;
587 rv = mConnection->CreateStatement(query, getter_AddRefs(stmt));
588 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 588); return rv; } } while (false)
;
589 bool hasResult = false;
590 bool changeAutoVacuum = false;
591 if (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
592 bool isIncrementalVacuum = stmt->AsInt32(0) == 2;
593 changeAutoVacuum = isIncrementalVacuum != mUseIncremental;
594 if (isIncrementalVacuum && !changeAutoVacuum) {
595 needsFullVacuum = false;
596 }
597 }
598 // Changing auto_vacuum is only supported on the main schema.
599 if (aSchemaName.EqualsLiteral("main") && changeAutoVacuum) {
600 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA ");
601 query.Append(aSchemaName);
602 query.AppendLiteral(".auto_vacuum = ");
603 query.AppendInt(mUseIncremental ? 2 : 0);
604 rv = mConnection->ExecuteSimpleSQL(query);
605 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 605); return rv; } } while (false)
;
606 }
607 }
608
609 if (needsFullVacuum) {
610 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "VACUUM ");
611 query.Append(aSchemaName);
612 rv = mConnection->ExecuteSimpleSQL(query);
613 // TODO (Bug 1818039): Report failed vacuum telemetry.
614 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 614); return rv; } } while (false)
;
615 } else {
616 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA ");
617 query.Append(aSchemaName);
618 query.AppendLiteral(".incremental_vacuum(");
619 query.AppendInt(removablePages);
620 query.AppendLiteral(")");
621 rv = mConnection->ExecuteSimpleSQL(query);
622 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 622); return rv; } } while (false)
;
623 }
624
625 return NS_OK;
626 }
627
628 ~AsyncVacuumEvent() override {
629 NS_ReleaseOnMainThread("AsyncVacuum::mConnection", mConnection.forget());
630 NS_ReleaseOnMainThread("AsyncVacuum::mCallback", mCallback.forget());
631 }
632
633 private:
634 RefPtr<Connection> mConnection;
635 nsCOMPtr<mozIStorageCompletionCallback> mCallback;
636 bool mUseIncremental;
637 int32_t mSetPageSize;
638 Atomic<nsresult> mStatus;
639};
640
641/**
642 * A runnable to perform an SQLite database backup when there may be one or more
643 * open connections on that database.
644 */
645class AsyncBackupDatabaseFile final : public Runnable, public nsITimerCallback {
646 public:
647 NS_DECL_ISUPPORTS_INHERITEDpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override;
648
649 /**
650 * @param aConnection The connection to the database being backed up.
651 * @param aNativeConnection The native connection to the database being backed
652 * up.
653 * @param aDestinationFile The destination file for the created backup.
654 * @param aCallback A callback to trigger once the backup process has
655 * completed. The callback will be supplied with an nsresult
656 * indicating whether or not the backup was successfully
657 * created. This callback will be called on the
658 * mConnection->eventTargetOpenedOn thread.
659 * @throws
660 */
661 AsyncBackupDatabaseFile(Connection* aConnection, sqlite3* aNativeConnection,
662 nsIFile* aDestinationFile,
663 mozIStorageCompletionCallback* aCallback,
664 int32_t aPagesPerStep, uint32_t aStepDelayMs)
665 : Runnable("storage::AsyncBackupDatabaseFile"),
666 mConnection(aConnection),
667 mNativeConnection(aNativeConnection),
668 mDestinationFile(aDestinationFile),
669 mCallback(aCallback),
670 mPagesPerStep(aPagesPerStep),
671 mStepDelayMs(aStepDelayMs),
672 mBackupFile(nullptr),
673 mBackupHandle(nullptr) {
674 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()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 674
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 674); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
675 }
676
677 NS_IMETHODvirtual nsresult Run() override {
678 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()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 678
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 678); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
679
680 nsAutoString path;
681 nsresult rv = mDestinationFile->GetPath(path);
682 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
683 return Dispatch(rv, nullptr);
684 }
685 // Put a .tmp on the end of the destination while the backup is underway.
686 // This extension will be stripped off after the backup successfully
687 // completes.
688 path.AppendLiteral(".tmp");
689
690 int srv = ::sqlite3_open(NS_ConvertUTF16toUTF8(path).get(), &mBackupFile);
691 if (srv != SQLITE_OK0) {
692 ::sqlite3_close(mBackupFile);
693 mBackupFile = nullptr;
694 return Dispatch(NS_ERROR_FAILURE, nullptr);
695 }
696
697 static const char* mainDBName = "main";
698
699 mBackupHandle = ::sqlite3_backup_init(mBackupFile, mainDBName,
700 mNativeConnection, mainDBName);
701 if (!mBackupHandle) {
702 MOZ_ALWAYS_TRUE(::sqlite3_close(mBackupFile) == SQLITE_OK)do { if ((__builtin_expect(!!(::sqlite3_close(mBackupFile) ==
0), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "::sqlite3_close(mBackupFile) == SQLITE_OK", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 702); AnnotateMozCrashReason("MOZ_CRASH(" "::sqlite3_close(mBackupFile) == SQLITE_OK"
")"); do { MOZ_CrashSequence(__null, 702); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
703 return Dispatch(NS_ERROR_FAILURE, nullptr);
704 }
705
706 return DoStep();
707 }
708
709 NS_IMETHODvirtual nsresult
710 Notify(nsITimer* aTimer) override { return DoStep(); }
711
712 private:
713 nsresult DoStep() {
714#define DISPATCH_AND_RETURN_IF_FAILED(rv) \
715 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { \
716 return Dispatch(rv, nullptr); \
717 }
718
719 // This guard is used to close the backup database in the event of
720 // some failure throughout this process. We release the exit guard
721 // only if we complete the backup successfully, or defer to another
722 // later call to DoStep.
723 auto guard = MakeScopeExit([&]() {
724 MOZ_ALWAYS_TRUE(::sqlite3_close(mBackupFile) == SQLITE_OK)do { if ((__builtin_expect(!!(::sqlite3_close(mBackupFile) ==
0), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "::sqlite3_close(mBackupFile) == SQLITE_OK", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 724); AnnotateMozCrashReason("MOZ_CRASH(" "::sqlite3_close(mBackupFile) == SQLITE_OK"
")"); do { MOZ_CrashSequence(__null, 724); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
725 mBackupFile = nullptr;
726 });
727
728 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()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 728
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 728); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
729 nsAutoString originalPath;
730 nsresult rv = mDestinationFile->GetPath(originalPath);
731 DISPATCH_AND_RETURN_IF_FAILED(rv);
732
733 nsAutoString tempPath = originalPath;
734 tempPath.AppendLiteral(".tmp");
735
736 nsCOMPtr<nsIFile> file;
737 rv = NS_NewLocalFile(tempPath, getter_AddRefs(file));
738 DISPATCH_AND_RETURN_IF_FAILED(rv);
739
740 int srv = ::sqlite3_backup_step(mBackupHandle, mPagesPerStep);
741 if (srv == SQLITE_OK0 || srv == SQLITE_BUSY5 || srv == SQLITE_LOCKED6) {
742 // We're continuing the backup later. Release the guard to avoid closing
743 // the database.
744 guard.release();
745 // Queue up the next step
746 return NS_NewTimerWithCallback(getter_AddRefs(mTimer), this, mStepDelayMs,
747 nsITimer::TYPE_ONE_SHOT,
748 GetCurrentSerialEventTarget());
749 }
750#ifdef DEBUG1
751 if (srv != SQLITE_DONE101) {
752 nsCString warnMsg;
753 warnMsg.AppendLiteral(
754 "The SQLite database copy could not be completed due to an error: ");
755 warnMsg.Append(::sqlite3_errmsg(mBackupFile));
756 NS_WARNING(warnMsg.get())NS_DebugBreak(NS_DEBUG_WARNING, warnMsg.get(), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 756)
;
757 }
758#endif
759
760 (void)::sqlite3_backup_finish(mBackupHandle);
761 MOZ_ALWAYS_TRUE(::sqlite3_close(mBackupFile) == SQLITE_OK)do { if ((__builtin_expect(!!(::sqlite3_close(mBackupFile) ==
0), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "::sqlite3_close(mBackupFile) == SQLITE_OK", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 761); AnnotateMozCrashReason("MOZ_CRASH(" "::sqlite3_close(mBackupFile) == SQLITE_OK"
")"); do { MOZ_CrashSequence(__null, 761); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
762 mBackupFile = nullptr;
763
764 // The database is already closed, so we can release this guard now.
765 guard.release();
766
767 if (srv != SQLITE_DONE101) {
768 NS_WARNING("Failed to create database copy.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to create database copy."
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 768)
;
769
770 // The partially created database file is not useful. Let's remove it.
771 rv = file->Remove(false);
772 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
773 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Removing a partially backed up SQLite database file failed."
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 774)
774 "Removing a partially backed up SQLite database file failed.")NS_DebugBreak(NS_DEBUG_WARNING, "Removing a partially backed up SQLite database file failed."
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 774)
;
775 }
776
777 return Dispatch(convertResultCode(srv), nullptr);
778 }
779
780 // Now that we've successfully created the copy, we'll strip off the .tmp
781 // extension.
782
783 nsAutoString leafName;
784 rv = mDestinationFile->GetLeafName(leafName);
785 DISPATCH_AND_RETURN_IF_FAILED(rv);
786
787 rv = file->RenameTo(nullptr, leafName);
788 DISPATCH_AND_RETURN_IF_FAILED(rv);
789
790#undef DISPATCH_AND_RETURN_IF_FAILED
791 return Dispatch(NS_OK, nullptr);
792 }
793
794 nsresult Dispatch(nsresult aResult, nsISupports* aValue) {
795 auto event =
796 MakeRefPtr<CallbackComplete>(aResult, aValue, mCallback.forget());
797 return mConnection->eventTargetOpenedOn->Dispatch(event,
798 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
799 }
800
801 ~AsyncBackupDatabaseFile() override {
802 nsresult rv;
803 nsCOMPtr<nsIThread> thread =
804 do_QueryInterface(mConnection->eventTargetOpenedOn, &rv);
805 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 805); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 805); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
806
807 // Handle ambiguous nsISupports inheritance.
808 NS_ProxyRelease("AsyncBackupDatabaseFile::mConnection", thread,
809 mConnection.forget());
810 NS_ProxyRelease("AsyncBackupDatabaseFile::mDestinationFile", thread,
811 mDestinationFile.forget());
812
813 // Generally, the callback will be released by CallbackComplete.
814 // However, if for some reason Run() is not executed, we still
815 // need to ensure that it is released here.
816 NS_ProxyRelease("AsyncInitializeClone::mCallback", thread,
817 mCallback.forget());
818 }
819
820 RefPtr<Connection> mConnection;
821 sqlite3* mNativeConnection;
822 nsCOMPtr<nsITimer> mTimer;
823 nsCOMPtr<nsIFile> mDestinationFile;
824 nsCOMPtr<mozIStorageCompletionCallback> mCallback;
825 int32_t mPagesPerStep;
826 uint32_t mStepDelayMs;
827 sqlite3* mBackupFile;
828 sqlite3_backup* mBackupHandle;
829};
830
831NS_IMPL_ISUPPORTS_INHERITED(AsyncBackupDatabaseFile, Runnable, nsITimerCallback)nsresult AsyncBackupDatabaseFile::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 831); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE_INHERITED"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<AsyncBackupDatabaseFile, nsITimerCallback
>, int32_t( reinterpret_cast<char*>(static_cast<nsITimerCallback
*>((AsyncBackupDatabaseFile*)0x1000)) - reinterpret_cast<
char*>((AsyncBackupDatabaseFile*)0x1000))}, { nullptr, 0 }
} ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); if (((bool)(__builtin_expect(!!(!NS_FAILED_impl
(rv)), 1)))) return rv; return Runnable::QueryInterface(aIID,
aInstancePtr); } MozExternalRefCountType AsyncBackupDatabaseFile
::AddRef(void) { static_assert(!std::is_destructible_v<AsyncBackupDatabaseFile
>, "Reference-counted class " "AsyncBackupDatabaseFile" " should not have a public destructor. "
"Make this class's destructor non-public"); nsrefcnt r = Runnable
::AddRef(); if constexpr (::mozilla::detail::ShouldLogInheritedRefcnt
<AsyncBackupDatabaseFile>) { NS_LogAddRef((this), (r), (
"AsyncBackupDatabaseFile"), (uint32_t)(sizeof(*this))); } return
r; } MozExternalRefCountType AsyncBackupDatabaseFile::Release
(void) { nsrefcnt r = Runnable::Release(); if constexpr (::mozilla
::detail::ShouldLogInheritedRefcnt<AsyncBackupDatabaseFile
>) { NS_LogRelease((this), (r), ("AsyncBackupDatabaseFile"
)); } return r; }
832
833} // namespace
834
835////////////////////////////////////////////////////////////////////////////////
836//// Connection
837
838Connection::Connection(Service* aService, int aFlags,
839 ConnectionOperation aSupportedOperations,
840 const nsCString& aTelemetryFilename, bool aInterruptible,
841 bool aIgnoreLockingMode, bool aOpenNotExclusive)
842 : sharedAsyncExecutionMutex("Connection::sharedAsyncExecutionMutex"),
843 sharedDBMutex("Connection::sharedDBMutex"),
844 eventTargetOpenedOn(WrapNotNull(GetCurrentSerialEventTarget())),
845 mIsStatementOnHelperThreadInterruptible(false),
846 mDBConn(nullptr),
847 mDefaultTransactionType(mozIStorageConnection::TRANSACTION_DEFERRED),
848 mDestroying(false),
849 mProgressHandler(nullptr),
850 mStorageService(aService),
851 mFlags(aFlags),
852 mTransactionNestingLevel(0),
853 mSupportedOperations(aSupportedOperations),
854 mInterruptible(aSupportedOperations == Connection::ASYNCHRONOUS ||
855 aInterruptible),
856 mIgnoreLockingMode(aIgnoreLockingMode),
857 mOpenNotExclusive(aOpenNotExclusive),
858 mAsyncExecutionThreadShuttingDown(false),
859 mConnectionClosed(false),
860 mDatabaseEncrypted(false),
861 mPageSize(Service::kDefaultPageSize),
862 mGrowthChunkSize(0) {
863 MOZ_ASSERT(!mIgnoreLockingMode || mFlags & SQLITE_OPEN_READONLY,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIgnoreLockingMode || mFlags & 0x00000001)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mIgnoreLockingMode || mFlags & 0x00000001))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mIgnoreLockingMode || mFlags & 0x00000001"
" (" "Can't ignore locking for a non-readonly connection!" ")"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 864
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIgnoreLockingMode || mFlags & 0x00000001"
") (" "Can't ignore locking for a non-readonly connection!" ")"
); do { MOZ_CrashSequence(__null, 864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
864 "Can't ignore locking for a non-readonly connection!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIgnoreLockingMode || mFlags & 0x00000001)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mIgnoreLockingMode || mFlags & 0x00000001))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mIgnoreLockingMode || mFlags & 0x00000001"
" (" "Can't ignore locking for a non-readonly connection!" ")"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 864
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIgnoreLockingMode || mFlags & 0x00000001"
") (" "Can't ignore locking for a non-readonly connection!" ")"
); do { MOZ_CrashSequence(__null, 864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
865 mStorageService->registerConnection(this);
866 MOZ_ASSERT(!aTelemetryFilename.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aTelemetryFilename.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aTelemetryFilename.IsEmpty(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aTelemetryFilename.IsEmpty()" " (" "A telemetry filename should have been passed-in."
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aTelemetryFilename.IsEmpty()"
") (" "A telemetry filename should have been passed-in." ")"
); do { MOZ_CrashSequence(__null, 867); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
867 "A telemetry filename should have been passed-in.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aTelemetryFilename.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aTelemetryFilename.IsEmpty(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aTelemetryFilename.IsEmpty()" " (" "A telemetry filename should have been passed-in."
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aTelemetryFilename.IsEmpty()"
") (" "A telemetry filename should have been passed-in." ")"
); do { MOZ_CrashSequence(__null, 867); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
868 mTelemetryFilename.Assign(aTelemetryFilename);
869}
870
871Connection::~Connection() {
872 // Failsafe Close() occurs in our custom Release method because of
873 // complications related to Close() potentially invoking AsyncClose() which
874 // will increment our refcount.
875 MOZ_ASSERT(!mAsyncExecutionThread,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAsyncExecutionThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mAsyncExecutionThread))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mAsyncExecutionThread"
" (" "The async thread has not been shutdown properly!" ")",
"/root/firefox-clang/storage/mozStorageConnection.cpp", 876)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAsyncExecutionThread"
") (" "The async thread has not been shutdown properly!" ")"
); do { MOZ_CrashSequence(__null, 876); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
876 "The async thread has not been shutdown properly!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAsyncExecutionThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mAsyncExecutionThread))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mAsyncExecutionThread"
" (" "The async thread has not been shutdown properly!" ")",
"/root/firefox-clang/storage/mozStorageConnection.cpp", 876)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAsyncExecutionThread"
") (" "The async thread has not been shutdown properly!" ")"
); do { MOZ_CrashSequence(__null, 876); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
877}
878
879NS_IMPL_ADDREF(Connection)MozExternalRefCountType Connection::AddRef(void) { static_assert
(!std::is_destructible_v<Connection>, "Reference-counted class "
"Connection" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 879
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("Connection" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("Connection" != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("\"Connection\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"Connection\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 879); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("Connection" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("Connection"), (uint32_t)(sizeof
(*this))); return count; }
880
881NS_INTERFACE_MAP_BEGIN(Connection)nsresult Connection::QueryInterface(const nsIID& aIID, void
** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(
NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 881); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
882 NS_INTERFACE_MAP_ENTRY(mozIStorageAsyncConnection)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, mozIStorageAsyncConnection>)) foundInterface
= static_cast<mozIStorageAsyncConnection*>(this); else
883 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIInterfaceRequestor>)) foundInterface
= static_cast<nsIInterfaceRequestor*>(this); else
884 NS_INTERFACE_MAP_ENTRY(mozIStorageConnection)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, mozIStorageConnection>)) foundInterface
= static_cast<mozIStorageConnection*>(this); else
885 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozIStorageConnection)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<mozIStorageConnection*>
(this)); else
886NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::kIID
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aIID.Equals((nsISupports::kIID))", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 886); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 886); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
887
888// This is identical to what NS_IMPL_RELEASE provides, but with the
889// extra |1 == count| case.
890NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType Connection::Release(void) {
891 MOZ_ASSERT(0 != mRefCnt, "dup release")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0 != mRefCnt)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(0 != mRefCnt))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("0 != mRefCnt" " ("
"dup release" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 891); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 != mRefCnt"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 891
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
892 nsrefcnt count = --mRefCnt;
893 NS_LOG_RELEASE(this, count, "Connection")NS_LogRelease((this), (count), ("Connection"));
894 if (1 == count) {
895 // If the refcount went to 1, the single reference must be from
896 // gService->mConnections (in class |Service|). And the code calling
897 // Release is either:
898 // - The "user" code that had created the connection, releasing on any
899 // thread.
900 // - One of Service's getConnections() callers had acquired a strong
901 // reference to the Connection that out-lived the last "user" reference,
902 // and now that just got dropped. Note that this reference could be
903 // getting dropped on the main thread or Connection->eventTargetOpenedOn
904 // (because of the NewRunnableMethod used by minimizeMemory).
905 //
906 // Either way, we should now perform our failsafe Close() and unregister.
907 // However, we only want to do this once, and the reality is that our
908 // refcount could go back up above 1 and down again at any time if we are
909 // off the main thread and getConnections() gets called on the main thread,
910 // so we use an atomic here to do this exactly once.
911 if (mDestroying.compareExchange(false, true)) {
912 // Close the connection, dispatching to the opening event target if we're
913 // not on that event target already and that event target is still
914 // accepting runnables. We do this because it's possible we're on the main
915 // thread because of getConnections(), and we REALLY don't want to
916 // transfer I/O to the main thread if we can avoid it.
917 if (IsOnCurrentSerialEventTarget(eventTargetOpenedOn)) {
918 // This could cause SpinningSynchronousClose() to be invoked and AddRef
919 // triggered for AsyncCloseConnection's strong ref if the conn was ever
920 // use for async purposes. (Main-thread only, though.)
921 (void)synchronousClose();
922 } else {
923 nsCOMPtr<nsIRunnable> event =
924 NewRunnableMethod("storage::Connection::synchronousClose", this,
925 &Connection::synchronousClose);
926 if (NS_FAILED(eventTargetOpenedOn->Dispatch(event.forget(),((bool)(__builtin_expect(!!(NS_FAILED_impl(eventTargetOpenedOn
->Dispatch(event.forget(), nsIEventTarget::DISPATCH_NORMAL
))), 0)))
927 NS_DISPATCH_NORMAL))((bool)(__builtin_expect(!!(NS_FAILED_impl(eventTargetOpenedOn
->Dispatch(event.forget(), nsIEventTarget::DISPATCH_NORMAL
))), 0)))
) {
928 // The event target was dead and so we've just leaked our runnable.
929 // This should not happen because our non-main-thread consumers should
930 // be explicitly closing their connections, not relying on us to close
931 // them for them. (It's okay to let a statement go out of scope for
932 // automatic cleanup, but not a Connection.)
933 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Leaked Connection::synchronousClose(), ownership fail."
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Leaked Connection::synchronousClose(), ownership fail."
")"); do { MOZ_CrashSequence(__null, 934); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
934 "Leaked Connection::synchronousClose(), ownership fail.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Leaked Connection::synchronousClose(), ownership fail."
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Leaked Connection::synchronousClose(), ownership fail."
")"); do { MOZ_CrashSequence(__null, 934); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
935 (void)synchronousClose();
936 }
937 }
938
939 // This will drop its strong reference right here, right now.
940 mStorageService->unregisterConnection(this);
941 }
942 } else if (0 == count) {
943 mRefCnt = 1; /* stabilize */
944#if 0 /* enable this to find non-threadsafe destructors: */
945 NS_ASSERT_OWNINGTHREAD(Connection)_mOwningThread.AssertOwnership("Connection" " not thread-safe"
)
;
946#endif
947 delete (this);
948 return 0;
949 }
950 return count;
951}
952
953int32_t Connection::getSqliteRuntimeStatus(int32_t aStatusOption,
954 int32_t* aMaxValue) {
955 MOZ_ASSERT(connectionReady(), "A connection must exist at this point")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(connectionReady())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(connectionReady()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("connectionReady()"
" (" "A connection must exist at this point" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "connectionReady()"
") (" "A connection must exist at this point" ")"); do { MOZ_CrashSequence
(__null, 955); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
956 int curr = 0, max = 0;
957 DebugOnly<int> rc =
958 ::sqlite3_db_status(mDBConn, aStatusOption, &curr, &max, 0);
959 MOZ_ASSERT(NS_SUCCEEDED(convertResultCode(rc)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(convertResultCode
(rc))), 1))))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(convertResultCode(rc))), 1)))))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(!NS_FAILED_impl(convertResultCode(rc))), 1)))"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 959
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(convertResultCode(rc))), 1)))"
")"); do { MOZ_CrashSequence(__null, 959); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
960 if (aMaxValue) *aMaxValue = max;
961 return curr;
962}
963
964nsIEventTarget* Connection::getAsyncExecutionTarget() {
965 NS_ENSURE_TRUE(IsOnCurrentSerialEventTarget(eventTargetOpenedOn), nullptr)do { if ((__builtin_expect(!!(!(IsOnCurrentSerialEventTarget(
eventTargetOpenedOn))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
") failed", nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 965); return nullptr; } } while (false)
;
966
967 // Don't return the asynchronous event target if we are shutting down.
968 if (mAsyncExecutionThreadShuttingDown) {
969 return nullptr;
970 }
971
972 // Create the async event target if there's none yet.
973 if (!mAsyncExecutionThread) {
974 // Names start with "sqldb:" followed by a recognizable name, like the
975 // database file name, or a specially crafted name like "memory".
976 // This name will be surfaced on https://crash-stats.mozilla.org, so any
977 // sensitive part of the file name (e.g. an URL origin) should be replaced
978 // by passing an explicit telemetryName to openDatabaseWithFileURL.
979 nsAutoCString name("sqldb:"_ns);
980 name.Append(mTelemetryFilename);
981 static nsThreadPoolNaming naming;
982 nsresult rv = NS_NewNamedThread(naming.GetNextThreadName(name),
983 getter_AddRefs(mAsyncExecutionThread));
984 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
985 NS_WARNING("Failed to create async thread.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to create async thread."
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 985)
;
986 return nullptr;
987 }
988 }
989
990 return mAsyncExecutionThread;
991}
992
993void Connection::RecordOpenStatus(nsresult rv) {
994 nsCString histogramKey = mTelemetryFilename;
995
996 if (histogramKey.IsEmpty()) {
997 histogramKey.AssignLiteral("unknown");
998 }
999
1000 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1001 return;
1002 }
1003
1004 switch (rv) {
1005 case NS_ERROR_FILE_CORRUPTED:
1006 mozilla::glean::sqlite_store::open.Get(histogramKey, "corrupt"_ns).Add();
1007 break;
1008 case NS_ERROR_STORAGE_IOERR:
1009 mozilla::glean::sqlite_store::open.Get(histogramKey, "diskio"_ns).Add();
1010 break;
1011 case NS_ERROR_FILE_ACCESS_DENIED:
1012 case NS_ERROR_FILE_IS_LOCKED:
1013 case NS_ERROR_FILE_READ_ONLY:
1014 mozilla::glean::sqlite_store::open.Get(histogramKey, "access"_ns).Add();
1015 break;
1016 case NS_ERROR_FILE_NO_DEVICE_SPACE:
1017 mozilla::glean::sqlite_store::open.Get(histogramKey, "diskspace"_ns)
1018 .Add();
1019 break;
1020 default:
1021 mozilla::glean::sqlite_store::open.Get(histogramKey, "failure"_ns).Add();
1022 }
1023}
1024
1025void Connection::RecordQueryStatus(int srv) {
1026 nsCString histogramKey = mTelemetryFilename;
1027
1028 if (histogramKey.IsEmpty()) {
1029 histogramKey.AssignLiteral("unknown");
1030 }
1031
1032 switch (srv) {
1033 case SQLITE_OK0:
1034 case SQLITE_ROW100:
1035 case SQLITE_DONE101:
1036
1037 // Note that these are returned when we intentionally cancel a statement so
1038 // they aren't indicating a failure.
1039 case SQLITE_ABORT4:
1040 case SQLITE_INTERRUPT9:
1041 break;
1042 case SQLITE_CORRUPT11:
1043 case SQLITE_NOTADB26:
1044 mozilla::glean::sqlite_store::query.Get(histogramKey, "corrupt"_ns).Add();
1045 break;
1046 case SQLITE_PERM3:
1047 case SQLITE_CANTOPEN14:
1048 case SQLITE_LOCKED6:
1049 case SQLITE_READONLY8:
1050 mozilla::glean::sqlite_store::query.Get(histogramKey, "access"_ns).Add();
1051 break;
1052 case SQLITE_IOERR10:
1053 case SQLITE_NOLFS22:
1054 mozilla::glean::sqlite_store::query.Get(histogramKey, "diskio"_ns).Add();
1055 break;
1056 case SQLITE_FULL13:
1057 case SQLITE_TOOBIG18:
1058 mozilla::glean::sqlite_store::query.Get(histogramKey, "diskspace"_ns)
1059 .Add();
1060 break;
1061 case SQLITE_CONSTRAINT19:
1062 case SQLITE_RANGE25:
1063 case SQLITE_MISMATCH20:
1064 case SQLITE_MISUSE21:
1065 mozilla::glean::sqlite_store::query.Get(histogramKey, "misuse"_ns).Add();
1066 break;
1067 case SQLITE_BUSY5:
1068 mozilla::glean::sqlite_store::query.Get(histogramKey, "busy"_ns).Add();
1069 break;
1070 default:
1071 mozilla::glean::sqlite_store::query.Get(histogramKey, "failure"_ns).Add();
1072 }
1073}
1074
1075nsresult Connection::initialize(const nsACString& aStorageKey,
1076 const nsACString& aName) {
1077 MOZ_ASSERT(aStorageKey.Equals(kMozStorageMemoryStorageKey))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStorageKey.Equals(kMozStorageMemoryStorageKey))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aStorageKey.Equals(kMozStorageMemoryStorageKey)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aStorageKey.Equals(kMozStorageMemoryStorageKey)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1077
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStorageKey.Equals(kMozStorageMemoryStorageKey)"
")"); do { MOZ_CrashSequence(__null, 1077); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1078 NS_ASSERTION(!connectionReady(),do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1079
); MOZ_PretendNoReturn(); } } while (0)
1079 "Initialize called on already opened database!")do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1079
); MOZ_PretendNoReturn(); } } while (0)
;
1080 MOZ_ASSERT(!mIgnoreLockingMode, "Can't ignore locking on an in-memory db.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIgnoreLockingMode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIgnoreLockingMode))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!mIgnoreLockingMode"
" (" "Can't ignore locking on an in-memory db." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIgnoreLockingMode"
") (" "Can't ignore locking on an in-memory db." ")"); do { MOZ_CrashSequence
(__null, 1080); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1081 AUTO_PROFILER_LABEL("Connection::initialize", OTHER)mozilla::AutoProfilerLabel raiiObject1081( "Connection::initialize"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
1082
1083 mStorageKey = aStorageKey;
1084 mName = aName;
1085
1086 // in memory database requested, sqlite uses a magic file name
1087
1088 const nsAutoCString path =
1089 mName.IsEmpty() ? nsAutoCString(":memory:"_ns)
1090 : "file:"_ns + mName + "?mode=memory&cache=shared"_ns;
1091
1092 int srv = ::sqlite3_open_v2(path.get(), &mDBConn, mFlags,
1093 basevfs::GetVFSName(true));
1094 if (srv != SQLITE_OK0) {
1095 ::sqlite3_close(mDBConn);
1096 mDBConn = nullptr;
1097 nsresult rv = convertResultCode(srv);
1098 RecordOpenStatus(rv);
1099 return rv;
1100 }
1101
1102#ifdef MOZ_SQLITE_FTS3_TOKENIZER
1103 srv =
1104 ::sqlite3_db_config(mDBConn, SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER1004, 1, 0);
1105 MOZ_ASSERT(srv == SQLITE_OK,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("srv == 0" " (" "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1106); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv == 0" ") ("
"SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled" ")"
); do { MOZ_CrashSequence(__null, 1106); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1106 "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("srv == 0" " (" "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1106); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv == 0" ") ("
"SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled" ")"
); do { MOZ_CrashSequence(__null, 1106); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1107#endif
1108
1109 // Do not set mDatabaseFile or mFileURL here since this is a "memory"
1110 // database.
1111
1112 nsresult rv = initializeInternal();
1113 RecordOpenStatus(rv);
1114 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1114); return rv; } } while (false)
;
1115
1116 return NS_OK;
1117}
1118
1119nsresult Connection::initialize(nsIFile* aDatabaseFile) {
1120 NS_ASSERTION(aDatabaseFile, "Passed null file!")do { if (!(aDatabaseFile)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Passed null file!", "aDatabaseFile", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1120); MOZ_PretendNoReturn(); } } while (0)
;
1121 NS_ASSERTION(!connectionReady(),do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1122
); MOZ_PretendNoReturn(); } } while (0)
1122 "Initialize called on already opened database!")do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1122
); MOZ_PretendNoReturn(); } } while (0)
;
1123 AUTO_PROFILER_LABEL("Connection::initialize", OTHER)mozilla::AutoProfilerLabel raiiObject1123( "Connection::initialize"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
1124
1125 // Do not set mFileURL here since this is database does not have an associated
1126 // URL.
1127 mDatabaseFile = aDatabaseFile;
1128
1129 nsAutoString path;
1130 nsresult rv = aDatabaseFile->GetPath(path);
1131 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1131); return rv; } } while (false)
;
1132
1133 // Open through obfsvfs with a per-file key when encryption is on and the DB
1134 // lives inside the profile. Outside-profile DBs (e.g. xpcshell tmp files)
1135 // are explicitly opened as plaintext on the base VFS below.
1136 if (StaticPrefs::security_storage_encryption_sqlite_enabled()) {
1137 nsAutoCString dbPath = NS_ConvertUTF16toUTF8(path);
1138 EncryptionStatus encStatus;
1139 rv = GetDatabaseEncryptionStatus(dbPath, encStatus);
1140 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1140); return rv; } } while (false)
;
1141
1142 bool exists = false;
1143 aDatabaseFile->Exists(&exists);
1144 const bool readOnly = mFlags & SQLITE_OPEN_READONLY0x00000001;
1145
1146 // A read-only open of a database that does not exist has nothing to
1147 // decrypt and cannot mint a key; fall through to the base open, which
1148 // fails with the natural file error rather than a key-lookup failure.
1149 if (encStatus == EncryptionStatus::Encrypted && !(readOnly && !exists)) {
1150 if (!EnsureNSSInitializedChromeOrContent()) {
1151 return NS_ERROR_FAILURE;
1152 }
1153
1154 OpenIntent intent =
1155 exists ? OpenIntent::LoadExisting : OpenIntent::CreateIfNew;
1156
1157 nsCString dbKey;
1158 rv = GetEncryptionKey(dbPath, intent, dbKey);
1159 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1159); return rv; } } while (false)
;
1160
1161 SetDatabaseEncrypted(true);
1162
1163 PreparePathForURI(dbPath);
1164 nsAutoCString dbSpec = "file:"_ns + dbPath + "?key="_ns + dbKey;
1165
1166 int srv =
1167 ::sqlite3_open_v2(dbSpec.get(), &mDBConn, mFlags | SQLITE_OPEN_URI0x00000040,
1168 obfsvfs::GetVFSName());
1169 if (srv != SQLITE_OK0) {
1170 ::sqlite3_close(mDBConn);
1171 mDBConn = nullptr;
1172 rv = convertResultCode(srv);
1173 RecordOpenStatus(rv);
1174 return rv;
1175 }
1176
1177 rv = initializeInternal();
1178 RecordOpenStatus(rv);
1179 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1179); return rv; } } while (false)
;
1180 return NS_OK;
1181 }
1182 // Plaintext (out-of-profile), or a read-only open of a missing database:
1183 // fall through to the base-VFS open below. The encrypted branch above is
1184 // the only way an in-profile encrypted database opens; an existing one must
1185 // never reach the plaintext base VFS.
1186 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(encStatus != EncryptionStatus::Encrypted || (readOnly
&& !exists))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(encStatus != EncryptionStatus
::Encrypted || (readOnly && !exists)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
" (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
") (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")"); do { MOZ_CrashSequence(__null, 1189); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1187 encStatus != EncryptionStatus::Encrypted || (readOnly && !exists),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(encStatus != EncryptionStatus::Encrypted || (readOnly
&& !exists))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(encStatus != EncryptionStatus
::Encrypted || (readOnly && !exists)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
" (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
") (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")"); do { MOZ_CrashSequence(__null, 1189); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1188 "an existing encrypted database must not fall through to a "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(encStatus != EncryptionStatus::Encrypted || (readOnly
&& !exists))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(encStatus != EncryptionStatus
::Encrypted || (readOnly && !exists)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
" (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
") (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")"); do { MOZ_CrashSequence(__null, 1189); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1189 "plaintext VFS")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(encStatus != EncryptionStatus::Encrypted || (readOnly
&& !exists))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(encStatus != EncryptionStatus
::Encrypted || (readOnly && !exists)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
" (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
") (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")"); do { MOZ_CrashSequence(__null, 1189); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
1190 }
1191
1192 bool exclusive =
1193 StaticPrefs::storage_sqlite_exclusiveLock_enabled() && !mOpenNotExclusive;
1194 int srv;
1195 if (mIgnoreLockingMode) {
1196 exclusive = false;
1197 srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, mFlags,
1198 "readonly-immutable-nolock");
1199 } else {
1200 srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, mFlags,
1201 basevfs::GetVFSName(exclusive));
1202 if (exclusive && (srv == SQLITE_LOCKED6 || srv == SQLITE_BUSY5)) {
1203 ::sqlite3_close(mDBConn);
1204 // Retry without trying to get an exclusive lock.
1205 exclusive = false;
1206 srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn,
1207 mFlags, basevfs::GetVFSName(false));
1208 }
1209 }
1210 if (srv != SQLITE_OK0) {
1211 ::sqlite3_close(mDBConn);
1212 mDBConn = nullptr;
1213 rv = convertResultCode(srv);
1214 RecordOpenStatus(rv);
1215 return rv;
1216 }
1217
1218 rv = initializeInternal();
1219 if (exclusive &&
1220 (rv == NS_ERROR_STORAGE_BUSY || rv == NS_ERROR_FILE_IS_LOCKED)) {
1221 // Usually SQLite will fail to acquire an exclusive lock on opening, but in
1222 // some cases it may successfully open the database and then lock on the
1223 // first query execution. When initializeInternal fails it closes the
1224 // connection, so we can try to restart it in non-exclusive mode.
1225 srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, mFlags,
1226 basevfs::GetVFSName(false));
1227 if (srv == SQLITE_OK0) {
1228 rv = initializeInternal();
1229 } else {
1230 ::sqlite3_close(mDBConn);
1231 mDBConn = nullptr;
1232 }
1233 }
1234
1235 RecordOpenStatus(rv);
1236 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1236); return rv; } } while (false)
;
1237
1238 return NS_OK;
1239}
1240
1241nsresult Connection::initialize(nsIFileURL* aFileURL) {
1242 NS_ASSERTION(aFileURL, "Passed null file URL!")do { if (!(aFileURL)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Passed null file URL!"
, "aFileURL", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1242); MOZ_PretendNoReturn(); } } while (0)
;
1243 NS_ASSERTION(!connectionReady(),do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1244
); MOZ_PretendNoReturn(); } } while (0)
1244 "Initialize called on already opened database!")do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1244
); MOZ_PretendNoReturn(); } } while (0)
;
1245 AUTO_PROFILER_LABEL("Connection::initialize", OTHER)mozilla::AutoProfilerLabel raiiObject1245( "Connection::initialize"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
1246
1247 nsCOMPtr<nsIFile> databaseFile;
1248 nsresult rv = aFileURL->GetFile(getter_AddRefs(databaseFile));
1249 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1249); return rv; } } while (false)
;
1250
1251 // Set both mDatabaseFile and mFileURL here.
1252 mFileURL = aFileURL;
1253 mDatabaseFile = databaseFile;
1254
1255 nsAutoCString spec;
1256 rv = aFileURL->GetSpec(spec);
1257 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1257); return rv; } } while (false)
;
1258
1259 // If there is a key specified, we need to use the obfuscating VFS.
1260 nsAutoCString query;
1261 rv = aFileURL->GetQuery(query);
1262 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1262); return rv; } } while (false)
;
1263
1264 bool hasKey = false;
1265 bool hasDirectoryLockId = false;
1266 // Set when the encryption policy says this database must be encrypted; used
1267 // below to fail closed rather than ever open an expected-encrypted database
1268 // through a plaintext VFS.
1269 bool mustEncrypt = false;
1270
1271 MOZ_ALWAYS_TRUE(do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1272 URLParams::Parse(query, true,do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1273 [&hasKey, &hasDirectoryLockId](do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1274 const nsACString& aName, const nsACString& aValue) {do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1275 if (aName.EqualsLiteral("key")) {do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1276 hasKey = true;do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1277 return true;do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1278 }do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1279 if (aName.EqualsLiteral("directoryLockId")) {do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1280 hasDirectoryLockId = true;do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1281 return true;do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1282 }do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1283 return true;do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1284 }))do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1284
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1285
1286 if (StaticPrefs::security_storage_encryption_sqlite_enabled()) {
1287 // A key already in the URL means the caller is opening an encrypted DB
1288 // with its own key, so trust it. Otherwise look up the per-file key for
1289 // in-profile databases; databases outside the profile have no stable key
1290 // and stay unencrypted on the base VFS.
1291 if (!hasKey) {
1292 nsAutoString dbPathUtf16;
1293 rv = mDatabaseFile->GetPath(dbPathUtf16);
1294 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1294); return rv; } } while (false)
;
1295 nsAutoCString dbPath = NS_ConvertUTF16toUTF8(dbPathUtf16);
1296
1297 EncryptionStatus encStatus;
1298 rv = GetDatabaseEncryptionStatus(dbPath, encStatus);
1299 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1299); return rv; } } while (false)
;
1300
1301 bool exists = false;
1302 mDatabaseFile->Exists(&exists);
1303 const bool readOnly = mFlags & SQLITE_OPEN_READONLY0x00000001;
1304
1305 // A read-only open of a database that does not exist has nothing to
1306 // decrypt and cannot mint a key; leave it unencrypted so the base open
1307 // fails with the natural file error rather than a key-lookup failure.
1308 mustEncrypt =
1309 encStatus == EncryptionStatus::Encrypted && !(readOnly && !exists);
1310 if (mustEncrypt) {
1311 if (!EnsureNSSInitializedChromeOrContent()) {
1312 return NS_ERROR_FAILURE;
1313 }
1314
1315 OpenIntent intent =
1316 exists ? OpenIntent::LoadExisting : OpenIntent::CreateIfNew;
1317
1318 nsCString dbKey;
1319 rv = GetEncryptionKey(dbPath, intent, dbKey);
1320 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1320); return rv; } } while (false)
;
1321 spec += (query.IsEmpty() ? "?key="_ns : "&key="_ns) + dbKey;
1322 hasKey = true;
1323 }
1324 }
1325 // hasKey now decides whether we open through obfsvfs (see the VFS
1326 // selection below); keep mDatabaseEncrypted and the page size in step.
1327 SetDatabaseEncrypted(hasKey);
1328 }
1329
1330 // Conservative fail-closed: a database the encryption policy says must be
1331 // encrypted opens through obfsvfs with its key, or not at all -- it must
1332 // never fall through to a plaintext VFS. GetEncryptionKey failures already
1333 // return above, so this also guards against a future regression adding a
1334 // silent-plaintext path.
1335 if (mustEncrypt && !hasKey) {
1336 RecordOpenStatus(NS_ERROR_FAILURE);
1337 return NS_ERROR_FAILURE;
1338 }
1339
1340 bool exclusive =
1341 StaticPrefs::storage_sqlite_exclusiveLock_enabled() && !mOpenNotExclusive;
1342
1343 const char* const vfs = hasKey ? obfsvfs::GetVFSName()
1344 : hasDirectoryLockId ? quotavfs::GetVFSName()
1345 : basevfs::GetVFSName(exclusive);
1346
1347 int srv = ::sqlite3_open_v2(spec.get(), &mDBConn, mFlags, vfs);
1348 if (srv != SQLITE_OK0) {
1349 ::sqlite3_close(mDBConn);
1350 mDBConn = nullptr;
1351 rv = convertResultCode(srv);
1352 RecordOpenStatus(rv);
1353 return rv;
1354 }
1355
1356 rv = initializeInternal();
1357 RecordOpenStatus(rv);
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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1358); return rv; } } while (false)
;
1359
1360 return NS_OK;
1361}
1362
1363nsresult Connection::initializeInternal() {
1364 MOZ_ASSERT(mDBConn)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDBConn)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDBConn))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDBConn", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDBConn" ")"
); do { MOZ_CrashSequence(__null, 1364); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1365 auto guard = MakeScopeExit([&]() { initializeFailed(); });
1366
1367 mConnectionClosed = false;
1368
1369#ifdef MOZ_SQLITE_FTS3_TOKENIZER
1370 DebugOnly<int> srv2 =
1371 ::sqlite3_db_config(mDBConn, SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER1004, 1, 0);
1372 MOZ_ASSERT(srv2 == SQLITE_OK,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv2 == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv2 == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("srv2 == 0" " (" "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1373); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv2 == 0" ") ("
"SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled" ")"
); do { MOZ_CrashSequence(__null, 1373); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1373 "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv2 == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv2 == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("srv2 == 0" " (" "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1373); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv2 == 0" ") ("
"SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled" ")"
); do { MOZ_CrashSequence(__null, 1373); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1374#endif
1375
1376 // Properly wrap the database handle's mutex.
1377 sharedDBMutex.initWithMutex(sqlite3_db_mutex(mDBConn));
1378
1379 // SQLite tracing can slow down queries (especially long queries)
1380 // significantly. Don't trace unless the user is actively monitoring SQLite.
1381 if (MOZ_LOG_TEST(gStorageLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gStorageLog, LogLevel
::Debug)), 0))
) {
1382 ::sqlite3_trace_v2(mDBConn, SQLITE_TRACE_STMT0x01 | SQLITE_TRACE_PROFILE0x02,
1383 tracefunc, this);
1384
1385 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Opening connection to '%s' (%p)", mTelemetryFilename
.get(), this); } } while (0)
1386 gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Opening connection to '%s' (%p)", mTelemetryFilename
.get(), this); } } while (0)
1387 ("Opening connection to '%s' (%p)", mTelemetryFilename.get(), this))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Opening connection to '%s' (%p)", mTelemetryFilename
.get(), this); } } while (0)
;
1388 }
1389
1390 // Encrypted DBs go through obfsvfs which writes whole pages of exactly
1391 // obfsvfs::kObfsPageSize. If we issued PRAGMA page_size = 32768 here, the
1392 // obfsvfs xWrite would see iAmt != kObfsPageSize and silently pass writes
1393 // through to the base VFS plaintext, even though a DEK had been minted in
1394 // lockstore. Match GetDefaultPageSize.
1395 int64_t pageSize = mPageSize;
1396
1397 // Set page_size to the preferred default value. This is effective only if
1398 // the database has just been created, otherwise, if the database does not
1399 // use WAL journal mode, a VACUUM operation will updated its page_size.
1400 nsAutoCString pageSizeQuery(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ "
1401 "PRAGMA page_size = ");
1402 pageSizeQuery.AppendInt(pageSize);
1403 int srv = executeSql(mDBConn, pageSizeQuery.get());
1404 if (srv != SQLITE_OK0) {
1405 return convertResultCode(srv);
1406 }
1407
1408 // Setting the cache_size forces the database open, verifying if it is valid
1409 // or corrupt. So this is executed regardless it being actually needed.
1410 // The cache_size is calculated from the actual page_size, to save memory.
1411 nsAutoCString cacheSizeQuery(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ "
1412 "PRAGMA cache_size = ");
1413 cacheSizeQuery.AppendInt(-MAX_CACHE_SIZE_KIBIBYTES2048);
1414 srv = executeSql(mDBConn, cacheSizeQuery.get());
1415 if (srv != SQLITE_OK0) {
1416 return convertResultCode(srv);
1417 }
1418
1419 // Register our built-in SQL functions.
1420 srv = registerFunctions(mDBConn);
1421 if (srv != SQLITE_OK0) {
1422 return convertResultCode(srv);
1423 }
1424
1425 // Register our built-in SQL collating sequences.
1426 srv = mozilla::intl::AppCollator::InstallCallbacks(mDBConn);
1427 if (srv != SQLITE_OK0) {
1428 return convertResultCode(srv);
1429 }
1430
1431 // Set the default synchronous value. Each consumer can switch this
1432 // accordingly to their needs.
1433#if defined(ANDROID)
1434 // Android prefers synchronous = OFF for performance reasons.
1435 (void)ExecuteSimpleSQL("PRAGMA synchronous = OFF;"_ns);
1436#else
1437 // Normal is the suggested value for WAL journals.
1438 (void)ExecuteSimpleSQL("PRAGMA synchronous = NORMAL;"_ns);
1439#endif
1440
1441 // Initialization succeeded, we can stop guarding for failures.
1442 guard.release();
1443 return NS_OK;
1444}
1445
1446nsresult Connection::initializeOnAsyncThread(nsIFile* aStorageFile) {
1447 MOZ_ASSERT(!IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1447
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 1447); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1448 nsresult rv = aStorageFile
1449 ? initialize(aStorageFile)
1450 : initialize(kMozStorageMemoryStorageKey, VoidCString());
1451 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1452 // Shutdown the async thread, since initialization failed.
1453 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1454 mAsyncExecutionThreadShuttingDown = true;
1455 nsCOMPtr<nsIRunnable> event =
1456 NewRunnableMethod("Connection::shutdownAsyncThread", this,
1457 &Connection::shutdownAsyncThread);
1458 (void)NS_DispatchToMainThread(event);
1459 }
1460 return rv;
1461}
1462
1463void Connection::initializeFailed() {
1464 {
1465 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1466 mConnectionClosed = true;
1467 }
1468 MOZ_ALWAYS_TRUE(::sqlite3_close(mDBConn) == SQLITE_OK)do { if ((__builtin_expect(!!(::sqlite3_close(mDBConn) == 0),
1))) { } else { do { do { } while (false); MOZ_ReportCrash(""
"::sqlite3_close(mDBConn) == SQLITE_OK", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1468); AnnotateMozCrashReason("MOZ_CRASH(" "::sqlite3_close(mDBConn) == SQLITE_OK"
")"); do { MOZ_CrashSequence(__null, 1468); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1469 mDBConn = nullptr;
1470 sharedDBMutex.destroy();
1471}
1472
1473nsresult Connection::databaseElementExists(
1474 enum DatabaseElementType aElementType, const nsACString& aElementName,
1475 bool* _exists) {
1476 if (!connectionReady()) {
1477 return NS_ERROR_NOT_AVAILABLE;
1478 }
1479 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
1480 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1481 return rv;
1482 }
1483
1484 // When constructing the query, make sure to SELECT the correct db's
1485 // sqlite_master if the user is prefixing the element with a specific db. ex:
1486 // sample.test
1487 nsCString query("SELECT name FROM (SELECT * FROM ");
1488 nsDependentCSubstring element;
1489 int32_t ind = aElementName.FindChar('.');
1490 if (ind == kNotFound) {
1491 element.Assign(aElementName);
1492 } else {
1493 nsDependentCSubstring db(Substring(aElementName, 0, ind + 1));
1494 element.Assign(Substring(aElementName, ind + 1, aElementName.Length()));
1495 query.Append(db);
1496 }
1497 query.AppendLiteral(
1498 "sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type = "
1499 "'");
1500
1501 switch (aElementType) {
1502 case INDEX:
1503 query.AppendLiteral("index");
1504 break;
1505 case TABLE:
1506 query.AppendLiteral("table");
1507 break;
1508 }
1509 query.AppendLiteral("' AND name ='");
1510 query.Append(element);
1511 query.Append('\'');
1512
1513 sqlite3_stmt* stmt;
1514 int srv = prepareStatement(mDBConn, query, &stmt);
1515 if (srv != SQLITE_OK0) {
1516 RecordQueryStatus(srv);
1517 return convertResultCode(srv);
1518 }
1519
1520 srv = stepStatement(mDBConn, stmt);
1521 // we just care about the return value from step
1522 (void)::sqlite3_finalize(stmt);
1523
1524 RecordQueryStatus(srv);
1525
1526 if (srv == SQLITE_ROW100) {
1527 *_exists = true;
1528 return NS_OK;
1529 }
1530 if (srv == SQLITE_DONE101) {
1531 *_exists = false;
1532 return NS_OK;
1533 }
1534
1535 return convertResultCode(srv);
1536}
1537
1538bool Connection::findFunctionByInstance(mozIStorageFunction* aInstance) {
1539 sharedDBMutex.assertCurrentThreadOwns();
1540
1541 for (const auto& data : mFunctions.Values()) {
1542 if (data.function == aInstance) {
1543 return true;
1544 }
1545 }
1546 return false;
1547}
1548
1549/* static */
1550int Connection::sProgressHelper(void* aArg) {
1551 Connection* _this = static_cast<Connection*>(aArg);
1552 return _this->progressHandler();
1553}
1554
1555int Connection::progressHandler() {
1556 sharedDBMutex.assertCurrentThreadOwns();
1557 if (mProgressHandler) {
1558 bool result;
1559 nsresult rv = mProgressHandler->OnProgress(this, &result);
1560 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return 0; // Don't break request
1561 return result ? 1 : 0;
1562 }
1563 return 0;
1564}
1565
1566nsresult Connection::setClosedState() {
1567 // Flag that we are shutting down the async thread, so that
1568 // getAsyncExecutionTarget knows not to expose/create the async thread.
1569 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1570 NS_ENSURE_FALSE(mAsyncExecutionThreadShuttingDown, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(!(mAsyncExecutionThreadShuttingDown
))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!(mAsyncExecutionThreadShuttingDown)" ") failed", nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1570); return NS_ERROR_UNEXPECTED; } } while (false)
;
1571
1572 mAsyncExecutionThreadShuttingDown = true;
1573
1574 // Set the property to null before closing the connection, otherwise the
1575 // other functions in the module may try to use the connection after it is
1576 // closed.
1577 mDBConn = nullptr;
1578
1579 return NS_OK;
1580}
1581
1582bool Connection::operationSupported(ConnectionOperation aOperationType) {
1583 if (aOperationType == ASYNCHRONOUS) {
1584 // Async operations are supported for all connections, on any thread.
1585 return true;
1586 }
1587 // Sync operations are supported for sync connections (on any thread), and
1588 // async connections on a background thread.
1589 MOZ_ASSERT(aOperationType == SYNCHRONOUS)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOperationType == SYNCHRONOUS)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOperationType == SYNCHRONOUS
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aOperationType == SYNCHRONOUS", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1589); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOperationType == SYNCHRONOUS"
")"); do { MOZ_CrashSequence(__null, 1589); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1590 return mSupportedOperations == SYNCHRONOUS || !NS_IsMainThread();
1591}
1592
1593nsresult Connection::ensureOperationSupported(
1594 ConnectionOperation aOperationType) {
1595 if (NS_WARN_IF(!operationSupported(aOperationType))NS_warn_if_impl(!operationSupported(aOperationType), "!operationSupported(aOperationType)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1595
)
) {
1596#ifdef DEBUG1
1597 if (NS_IsMainThread()) {
1598 nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
1599 (void)xpc->DebugDumpJSStack(false, false, false);
1600 }
1601#endif
1602 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Don't use async connections synchronously on the main thread"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Don't use async connections synchronously on the main thread"
")"); do { MOZ_CrashSequence(__null, 1603); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1603 "Don't use async connections synchronously on the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Don't use async connections synchronously on the main thread"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Don't use async connections synchronously on the main thread"
")"); do { MOZ_CrashSequence(__null, 1603); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1604 return NS_ERROR_NOT_AVAILABLE;
1605 }
1606 return NS_OK;
1607}
1608
1609bool Connection::isConnectionReadyOnThisThread() {
1610 MOZ_ASSERT_IF(connectionReady(), !mConnectionClosed)do { if (connectionReady()) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(!mConnectionClosed)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mConnectionClosed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mConnectionClosed", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mConnectionClosed"
")"); do { MOZ_CrashSequence(__null, 1610); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1611 if (mAsyncExecutionThread && mAsyncExecutionThread->IsOnCurrentThread()) {
1612 return true;
1613 }
1614 return connectionReady();
1615}
1616
1617bool Connection::isClosing() {
1618 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1619 return mAsyncExecutionThreadShuttingDown && !mConnectionClosed;
1620}
1621
1622bool Connection::isClosed() {
1623 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1624 return mConnectionClosed;
1625}
1626
1627bool Connection::isClosed(MutexAutoLock& lock) { return mConnectionClosed; }
1628
1629bool Connection::isAsyncExecutionThreadAvailable() {
1630 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1630
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 1630); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1631 return mAsyncExecutionThread && !mAsyncExecutionThreadShuttingDown;
1632}
1633
1634void Connection::shutdownAsyncThread() {
1635 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1635
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 1635); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1636 MOZ_ASSERT(mAsyncExecutionThread)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncExecutionThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncExecutionThread))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("mAsyncExecutionThread"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1636
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncExecutionThread"
")"); do { MOZ_CrashSequence(__null, 1636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1637 MOZ_ASSERT(mAsyncExecutionThreadShuttingDown)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncExecutionThreadShuttingDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncExecutionThreadShuttingDown
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAsyncExecutionThreadShuttingDown", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1637); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncExecutionThreadShuttingDown"
")"); do { MOZ_CrashSequence(__null, 1637); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1638
1639 MOZ_ALWAYS_SUCCEEDS(mAsyncExecutionThread->Shutdown())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mAsyncExecutionThread->Shutdown())), 1)))), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mAsyncExecutionThread->Shutdown())"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1639
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mAsyncExecutionThread->Shutdown())"
")"); do { MOZ_CrashSequence(__null, 1639); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1640 mAsyncExecutionThread = nullptr;
1641}
1642
1643nsresult Connection::internalClose(sqlite3* aNativeConnection) {
1644#ifdef DEBUG1
1645 { // Make sure we have marked our async thread as shutting down.
1646 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1647 MOZ_ASSERT(mAsyncExecutionThreadShuttingDown,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncExecutionThreadShuttingDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncExecutionThreadShuttingDown
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAsyncExecutionThreadShuttingDown" " (" "Did not call setClosedState!"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncExecutionThreadShuttingDown"
") (" "Did not call setClosedState!" ")"); do { MOZ_CrashSequence
(__null, 1648); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1648 "Did not call setClosedState!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncExecutionThreadShuttingDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncExecutionThreadShuttingDown
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAsyncExecutionThreadShuttingDown" " (" "Did not call setClosedState!"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncExecutionThreadShuttingDown"
") (" "Did not call setClosedState!" ")"); do { MOZ_CrashSequence
(__null, 1648); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1649 MOZ_ASSERT(!isClosed(lockedScope), "Unexpected closed state")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isClosed(lockedScope))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isClosed(lockedScope)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!isClosed(lockedScope)"
" (" "Unexpected closed state" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1649); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isClosed(lockedScope)"
") (" "Unexpected closed state" ")"); do { MOZ_CrashSequence
(__null, 1649); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1650 }
1651#endif // DEBUG
1652
1653 if (MOZ_LOG_TEST(gStorageLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gStorageLog, LogLevel
::Debug)), 0))
) {
1654 nsAutoCString leafName(":memory");
1655 if (mDatabaseFile) (void)mDatabaseFile->GetNativeLeafName(leafName);
1656 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Closing connection to '%s'", leafName.get
()); } } while (0)
1657 ("Closing connection to '%s'", leafName.get()))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Closing connection to '%s'", leafName.get
()); } } while (0)
;
1658 }
1659
1660 // At this stage, we may still have statements that need to be
1661 // finalized. Attempt to close the database connection. This will
1662 // always disconnect any virtual tables and cleanly finalize their
1663 // internal statements. Once this is done, closing may fail due to
1664 // unfinalized client statements, in which case we need to finalize
1665 // these statements and close again.
1666 {
1667 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1668 mConnectionClosed = true;
1669 }
1670
1671 // Nothing else needs to be done if we don't have a connection here.
1672 if (!aNativeConnection) return NS_OK;
1673
1674 int srv = ::sqlite3_close(aNativeConnection);
1675
1676 if (srv == SQLITE_BUSY5) {
1677 {
1678 // Nothing else should change the connection or statements status until we
1679 // are done here.
1680 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
1681 // We still have non-finalized statements. Finalize them.
1682 while (sqlite3_stmt* stmt =
1683 ::sqlite3_next_stmt(aNativeConnection, nullptr)) {
1684 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Auto-finalizing SQL statement '%s' (%p)",
::sqlite3_sql(stmt), stmt); } } while (0)
1685 ("Auto-finalizing SQL statement '%s' (%p)", ::sqlite3_sql(stmt),do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Auto-finalizing SQL statement '%s' (%p)",
::sqlite3_sql(stmt), stmt); } } while (0)
1686 stmt))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Auto-finalizing SQL statement '%s' (%p)",
::sqlite3_sql(stmt), stmt); } } while (0)
;
1687
1688#ifdef DEBUG1
1689 SmprintfPointer msg = ::mozilla::Smprintf(
1690 "SQL statement '%s' (%p) should have been finalized before closing "
1691 "the connection",
1692 ::sqlite3_sql(stmt), stmt);
1693 NS_WARNING(msg.get())NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1693)
;
1694#endif // DEBUG
1695
1696 (void)::sqlite3_finalize(stmt);
1697 }
1698 // Scope exiting will unlock the mutex before we invoke sqlite3_close()
1699 // again, since Sqlite will try to acquire it.
1700 }
1701
1702 // Now that all statements have been finalized, we
1703 // should be able to close.
1704 srv = ::sqlite3_close(aNativeConnection);
Value stored to 'srv' is never read
1705 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Had to forcibly close the database connection because not all "
"the statements have been finalized." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Had to forcibly close the database connection because not all "
"the statements have been finalized." ")"); do { MOZ_CrashSequence
(__null, 1707); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1706 "Had to forcibly close the database connection because not all "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Had to forcibly close the database connection because not all "
"the statements have been finalized." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Had to forcibly close the database connection because not all "
"the statements have been finalized." ")"); do { MOZ_CrashSequence
(__null, 1707); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1707 "the statements have been finalized.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Had to forcibly close the database connection because not all "
"the statements have been finalized." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Had to forcibly close the database connection because not all "
"the statements have been finalized." ")"); do { MOZ_CrashSequence
(__null, 1707); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1708 }
1709
1710 if (srv == SQLITE_OK0) {
1711 sharedDBMutex.destroy();
1712 } else {
1713 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "sqlite3_close failed. There are probably outstanding "
"statements that are listed above!" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1715); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"sqlite3_close failed. There are probably outstanding " "statements that are listed above!"
")"); do { MOZ_CrashSequence(__null, 1715); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1714 "sqlite3_close failed. There are probably outstanding "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "sqlite3_close failed. There are probably outstanding "
"statements that are listed above!" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1715); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"sqlite3_close failed. There are probably outstanding " "statements that are listed above!"
")"); do { MOZ_CrashSequence(__null, 1715); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1715 "statements that are listed above!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "sqlite3_close failed. There are probably outstanding "
"statements that are listed above!" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1715); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"sqlite3_close failed. There are probably outstanding " "statements that are listed above!"
")"); do { MOZ_CrashSequence(__null, 1715); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1716 }
1717
1718 return convertResultCode(srv);
1719}
1720
1721nsCString Connection::getFilename() { return mTelemetryFilename; }
1722
1723int Connection::stepStatement(sqlite3* aNativeConnection,
1724 sqlite3_stmt* aStatement) {
1725 MOZ_ASSERT(aStatement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStatement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStatement))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aStatement", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1725); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatement"
")"); do { MOZ_CrashSequence(__null, 1725); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1726
1727 AUTO_PROFILER_LABEL_DYNAMIC_CSTR("Connection::stepStatement", OTHER,mozilla::AutoProfilerLabel raiiObject1728( "Connection::stepStatement"
, ::sqlite3_sql(aStatement), JS::ProfilingCategoryPair::OTHER
)
1728 ::sqlite3_sql(aStatement))mozilla::AutoProfilerLabel raiiObject1728( "Connection::stepStatement"
, ::sqlite3_sql(aStatement), JS::ProfilingCategoryPair::OTHER
)
;
1729
1730 bool checkedMainThread = false;
1731 TimeStamp startTime = TimeStamp::Now();
1732
1733 // The connection may have been closed if the executing statement has been
1734 // created and cached after a call to asyncClose() but before the actual
1735 // sqlite3_close(). This usually happens when other tasks using cached
1736 // statements are asynchronously scheduled for execution and any of them ends
1737 // up after asyncClose. See bug 728653 for details.
1738 if (!isConnectionReadyOnThisThread()) return SQLITE_MISUSE21;
1739
1740 (void)::sqlite3_extended_result_codes(aNativeConnection, 1);
1741
1742 int srv;
1743 while ((srv = ::sqlite3_step(aStatement)) == SQLITE_LOCKED_SHAREDCACHE(6 | (1<<8))) {
1744 if (!checkedMainThread) {
1745 checkedMainThread = true;
1746 if (::NS_IsMainThread()) {
1747 NS_WARNING("We won't allow blocking on the main thread!")NS_DebugBreak(NS_DEBUG_WARNING, "We won't allow blocking on the main thread!"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1747)
;
1748 break;
1749 }
1750 }
1751
1752 srv = WaitForUnlockNotify(aNativeConnection);
1753 if (srv != SQLITE_OK0) {
1754 break;
1755 }
1756
1757 ::sqlite3_reset(aStatement);
1758 }
1759
1760 // Report very slow SQL statements to Telemetry
1761 TimeDuration duration = TimeStamp::Now() - startTime;
1762 const uint32_t threshold = NS_IsMainThread()
1763 ? Telemetry::kSlowSQLThresholdForMainThread
1764 : Telemetry::kSlowSQLThresholdForHelperThreads;
1765 if (duration.ToMilliseconds() >= threshold) {
1766 nsDependentCString statementString(::sqlite3_sql(aStatement));
1767 Telemetry::RecordSlowSQLStatement(
1768 statementString, mTelemetryFilename,
1769 static_cast<uint32_t>(duration.ToMilliseconds()));
1770 }
1771
1772 (void)::sqlite3_extended_result_codes(aNativeConnection, 0);
1773 // Drop off the extended result bits of the result code.
1774 return srv & 0xFF;
1775}
1776
1777int Connection::prepareStatement(sqlite3* aNativeConnection,
1778 const nsCString& aSQL, sqlite3_stmt** _stmt) {
1779 // We should not even try to prepare statements after the connection has
1780 // been closed.
1781 if (!isConnectionReadyOnThisThread()) return SQLITE_MISUSE21;
1782
1783 bool checkedMainThread = false;
1784
1785 (void)::sqlite3_extended_result_codes(aNativeConnection, 1);
1786
1787 int srv;
1788 while ((srv = ::sqlite3_prepare_v2(aNativeConnection, aSQL.get(), -1, _stmt,
1789 nullptr)) == SQLITE_LOCKED_SHAREDCACHE(6 | (1<<8))) {
1790 if (!checkedMainThread) {
1791 checkedMainThread = true;
1792 if (::NS_IsMainThread()) {
1793 NS_WARNING("We won't allow blocking on the main thread!")NS_DebugBreak(NS_DEBUG_WARNING, "We won't allow blocking on the main thread!"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1793)
;
1794 break;
1795 }
1796 }
1797
1798 srv = WaitForUnlockNotify(aNativeConnection);
1799 if (srv != SQLITE_OK0) {
1800 break;
1801 }
1802 }
1803
1804 if (srv != SQLITE_OK0) {
1805 nsCString warnMsg;
1806 warnMsg.AppendLiteral("The SQL statement '");
1807 warnMsg.Append(aSQL);
1808 warnMsg.AppendLiteral("' could not be compiled due to an error: ");
1809 warnMsg.Append(::sqlite3_errmsg(aNativeConnection));
1810
1811#ifdef DEBUG1
1812 NS_WARNING(warnMsg.get())NS_DebugBreak(NS_DEBUG_WARNING, warnMsg.get(), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1812)
;
1813#endif
1814 MOZ_LOG(gStorageLog, LogLevel::Error, ("%s", warnMsg.get()))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Error)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Error, "%s", warnMsg.get()); } } while (0)
;
1815 }
1816
1817 (void)::sqlite3_extended_result_codes(aNativeConnection, 0);
1818 // Drop off the extended result bits of the result code.
1819 int rc = srv & 0xFF;
1820 // sqlite will return OK on a comment only string and set _stmt to nullptr.
1821 // The callers of this function are used to only checking the return value,
1822 // so it is safer to return an error code.
1823 if (rc == SQLITE_OK0 && *_stmt == nullptr) {
1824 return SQLITE_MISUSE21;
1825 }
1826
1827 return rc;
1828}
1829
1830int Connection::executeSql(sqlite3* aNativeConnection, const char* aSqlString) {
1831 if (!isConnectionReadyOnThisThread()) return SQLITE_MISUSE21;
1832
1833 AUTO_PROFILER_LABEL_DYNAMIC_CSTR("Connection::executeSql", OTHER, aSqlString)mozilla::AutoProfilerLabel raiiObject1833( "Connection::executeSql"
, aSqlString, JS::ProfilingCategoryPair::OTHER)
;
1834
1835 TimeStamp startTime = TimeStamp::Now();
1836 int srv =
1837 ::sqlite3_exec(aNativeConnection, aSqlString, nullptr, nullptr, nullptr);
1838 RecordQueryStatus(srv);
1839
1840 // Report very slow SQL statements to Telemetry
1841 TimeDuration duration = TimeStamp::Now() - startTime;
1842 const uint32_t threshold = NS_IsMainThread()
1843 ? Telemetry::kSlowSQLThresholdForMainThread
1844 : Telemetry::kSlowSQLThresholdForHelperThreads;
1845 if (duration.ToMilliseconds() >= threshold) {
1846 nsDependentCString statementString(aSqlString);
1847 Telemetry::RecordSlowSQLStatement(
1848 statementString, mTelemetryFilename,
1849 static_cast<uint32_t>(duration.ToMilliseconds()));
1850 }
1851
1852 return srv;
1853}
1854
1855////////////////////////////////////////////////////////////////////////////////
1856//// nsIInterfaceRequestor
1857
1858NS_IMETHODIMPnsresult
1859Connection::GetInterface(const nsIID& aIID, void** _result) {
1860 if (aIID.Equals(NS_GET_IID(nsIEventTarget)(nsIEventTarget::kIID))) {
1861 nsIEventTarget* background = getAsyncExecutionTarget();
1862 NS_IF_ADDREF(background)ns_if_addref(background);
1863 *_result = background;
1864 return NS_OK;
1865 }
1866 return NS_ERROR_NO_INTERFACE;
1867}
1868
1869////////////////////////////////////////////////////////////////////////////////
1870//// mozIStorageConnection
1871
1872NS_IMETHODIMPnsresult
1873Connection::Close() {
1874 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
1875 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1876 return rv;
1877 }
1878 return synchronousClose();
1879}
1880
1881nsresult Connection::synchronousClose() {
1882 if (!connectionReady()) {
1883 return NS_ERROR_NOT_INITIALIZED;
1884 }
1885
1886#ifdef DEBUG1
1887 // Since we're accessing mAsyncExecutionThread, we need to be on the opener
1888 // event target. We make this check outside of debug code below in
1889 // setClosedState, but this is here to be explicit.
1890 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1890
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 1890); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1891#endif // DEBUG
1892
1893 // Make sure we have not executed any asynchronous statements.
1894 // If this fails, the mDBConn may be left open, resulting in a leak.
1895 // We'll try to finalize the pending statements and close the connection.
1896 if (isAsyncExecutionThreadAvailable()) {
1897#ifdef DEBUG1
1898 if (NS_IsMainThread()) {
1899 nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
1900 (void)xpc->DebugDumpJSStack(false, false, false);
1901 }
1902#endif
1903 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")"); do { MOZ_CrashSequence
(__null, 1906); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1904 "Close() was invoked on a connection that executed asynchronous "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")"); do { MOZ_CrashSequence
(__null, 1906); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1905 "statements. "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")"); do { MOZ_CrashSequence
(__null, 1906); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1906 "Should have used asyncClose().")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")"); do { MOZ_CrashSequence
(__null, 1906); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1907 // Try to close the database regardless, to free up resources.
1908 (void)SpinningSynchronousClose();
1909 return NS_ERROR_UNEXPECTED;
1910 }
1911
1912 // setClosedState nullifies our connection pointer, so we take a raw pointer
1913 // off it, to pass it through the close procedure.
1914 sqlite3* nativeConn = mDBConn;
1915 nsresult rv = setClosedState();
1916 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1916); return rv; } } while (false)
;
1917
1918 return internalClose(nativeConn);
1919}
1920
1921NS_IMETHODIMPnsresult
1922Connection::SpinningSynchronousClose() {
1923 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
1924 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1925 return rv;
1926 }
1927 if (!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)) {
1928 return NS_ERROR_NOT_SAME_THREAD;
1929 }
1930
1931 // As currently implemented, we can't spin to wait for an existing AsyncClose.
1932 // Our only existing caller will never have called close; assert if misused
1933 // so that no new callers assume this works after an AsyncClose.
1934 MOZ_DIAGNOSTIC_ASSERT(connectionReady())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(connectionReady())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(connectionReady()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1934
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "connectionReady()"
")"); do { MOZ_CrashSequence(__null, 1934); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1935 if (!connectionReady()) {
1936 return NS_ERROR_UNEXPECTED;
1937 }
1938
1939 auto listener = MakeRefPtr<CloseListener>();
1940 rv = AsyncClose(listener);
1941 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1941); return rv; } } while (false)
;
1942 MOZ_ALWAYS_TRUE(do { if ((__builtin_expect(!!(SpinEventLoopUntil("storage::Connection::SpinningSynchronousClose"_ns
, [&]() { return listener->mClosed; })), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1944
); AnnotateMozCrashReason("MOZ_CRASH(" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
")"); do { MOZ_CrashSequence(__null, 1944); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1943 SpinEventLoopUntil("storage::Connection::SpinningSynchronousClose"_ns,do { if ((__builtin_expect(!!(SpinEventLoopUntil("storage::Connection::SpinningSynchronousClose"_ns
, [&]() { return listener->mClosed; })), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1944
); AnnotateMozCrashReason("MOZ_CRASH(" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
")"); do { MOZ_CrashSequence(__null, 1944); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1944 [&]() { return listener->mClosed; }))do { if ((__builtin_expect(!!(SpinEventLoopUntil("storage::Connection::SpinningSynchronousClose"_ns
, [&]() { return listener->mClosed; })), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1944
); AnnotateMozCrashReason("MOZ_CRASH(" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
")"); do { MOZ_CrashSequence(__null, 1944); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1945 MOZ_ASSERT(isClosed(), "The connection should be closed at this point")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isClosed())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isClosed()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("isClosed()" " (" "The connection should be closed at this point"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1945); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isClosed()" ") ("
"The connection should be closed at this point" ")"); do { MOZ_CrashSequence
(__null, 1945); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1946
1947 return rv;
1948}
1949
1950NS_IMETHODIMPnsresult
1951Connection::AsyncClose(mozIStorageCompletionCallback* aCallback) {
1952 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1952); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
1953 // Check if AsyncClose or Close were already invoked.
1954 if (!connectionReady()) {
1955 return NS_ERROR_NOT_INITIALIZED;
1956 }
1957 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
1958 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1959 return rv;
1960 }
1961
1962 // The two relevant factors at this point are whether we have a database
1963 // connection and whether we have an async execution thread. Here's what the
1964 // states mean and how we handle them:
1965 //
1966 // - (mDBConn && asyncThread): The expected case where we are either an
1967 // async connection or a sync connection that has been used asynchronously.
1968 // Either way the caller must call us and not Close(). Nothing surprising
1969 // about this. We'll dispatch AsyncCloseConnection to the already-existing
1970 // async thread.
1971 //
1972 // - (mDBConn && !asyncThread): A somewhat unusual case where the caller
1973 // opened the connection synchronously and was planning to use it
1974 // asynchronously, but never got around to using it asynchronously before
1975 // needing to shutdown. This has been observed to happen for the cookie
1976 // service in a case where Firefox shuts itself down almost immediately
1977 // after startup (for unknown reasons). In the Firefox shutdown case,
1978 // we may also fail to create a new async execution thread if one does not
1979 // already exist. (nsThreadManager will refuse to create new threads when
1980 // it has already been told to shutdown.) As such, we need to handle a
1981 // failure to create the async execution thread by falling back to
1982 // synchronous Close() and also dispatching the completion callback because
1983 // at least Places likes to spin a nested event loop that depends on the
1984 // callback being invoked.
1985 //
1986 // Note that we have considered not trying to spin up the async execution
1987 // thread in this case if it does not already exist, but the overhead of
1988 // thread startup (if successful) is significantly less expensive than the
1989 // worst-case potential I/O hit of synchronously closing a database when we
1990 // could close it asynchronously.
1991 //
1992 // - (!mDBConn && asyncThread): This happens in some but not all cases where
1993 // OpenAsyncDatabase encountered a problem opening the database. If it
1994 // happened in all cases AsyncInitDatabase would just shut down the thread
1995 // directly and we would avoid this case. But it doesn't, so for simplicity
1996 // and consistency AsyncCloseConnection knows how to handle this and we
1997 // act like this was the (mDBConn && asyncThread) case in this method.
1998 //
1999 // - (!mDBConn && !asyncThread): The database was never successfully opened or
2000 // Close() or AsyncClose() has already been called (at least) once. This is
2001 // undeniably a misuse case by the caller. We could optimize for this
2002 // case by adding an additional check of mAsyncExecutionThread without using
2003 // getAsyncExecutionTarget() to avoid wastefully creating a thread just to
2004 // shut it down. But this complicates the method for broken caller code
2005 // whereas we're still correct and safe without the special-case.
2006 nsIEventTarget* asyncThread = getAsyncExecutionTarget();
2007
2008 // Create our callback event if we were given a callback. This will
2009 // eventually be dispatched in all cases, even if we fall back to Close() and
2010 // the database wasn't open and we return an error. The rationale is that
2011 // no existing consumer checks our return value and several of them like to
2012 // spin nested event loops until the callback fires. Given that, it seems
2013 // preferable for us to dispatch the callback in all cases. (Except the
2014 // wrong thread misuse case we bailed on up above. But that's okay because
2015 // that is statically wrong whereas these edge cases are dynamic.)
2016 nsCOMPtr<nsIRunnable> completeEvent;
2017 if (aCallback) {
2018 completeEvent = newCompletionEvent(aCallback);
2019 }
2020
2021 if (!asyncThread) {
2022 // We were unable to create an async thread, so we need to fall back to
2023 // using normal Close(). Since there is no async thread, Close() will
2024 // not complain about that. (Close() may, however, complain if the
2025 // connection is closed, but that's okay.)
2026 if (completeEvent) {
2027 // Closing the database is more important than returning an error code
2028 // about a failure to dispatch, especially because all existing native
2029 // callers ignore our return value.
2030 (void)NS_DispatchToMainThread(completeEvent.forget());
2031 }
2032 MOZ_ALWAYS_SUCCEEDS(synchronousClose())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(synchronousClose())), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(synchronousClose())"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2032
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(synchronousClose())"
")"); do { MOZ_CrashSequence(__null, 2032); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2033 // Return a success inconditionally here, since Close() is unlikely to fail
2034 // and we want to reassure the consumer that its callback will be invoked.
2035 return NS_OK;
2036 }
2037
2038 // If we're closing the connection during shutdown, and there is an
2039 // interruptible statement running on the helper thread, issue a
2040 // sqlite3_interrupt() to avoid crashing when that statement takes a long
2041 // time (for example a vacuum).
2042 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed) &&
2043 mInterruptible && mIsStatementOnHelperThreadInterruptible) {
2044 MOZ_ASSERT(!isClosing(), "Must not be closing, see Interrupt()")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isClosing())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isClosing()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!isClosing()" " ("
"Must not be closing, see Interrupt()" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2044); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isClosing()"
") (" "Must not be closing, see Interrupt()" ")"); do { MOZ_CrashSequence
(__null, 2044); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2045 DebugOnly<nsresult> rv2 = Interrupt();
2046 MOZ_ASSERT(NS_SUCCEEDED(rv2))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1)))", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2046); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2047 }
2048
2049 // setClosedState nullifies our connection pointer, so we take a raw pointer
2050 // off it, to pass it through the close procedure.
2051 sqlite3* nativeConn = mDBConn;
2052 rv = setClosedState();
2053 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2053); return rv; } } while (false)
;
2054
2055 // Create and dispatch our close event to the background thread.
2056 nsCOMPtr<nsIRunnable> closeEvent =
2057 new AsyncCloseConnection(this, nativeConn, completeEvent);
2058 rv = asyncThread->Dispatch(closeEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2059 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2059); return rv; } } while (false)
;
2060
2061 return NS_OK;
2062}
2063
2064NS_IMETHODIMPnsresult
2065Connection::AsyncClone(bool aReadOnly,
2066 mozIStorageCompletionCallback* aCallback) {
2067 AUTO_PROFILER_LABEL("Connection::AsyncClone", OTHER)mozilla::AutoProfilerLabel raiiObject2067( "Connection::AsyncClone"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
2068
2069 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2069); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
2070 if (!connectionReady()) {
2071 return NS_ERROR_NOT_INITIALIZED;
2072 }
2073 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2074 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2075 return rv;
2076 }
2077 if (!mDatabaseFile) return NS_ERROR_UNEXPECTED;
2078
2079 int flags = mFlags;
2080 if (aReadOnly) {
2081 // Turn off SQLITE_OPEN_READWRITE, and set SQLITE_OPEN_READONLY.
2082 flags = (~SQLITE_OPEN_READWRITE0x00000002 & flags) | SQLITE_OPEN_READONLY0x00000001;
2083 // Turn off SQLITE_OPEN_CREATE.
2084 flags = (~SQLITE_OPEN_CREATE0x00000004 & flags);
2085 }
2086
2087 // The cloned connection will still implement the synchronous API, but throw
2088 // if any synchronous methods are called on the main thread.
2089 auto clone = MakeRefPtr<Connection>(mStorageService, flags, ASYNCHRONOUS,
2090 mTelemetryFilename, mInterruptible,
2091 mIgnoreLockingMode, mOpenNotExclusive);
2092
2093 auto initEvent =
2094 MakeRefPtr<AsyncInitializeClone>(this, clone, aReadOnly, aCallback);
2095 // Dispatch to our async thread, since the originating connection must remain
2096 // valid and open for the whole cloning process. This also ensures we are
2097 // properly serialized with a `close` operation, rather than race with it.
2098 nsCOMPtr<nsIEventTarget> target = getAsyncExecutionTarget();
2099 if (!target) {
2100 return NS_ERROR_UNEXPECTED;
2101 }
2102 return target->Dispatch(initEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2103}
2104
2105nsresult Connection::initializeClone(Connection* aClone, bool aReadOnly) {
2106 nsresult rv;
2107 if (!mStorageKey.IsEmpty()) {
2108 rv = aClone->initialize(mStorageKey, mName);
2109 } else if (mFileURL) {
2110 rv = aClone->initialize(mFileURL);
2111 } else {
2112 rv = aClone->initialize(mDatabaseFile);
2113 }
2114 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2115 return rv;
2116 }
2117
2118 auto guard = MakeScopeExit([&]() { aClone->initializeFailed(); });
2119
2120 rv = aClone->SetDefaultTransactionType(mDefaultTransactionType);
2121 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2121); return rv; } } while (false)
;
2122
2123 // Re-attach on-disk databases that were attached to the original connection.
2124 {
2125 nsCOMPtr<mozIStorageStatement> stmt;
2126 rv = CreateStatement("PRAGMA database_list"_ns, getter_AddRefs(stmt));
2127 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2127); return rv; } } while (false)
;
2128 bool hasResult = false;
2129 while (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2130 nsAutoCString name;
2131 rv = stmt->GetUTF8String(1, name);
2132 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !name.EqualsLiteral("main") &&
2133 !name.EqualsLiteral("temp")) {
2134 nsCString path;
2135 rv = stmt->GetUTF8String(2, path);
2136 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !path.IsEmpty()) {
2137 nsCOMPtr<mozIStorageStatement> attachStmt;
2138 rv = aClone->CreateStatement("ATTACH DATABASE :path AS "_ns + name,
2139 getter_AddRefs(attachStmt));
2140 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2140); return rv; } } while (false)
;
2141
2142 if (mDatabaseEncrypted) {
2143 // Extract into a distinct dbPath: BuildFileURIWithKey must not
2144 // alias its input and output. It assigns "file:" to the output
2145 // first and then appends the input path, so passing the same
2146 // string for both clobbers the path and yields "file:file:?key="
2147 // -- a malformed URI that fails the ATTACH and the whole clone.
2148 nsCString dbKey, query, dbPath;
2149 rv = ExtractURIPathAndQuery(path.get(), dbPath, query);
2150 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2150); return rv; } } while (false)
;
2151
2152 EncryptionStatus encStatus;
2153 rv = GetDatabaseEncryptionStatus(dbPath, encStatus);
2154 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2154); return rv; } } while (false)
;
2155
2156 // An out-of-profile attached DB stays unencrypted (path left as
2157 // is). In-profile attached DBs always pre-exist, so load the DEK.
2158 if (encStatus == EncryptionStatus::Encrypted) {
2159 rv = GetEncryptionKey(dbPath, OpenIntent::LoadExisting, dbKey);
2160 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2160); return rv; } } while (false)
;
2161
2162 PreparePathForURI(dbPath);
2163 BuildFileURIWithKey(dbPath, query, dbKey, path);
2164 }
2165 }
2166 rv = attachStmt->BindUTF8StringByName("path"_ns, path);
2167 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2167); return rv; } } while (false)
;
2168 rv = attachStmt->Execute();
2169 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2169); return rv; } } while (false)
;
2170 }
2171 }
2172 }
2173 }
2174
2175 // Copy over pragmas from the original connection.
2176 // LIMITATION WARNING! Many of these pragmas are actually scoped to the
2177 // schema ("main" and any other attached databases), and this implmentation
2178 // fails to propagate them. This is being addressed on trunk.
2179 static const char* pragmas[] = {
2180 "cache_size", "temp_store", "foreign_keys", "journal_size_limit",
2181 "synchronous", "wal_autocheckpoint", "busy_timeout"};
2182 for (auto& pragma : pragmas) {
2183 // Read-only connections just need cache_size and temp_store pragmas.
2184 if (aReadOnly && ::strcmp(pragma, "cache_size") != 0 &&
2185 ::strcmp(pragma, "temp_store") != 0) {
2186 continue;
2187 }
2188
2189 nsAutoCString pragmaQuery("PRAGMA ");
2190 pragmaQuery.Append(pragma);
2191 nsCOMPtr<mozIStorageStatement> stmt;
2192 rv = CreateStatement(pragmaQuery, getter_AddRefs(stmt));
2193 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2193); return rv; } } while (false)
;
2194 bool hasResult = false;
2195 if (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2196 pragmaQuery.AppendLiteral(" = ");
2197 pragmaQuery.AppendInt(stmt->AsInt32(0));
2198 rv = aClone->ExecuteSimpleSQL(pragmaQuery);
2199 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2199); return rv; } } while (false)
;
2200 }
2201 }
2202
2203 // Copy over temporary tables, triggers, and views from the original
2204 // connections. Entities in `sqlite_temp_master` are only visible to the
2205 // connection that created them.
2206 if (!aReadOnly) {
2207 rv = aClone->ExecuteSimpleSQL("BEGIN TRANSACTION"_ns);
2208 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2208); return rv; } } while (false)
;
2209
2210 nsCOMPtr<mozIStorageStatement> stmt;
2211 rv = CreateStatement(nsLiteralCString("SELECT sql FROM sqlite_temp_master "
2212 "WHERE type IN ('table', 'view', "
2213 "'index', 'trigger')"),
2214 getter_AddRefs(stmt));
2215 // Propagate errors, because failing to copy triggers might cause schema
2216 // coherency issues when writing to the database from the cloned connection.
2217 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2217); return rv; } } while (false)
;
2218 bool hasResult = false;
2219 while (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2220 nsAutoCString query;
2221 rv = stmt->GetUTF8String(0, query);
2222 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2222); return rv; } } while (false)
;
2223
2224 // The `CREATE` SQL statements in `sqlite_temp_master` omit the `TEMP`
2225 // keyword. We need to add it back, or we'll recreate temporary entities
2226 // as persistent ones. `sqlite_temp_master` also holds `CREATE INDEX`
2227 // statements, but those don't need `TEMP` keywords.
2228 if (StringBeginsWith(query, "CREATE TABLE "_ns) ||
2229 StringBeginsWith(query, "CREATE TRIGGER "_ns) ||
2230 StringBeginsWith(query, "CREATE VIEW "_ns)) {
2231 query.Replace(0, 6, "CREATE TEMP");
2232 }
2233
2234 rv = aClone->ExecuteSimpleSQL(query);
2235 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2235); return rv; } } while (false)
;
2236 }
2237
2238 rv = aClone->ExecuteSimpleSQL("COMMIT"_ns);
2239 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2239); return rv; } } while (false)
;
2240 }
2241
2242 // Copy any functions that have been added to this connection.
2243 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2244 for (const auto& entry : mFunctions) {
2245 const nsACString& key = entry.GetKey();
2246 Connection::FunctionInfo data = entry.GetData();
2247
2248 rv = aClone->CreateFunction(key, data.numArgs, data.function);
2249 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2250 NS_WARNING("Failed to copy function to cloned connection")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to copy function to cloned connection"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2250)
;
2251 }
2252 }
2253
2254 // Load SQLite extensions that were on this connection.
2255 // Copy into an array rather than holding the mutex while we load extensions.
2256 nsTArray<nsCString> loadedExtensions;
2257 {
2258 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
2259 AppendToArray(loadedExtensions, mLoadedExtensions);
2260 }
2261 for (const auto& extension : loadedExtensions) {
2262 (void)aClone->LoadExtension(extension, nullptr);
2263 }
2264
2265 guard.release();
2266 return NS_OK;
2267}
2268
2269NS_IMETHODIMPnsresult
2270Connection::Clone(bool aReadOnly, mozIStorageConnection** _connection) {
2271 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2271
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 2271); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2272
2273 AUTO_PROFILER_LABEL("Connection::Clone", OTHER)mozilla::AutoProfilerLabel raiiObject2273( "Connection::Clone"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
2274
2275 if (!connectionReady()) {
2276 return NS_ERROR_NOT_INITIALIZED;
2277 }
2278 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2279 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2280 return rv;
2281 }
2282
2283 int flags = mFlags;
2284 if (aReadOnly) {
2285 // Turn off SQLITE_OPEN_READWRITE, and set SQLITE_OPEN_READONLY.
2286 flags = (~SQLITE_OPEN_READWRITE0x00000002 & flags) | SQLITE_OPEN_READONLY0x00000001;
2287 // Turn off SQLITE_OPEN_CREATE.
2288 flags = (~SQLITE_OPEN_CREATE0x00000004 & flags);
2289 }
2290
2291 auto clone =
2292 MakeRefPtr<Connection>(mStorageService, flags, mSupportedOperations,
2293 mTelemetryFilename, mInterruptible);
2294
2295 rv = initializeClone(clone, aReadOnly);
2296 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2297 return rv;
2298 }
2299
2300 NS_IF_ADDREF(*_connection = clone)ns_if_addref(*_connection = clone);
2301 return NS_OK;
2302}
2303
2304NS_IMETHODIMPnsresult
2305Connection::Interrupt() {
2306 MOZ_ASSERT(mInterruptible, "Interrupt method not allowed")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInterruptible)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInterruptible))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mInterruptible"
" (" "Interrupt method not allowed" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2306); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInterruptible"
") (" "Interrupt method not allowed" ")"); do { MOZ_CrashSequence
(__null, 2306); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2307 MOZ_ASSERT_IF(SYNCHRONOUS == mSupportedOperations,do { if (SYNCHRONOUS == mSupportedOperations) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!IsOnCurrentSerialEventTarget
(eventTargetOpenedOn))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsOnCurrentSerialEventTarget
(eventTargetOpenedOn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2308); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 2308); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2308 !IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { if (SYNCHRONOUS == mSupportedOperations) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!IsOnCurrentSerialEventTarget
(eventTargetOpenedOn))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsOnCurrentSerialEventTarget
(eventTargetOpenedOn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2308); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 2308); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2309 MOZ_ASSERT_IF(ASYNCHRONOUS == mSupportedOperations,do { if (ASYNCHRONOUS == mSupportedOperations) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(IsOnCurrentSerialEventTarget
(eventTargetOpenedOn))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsOnCurrentSerialEventTarget
(eventTargetOpenedOn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 2310); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2310 IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { if (ASYNCHRONOUS == mSupportedOperations) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(IsOnCurrentSerialEventTarget
(eventTargetOpenedOn))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsOnCurrentSerialEventTarget
(eventTargetOpenedOn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 2310); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2311
2312 if (!connectionReady()) {
2313 return NS_ERROR_NOT_INITIALIZED;
2314 }
2315
2316 if (isClosing()) { // Closing already in asynchronous case
2317 return NS_OK;
2318 }
2319
2320 {
2321 // As stated on https://www.sqlite.org/c3ref/interrupt.html,
2322 // it is not safe to call sqlite3_interrupt() when
2323 // database connection is closed or might close before
2324 // sqlite3_interrupt() returns.
2325 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
2326 if (!isClosed(lockedScope)) {
2327 MOZ_ASSERT(mDBConn)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDBConn)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDBConn))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDBConn", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDBConn" ")"
); do { MOZ_CrashSequence(__null, 2327); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2328 ::sqlite3_interrupt(mDBConn);
2329 }
2330 }
2331
2332 return NS_OK;
2333}
2334
2335NS_IMETHODIMPnsresult
2336Connection::AsyncVacuum(mozIStorageCompletionCallback* aCallback,
2337 bool aUseIncremental, int32_t aSetPageSize) {
2338 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2338); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
2339 // Abort if we're shutting down.
2340 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
2341 return NS_ERROR_ABORT;
2342 }
2343 // Check if AsyncClose or Close were already invoked.
2344 if (!connectionReady()) {
2345 return NS_ERROR_NOT_INITIALIZED;
2346 }
2347 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2348 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2349 return rv;
2350 }
2351 nsIEventTarget* asyncThread = getAsyncExecutionTarget();
2352 if (!asyncThread) {
2353 return NS_ERROR_NOT_INITIALIZED;
2354 }
2355
2356 // Create and dispatch our vacuum event to the background thread.
2357 nsCOMPtr<nsIRunnable> vacuumEvent =
2358 new AsyncVacuumEvent(this, aCallback, aUseIncremental, aSetPageSize);
2359 rv = asyncThread->Dispatch(vacuumEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2360 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2360); return rv; } } while (false)
;
2361
2362 return NS_OK;
2363}
2364
2365void Connection::SetDatabaseEncrypted(bool aEncrypted) {
2366 mDatabaseEncrypted = aEncrypted;
2367 // Encrypted DBs go through obfsvfs, which writes whole pages of exactly
2368 // kObfsPageSize. Keep the default page size in sync here so
2369 // initializeInternal() and GetDefaultPageSize() can't disagree.
2370 mPageSize = aEncrypted ? obfsvfs::kObfsPageSize : Service::kDefaultPageSize;
2371}
2372
2373NS_IMETHODIMPnsresult
2374Connection::GetDefaultPageSize(int32_t* _defaultPageSize) {
2375 // Mirrors the PRAGMA page_size set in initializeInternal(); both read
2376 // mPageSize, which SetDatabaseEncrypted() keeps in step with
2377 // mDatabaseEncrypted (a mismatch makes obfsvfs drop writes silently).
2378 *_defaultPageSize = mPageSize;
2379 return NS_OK;
2380}
2381
2382NS_IMETHODIMPnsresult
2383Connection::GetConnectionReady(bool* _ready) {
2384 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2384
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 2384); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2385 *_ready = connectionReady();
2386 return NS_OK;
2387}
2388
2389NS_IMETHODIMPnsresult
2390Connection::GetDatabaseFile(nsIFile** _dbFile) {
2391 if (!connectionReady()) {
2392 return NS_ERROR_NOT_INITIALIZED;
2393 }
2394 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2395 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2396 return rv;
2397 }
2398
2399 NS_IF_ADDREF(*_dbFile = mDatabaseFile)ns_if_addref(*_dbFile = mDatabaseFile);
2400
2401 return NS_OK;
2402}
2403
2404NS_IMETHODIMPnsresult
2405Connection::GetLastInsertRowID(int64_t* _id) {
2406 if (!connectionReady()) {
2407 return NS_ERROR_NOT_INITIALIZED;
2408 }
2409 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2410 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2411 return rv;
2412 }
2413
2414 sqlite_int64 id = ::sqlite3_last_insert_rowid(mDBConn);
2415 *_id = id;
2416
2417 return NS_OK;
2418}
2419
2420NS_IMETHODIMPnsresult
2421Connection::GetAffectedRows(int32_t* _rows) {
2422 if (!connectionReady()) {
2423 return NS_ERROR_NOT_INITIALIZED;
2424 }
2425 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2426 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2427 return rv;
2428 }
2429
2430 *_rows = ::sqlite3_changes(mDBConn);
2431
2432 return NS_OK;
2433}
2434
2435NS_IMETHODIMPnsresult
2436Connection::GetLastError(int32_t* _error) {
2437 if (!connectionReady()) {
2438 return NS_ERROR_NOT_INITIALIZED;
2439 }
2440 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2441 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2442 return rv;
2443 }
2444
2445 *_error = ::sqlite3_errcode(mDBConn);
2446
2447 return NS_OK;
2448}
2449
2450NS_IMETHODIMPnsresult
2451Connection::GetLastErrorString(nsACString& _errorString) {
2452 if (!connectionReady()) {
2453 return NS_ERROR_NOT_INITIALIZED;
2454 }
2455 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2456 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2457 return rv;
2458 }
2459
2460 const char* serr = ::sqlite3_errmsg(mDBConn);
2461 _errorString.Assign(serr);
2462
2463 return NS_OK;
2464}
2465
2466NS_IMETHODIMPnsresult
2467Connection::GetSchemaVersion(int32_t* _version) {
2468 if (!connectionReady()) {
2469 return NS_ERROR_NOT_INITIALIZED;
2470 }
2471 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2472 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2473 return rv;
2474 }
2475
2476 nsCOMPtr<mozIStorageStatement> stmt;
2477 (void)CreateStatement("PRAGMA user_version"_ns, getter_AddRefs(stmt));
2478 NS_ENSURE_TRUE(stmt, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(stmt)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stmt" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2478
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2479
2480 *_version = 0;
2481 bool hasResult;
2482 if (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2483 *_version = stmt->AsInt32(0);
2484 }
2485
2486 return NS_OK;
2487}
2488
2489NS_IMETHODIMPnsresult
2490Connection::SetSchemaVersion(int32_t aVersion) {
2491 if (!connectionReady()) {
2492 return NS_ERROR_NOT_INITIALIZED;
2493 }
2494 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2495 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2496 return rv;
2497 }
2498
2499 nsAutoCString stmt("PRAGMA user_version = "_ns);
2500 stmt.AppendInt(aVersion);
2501
2502 return ExecuteSimpleSQL(stmt);
2503}
2504
2505NS_IMETHODIMPnsresult
2506Connection::CreateStatement(const nsACString& aSQLStatement,
2507 mozIStorageStatement** _stmt) {
2508 NS_ENSURE_ARG_POINTER(_stmt)do { if ((__builtin_expect(!!(!(_stmt)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_stmt" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2508
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2509 if (!connectionReady()) {
2510 return NS_ERROR_NOT_INITIALIZED;
2511 }
2512 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2513 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2514 return rv;
2515 }
2516
2517 RefPtr<Statement> statement(new Statement());
2518 NS_ENSURE_TRUE(statement, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(statement)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "statement" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2518
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2519
2520 rv = statement->initialize(this, mDBConn, aSQLStatement);
2521 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2521); return rv; } } while (false)
;
2522
2523 Statement* rawPtr;
2524 statement.forget(&rawPtr);
2525 *_stmt = rawPtr;
2526 return NS_OK;
2527}
2528
2529NS_IMETHODIMPnsresult
2530Connection::CreateAsyncStatement(const nsACString& aSQLStatement,
2531 mozIStorageAsyncStatement** _stmt) {
2532 NS_ENSURE_ARG_POINTER(_stmt)do { if ((__builtin_expect(!!(!(_stmt)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_stmt" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2532
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2533 if (!connectionReady()) {
2534 return NS_ERROR_NOT_INITIALIZED;
2535 }
2536 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2537 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2538 return rv;
2539 }
2540
2541 RefPtr<AsyncStatement> statement(new AsyncStatement());
2542 NS_ENSURE_TRUE(statement, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(statement)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "statement" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2542
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2543
2544 rv = statement->initialize(this, mDBConn, aSQLStatement);
2545 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2545); return rv; } } while (false)
;
2546
2547 AsyncStatement* rawPtr;
2548 statement.forget(&rawPtr);
2549 *_stmt = rawPtr;
2550 return NS_OK;
2551}
2552
2553NS_IMETHODIMPnsresult
2554Connection::ExecuteSimpleSQL(const nsACString& aSQLStatement) {
2555 CHECK_MAINTHREAD_ABUSE()do { do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2555
); } } while (false); } while (0)
;
2556 if (!connectionReady()) {
2557 return NS_ERROR_NOT_INITIALIZED;
2558 }
2559 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2560 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2561 return rv;
2562 }
2563
2564 int srv = executeSql(mDBConn, PromiseFlatCStringTPromiseFlatString<char>(aSQLStatement).get());
2565 return convertResultCode(srv);
2566}
2567
2568NS_IMETHODIMPnsresult
2569Connection::ExecuteAsync(
2570 const nsTArray<RefPtr<mozIStorageBaseStatement>>& aStatements,
2571 mozIStorageStatementCallback* aCallback,
2572 mozIStoragePendingStatement** _handle) {
2573 nsTArray<StatementData> stmts(aStatements.Length());
2574 for (uint32_t i = 0; i < aStatements.Length(); i++) {
2575 nsCOMPtr<StorageBaseStatementInternal> stmt =
2576 do_QueryInterface(aStatements[i]);
2577 NS_ENSURE_STATE(stmt)do { if ((__builtin_expect(!!(!(stmt)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stmt" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2577
); return NS_ERROR_UNEXPECTED; } } while (false)
;
2578
2579 // Obtain our StatementData.
2580 StatementData data;
2581 nsresult rv = stmt->getAsynchronousStatementData(data);
2582 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2582); return rv; } } while (false)
;
2583
2584 NS_ASSERTION(stmt->getOwner() == this,do { if (!(stmt->getOwner() == this)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Statement must be from this database connection!", "stmt->getOwner() == this"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2585
); MOZ_PretendNoReturn(); } } while (0)
2585 "Statement must be from this database connection!")do { if (!(stmt->getOwner() == this)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Statement must be from this database connection!", "stmt->getOwner() == this"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2585
); MOZ_PretendNoReturn(); } } while (0)
;
2586
2587 // Now append it to our array.
2588 stmts.AppendElement(data);
2589 }
2590
2591 // Dispatch to the background
2592 return AsyncExecuteStatements::execute(std::move(stmts), this, mDBConn,
2593 aCallback, _handle);
2594}
2595
2596NS_IMETHODIMPnsresult
2597Connection::ExecuteSimpleSQLAsync(const nsACString& aSQLStatement,
2598 mozIStorageStatementCallback* aCallback,
2599 mozIStoragePendingStatement** _handle) {
2600 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2600); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
2601
2602 nsCOMPtr<mozIStorageAsyncStatement> stmt;
2603 nsresult rv = CreateAsyncStatement(aSQLStatement, getter_AddRefs(stmt));
2604 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2605 return rv;
2606 }
2607
2608 nsCOMPtr<mozIStoragePendingStatement> pendingStatement;
2609 rv = stmt->ExecuteAsync(aCallback, getter_AddRefs(pendingStatement));
2610 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2611 return rv;
2612 }
2613
2614 pendingStatement.forget(_handle);
2615 return rv;
2616}
2617
2618NS_IMETHODIMPnsresult
2619Connection::TableExists(const nsACString& aTableName, bool* _exists) {
2620 return databaseElementExists(TABLE, aTableName, _exists);
2621}
2622
2623NS_IMETHODIMPnsresult
2624Connection::IndexExists(const nsACString& aIndexName, bool* _exists) {
2625 return databaseElementExists(INDEX, aIndexName, _exists);
2626}
2627
2628NS_IMETHODIMPnsresult
2629Connection::GetTransactionInProgress(bool* _inProgress) {
2630 if (!connectionReady()) {
2631 return NS_ERROR_NOT_INITIALIZED;
2632 }
2633 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2634 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2635 return rv;
2636 }
2637
2638 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2639 *_inProgress = transactionInProgress(lockedScope);
2640 return NS_OK;
2641}
2642
2643NS_IMETHODIMPnsresult
2644Connection::GetDefaultTransactionType(int32_t* _type) {
2645 *_type = mDefaultTransactionType;
2646 return NS_OK;
2647}
2648
2649NS_IMETHODIMPnsresult
2650Connection::SetDefaultTransactionType(int32_t aType) {
2651 NS_ENSURE_ARG_RANGE(aType, TRANSACTION_DEFERRED, TRANSACTION_EXCLUSIVE)do { if ((__builtin_expect(!!(!(((aType) >= TRANSACTION_DEFERRED
) && ((aType) <= TRANSACTION_EXCLUSIVE))), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "((aType) >= TRANSACTION_DEFERRED) && ((aType) <= TRANSACTION_EXCLUSIVE)"
") failed", nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2651); return NS_ERROR_INVALID_ARG; } } while (false)
;
2652 mDefaultTransactionType = aType;
2653 return NS_OK;
2654}
2655
2656NS_IMETHODIMPnsresult
2657Connection::GetVariableLimit(int32_t* _limit) {
2658 if (!connectionReady()) {
2659 return NS_ERROR_NOT_INITIALIZED;
2660 }
2661 int limit = ::sqlite3_limit(mDBConn, SQLITE_LIMIT_VARIABLE_NUMBER9, -1);
2662 if (limit < 0) {
2663 return NS_ERROR_UNEXPECTED;
2664 }
2665 *_limit = limit;
2666 return NS_OK;
2667}
2668
2669NS_IMETHODIMPnsresult
2670Connection::SetVariableLimit(int32_t limit) {
2671 if (!connectionReady()) {
2672 return NS_ERROR_NOT_INITIALIZED;
2673 }
2674 int oldLimit = ::sqlite3_limit(mDBConn, SQLITE_LIMIT_VARIABLE_NUMBER9, limit);
2675 if (oldLimit < 0) {
2676 return NS_ERROR_UNEXPECTED;
2677 }
2678 return NS_OK;
2679}
2680
2681NS_IMETHODIMPnsresult
2682Connection::BeginTransaction() {
2683 if (!connectionReady()) {
2684 return NS_ERROR_NOT_INITIALIZED;
2685 }
2686 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2687 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2688 return rv;
2689 }
2690
2691 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2692 return beginTransactionInternal(lockedScope, mDBConn,
2693 mDefaultTransactionType);
2694}
2695
2696nsresult Connection::beginTransactionInternal(
2697 const SQLiteMutexAutoLock& aProofOfLock, sqlite3* aNativeConnection,
2698 int32_t aTransactionType) {
2699 if (transactionInProgress(aProofOfLock, aNativeConnection)) {
2700 return NS_ERROR_FAILURE;
2701 }
2702 nsresult rv;
2703 switch (aTransactionType) {
2704 case TRANSACTION_DEFERRED:
2705 rv = convertResultCode(executeSql(aNativeConnection, "BEGIN DEFERRED"));
2706 break;
2707 case TRANSACTION_IMMEDIATE:
2708 rv = convertResultCode(executeSql(aNativeConnection, "BEGIN IMMEDIATE"));
2709 break;
2710 case TRANSACTION_EXCLUSIVE:
2711 rv = convertResultCode(executeSql(aNativeConnection, "BEGIN EXCLUSIVE"));
2712 break;
2713 default:
2714 return NS_ERROR_ILLEGAL_VALUE;
2715 }
2716 return rv;
2717}
2718
2719NS_IMETHODIMPnsresult
2720Connection::CommitTransaction() {
2721 if (!connectionReady()) {
2722 return NS_ERROR_NOT_INITIALIZED;
2723 }
2724 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2725 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2726 return rv;
2727 }
2728
2729 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2730 return commitTransactionInternal(lockedScope, mDBConn);
2731}
2732
2733nsresult Connection::commitTransactionInternal(
2734 const SQLiteMutexAutoLock& aProofOfLock, sqlite3* aNativeConnection) {
2735 if (!transactionInProgress(aProofOfLock, aNativeConnection)) {
2736 return NS_ERROR_UNEXPECTED;
2737 }
2738 nsresult rv =
2739 convertResultCode(executeSql(aNativeConnection, "COMMIT TRANSACTION"));
2740 return rv;
2741}
2742
2743NS_IMETHODIMPnsresult
2744Connection::RollbackTransaction() {
2745 if (!connectionReady()) {
2746 return NS_ERROR_NOT_INITIALIZED;
2747 }
2748 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2749 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2750 return rv;
2751 }
2752
2753 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2754 return rollbackTransactionInternal(lockedScope, mDBConn);
2755}
2756
2757nsresult Connection::rollbackTransactionInternal(
2758 const SQLiteMutexAutoLock& aProofOfLock, sqlite3* aNativeConnection) {
2759 if (!transactionInProgress(aProofOfLock, aNativeConnection)) {
2760 return NS_ERROR_UNEXPECTED;
2761 }
2762
2763 nsresult rv =
2764 convertResultCode(executeSql(aNativeConnection, "ROLLBACK TRANSACTION"));
2765 return rv;
2766}
2767
2768NS_IMETHODIMPnsresult
2769Connection::CreateTable(const char* aTableName, const char* aTableSchema) {
2770 if (!connectionReady()) {
2771 return NS_ERROR_NOT_INITIALIZED;
2772 }
2773 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2774 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2775 return rv;
2776 }
2777
2778 SmprintfPointer buf =
2779 ::mozilla::Smprintf("CREATE TABLE %s (%s)", aTableName, aTableSchema);
2780 if (!buf) return NS_ERROR_OUT_OF_MEMORY;
2781
2782 int srv = executeSql(mDBConn, buf.get());
2783
2784 return convertResultCode(srv);
2785}
2786
2787NS_IMETHODIMPnsresult
2788Connection::AttachDatabase(const char* aPath, const char* aName,
2789 mozIStorageStatementCallback* aCallback,
2790 mozIStoragePendingStatement** _handle) {
2791 nsresult rv;
2792 nsCString uri;
2793
2794 bool encryptionEnabled =
2795 StaticPrefs::security_storage_encryption_sqlite_enabled();
2796 if (encryptionEnabled) {
2797 nsCString dbKey, path, query;
2798
2799 rv = ExtractURIPathAndQuery(aPath, path, query);
2800 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2800); return rv; } } while (false)
;
2801
2802 EncryptionStatus encStatus;
2803 rv = GetDatabaseEncryptionStatus(path, encStatus);
2804 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2804); return rv; } } while (false)
;
2805
2806 if (encStatus == EncryptionStatus::Encrypted) {
2807 // Attach targets always pre-exist, so load the DEK (never create one).
2808 rv = GetEncryptionKey(path, OpenIntent::LoadExisting, dbKey);
2809 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2809); return rv; } } while (false)
;
2810
2811 PreparePathForURI(path);
2812 BuildFileURIWithKey(path, query, dbKey, uri);
2813 } else {
2814 // Outside-profile DB; attach it unencrypted.
2815 uri = aPath;
2816 }
2817 } else {
2818 uri = aPath;
2819 }
2820
2821 nsCOMPtr<mozIStorageAsyncStatement> stmt;
2822 rv = CreateAsyncStatement("ATTACH DATABASE :path AS "_ns + nsCString(aName),
2823 getter_AddRefs(stmt));
2824 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2824); return rv; } } while (false)
;
2825
2826 rv = stmt->BindUTF8StringByName("path"_ns, uri);
2827 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2827); return rv; } } while (false)
;
2828
2829 nsCOMPtr<mozIStoragePendingStatement> pendingStatement;
2830 rv = stmt->ExecuteAsync(aCallback, getter_AddRefs(pendingStatement));
2831 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2831); return rv; } } while (false)
;
2832
2833 pendingStatement.forget(_handle);
2834
2835 return NS_OK;
2836}
2837
2838NS_IMETHODIMPnsresult
2839Connection::CreateFunction(const nsACString& aFunctionName,
2840 int32_t aNumArguments,
2841 mozIStorageFunction* aFunction) {
2842 if (!connectionReady()) {
2843 return NS_ERROR_NOT_INITIALIZED;
2844 }
2845 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2846 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2847 return rv;
2848 }
2849
2850 // Check to see if this function is already defined. We only check the name
2851 // because a function can be defined with the same body but different names.
2852 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2853 NS_ENSURE_FALSE(mFunctions.Contains(aFunctionName), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(!(mFunctions.Contains(aFunctionName
)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!(mFunctions.Contains(aFunctionName))" ") failed", nullptr,
"/root/firefox-clang/storage/mozStorageConnection.cpp", 2853
); return NS_ERROR_FAILURE; } } while (false)
;
2854
2855 int srv = ::sqlite3_create_function(
2856 mDBConn, nsPromiseFlatCString(aFunctionName).get(), aNumArguments,
2857 SQLITE_ANY5, aFunction, basicFunctionHelper, nullptr, nullptr);
2858 if (srv != SQLITE_OK0) return convertResultCode(srv);
2859
2860 FunctionInfo info = {aFunction, aNumArguments};
2861 mFunctions.InsertOrUpdate(aFunctionName, info);
2862
2863 return NS_OK;
2864}
2865
2866NS_IMETHODIMPnsresult
2867Connection::RemoveFunction(const nsACString& aFunctionName) {
2868 if (!connectionReady()) {
2869 return NS_ERROR_NOT_INITIALIZED;
2870 }
2871 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2872 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2873 return rv;
2874 }
2875
2876 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2877 auto entry = mFunctions.Lookup(aFunctionName);
2878 NS_ENSURE_TRUE(entry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(entry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "entry" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2878
); return NS_ERROR_FAILURE; } } while (false)
;
2879
2880 // SQLite allows to register the same function name with different number
2881 // of arguments, thus to properly remove our function we must use the same
2882 // nArg used at registration time.
2883 int srv = ::sqlite3_create_function(
2884 mDBConn, nsPromiseFlatCString(aFunctionName).get(), entry->numArgs,
2885 SQLITE_ANY5, nullptr, nullptr, nullptr, nullptr);
2886 if (srv != SQLITE_OK0) return convertResultCode(srv);
2887
2888 entry.Remove();
2889
2890 return NS_OK;
2891}
2892
2893NS_IMETHODIMPnsresult
2894Connection::SetProgressHandler(int32_t aGranularity,
2895 mozIStorageProgressHandler* aHandler,
2896 mozIStorageProgressHandler** _oldHandler) {
2897 if (!connectionReady()) {
2898 return NS_ERROR_NOT_INITIALIZED;
2899 }
2900 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2901 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2902 return rv;
2903 }
2904
2905 // Return previous one
2906 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2907 NS_IF_ADDREF(*_oldHandler = mProgressHandler)ns_if_addref(*_oldHandler = mProgressHandler);
2908
2909 if (!aHandler || aGranularity <= 0) {
2910 aHandler = nullptr;
2911 aGranularity = 0;
2912 }
2913 mProgressHandler = aHandler;
2914 ::sqlite3_progress_handler(mDBConn, aGranularity, sProgressHelper, this);
2915
2916 return NS_OK;
2917}
2918
2919NS_IMETHODIMPnsresult
2920Connection::RemoveProgressHandler(mozIStorageProgressHandler** _oldHandler) {
2921 if (!connectionReady()) {
2922 return NS_ERROR_NOT_INITIALIZED;
2923 }
2924 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2925 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2926 return rv;
2927 }
2928
2929 // Return previous one
2930 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2931 NS_IF_ADDREF(*_oldHandler = mProgressHandler)ns_if_addref(*_oldHandler = mProgressHandler);
2932
2933 mProgressHandler = nullptr;
2934 ::sqlite3_progress_handler(mDBConn, 0, nullptr, nullptr);
2935
2936 return NS_OK;
2937}
2938
2939NS_IMETHODIMPnsresult
2940Connection::SetGrowthIncrement(int32_t aChunkSize,
2941 const nsACString& aDatabaseName) {
2942 if (!connectionReady()) {
2943 return NS_ERROR_NOT_INITIALIZED;
2944 }
2945 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2946 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2947 return rv;
2948 }
2949
2950 // Bug 597215: Disk space is extremely limited on Android
2951 // so don't preallocate space. This is also not effective
2952 // on log structured file systems used by Android devices
2953#if !defined(ANDROID) && !defined(MOZ_PLATFORM_MAEMO)
2954 // Don't preallocate if less than 500MiB is available.
2955 int64_t bytesAvailable;
2956 rv = mDatabaseFile->GetDiskSpaceAvailable(&bytesAvailable);
2957 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, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2957); return rv; } } while (false)
;
2958 if (bytesAvailable < MIN_AVAILABLE_BYTES_PER_CHUNKED_GROWTH524288000) {
2959 return NS_ERROR_FILE_TOO_BIG;
2960 }
2961
2962 int srv = ::sqlite3_file_control(
2963 mDBConn,
2964 aDatabaseName.Length() ? nsPromiseFlatCString(aDatabaseName).get()
2965 : nullptr,
2966 SQLITE_FCNTL_CHUNK_SIZE6, &aChunkSize);
2967 if (srv == SQLITE_OK0) {
2968 mGrowthChunkSize = aChunkSize;
2969 }
2970#endif
2971 return NS_OK;
2972}
2973
2974int32_t Connection::RemovablePagesInFreeList(const nsACString& aSchemaName) {
2975 int32_t freeListPagesCount = 0;
2976 if (!isConnectionReadyOnThisThread()) {
2977 MOZ_ASSERT(false, "Database connection is not ready")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Database connection is not ready"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
2977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Database connection is not ready" ")"); do { MOZ_CrashSequence
(__null, 2977); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2978 return freeListPagesCount;
2979 }
2980 {
2981 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA ");
2982 query.Append(aSchemaName);
2983 query.AppendLiteral(".freelist_count");
2984 nsCOMPtr<mozIStorageStatement> stmt;
2985 DebugOnly<nsresult> rv = CreateStatement(query, getter_AddRefs(stmt));
2986 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2986); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2986); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2987 bool hasResult = false;
2988 if (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2989 freeListPagesCount = stmt->AsInt32(0);
2990 }
2991 }
2992 // If there's no chunk size set, any page is good to be removed.
2993 if (mGrowthChunkSize == 0 || freeListPagesCount == 0) {
2994 return freeListPagesCount;
2995 }
2996 int32_t pageSize;
2997 {
2998 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA ");
2999 query.Append(aSchemaName);
3000 query.AppendLiteral(".page_size");
3001 nsCOMPtr<mozIStorageStatement> stmt;
3002 DebugOnly<nsresult> rv = CreateStatement(query, getter_AddRefs(stmt));
3003 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3003); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 3003); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3004 bool hasResult = false;
3005 if (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
3006 pageSize = stmt->AsInt32(0);
3007 } else {
3008 MOZ_ASSERT(false, "Couldn't get page_size")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Couldn't get page_size"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
3008); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Couldn't get page_size" ")"); do { MOZ_CrashSequence(__null
, 3008); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
3009 return 0;
3010 }
3011 }
3012 return std::max(0, freeListPagesCount - (mGrowthChunkSize / pageSize));
3013}
3014
3015NS_IMETHODIMPnsresult
3016Connection::LoadExtension(const nsACString& aExtensionName,
3017 mozIStorageCompletionCallback* aCallback) {
3018 AUTO_PROFILER_LABEL("Connection::LoadExtension", OTHER)mozilla::AutoProfilerLabel raiiObject3018( "Connection::LoadExtension"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
3019
3020 // This is a static list of extensions we can load.
3021 // Please use lowercase ASCII names and keep this list alphabetically ordered.
3022 static constexpr nsLiteralCString sSupportedExtensions[] = {
3023 // clang-format off
3024 "fts5"_ns,
3025 #ifdef MOZ_SQLITE_VEC0_EXT1
3026 "vec"_ns,
3027 #endif
3028 // clang-format on
3029 };
3030 if (std::find(std::begin(sSupportedExtensions),
3031 std::end(sSupportedExtensions),
3032 aExtensionName) == std::end(sSupportedExtensions)) {
3033 return NS_ERROR_INVALID_ARG;
3034 }
3035
3036 if (!connectionReady()) {
3037 return NS_ERROR_NOT_INITIALIZED;
3038 }
3039
3040 int srv = ::sqlite3_db_config(mDBConn, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION1005,
3041 1, nullptr);
3042 if (srv != SQLITE_OK0) {
3043 return NS_ERROR_UNEXPECTED;
3044 }
3045
3046 // Track the loaded extension for later connection cloning operations.
3047 {
3048 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
3049 if (!mLoadedExtensions.EnsureInserted(aExtensionName)) {
3050 // Already loaded, bail out but issue a warning.
3051 NS_WARNING(nsPrintfCString(NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Tried to register '%s' SQLite extension multiple times!"
, TPromiseFlatString<char>(aExtensionName).get()) .get(
), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3054)
3052 "Tried to register '%s' SQLite extension multiple times!",NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Tried to register '%s' SQLite extension multiple times!"
, TPromiseFlatString<char>(aExtensionName).get()) .get(
), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3054)
3053 PromiseFlatCString(aExtensionName).get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Tried to register '%s' SQLite extension multiple times!"
, TPromiseFlatString<char>(aExtensionName).get()) .get(
), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3054)
3054 .get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Tried to register '%s' SQLite extension multiple times!"
, TPromiseFlatString<char>(aExtensionName).get()) .get(
), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3054)
;
3055 return NS_OK;
3056 }
3057 }
3058
3059 nsAutoCString entryPoint("sqlite3_");
3060 entryPoint.Append(aExtensionName);
3061 entryPoint.AppendLiteral("_init");
3062
3063 RefPtr<Runnable> loadTask = NS_NewRunnableFunction(
3064 "mozStorageConnection::LoadExtension",
3065 [this, self = RefPtr(this), entryPoint = std::move(entryPoint),
3066 callback = RefPtr(aCallback)]() mutable {
3067 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { MOZ_CrashSequence(__null
, 3072); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
3068 !NS_IsMainThread() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { MOZ_CrashSequence(__null
, 3072); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
3069 (operationSupported(Connection::SYNCHRONOUS) &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { MOZ_CrashSequence(__null
, 3072); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
3070 eventTargetOpenedOn == GetMainThreadSerialEventTarget()),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { MOZ_CrashSequence(__null
, 3072); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
3071 "Should happen on main-thread only for synchronous connections "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { MOZ_CrashSequence(__null
, 3072); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
3072 "opened on the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { MOZ_CrashSequence(__null
, 3072); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
3073#ifdef MOZ_FOLD_LIBS
3074 int srv = ::sqlite3_load_extension(mDBConn,
3075 MOZ_DLL_PREFIX"lib" "nss3" MOZ_DLL_SUFFIX".so",
3076 entryPoint.get(), nullptr);
3077#else
3078 int srv = ::sqlite3_load_extension(
3079 mDBConn, MOZ_DLL_PREFIX"lib" "mozsqlite3" MOZ_DLL_SUFFIX".so",
3080 entryPoint.get(), nullptr);
3081#endif
3082 if (!callback) {
3083 return;
3084 };
3085 RefPtr<Runnable> callbackTask = NS_NewRunnableFunction(
3086 "mozStorageConnection::LoadExtension_callback",
3087 [callback = std::move(callback), srv]() {
3088 (void)callback->Complete(convertResultCode(srv), nullptr);
3089 });
3090 if (IsOnCurrentSerialEventTarget(eventTargetOpenedOn)) {
3091 MOZ_ALWAYS_SUCCEEDS(callbackTask->Run())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(callbackTask->Run())), 1)))), 1))) { } else { do { do { }
while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(callbackTask->Run())"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3091
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(callbackTask->Run())"
")"); do { MOZ_CrashSequence(__null, 3091); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3092 } else {
3093 // Redispatch the callback to the calling thread.
3094 MOZ_ALWAYS_SUCCEEDS(eventTargetOpenedOn->Dispatch(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget
::DISPATCH_NORMAL))), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3095
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
")"); do { MOZ_CrashSequence(__null, 3095); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3095 callbackTask.forget(), NS_DISPATCH_NORMAL))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget
::DISPATCH_NORMAL))), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3095
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
")"); do { MOZ_CrashSequence(__null, 3095); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3096 }
3097 });
3098
3099 if (NS_IsMainThread() && !operationSupported(Connection::SYNCHRONOUS)) {
3100 // This is a main-thread call to an async-only connection, thus we should
3101 // load the library in the helper thread.
3102 nsIEventTarget* helperThread = getAsyncExecutionTarget();
3103 if (!helperThread) {
3104 return NS_ERROR_NOT_INITIALIZED;
3105 }
3106 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::
DISPATCH_NORMAL))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3107
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
")"); do { MOZ_CrashSequence(__null, 3107); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3107 helperThread->Dispatch(loadTask.forget(), NS_DISPATCH_NORMAL))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::
DISPATCH_NORMAL))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3107
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
")"); do { MOZ_CrashSequence(__null, 3107); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3108 } else {
3109 // In any other case we just load the extension on the current thread.
3110 MOZ_ALWAYS_SUCCEEDS(loadTask->Run())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(loadTask->Run())), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(loadTask->Run())"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3110
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(loadTask->Run())"
")"); do { MOZ_CrashSequence(__null, 3110); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3111 }
3112 return NS_OK;
3113}
3114
3115NS_IMETHODIMPnsresult
3116Connection::EnableModule(const nsACString& aModuleName) {
3117 if (!connectionReady()) {
3118 return NS_ERROR_NOT_INITIALIZED;
3119 }
3120 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
3121 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3122 return rv;
3123 }
3124
3125 for (auto& gModule : gModules) {
3126 struct Module* m = &gModule;
3127 if (aModuleName.Equals(m->name)) {
3128 int srv = m->registerFunc(mDBConn, m->name);
3129 if (srv != SQLITE_OK0) return convertResultCode(srv);
3130
3131 return NS_OK;
3132 }
3133 }
3134
3135 return NS_ERROR_FAILURE;
3136}
3137
3138NS_IMETHODIMPnsresult
3139Connection::GetQuotaObjects(QuotaObject** aDatabaseQuotaObject,
3140 QuotaObject** aJournalQuotaObject) {
3141 MOZ_ASSERT(aDatabaseQuotaObject)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDatabaseQuotaObject)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDatabaseQuotaObject))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aDatabaseQuotaObject"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3141
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDatabaseQuotaObject"
")"); do { MOZ_CrashSequence(__null, 3141); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3142 MOZ_ASSERT(aJournalQuotaObject)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aJournalQuotaObject)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aJournalQuotaObject))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("aJournalQuotaObject"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3142
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aJournalQuotaObject"
")"); do { MOZ_CrashSequence(__null, 3142); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3143
3144 if (!connectionReady()) {
3145 return NS_ERROR_NOT_INITIALIZED;
3146 }
3147 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
3148 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3149 return rv;
3150 }
3151
3152 sqlite3_file* file;
3153 int srv = ::sqlite3_file_control(mDBConn, nullptr, SQLITE_FCNTL_FILE_POINTER7,
3154 &file);
3155 if (srv != SQLITE_OK0) {
3156 return convertResultCode(srv);
3157 }
3158
3159 sqlite3_vfs* vfs;
3160 srv =
3161 ::sqlite3_file_control(mDBConn, nullptr, SQLITE_FCNTL_VFS_POINTER27, &vfs);
3162 if (srv != SQLITE_OK0) {
3163 return convertResultCode(srv);
3164 }
3165
3166 bool obfusactingVFS = false;
3167
3168 {
3169 const nsDependentCString vfsName{vfs->zName};
3170
3171 if (vfsName == obfsvfs::GetVFSName()) {
3172 obfusactingVFS = true;
3173 } else if (vfsName != quotavfs::GetVFSName()) {
3174 NS_WARNING("Got unexpected vfs")NS_DebugBreak(NS_DEBUG_WARNING, "Got unexpected vfs", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3174
)
;
3175 return NS_ERROR_FAILURE;
3176 }
3177 }
3178
3179 RefPtr<QuotaObject> databaseQuotaObject =
3180 GetQuotaObject(file, obfusactingVFS);
3181 if (NS_WARN_IF(!databaseQuotaObject)NS_warn_if_impl(!databaseQuotaObject, "!databaseQuotaObject",
"/root/firefox-clang/storage/mozStorageConnection.cpp", 3181
)
) {
3182 return NS_ERROR_FAILURE;
3183 }
3184
3185 srv = ::sqlite3_file_control(mDBConn, nullptr, SQLITE_FCNTL_JOURNAL_POINTER28,
3186 &file);
3187 if (srv != SQLITE_OK0) {
3188 return convertResultCode(srv);
3189 }
3190
3191 RefPtr<QuotaObject> journalQuotaObject = GetQuotaObject(file, obfusactingVFS);
3192 if (NS_WARN_IF(!journalQuotaObject)NS_warn_if_impl(!journalQuotaObject, "!journalQuotaObject", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3192)
) {
3193 return NS_ERROR_FAILURE;
3194 }
3195
3196 databaseQuotaObject.forget(aDatabaseQuotaObject);
3197 journalQuotaObject.forget(aJournalQuotaObject);
3198 return NS_OK;
3199}
3200
3201SQLiteMutex& Connection::GetSharedDBMutex() { return sharedDBMutex; }
3202
3203uint32_t Connection::GetTransactionNestingLevel(
3204 const mozilla::storage::SQLiteMutexAutoLock& aProofOfLock) {
3205 return mTransactionNestingLevel;
3206}
3207
3208uint32_t Connection::IncreaseTransactionNestingLevel(
3209 const mozilla::storage::SQLiteMutexAutoLock& aProofOfLock) {
3210 return ++mTransactionNestingLevel;
3211}
3212
3213uint32_t Connection::DecreaseTransactionNestingLevel(
3214 const mozilla::storage::SQLiteMutexAutoLock& aProofOfLock) {
3215 return --mTransactionNestingLevel;
3216}
3217
3218NS_IMETHODIMPnsresult
3219Connection::BackupToFileAsync(nsIFile* aDestinationFile,
3220 mozIStorageCompletionCallback* aCallback,
3221 uint32_t aPagesPerStep, uint32_t aStepDelayMs) {
3222 NS_ENSURE_ARG(aDestinationFile)do { if ((__builtin_expect(!!(!(aDestinationFile)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDestinationFile" ") failed"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3222); return NS_ERROR_INVALID_ARG; } } while (false)
;
3223 NS_ENSURE_ARG(aCallback)do { if ((__builtin_expect(!!(!(aCallback)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aCallback" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3223
); return NS_ERROR_INVALID_ARG; } } while (false)
;
3224 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3224); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
3225
3226 // Abort if we're shutting down.
3227 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
3228 return NS_ERROR_ABORT;
3229 }
3230 // Check if AsyncClose or Close were already invoked.
3231 if (!connectionReady()) {
3232 return NS_ERROR_NOT_INITIALIZED;
3233 }
3234 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
3235 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3236 return rv;
3237 }
3238 nsIEventTarget* asyncThread = getAsyncExecutionTarget();
3239 if (!asyncThread) {
3240 return NS_ERROR_NOT_INITIALIZED;
3241 }
3242
3243 // The number of pages of the database to copy per step
3244 static constexpr int32_t DEFAULT_PAGES_PER_STEP = 5;
3245 // The number of milliseconds to wait between each step.
3246 static constexpr uint32_t DEFAULT_STEP_DELAY_MS = 250;
3247
3248 CheckedInt<int32_t> pagesPerStep(aPagesPerStep);
3249 if (!pagesPerStep.isValid()) {
3250 return NS_ERROR_INVALID_ARG;
3251 }
3252
3253 if (!pagesPerStep.value()) {
3254 pagesPerStep = DEFAULT_PAGES_PER_STEP;
3255 }
3256
3257 if (!aStepDelayMs) {
3258 aStepDelayMs = DEFAULT_STEP_DELAY_MS;
3259 }
3260
3261 // Create and dispatch our backup event to the execution thread.
3262 nsCOMPtr<nsIRunnable> backupEvent =
3263 new AsyncBackupDatabaseFile(this, mDBConn, aDestinationFile, aCallback,
3264 pagesPerStep.value(), aStepDelayMs);
3265 rv = asyncThread->Dispatch(backupEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
3266 return rv;
3267}
3268
3269} // namespace mozilla::storage