/src/sqlite3/test/ossfuzz.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | ** This module interfaces SQLite to the Google OSS-Fuzz, fuzzer as a service. |
3 | | ** (https://github.com/google/oss-fuzz) |
4 | | */ |
5 | | #include <stddef.h> |
6 | | #if !defined(_MSC_VER) |
7 | | # include <stdint.h> |
8 | | #endif |
9 | | #include <stdio.h> |
10 | | #include <string.h> |
11 | | #include "sqlite3.h" |
12 | | |
13 | | #if defined(_MSC_VER) |
14 | | typedef unsigned char uint8_t; |
15 | | #endif |
16 | | |
17 | | /* Global debugging settings. OSS-Fuzz will have all debugging turned |
18 | | ** off. But if LLVMFuzzerTestOneInput() is called interactively from |
19 | | ** the ossshell utility program, then these flags might be set. |
20 | | */ |
21 | | static unsigned mDebug = 0; |
22 | | #define FUZZ_SQL_TRACE 0x0001 /* Set an sqlite3_trace() callback */ |
23 | 259k | #define FUZZ_SHOW_MAX_DELAY 0x0002 /* Show maximum progress callback delay */ |
24 | 259k | #define FUZZ_SHOW_ERRORS 0x0004 /* Print error messages from SQLite */ |
25 | | |
26 | | /* The ossshell utility program invokes this interface to see the |
27 | | ** debugging flags. Unused by OSS-Fuzz. |
28 | | */ |
29 | 0 | void ossfuzz_set_debug_flags(unsigned x){ |
30 | 0 | mDebug = x; |
31 | 0 | } |
32 | | |
33 | | /* Return the current real-world time in milliseconds since the |
34 | | ** Julian epoch (-4714-11-24). |
35 | | */ |
36 | 8.54G | static sqlite3_int64 timeOfDay(void){ |
37 | 8.54G | static sqlite3_vfs *clockVfs = 0; |
38 | 8.54G | sqlite3_int64 t; |
39 | 8.54G | if( clockVfs==0 ){ |
40 | 1.76k | clockVfs = sqlite3_vfs_find(0); |
41 | 1.76k | if( clockVfs==0 ) return 0; |
42 | 1.76k | } |
43 | 8.54G | if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){ |
44 | 8.54G | clockVfs->xCurrentTimeInt64(clockVfs, &t); |
45 | 8.54G | }else{ |
46 | 0 | double r; |
47 | 0 | clockVfs->xCurrentTime(clockVfs, &r); |
48 | 0 | t = (sqlite3_int64)(r*86400000.0); |
49 | 0 | } |
50 | 8.54G | return t; |
51 | 8.54G | } |
52 | | |
53 | | /* An instance of the following object is passed by pointer as the |
54 | | ** client data to various callbacks. |
55 | | */ |
56 | | typedef struct FuzzCtx { |
57 | | sqlite3 *db; /* The database connection */ |
58 | | sqlite3_int64 iCutoffTime; /* Stop processing at this time. */ |
59 | | sqlite3_int64 iLastCb; /* Time recorded for previous progress callback */ |
60 | | sqlite3_int64 mxInterval; /* Longest interval between two progress calls */ |
61 | | unsigned nCb; /* Number of progress callbacks */ |
62 | | unsigned execCnt; /* Number of calls to the sqlite3_exec callback */ |
63 | | } FuzzCtx; |
64 | | |
65 | | /* |
66 | | ** Progress handler callback. |
67 | | ** |
68 | | ** The argument is the cutoff-time after which all processing should |
69 | | ** stop. So return non-zero if the cut-off time is exceeded. |
70 | | */ |
71 | 8.54G | static int progress_handler(void *pClientData) { |
72 | 8.54G | FuzzCtx *p = (FuzzCtx*)pClientData; |
73 | 8.54G | sqlite3_int64 iNow = timeOfDay(); |
74 | 8.54G | int rc = iNow>=p->iCutoffTime; |
75 | 8.54G | sqlite3_int64 iDiff = iNow - p->iLastCb; |
76 | 8.54G | if( iDiff > p->mxInterval ) p->mxInterval = iDiff; |
77 | 8.54G | p->nCb++; |
78 | 8.54G | return rc; |
79 | 8.54G | } |
80 | | |
81 | | /* |
82 | | ** Disallow debugging pragmas such as "PRAGMA vdbe_debug" and |
83 | | ** "PRAGMA parser_trace" since they can dramatically increase the |
84 | | ** amount of output without actually testing anything useful. |
85 | | */ |
86 | | static int block_debug_pragmas( |
87 | | void *Notused, |
88 | | int eCode, |
89 | | const char *zArg1, |
90 | | const char *zArg2, |
91 | | const char *zArg3, |
92 | | const char *zArg4 |
93 | 12.5M | ){ |
94 | 12.5M | if( eCode==SQLITE_PRAGMA |
95 | 12.5M | && (sqlite3_strnicmp("vdbe_", zArg1, 5)==0 |
96 | 390k | || sqlite3_stricmp("parser_trace", zArg1)==0) |
97 | 12.5M | ){ |
98 | 29 | return SQLITE_DENY; |
99 | 29 | } |
100 | 12.5M | return SQLITE_OK; |
101 | 12.5M | } |
102 | | |
103 | | /* |
104 | | ** Callback for sqlite3_exec(). |
105 | | */ |
106 | 1.11M | static int exec_handler(void *pClientData, int argc, char **argv, char **namev){ |
107 | 1.11M | FuzzCtx *p = (FuzzCtx*)pClientData; |
108 | 1.11M | int i; |
109 | 1.11M | if( argv ){ |
110 | 3.15M | for(i=0; i<argc; i++) sqlite3_free(sqlite3_mprintf("%s", argv[i])); |
111 | 1.11M | } |
112 | 1.11M | return (p->execCnt--)<=0 || progress_handler(pClientData); |
113 | 1.11M | } |
114 | | |
115 | | /* |
116 | | ** Main entry point. The fuzzer invokes this function with each |
117 | | ** fuzzed input. |
118 | | */ |
119 | 259k | int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
120 | 259k | char *zErrMsg = 0; /* Error message returned by sqlite_exec() */ |
121 | 259k | uint8_t uSelector; /* First byte of input data[] */ |
122 | 259k | int rc; /* Return code from various interfaces */ |
123 | 259k | char *zSql; /* Zero-terminated copy of data[] */ |
124 | 259k | FuzzCtx cx; /* Fuzzing context */ |
125 | | |
126 | 259k | memset(&cx, 0, sizeof(cx)); |
127 | 259k | if( size<3 ) return 0; /* Early out if unsufficient data */ |
128 | | |
129 | | /* Extract the selector byte from the beginning of the input. But only |
130 | | ** do this if the second byte is a \n. If the second byte is not \n, |
131 | | ** then use a default selector */ |
132 | 259k | if( data[1]=='\n' ){ |
133 | 1.64k | uSelector = data[0]; data += 2; size -= 2; |
134 | 257k | }else{ |
135 | 257k | uSelector = 0xfd; |
136 | 257k | } |
137 | | |
138 | | /* Open the database connection. Only use an in-memory database. */ |
139 | 259k | if( sqlite3_initialize() ) return 0; |
140 | 259k | rc = sqlite3_open_v2("fuzz.db", &cx.db, |
141 | 259k | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0); |
142 | 259k | if( rc ) return 0; |
143 | | |
144 | | /* Invoke the progress handler frequently to check to see if we |
145 | | ** are taking too long. The progress handler will return true |
146 | | ** (which will block further processing) if more than 10 seconds have |
147 | | ** elapsed since the start of the test. |
148 | | */ |
149 | 259k | cx.iLastCb = timeOfDay(); |
150 | 259k | cx.iCutoffTime = cx.iLastCb + 10000; /* Now + 10 seconds */ |
151 | 259k | #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
152 | 259k | sqlite3_progress_handler(cx.db, 10, progress_handler, (void*)&cx); |
153 | 259k | #endif |
154 | | |
155 | | /* Set a limit on the maximum size of a prepared statement */ |
156 | 259k | sqlite3_limit(cx.db, SQLITE_LIMIT_VDBE_OP, 25000); |
157 | | |
158 | | /* Limit total memory available to SQLite to 20MB */ |
159 | 259k | sqlite3_hard_heap_limit64(20000000); |
160 | | |
161 | | /* Set a limit on the maximum length of a string or BLOB. Without this |
162 | | ** limit, fuzzers will invoke randomblob(N) for a large N, and the process |
163 | | ** will timeout trying to generate the huge blob */ |
164 | 259k | sqlite3_limit(cx.db, SQLITE_LIMIT_LENGTH, 50000); |
165 | | |
166 | | /* Bit 1 of the selector enables foreign key constraints */ |
167 | 259k | sqlite3_db_config(cx.db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc); |
168 | 259k | uSelector >>= 1; |
169 | | |
170 | | /* Do not allow debugging pragma statements that might cause excess output */ |
171 | 259k | sqlite3_set_authorizer(cx.db, block_debug_pragmas, 0); |
172 | | |
173 | | /* Remaining bits of the selector determine a limit on the number of |
174 | | ** output rows */ |
175 | 259k | cx.execCnt = uSelector + 1; |
176 | | |
177 | | /* Run the SQL. The sqlite_exec() interface expects a zero-terminated |
178 | | ** string, so make a copy. */ |
179 | 259k | zSql = sqlite3_mprintf("%.*s", (int)size, data); |
180 | 259k | #ifndef SQLITE_OMIT_COMPLETE |
181 | 259k | sqlite3_complete(zSql); |
182 | 259k | #endif |
183 | 259k | sqlite3_exec(cx.db, zSql, exec_handler, (void*)&cx, &zErrMsg); |
184 | | |
185 | | /* Show any errors */ |
186 | 259k | if( (mDebug & FUZZ_SHOW_ERRORS)!=0 && zErrMsg ){ |
187 | 0 | printf("Error: %s\n", zErrMsg); |
188 | 0 | } |
189 | | |
190 | | /* Cleanup and return */ |
191 | 259k | sqlite3_free(zErrMsg); |
192 | 259k | sqlite3_free(zSql); |
193 | 259k | sqlite3_exec(cx.db, "PRAGMA temp_store_directory=''", 0, 0, 0); |
194 | 259k | sqlite3_close(cx.db); |
195 | | |
196 | 259k | if( mDebug & FUZZ_SHOW_MAX_DELAY ){ |
197 | 0 | printf("Progress callback count....... %d\n", cx.nCb); |
198 | 0 | printf("Max time between callbacks.... %d ms\n", (int)cx.mxInterval); |
199 | 0 | } |
200 | 259k | return 0; |
201 | 259k | } |