Commit 5cb3a6cd authored by Matthew Denton's avatar Matthew Denton Committed by Commit Bot

Fixed sqlite fuzzer to use upstream version

Deleted our custom sqlite fuzzers that crash on startup. Also added a
patch for the upstream version of ossfuzz.c so that it will actually
compile and run with our config (SQLITE_OMIT_PROGRESS_CALLBACK and
SQLITE_OMIT_AUTOINIT both caused issues).

Bug: 900482
Change-Id: Ib314a8589b6c7b6e53704a2ae15bf69c0a62fcdf
Reviewed-on: https://chromium-review.googlesource.com/c/1330292
Commit-Queue: Matthew Denton <mpdenton@chromium.org>
Reviewed-by: default avatarMax Moroz <mmoroz@chromium.org>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#608967}
parent bda447c5
......@@ -375,21 +375,12 @@ if (is_linux) {
}
}
fuzzer_test("sqlite3_prepare_v2_fuzzer") {
sources = [
"fuzz/sqlite3_prepare_v2_fuzzer.cc",
]
deps = [
":sqlite",
]
dict = "fuzz/sqlite3_prepare_v2_fuzzer.dict"
}
fuzzer_test("sqlite3_ossfuzz_fuzzer") {
# TODO(mmoroz, pwnall): remove fuzz/ossfuzz.c in favor of test/osfuzz.c in
# sqlite's source code
include_dirs = [
".",
]
sources = [
"fuzz/ossfuzz.c",
"src/test/ossfuzz.c",
]
deps = [
":sqlite",
......
/*
** This module interfaces SQLite to the Google OSS-Fuzz, fuzzer as a service.
** (https://github.com/google/oss-fuzz)
*/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "third_party/sqlite/sqlite3.h"
/* Global debugging settings. OSS-Fuzz will have all debugging turned
** off. But if LLVMFuzzerTestOneInput() is called interactively from
** the ossshell utility program, then these flags might be set.
*/
static unsigned mDebug = 0;
#define FUZZ_SQL_TRACE 0x0001 /* Set an sqlite3_trace() callback */
#define FUZZ_SHOW_MAX_DELAY 0x0002 /* Show maximum progress callback delay */
#define FUZZ_SHOW_ERRORS 0x0004 /* Print error messages from SQLite */
/* The ossshell utility program invokes this interface to see the
** debugging flags. Unused by OSS-Fuzz.
*/
void ossfuzz_set_debug_flags(unsigned x){
mDebug = x;
}
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Return the current real-world time in milliseconds since the
** Julian epoch (-4714-11-24).
*/
static sqlite3_int64 timeOfDay(void){
static sqlite3_vfs *clockVfs = 0;
sqlite3_int64 t;
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
clockVfs->xCurrentTimeInt64(clockVfs, &t);
}else{
double r;
clockVfs->xCurrentTime(clockVfs, &r);
t = (sqlite3_int64)(r*86400000.0);
}
return t;
}
#endif
/* An instance of the following object is passed by pointer as the
** client data to various callbacks.
*/
typedef struct FuzzCtx {
sqlite3 *db; /* The database connection */
sqlite3_int64 iCutoffTime; /* Stop processing at this time. */
sqlite3_int64 iLastCb; /* Time recorded for previous progress callback */
sqlite3_int64 mxInterval; /* Longest interval between two progress calls */
unsigned nCb; /* Number of progress callbacks */
} FuzzCtx;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/*
** Progress handler callback.
**
** The argument is the cutoff-time after which all processing should
** stop. So return non-zero if the cut-off time is exceeded.
*/
static int progress_handler(void *pClientData) {
FuzzCtx *p = (FuzzCtx*)pClientData;
sqlite3_int64 iNow = timeOfDay();
int rc = iNow>=p->iCutoffTime;
sqlite3_int64 iDiff = iNow - p->iLastCb;
if( iDiff > p->mxInterval ) p->mxInterval = iDiff;
p->nCb++;
return rc;
}
#endif
/*
** Disallow debugging pragmas such as "PRAGMA vdbe_debug" and
** "PRAGMA parser_trace" since they can dramatically increase the
** amount of output without actually testing anything useful.
*/
static int block_debug_pragmas(
void *Notused,
int eCode,
const char *zArg1,
const char *zArg2,
const char *zArg3,
const char *zArg4
){
if( eCode==SQLITE_PRAGMA
&& (sqlite3_strnicmp("vdbe_", zArg1, 5)==0
|| sqlite3_stricmp("parser_trace", zArg1)==0)
){
return SQLITE_DENY;
}
return SQLITE_OK;
}
/*
** Callback for sqlite3_exec().
*/
static int exec_handler(void *pCnt, int argc, char **argv, char **namev){
int i;
if( argv ){
for(i=0; i<argc; i++) sqlite3_free(sqlite3_mprintf("%s", argv[i]));
}
return ((*(int*)pCnt)--)<=0;
}
/*
** Main entry point. The fuzzer invokes this function with each
** fuzzed input.
*/
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
int execCnt = 0; /* Abort row callback when count reaches zero */
char *zErrMsg = 0; /* Error message returned by sqlite_exec() */
uint8_t uSelector; /* First byte of input data[] */
int rc; /* Return code from various interfaces */
char *zSql; /* Zero-terminated copy of data[] */
FuzzCtx cx; /* Fuzzing context */
memset(&cx, 0, sizeof(cx));
if( size<3 ) return 0; /* Early out if unsufficient data */
/* Extract the selector byte from the beginning of the input. But only
** do this if the second byte is a \n. If the second byte is not \n,
** then use a default selector */
if( data[1]=='\n' ){
uSelector = data[0]; data += 2; size -= 2;
}else{
uSelector = 0xfd;
}
/* Open the database connection. Only use an in-memory database. */
rc = sqlite3_open_v2("fuzz.db", &cx.db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
if( rc ) return 0;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Invoke the progress handler frequently to check to see if we
** are taking too long. The progress handler will return true
** (which will block further processing) if more than 10 seconds have
** elapsed since the start of the test.
*/
cx.iLastCb = timeOfDay();
cx.iCutoffTime = cx.iLastCb + 10000; /* Now + 10 seconds */
sqlite3_progress_handler(cx.db, 10, progress_handler, (void*)&cx);
#endif
/* Set a limit on the maximum size of a prepared statement */
sqlite3_limit(cx.db, SQLITE_LIMIT_VDBE_OP, 25000);
/* Bit 1 of the selector enables foreign key constraints */
sqlite3_db_config(cx.db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc);
uSelector >>= 1;
/* Do not allow debugging pragma statements that might cause excess output */
sqlite3_set_authorizer(cx.db, block_debug_pragmas, 0);
/* Remaining bits of the selector determine a limit on the number of
** output rows */
execCnt = uSelector + 1;
/* Run the SQL. The sqlite_exec() interface expects a zero-terminated
** string, so make a copy. */
zSql = sqlite3_mprintf("%.*s", (int)size, data);
sqlite3_exec(cx.db, zSql, exec_handler, (void*)&execCnt, &zErrMsg);
/* Show any errors */
if( (mDebug & FUZZ_SHOW_ERRORS)!=0 && zErrMsg ){
printf("Error: %s\n", zErrMsg);
}
/* Cleanup and return */
sqlite3_free(zErrMsg);
sqlite3_free(zSql);
sqlite3_exec(cx.db, "PRAGMA temp_store_directory=''", 0, 0, 0);
sqlite3_close(cx.db);
if( mDebug & FUZZ_SHOW_MAX_DELAY ){
printf("Progress callback count....... %d\n", cx.nCb);
printf("Max time between callbacks.... %d ms\n", (int)cx.mxInterval);
}
return 0;
}
......@@ -280,3 +280,630 @@ pragma_vdbe_trace@1=" vdbe_trace"
pragma_wal_autocheckpoint@1=" wal_autocheckpoint"
pragma_wal_checkpoint@1=" wal_checkpoint"
pragma_writable_schema@1=" writable_schema"
# This part has been generated with testing/libfuzzer/dictionary_generator.py
# using sqlite3_prepare_v2_fuzzer binary and ISO/IEC FCD 9075-1.
"all"
"code"
"BE"
"text"
"TP2,"
"supported"
"GR4)"
"syntax"
"S151,"
"S043,"
"\xe2\x80\x9cCR\xe2\x80\x9d"
"(SQL/PSM)"
"query"
"expressions"
"TP2;"
"row"
"[ISO9075-14],"
"BNF."
"<SQL"
"parameters"
"title"
"S211,"
"ISO/IEC:"
"BNF,"
"SQL_FEATURES"
"should"
"to"
"only"
"program"
"present"
"T211,"
"G,"
"local"
"NY"
"columns"
"END."
"do"
"OBJECT"
"rollback"
"string"
"FEAT2."
"get"
"H"
"P001,"
"between"
"RI."
"[ISO9075-11]"
"cannot"
"entries"
"referencing"
"datetime"
"[UCS]."
"BNF"
"MINUTE"
"(BNF"
"IEC,"
"False"
"OF,"
"level"
"did"
"W."
"list"
"large"
"SQL)"
"PSM."
"(ISO/IEC"
"SQL,"
"SQL-"
"SQL."
"small"
"x"
"DEFINITION_SCHEMA;"
"view"
"Index"
"[ISO9075-3])."
"set"
"S024,"
"CHANGE."
"reference"
"T1,"
"OLAP."
"direct"
"(SQL/XML)."
"LARGE"
"likely"
"result"
"T341,"
"ST"
"ISO/JTC"
"INSERT,"
"PKG004"
"index"
"PKG006"
"PKG007"
"PKG001"
"PKG002"
"PKG008"
"supplied"
"T611,"
"access"
"3"
"version"
"NULL."
"routine"
"[ISO9075-10])."
"S1"
"[UCS],"
"P003,"
"C"
"terms"
"(SQL/MED)"
"JTC1/SC32"
"K"
"(SQL/JRT)"
"modify"
"reported"
"S"
"objects"
"32N1821"
"SECOND."
"key"
"UNDER"
"(ANSI)"
"rows"
"come"
"(CALL"
"change"
"P-"
"both"
"search"
"SQLSTATE,"
"[ISO9075-"
"[ISO9075-14]."
"many"
"changed"
"foreign"
"Symbols"
"S023,"
"connection"
"SQL\xe2\x80\x9d),"
"context"
"delete"
"changes"
"REFERENCES,"
"page."
"named"
"point"
"UPDATE."
"S2"
"UPDATE,"
"[ISO9075-13]"
"Y\xe2\x80\x9d"
"replace"
"\xe2\x80\x9cPSM\xe2\x80\x9d"
"SERIALIZABLE,"
"names"
"E"
"PUBLIC."
"table"
"REF"
"INFORMATION_SCHEMA"
"C1."
"ID."
"use"
"[ISO9075-2]."
"from"
"USA"
"0"
"distinct"
"create"
"contains"
"due"
"ISO."
"few"
"duplicate"
"trigger"
"call"
"S111,"
"expected"
"REPEATABLE"
"C1"
"DOCUMENT"
"type"
"authorization"
"more"
"XML"
"[ISO9075-3],"
"<A>,"
"P"
"on"
"initial"
"name,"
"[ISO9075-11]),"
"QE,"
"STANDARD"
"PKG010"
"TRIGGER,"
"V"
"CS"
"SQL\xe2\x80\x9d:"
"IEC"
"Expression"
"F521,"
"sequence:"
"must"
"none"
"SR3)"
"word"
"INTERNATIONAL"
"ANSI"
"this"
"PSM"
"PUBLIC),"
"modified"
"value"
"<"
"descriptor"
"while"
"paragraph"
"values"
"resources"
"error"
"exceptions"
"IT"
"F,"
"CO,"
"[ISO9075-4],"
"control"
"type,"
"reserved"
"SQL:"
"<C>"
"[ISO9075-2])."
"F052,"
"attribute"
"is"
"type:"
"level,"
"it"
"[ISO9075-2],"
"incremental"
"MONTH,"
"dropped"
"MONTH."
"allowed"
"S241,"
"\xe2\x80\x9cSQL"
"TIMESTAMP"
"failed"
"SC"
"end"
"Format"
"ST."
"permission"
"V,"
"length"
"same"
"[ISO10646]."
"write"
"arguments"
"F555,"
"F671,"
"<C>,"
"<C>."
"parameter"
"NATIONAL"
"Types"
"A"
"Insert"
"32/WG"
"used"
"temporary"
"\xe2\x80\x9cOLAP\xe2\x80\x9d"
"(FCD)"
"may"
"after"
"(SQL/OLB)"
"THIS"
"Q"
"SQL/CLI"
"levels"
"two"
"characters"
"date"
"such"
"[ISO9075-9]"
"data"
"stack"
"single"
"a"
"FEAT,"
"lower"
"transaction"
"in"
"database"
"EXTRACT)"
"expression"
"32N1963"
"CD"
"without"
"QE."
"1"
"CALL"
"F"
"[ISO9075-4])."
"entry"
"the"
"SUBJECT"
"N1968;"
"order"
"left"
"FEAT1,"
"FEAT1."
"S081,"
"YEAR"
"READ,"
"SQL;"
"A,"
"symbols"
"S161,"
"[ISO9075-10]"
"already"
"identify"
"V."
"during"
"differs"
"(UCS)."
"Final"
"before"
"tables"
"[UCS]"
"Multiple"
"integer"
"NT,"
"character"
","
"ID\xe2\x80\x9d"
"(INFORMATION_SCHEMA)"
"source"
"add"
"other"
"TP1"
"SQLSTATE"
"has"
"match"
"KEY."
"real"
"On"
"C1,"
"D"
"[ISO14651]"
"views"
"read"
"\xe2\x80\x9cGR\xe2\x80\x9d"
"L"
"primary"
"TB1."
"qualified"
"(SUBSTRING,"
"T"
"compound"
"not"
"using"
"unique"
"LOB"
"name"
"term"
"sorting"
"like"
"B,"
"[ISO9075-1]"
"RESULT,"
"Numeric"
"MONTH"
"PURPOSES."
"[ISO9075-11]."
"mode"
"(DEFINITION_SCHEMA)."
"SQL"
"ISO"
"page"
"constraints"
"\xc2\xa9ISO/IEC"
"right"
"Java"
"sequence"
"TB1"
"TB2"
"P002,"
"DAY,"
"extended"
"(SQL/CLI)"
"X"
"specified"
"S051,"
"clauses"
"operation"
"FEAT"
"out"
"E,"
"XML."
"for"
"space"
"support"
"T041,"
"[ISO9075-4]"
"content"
"I"
"does"
"STUDY"
"CHARACTER,"
"B1"
"T212,"
"be"
"object"
"[ISO9075-11],"
"G"
"ZONE,"
"S2."
"collations"
"[ISO9075-2]:"
"<A>"
"O"
"standard"
"[ISO9075-2]"
"base"
"W"
"collation"
"HOUR,"
"UNDER,"
"JTC"
"C."
"definition"
"Square"
"\xe2\x80\x9cSR\xe2\x80\x9d"
"extension"
"constraint"
"column"
"of"
"C,"
"F701,"
"(SQL/CLI)."
"T191,"
"range"
"GR"
"1,"
"constructor"
"commit"
"or"
"first"
"referenced"
"statements"
"encoding"
"B1."
"clause"
"variables"
"within"
"number"
"one"
"NT"
"variable"
"because"
"references"
"another"
"blank"
"operator"
"RETURN"
"COMMITTED,"
"9075-1:2011(E)"
"[ISO9075-14]"
"(SQL/OLB)."
"D1"
"exists"
"REFERENCE"
"area"
"S041,"
"unknown"
"Symbol"
"there"
"system"
"long"
"ID"
"start"
"returns"
"2"
"authorized"
"statement"
"X2"
"FCD"
"STILL"
"S231,"
"final"
"READ"
"schema"
"function"
"DELETE,"
"B"
"TC\xe2\x80\x9d."
"declare"
"month"
"Deprecated"
"exactly"
"[ISO10646]"
"JTC1"
"but"
"9075-1:2010(E)"
"part"
"T201,"
"D2."
"<B>,"
"attempt"
"line"
"with"
"than"
"<B>"
"BEFORE,"
"DAY."
"DATE"
"default"
"EXECUTE."
"B1,"
"F191,"
"tree"
"second"
"SHOULD"
"[ISO9075-13],"
"A1,"
"1/SC"
"VARYING,"
"<B>."
"SQL/CLI,"
"were"
"1)"
"<A>."
"CLI,"
"called"
"are"
"and"
"(SQL/MED)."
"[ISO9075-4]:"
"associated"
"\xe2\x80\x9cAR\xe2\x80\x9d"
"defined"
"(SQL/XML)"
"CHARACTER"
"argument"
"an"
"[ISO9075-4])"
"non-deterministic"
"as"
"Other"
"at"
"have"
"[ISO9075-4]."
"CS."
"\xe2\x80\x9cV\xe2\x80\x9d"
"Y."
"null"
"any"
"CLI"
"Function"
"NOTE"
"functions"
"UCS"
"returned"
"F411,"
"no"
"TIME"
"that"
"-"
"RETURN),"
"A1"
"OLAP"
"internal"
"S071,"
"[ISO9075-10],"
"T431,"
"A1."
"\xe2\x80\x9cONLY"
"Y"
"SS"
"UNCOMMITTED,"
"multiple"
"Name"
"truncate"
"normal"
"symbol"
"literal"
"M"
"\xe2\x80\x9c<SQL"
"prepared"
"most"
"ATOMIC,"
"E."
"U"
"letter"
"PUBLIC"
"identical"
"F491,"
"N"
"inserted"
"Page"
"(SQL/JRT)."
"D,"
"SELECT,"
"USED"
"lead"
"Sequence"
"FEAT1"
"into"
"required"
"[ISO9075-9],"
"USAGE,"
"2nd"
"depth"
"R"
"ISO,"
"time"
"SQL\xe2\x80\x9d,"
"FEAT2"
"[ISO9075-3]"
"(SQL/PSM)."
"ISO/IEC"
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <array>
#include <cctype>
#include <string>
#include <vector>
#include "third_party/sqlite/sqlite3.h"
static const std::array<uint8_t, 6> kBadKeyword{{'R', 'E', 'G', 'E', 'X', 'P'}};
bool checkForBadKeyword(const uint8_t* data, size_t size) {
auto it = std::search(
data, data + size, kBadKeyword.begin(), kBadKeyword.end(),
[](char c1, char c2) { return std::toupper(c1) == std::toupper(c2); });
if (it != data + size)
return true;
return false;
}
#if !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
static int Progress(void *not_used_ptr) {
return 1;
}
#endif // !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
// Entry point for LibFuzzer.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size < 2)
return 0;
if (checkForBadKeyword(data, size))
return 0;
sqlite3* db;
int return_code = sqlite3_open_v2(
"db.db",
&db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
if (SQLITE_OK != return_code)
return 0;
// Use first byte as random selector for other parameters.
int selector = data[0];
#if !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
// To cover both cases when progress_handler is used and isn't used.
if (selector & 1)
sqlite3_progress_handler(db, 4, &Progress, NULL);
else
sqlite3_progress_handler(db, 0, NULL, NULL);
// Remove least significant bit to make further usage of selector independent.
selector >>= 1;
#endif // !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
sqlite3_stmt* statement = NULL;
int result = sqlite3_prepare_v2(db, reinterpret_cast<const char*>(data + 1),
static_cast<int>(size - 1), &statement, NULL);
if (result == SQLITE_OK) {
// Use selector value to randomize number of iterations.
for (int i = 0; i < selector; i++) {
if (sqlite3_step(statement) != SQLITE_ROW)
break;
}
sqlite3_finalize(statement);
}
sqlite3_close(db);
return 0;
}
This diff is collapsed.
From a5aecce84258458fb2743d242e16bb85bee6c8c9 Mon Sep 17 00:00:00 2001
From: Matthew Denton <mpdenton@chromium.org>
Date: Fri, 16 Nov 2018 10:32:17 -0800
Subject: [PATCH] Fix ossfuzz.c to compile and run with our config
---
third_party/sqlite/src/test/ossfuzz.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/third_party/sqlite/src/test/ossfuzz.c b/third_party/sqlite/src/test/ossfuzz.c
index a8a637f2ac85..7b69015129d9 100644
--- a/third_party/sqlite/src/test/ossfuzz.c
+++ b/third_party/sqlite/src/test/ossfuzz.c
@@ -30,6 +30,7 @@ void ossfuzz_set_debug_flags(unsigned x){
mDebug = x;
}
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Return the current real-world time in milliseconds since the
** Julian epoch (-4714-11-24).
*/
@@ -46,6 +47,7 @@ static sqlite3_int64 timeOfDay(void){
}
return t;
}
+#endif
/* An instance of the following object is passed by pointer as the
** client data to various callbacks.
@@ -133,6 +135,11 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
uSelector = 0xfd;
}
+#ifdef SQLITE_OMIT_AUTOINIT
+ rc = sqlite3_initialize();
+ if( rc ) return 0;
+#endif
+
/* Open the database connection. Only use an in-memory database. */
rc = sqlite3_open_v2("fuzz.db", &cx.db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
--
2.19.1.1215.g8438c0b245-goog
......@@ -30,6 +30,7 @@ void ossfuzz_set_debug_flags(unsigned x){
mDebug = x;
}
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Return the current real-world time in milliseconds since the
** Julian epoch (-4714-11-24).
*/
......@@ -46,6 +47,7 @@ static sqlite3_int64 timeOfDay(void){
}
return t;
}
#endif
/* An instance of the following object is passed by pointer as the
** client data to various callbacks.
......@@ -133,6 +135,11 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
uSelector = 0xfd;
}
#ifdef SQLITE_OMIT_AUTOINIT
rc = sqlite3_initialize();
if( rc ) return 0;
#endif
/* Open the database connection. Only use an in-memory database. */
rc = sqlite3_open_v2("fuzz.db", &cx.db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
......
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