1/*
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "SQLiteDatabase.h"
29
30#include "DatabaseAuthorizer.h"
31#include "Logging.h"
32#include "MemoryRelease.h"
33#include "SQLiteDatabaseTracker.h"
34#include "SQLiteFileSystem.h"
35#include "SQLiteStatement.h"
36#include <mutex>
37#include <sqlite3.h>
38#include <thread>
39#include <wtf/FileSystem.h>
40#include <wtf/Threading.h>
41#include <wtf/text/CString.h>
42#include <wtf/text/StringConcatenateNumbers.h>
43
44namespace WebCore {
45
46static const char notOpenErrorMessage[] = "database is not open";
47
48static void unauthorizedSQLFunction(sqlite3_context *context, int, sqlite3_value **)
49{
50 const char* functionName = (const char*)sqlite3_user_data(context);
51 sqlite3_result_error(context, makeString("Function ", functionName, " is unauthorized").utf8().data(), -1);
52}
53
54static void initializeSQLiteIfNecessary()
55{
56 static std::once_flag flag;
57 std::call_once(flag, [] {
58 // It should be safe to call this outside of std::call_once, since it is documented to be
59 // completely threadsafe. But in the past it was not safe, and the SQLite developers still
60 // aren't confident that it really is, and we still support ancient versions of SQLite. So
61 // std::call_once is used to stay on the safe side. See bug #143245.
62 int ret = sqlite3_initialize();
63 if (ret != SQLITE_OK) {
64#if SQLITE_VERSION_NUMBER >= 3007015
65 WTFLogAlways("Failed to initialize SQLite: %s", sqlite3_errstr(ret));
66#else
67 WTFLogAlways("Failed to initialize SQLite");
68#endif
69 CRASH();
70 }
71 });
72}
73
74static bool isDatabaseOpeningForbidden = false;
75static Lock isDatabaseOpeningForbiddenMutex;
76
77void SQLiteDatabase::setIsDatabaseOpeningForbidden(bool isForbidden)
78{
79 std::lock_guard<Lock> lock(isDatabaseOpeningForbiddenMutex);
80 isDatabaseOpeningForbidden = isForbidden;
81}
82
83SQLiteDatabase::SQLiteDatabase() = default;
84
85SQLiteDatabase::~SQLiteDatabase()
86{
87 close();
88}
89
90bool SQLiteDatabase::open(const String& filename, OpenMode openMode)
91{
92 initializeSQLiteIfNecessary();
93
94 close();
95
96 {
97 std::lock_guard<Lock> lock(isDatabaseOpeningForbiddenMutex);
98 if (isDatabaseOpeningForbidden) {
99 m_openErrorMessage = "opening database is forbidden";
100 return false;
101 }
102
103 int flags = SQLITE_OPEN_AUTOPROXY;
104 switch (openMode) {
105 case OpenMode::ReadOnly:
106 flags |= SQLITE_OPEN_READONLY;
107 break;
108 case OpenMode::ReadWrite:
109 flags |= SQLITE_OPEN_READWRITE;
110 break;
111 case OpenMode::ReadWriteCreate:
112 flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
113 break;
114 }
115
116 m_openError = sqlite3_open_v2(FileSystem::fileSystemRepresentation(filename).data(), &m_db, flags, nullptr);
117 if (m_openError != SQLITE_OK) {
118 m_openErrorMessage = m_db ? sqlite3_errmsg(m_db) : "sqlite_open returned null";
119 LOG_ERROR("SQLite database failed to load from %s\nCause - %s", filename.ascii().data(),
120 m_openErrorMessage.data());
121 sqlite3_close(m_db);
122 m_db = 0;
123 return false;
124 }
125 }
126
127 overrideUnauthorizedFunctions();
128
129 m_openError = sqlite3_extended_result_codes(m_db, 1);
130 if (m_openError != SQLITE_OK) {
131 m_openErrorMessage = sqlite3_errmsg(m_db);
132 LOG_ERROR("SQLite database error when enabling extended errors - %s", m_openErrorMessage.data());
133 sqlite3_close(m_db);
134 m_db = 0;
135 return false;
136 }
137
138 if (isOpen())
139 m_openingThread = &Thread::current();
140 else
141 m_openErrorMessage = "sqlite_open returned null";
142
143 {
144 SQLiteTransactionInProgressAutoCounter transactionCounter;
145 if (!SQLiteStatement(*this, "PRAGMA temp_store = MEMORY;"_s).executeCommand())
146 LOG_ERROR("SQLite database could not set temp_store to memory");
147 }
148
149 if (openMode != OpenMode::ReadOnly)
150 useWALJournalMode();
151
152 String shmFileName = makeString(filename, "-shm"_s);
153 if (FileSystem::fileExists(shmFileName)) {
154 if (!FileSystem::isSafeToUseMemoryMapForPath(shmFileName)) {
155 RELEASE_LOG_FAULT(SQLDatabase, "Opened an SQLite database with a Class A -shm file. This may trigger a crash when the user locks the device. (%s)", shmFileName.latin1().data());
156 FileSystem::makeSafeToUseMemoryMapForPath(shmFileName);
157 }
158 }
159
160 return isOpen();
161}
162
163void SQLiteDatabase::useWALJournalMode()
164{
165 m_useWAL = true;
166 {
167 SQLiteStatement walStatement(*this, "PRAGMA journal_mode=WAL;"_s);
168 if (walStatement.prepareAndStep() == SQLITE_ROW) {
169#ifndef NDEBUG
170 String mode = walStatement.getColumnText(0);
171 if (!equalLettersIgnoringASCIICase(mode, "wal"))
172 LOG_ERROR("journal_mode of database should be 'WAL', but is '%s'", mode.utf8().data());
173#endif
174 } else
175 LOG_ERROR("SQLite database failed to set journal_mode to WAL, error: %s", lastErrorMsg());
176 }
177
178 {
179 SQLiteTransactionInProgressAutoCounter transactionCounter;
180 SQLiteStatement checkpointStatement(*this, "PRAGMA wal_checkpoint(TRUNCATE)"_s);
181 if (checkpointStatement.prepareAndStep() == SQLITE_ROW) {
182 if (checkpointStatement.getColumnInt(0))
183 LOG(SQLDatabase, "SQLite database checkpoint is blocked");
184 } else
185 LOG_ERROR("SQLite database failed to checkpoint: %s", lastErrorMsg());
186 }
187}
188
189void SQLiteDatabase::close()
190{
191 if (m_db) {
192 // FIXME: This is being called on the main thread during JS GC. <rdar://problem/5739818>
193 // ASSERT(m_openingThread == &Thread::current());
194 sqlite3* db = m_db;
195 {
196 LockHolder locker(m_databaseClosingMutex);
197 m_db = 0;
198 }
199 if (m_useWAL) {
200 SQLiteTransactionInProgressAutoCounter transactionCounter;
201 sqlite3_close(db);
202 } else
203 sqlite3_close(db);
204 }
205
206 m_openingThread = nullptr;
207 m_openError = SQLITE_ERROR;
208 m_openErrorMessage = CString();
209}
210
211void SQLiteDatabase::overrideUnauthorizedFunctions()
212{
213 static const std::pair<const char*, int> functionParameters[] = {
214 { "rtreenode", 2 },
215 { "rtreedepth", 1 },
216 { "eval", 1 },
217 { "eval", 2 },
218 { "printf", -1 },
219 { "fts3_tokenizer", 1 },
220 { "fts3_tokenizer", 2 },
221 };
222
223 for (auto& functionParameter : functionParameters)
224 sqlite3_create_function(m_db, functionParameter.first, functionParameter.second, SQLITE_UTF8, const_cast<char*>(functionParameter.first), unauthorizedSQLFunction, 0, 0);
225}
226
227void SQLiteDatabase::setFullsync(bool fsync)
228{
229 if (fsync)
230 executeCommand("PRAGMA fullfsync = 1;"_s);
231 else
232 executeCommand("PRAGMA fullfsync = 0;"_s);
233}
234
235int64_t SQLiteDatabase::maximumSize()
236{
237 int64_t maxPageCount = 0;
238
239 {
240 LockHolder locker(m_authorizerLock);
241 enableAuthorizer(false);
242 SQLiteStatement statement(*this, "PRAGMA max_page_count"_s);
243 maxPageCount = statement.getColumnInt64(0);
244 enableAuthorizer(true);
245 }
246
247 return maxPageCount * pageSize();
248}
249
250void SQLiteDatabase::setMaximumSize(int64_t size)
251{
252 if (size < 0)
253 size = 0;
254
255 int currentPageSize = pageSize();
256
257 ASSERT(currentPageSize || !m_db);
258 int64_t newMaxPageCount = currentPageSize ? size / currentPageSize : 0;
259
260 LockHolder locker(m_authorizerLock);
261 enableAuthorizer(false);
262
263 SQLiteStatement statement(*this, makeString("PRAGMA max_page_count = ", newMaxPageCount));
264 statement.prepare();
265 if (statement.step() != SQLITE_ROW)
266 LOG_ERROR("Failed to set maximum size of database to %lli bytes", static_cast<long long>(size));
267
268 enableAuthorizer(true);
269
270}
271
272int SQLiteDatabase::pageSize()
273{
274 // Since the page size of a database is locked in at creation and therefore cannot be dynamic,
275 // we can cache the value for future use
276 if (m_pageSize == -1) {
277 LockHolder locker(m_authorizerLock);
278 enableAuthorizer(false);
279
280 SQLiteStatement statement(*this, "PRAGMA page_size"_s);
281 m_pageSize = statement.getColumnInt(0);
282
283 enableAuthorizer(true);
284 }
285
286 return m_pageSize;
287}
288
289int64_t SQLiteDatabase::freeSpaceSize()
290{
291 int64_t freelistCount = 0;
292
293 {
294 LockHolder locker(m_authorizerLock);
295 enableAuthorizer(false);
296 // Note: freelist_count was added in SQLite 3.4.1.
297 SQLiteStatement statement(*this, "PRAGMA freelist_count"_s);
298 freelistCount = statement.getColumnInt64(0);
299 enableAuthorizer(true);
300 }
301
302 return freelistCount * pageSize();
303}
304
305int64_t SQLiteDatabase::totalSize()
306{
307 int64_t pageCount = 0;
308
309 {
310 LockHolder locker(m_authorizerLock);
311 enableAuthorizer(false);
312 SQLiteStatement statement(*this, "PRAGMA page_count"_s);
313 pageCount = statement.getColumnInt64(0);
314 enableAuthorizer(true);
315 }
316
317 return pageCount * pageSize();
318}
319
320void SQLiteDatabase::setSynchronous(SynchronousPragma sync)
321{
322 executeCommand(makeString("PRAGMA synchronous = ", static_cast<unsigned>(sync)));
323}
324
325void SQLiteDatabase::setBusyTimeout(int ms)
326{
327 if (m_db)
328 sqlite3_busy_timeout(m_db, ms);
329 else
330 LOG(SQLDatabase, "BusyTimeout set on non-open database");
331}
332
333void SQLiteDatabase::setBusyHandler(int(*handler)(void*, int))
334{
335 if (m_db)
336 sqlite3_busy_handler(m_db, handler, NULL);
337 else
338 LOG(SQLDatabase, "Busy handler set on non-open database");
339}
340
341bool SQLiteDatabase::executeCommand(const String& sql)
342{
343 return SQLiteStatement(*this, sql).executeCommand();
344}
345
346bool SQLiteDatabase::returnsAtLeastOneResult(const String& sql)
347{
348 return SQLiteStatement(*this, sql).returnsAtLeastOneResult();
349}
350
351bool SQLiteDatabase::tableExists(const String& tablename)
352{
353 if (!isOpen())
354 return false;
355
356 String statement = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = '" + tablename + "';";
357
358 SQLiteStatement sql(*this, statement);
359 sql.prepare();
360 return sql.step() == SQLITE_ROW;
361}
362
363void SQLiteDatabase::clearAllTables()
364{
365 String query = "SELECT name FROM sqlite_master WHERE type='table';"_s;
366 Vector<String> tables;
367 if (!SQLiteStatement(*this, query).returnTextResults(0, tables)) {
368 LOG(SQLDatabase, "Unable to retrieve list of tables from database");
369 return;
370 }
371
372 for (Vector<String>::iterator table = tables.begin(); table != tables.end(); ++table ) {
373 if (*table == "sqlite_sequence")
374 continue;
375 if (!executeCommand("DROP TABLE " + *table))
376 LOG(SQLDatabase, "Unable to drop table %s", (*table).ascii().data());
377 }
378}
379
380int SQLiteDatabase::runVacuumCommand()
381{
382 if (!executeCommand("VACUUM;"_s))
383 LOG(SQLDatabase, "Unable to vacuum database - %s", lastErrorMsg());
384 return lastError();
385}
386
387int SQLiteDatabase::runIncrementalVacuumCommand()
388{
389 LockHolder locker(m_authorizerLock);
390 enableAuthorizer(false);
391
392 if (!executeCommand("PRAGMA incremental_vacuum"_s))
393 LOG(SQLDatabase, "Unable to run incremental vacuum - %s", lastErrorMsg());
394
395 enableAuthorizer(true);
396 return lastError();
397}
398
399void SQLiteDatabase::interrupt()
400{
401 LockHolder locker(m_databaseClosingMutex);
402 if (m_db)
403 sqlite3_interrupt(m_db);
404}
405
406int64_t SQLiteDatabase::lastInsertRowID()
407{
408 if (!m_db)
409 return 0;
410 return sqlite3_last_insert_rowid(m_db);
411}
412
413void SQLiteDatabase::updateLastChangesCount()
414{
415 if (!m_db)
416 return;
417
418 m_lastChangesCount = sqlite3_total_changes(m_db);
419}
420
421int SQLiteDatabase::lastChanges()
422{
423 if (!m_db)
424 return 0;
425
426 return sqlite3_total_changes(m_db) - m_lastChangesCount;
427}
428
429int SQLiteDatabase::lastError()
430{
431 return m_db ? sqlite3_errcode(m_db) : m_openError;
432}
433
434const char* SQLiteDatabase::lastErrorMsg()
435{
436 if (m_db)
437 return sqlite3_errmsg(m_db);
438 return m_openErrorMessage.isNull() ? notOpenErrorMessage : m_openErrorMessage.data();
439}
440
441#ifndef NDEBUG
442void SQLiteDatabase::disableThreadingChecks()
443{
444 // Note that SQLite could be compiled with -DTHREADSAFE, or you may have turned off the mutexes.
445 m_sharable = true;
446}
447#endif
448
449int SQLiteDatabase::authorizerFunction(void* userData, int actionCode, const char* parameter1, const char* parameter2, const char* /*databaseName*/, const char* /*trigger_or_view*/)
450{
451 DatabaseAuthorizer* auth = static_cast<DatabaseAuthorizer*>(userData);
452 ASSERT(auth);
453
454 switch (actionCode) {
455 case SQLITE_CREATE_INDEX:
456 return auth->createIndex(parameter1, parameter2);
457 case SQLITE_CREATE_TABLE:
458 return auth->createTable(parameter1);
459 case SQLITE_CREATE_TEMP_INDEX:
460 return auth->createTempIndex(parameter1, parameter2);
461 case SQLITE_CREATE_TEMP_TABLE:
462 return auth->createTempTable(parameter1);
463 case SQLITE_CREATE_TEMP_TRIGGER:
464 return auth->createTempTrigger(parameter1, parameter2);
465 case SQLITE_CREATE_TEMP_VIEW:
466 return auth->createTempView(parameter1);
467 case SQLITE_CREATE_TRIGGER:
468 return auth->createTrigger(parameter1, parameter2);
469 case SQLITE_CREATE_VIEW:
470 return auth->createView(parameter1);
471 case SQLITE_DELETE:
472 return auth->allowDelete(parameter1);
473 case SQLITE_DROP_INDEX:
474 return auth->dropIndex(parameter1, parameter2);
475 case SQLITE_DROP_TABLE:
476 return auth->dropTable(parameter1);
477 case SQLITE_DROP_TEMP_INDEX:
478 return auth->dropTempIndex(parameter1, parameter2);
479 case SQLITE_DROP_TEMP_TABLE:
480 return auth->dropTempTable(parameter1);
481 case SQLITE_DROP_TEMP_TRIGGER:
482 return auth->dropTempTrigger(parameter1, parameter2);
483 case SQLITE_DROP_TEMP_VIEW:
484 return auth->dropTempView(parameter1);
485 case SQLITE_DROP_TRIGGER:
486 return auth->dropTrigger(parameter1, parameter2);
487 case SQLITE_DROP_VIEW:
488 return auth->dropView(parameter1);
489 case SQLITE_INSERT:
490 return auth->allowInsert(parameter1);
491 case SQLITE_PRAGMA:
492 return auth->allowPragma(parameter1, parameter2);
493 case SQLITE_READ:
494 return auth->allowRead(parameter1, parameter2);
495 case SQLITE_SELECT:
496 return auth->allowSelect();
497 case SQLITE_TRANSACTION:
498 return auth->allowTransaction();
499 case SQLITE_UPDATE:
500 return auth->allowUpdate(parameter1, parameter2);
501 case SQLITE_ATTACH:
502 return auth->allowAttach(parameter1);
503 case SQLITE_DETACH:
504 return auth->allowDetach(parameter1);
505 case SQLITE_ALTER_TABLE:
506 return auth->allowAlterTable(parameter1, parameter2);
507 case SQLITE_REINDEX:
508 return auth->allowReindex(parameter1);
509 case SQLITE_ANALYZE:
510 return auth->allowAnalyze(parameter1);
511 case SQLITE_CREATE_VTABLE:
512 return auth->createVTable(parameter1, parameter2);
513 case SQLITE_DROP_VTABLE:
514 return auth->dropVTable(parameter1, parameter2);
515 case SQLITE_FUNCTION:
516 return auth->allowFunction(parameter2);
517 default:
518 ASSERT_NOT_REACHED();
519 return SQLAuthDeny;
520 }
521}
522
523void SQLiteDatabase::setAuthorizer(DatabaseAuthorizer& authorizer)
524{
525 if (!m_db) {
526 LOG_ERROR("Attempt to set an authorizer on a non-open SQL database");
527 ASSERT_NOT_REACHED();
528 return;
529 }
530
531 LockHolder locker(m_authorizerLock);
532
533 m_authorizer = &authorizer;
534
535 enableAuthorizer(true);
536}
537
538void SQLiteDatabase::enableAuthorizer(bool enable)
539{
540 if (m_authorizer && enable)
541 sqlite3_set_authorizer(m_db, SQLiteDatabase::authorizerFunction, m_authorizer.get());
542 else
543 sqlite3_set_authorizer(m_db, NULL, 0);
544}
545
546bool SQLiteDatabase::isAutoCommitOn() const
547{
548 return sqlite3_get_autocommit(m_db);
549}
550
551bool SQLiteDatabase::turnOnIncrementalAutoVacuum()
552{
553 SQLiteStatement statement(*this, "PRAGMA auto_vacuum"_s);
554 int autoVacuumMode = statement.getColumnInt(0);
555 int error = lastError();
556 statement.finalize();
557
558 // Check if we got an error while trying to get the value of the auto_vacuum flag.
559 // If we got a SQLITE_BUSY error, then there's probably another transaction in
560 // progress on this database. In this case, keep the current value of the
561 // auto_vacuum flag and try to set it to INCREMENTAL the next time we open this
562 // database. If the error is not SQLITE_BUSY, then we probably ran into a more
563 // serious problem and should return false (to log an error message).
564 if (error != SQLITE_ROW)
565 return false;
566
567 switch (autoVacuumMode) {
568 case AutoVacuumIncremental:
569 return true;
570 case AutoVacuumFull:
571 return executeCommand("PRAGMA auto_vacuum = 2"_s);
572 case AutoVacuumNone:
573 default:
574 if (!executeCommand("PRAGMA auto_vacuum = 2"_s))
575 return false;
576 runVacuumCommand();
577 error = lastError();
578 return (error == SQLITE_OK);
579 }
580}
581
582static void destroyCollationFunction(void* arg)
583{
584 auto f = static_cast<WTF::Function<int(int, const void*, int, const void*)>*>(arg);
585 delete f;
586}
587
588static int callCollationFunction(void* arg, int aLength, const void* a, int bLength, const void* b)
589{
590 auto f = static_cast<WTF::Function<int(int, const void*, int, const void*)>*>(arg);
591 return (*f)(aLength, a, bLength, b);
592}
593
594void SQLiteDatabase::setCollationFunction(const String& collationName, WTF::Function<int(int, const void*, int, const void*)>&& collationFunction)
595{
596 auto functionObject = new WTF::Function<int(int, const void*, int, const void*)>(WTFMove(collationFunction));
597 sqlite3_create_collation_v2(m_db, collationName.utf8().data(), SQLITE_UTF8, functionObject, callCollationFunction, destroyCollationFunction);
598}
599
600void SQLiteDatabase::removeCollationFunction(const String& collationName)
601{
602 sqlite3_create_collation_v2(m_db, collationName.utf8().data(), SQLITE_UTF8, nullptr, nullptr, nullptr);
603}
604
605} // namespace WebCore
606