Commit b05f99c3 authored by Victor Costan's avatar Victor Costan Committed by Commit Bot

sqlite: Disable unused features via compile-time options.

This CL shrinks the Linux binary by 34KB (138,266,816 to 138,232,320).
Code savings aside, this makes sure we don't unintentionally start
depending on these features.

The following compile-time options are recommended in the SQLite
documentation [1]:

* SQLITE_LIKE_DOESNT_MATCH_BLOBS - The LIKE and GLOB operators don't
  work on BLOB columns. This access pattern would be a performance
  wrench, so it's nice to fail hard here.
* SQLITE_OMIT_DEPRECATED - This removes support for deprecated SQLite
  APIs. Note that SQLite promises to maintain indefinite backwards
  compatbility for SQL queries (modulo features disabled via
  compile-time options), so this only applies to the SQLite API. We
  should never be using deprecated APIs.
* SQLITE_OMIT_PROGRESS_CALLBACK - Remove sqlite3_progress_handler(). We
  don't use this feature, and the documentation says it comes with a
  small performance penalty.
* SQLITE_OMIT_SHARED_CACHE - Using a shared cache sounds nice from a
  memory consumption standpoint, and we already do that for LevelDB.
  Unfortunately, Chromium's SQLite databases use a variety of page
  sizes, which makes cache sharing impossible.
* SQLITE_USE_ALLOCA - Use alloca() instead of malloc() for allocating
  temporary spaces in functions. All of Chrome's platforms support this
  option, and it results in a slightly smaller binary and less heap churn.

The following compile-time options disable features that happen not to
be used.

* SQLITE_OMIT_AUTOINIT: We initialize SQLite manually in //sql/connection.cc.
* SQLITE_OMIT_AUTORESET: We calls sqlite3_reset() correctly to reset prepared
  statements.
* SQLITE_OMIT_GET_TABLE: We don't use sqlite3_{get,free}_table().
* SQLITE_OMIT_LOAD_EXTENSION: We don't use sqlite3_{enable_}load_extension().
  Asides from the code savings, there's a tiny security benefit to
  knowing that extension loading code is definitely not reachable from WebSQL.
* SQLITE_OMIT_TCL_VARIABLE: We don't use TCL variables.
* SQLITE_OMIT_TRACE: We don't use sqlite3_{profile,trace}().

Bug: 807093
Change-Id: Ie5e59e55dd9b2ed52f7c27682a809c9f7c36d4a3
Reviewed-on: https://chromium-review.googlesource.com/882961
Commit-Queue: Victor Costan <pwnall@chromium.org>
Reviewed-by: default avatarChris Mumford <cmumford@chromium.org>
Cr-Commit-Position: refs/heads/master@{#532995}
parent 78444401
...@@ -75,6 +75,37 @@ config("chromium_sqlite3_compile_options") { ...@@ -75,6 +75,37 @@ config("chromium_sqlite3_compile_options") {
# syntax working but execution failing. Review: # syntax working but execution failing. Review:
# src/src/parse.py # src/src/parse.py
# src/tool/mkkeywordhash.c # src/tool/mkkeywordhash.c
# The flags below are recommended in the SQLite documentation, and disable
# features Chromium doesn't use.
"SQLITE_LIKE_DOESNT_MATCH_BLOBS",
"SQLITE_OMIT_DEPRECATED",
"SQLITE_OMIT_PROGRESS_CALLBACK",
"SQLITE_OMIT_SHARED_CACHE",
"SQLITE_USE_ALLOCA",
# Chromium initializes SQLite manually in //sql/connection.cc.
"SQLITE_OMIT_AUTOINIT",
# Chromium calls sqlite3_reset() correctly to reset prepared statements.
"SQLITE_OMIT_AUTORESET",
# Chromium does not use sqlite3_{get,free}_table().
"SQLITE_OMIT_GET_TABLE",
# Chromium does not use sqlite3_{enable_}load_extension().
# Asides from the code savings, there's a tiny security benefit to knowing
# that WebSQL can't possibly reach extension loading code.
"SQLITE_OMIT_LOAD_EXTENSION",
# Chromium doesn't use TCL variables.
"SQLITE_OMIT_TCL_VARIABLE",
# Chromium doesn't use sqlite3_{profile,trace}().
"SQLITE_OMIT_TRACE",
# TODO(pwnall): Add SQLITE_OMIT_COMPLETE when we import a SQLite release
# including https://www.sqlite.org/src/info/c3e816cca4ddf096
] ]
# Pull in config.h on Linux. This allows use of preprocessor macros which # Pull in config.h on Linux. This allows use of preprocessor macros which
...@@ -123,6 +154,9 @@ if (!use_system_sqlite) { ...@@ -123,6 +154,9 @@ if (!use_system_sqlite) {
"-Wno-pointer-to-int-cast", "-Wno-pointer-to-int-cast",
] ]
} }
if (is_win && !is_clang) {
cflags += [ "/wd4101" ] # 'zTrace' unreferenced variable in src/vdbe.c
}
} }
# "sqlite3" can cause conflicts with the system library. # "sqlite3" can cause conflicts with the system library.
......
...@@ -24,6 +24,7 @@ void ossfuzz_set_debug_flags(unsigned x){ ...@@ -24,6 +24,7 @@ void ossfuzz_set_debug_flags(unsigned x){
mDebug = x; mDebug = x;
} }
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Return the current real-world time in milliseconds since the /* Return the current real-world time in milliseconds since the
** Julian epoch (-4714-11-24). ** Julian epoch (-4714-11-24).
*/ */
...@@ -40,6 +41,7 @@ static sqlite3_int64 timeOfDay(void){ ...@@ -40,6 +41,7 @@ static sqlite3_int64 timeOfDay(void){
} }
return t; return t;
} }
#endif
/* An instance of the following object is passed by pointer as the /* An instance of the following object is passed by pointer as the
** client data to various callbacks. ** client data to various callbacks.
...@@ -179,3 +181,4 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { ...@@ -179,3 +181,4 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
} }
return 0; return 0;
} }
...@@ -28,10 +28,14 @@ bool checkForBadKeyword(const uint8_t* data, size_t size) { ...@@ -28,10 +28,14 @@ bool checkForBadKeyword(const uint8_t* data, size_t size) {
} }
#if !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
static int Progress(void *not_used_ptr) { static int Progress(void *not_used_ptr) {
return 1; return 1;
} }
#endif // !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
// Entry point for LibFuzzer. // Entry point for LibFuzzer.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
...@@ -53,6 +57,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { ...@@ -53,6 +57,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// Use first byte as random selector for other parameters. // Use first byte as random selector for other parameters.
int selector = data[0]; int selector = data[0];
#if !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
// To cover both cases when progress_handler is used and isn't used. // To cover both cases when progress_handler is used and isn't used.
if (selector & 1) if (selector & 1)
sqlite3_progress_handler(db, 4, &Progress, NULL); sqlite3_progress_handler(db, 4, &Progress, NULL);
...@@ -61,6 +66,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { ...@@ -61,6 +66,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// Remove least significant bit to make further usage of selector independent. // Remove least significant bit to make further usage of selector independent.
selector >>= 1; selector >>= 1;
#endif // !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
sqlite3_stmt* statement = NULL; sqlite3_stmt* statement = NULL;
int result = sqlite3_prepare_v2(db, reinterpret_cast<const char*>(data + 1), int result = sqlite3_prepare_v2(db, reinterpret_cast<const char*>(data + 1),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment