CoolFace
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
ossfuzz.c207 linesDownload Raw Back to test
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#endif9#include <stdio.h>10#include <string.h>11#include "sqlite3.h"12 13#if defined(_MSC_VER)14typedef unsigned char uint8_t;15#endif16 17/* Global debugging settings.  OSS-Fuzz will have all debugging turned18** off.  But if LLVMFuzzerTestOneInput() is called interactively from19** the ossshell utility program, then these flags might be set.20*/21static unsigned mDebug = 0;22#define FUZZ_SQL_TRACE       0x0001   /* Set an sqlite3_trace() callback */23#define FUZZ_SHOW_MAX_DELAY  0x0002   /* Show maximum progress callback delay */24#define FUZZ_SHOW_ERRORS     0x0004   /* Print error messages from SQLite */25 26/* The ossshell utility program invokes this interface to see the27** debugging flags.  Unused by OSS-Fuzz.28*/29void ossfuzz_set_debug_flags(unsigned x){30  mDebug = x;31}32 33/* Return the current real-world time in milliseconds since the34** Julian epoch (-4714-11-24).35*/36static sqlite3_int64 timeOfDay(void){37  static sqlite3_vfs *clockVfs = 0;38  sqlite3_int64 t;39  if( clockVfs==0 ){40    clockVfs = sqlite3_vfs_find(0);41    if( clockVfs==0 ) return 0;42  }43  if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){44    clockVfs->xCurrentTimeInt64(clockVfs, &t);45  }else{46    double r;47    clockVfs->xCurrentTime(clockVfs, &r);48    t = (sqlite3_int64)(r*86400000.0);49  }50  return t;51}52 53/* An instance of the following object is passed by pointer as the54** client data to various callbacks.55*/56typedef 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 should69** stop.  So return non-zero if the cut-off time is exceeded.70*/71static int progress_handler(void *pClientData) {72  FuzzCtx *p = (FuzzCtx*)pClientData;73  sqlite3_int64 iNow = timeOfDay();74  int rc = iNow>=p->iCutoffTime;75  sqlite3_int64 iDiff = iNow - p->iLastCb;76  if( iDiff > p->mxInterval ) p->mxInterval = iDiff;77  p->nCb++;78  return rc;79}80 81/*82** Disallow debugging pragmas such as "PRAGMA vdbe_debug" and83** "PRAGMA parser_trace" since they can dramatically increase the84** amount of output without actually testing anything useful.85*/86static 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 *zArg493){94  if( eCode==SQLITE_PRAGMA95   && (sqlite3_strnicmp("vdbe_", zArg1, 5)==096        || sqlite3_stricmp("parser_trace", zArg1)==0)97  ){98    return SQLITE_DENY;99  }100  return SQLITE_OK;101}102 103/*104** Callback for sqlite3_exec().105*/106static int exec_handler(void *pClientData, int argc, char **argv, char **namev){107  FuzzCtx *p = (FuzzCtx*)pClientData;108  int i;109  if( argv ){110    for(i=0; i<argc; i++) sqlite3_free(sqlite3_mprintf("%s", argv[i]));111  }112  return (p->execCnt--)<=0 || progress_handler(pClientData);113}114 115/*116** Main entry point.  The fuzzer invokes this function with each117** fuzzed input.118*/119int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {120  char *zErrMsg = 0;       /* Error message returned by sqlite_exec() */121  uint8_t uSelector;       /* First byte of input data[] */122  int rc;                  /* Return code from various interfaces */123  char *zSql;              /* Zero-terminated copy of data[] */124  FuzzCtx cx;              /* Fuzzing context */125 126  memset(&cx, 0, sizeof(cx));127  if( size<3 ) return 0;   /* Early out if unsufficient data */128 129  /* Extract the selector byte from the beginning of the input.  But only130  ** do this if the second byte is a \n.  If the second byte is not \n,131  ** then use a default selector */132  if( data[1]=='\n' ){133    uSelector = data[0];  data += 2; size -= 2;134  }else{135    uSelector = 0xfd;136  }137 138  /* Open the database connection.  Only use an in-memory database. */139  if( sqlite3_initialize() ) return 0;140  rc = sqlite3_open_v2("fuzz.db", &cx.db,141           SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);142  if( rc ) return 0;143 144  /* Invoke the progress handler frequently to check to see if we145  ** are taking too long.  The progress handler will return true146  ** (which will block further processing) if more than 10 seconds have147  ** elapsed since the start of the test.148  */149  cx.iLastCb = timeOfDay();150  cx.iCutoffTime = cx.iLastCb + 10000;  /* Now + 10 seconds */151#ifndef SQLITE_OMIT_PROGRESS_CALLBACK152  sqlite3_progress_handler(cx.db, 10, progress_handler, (void*)&cx);153#endif154 155  /* Set a limit on the maximum size of a prepared statement */156  sqlite3_limit(cx.db, SQLITE_LIMIT_VDBE_OP, 25000);157 158  /* Set a limit on the maximum LIKE or GLOB pattern length due to159  ** https://issues.oss-fuzz.com/issues/453240497.  The default is 50K160  ** which is causing timeouts in OSS-Fuzz */161  sqlite3_limit(cx.db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, 250);162 163  /* Limit total memory available to SQLite to 20MB */164  sqlite3_hard_heap_limit64(20000000);165 166  /* Set a limit on the maximum length of a string or BLOB.  Without this167  ** limit, fuzzers will invoke randomblob(N) for a large N, and the process168  ** will timeout trying to generate the huge blob */169  sqlite3_limit(cx.db, SQLITE_LIMIT_LENGTH, 50000);170 171  /* Bit 1 of the selector enables foreign key constraints */172  sqlite3_db_config(cx.db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc);173  uSelector >>= 1;174 175  /* Do not allow debugging pragma statements that might cause excess output */176  sqlite3_set_authorizer(cx.db, block_debug_pragmas, 0);177 178  /* Remaining bits of the selector determine a limit on the number of179  ** output rows */180  cx.execCnt = uSelector + 1;181 182  /* Run the SQL.  The sqlite_exec() interface expects a zero-terminated183  ** string, so make a copy. */184  zSql = sqlite3_mprintf("%.*s", (int)size, data);185#ifndef SQLITE_OMIT_COMPLETE186  sqlite3_complete(zSql);187#endif188  sqlite3_exec(cx.db, zSql, exec_handler, (void*)&cx, &zErrMsg);189 190  /* Show any errors */191  if( (mDebug & FUZZ_SHOW_ERRORS)!=0 && zErrMsg ){192    printf("Error: %s\n", zErrMsg);193  }194 195  /* Cleanup and return */196  sqlite3_free(zErrMsg);197  sqlite3_free(zSql);198  sqlite3_exec(cx.db, "PRAGMA temp_store_directory=''", 0, 0, 0);199  sqlite3_close(cx.db);200 201  if( mDebug & FUZZ_SHOW_MAX_DELAY ){202    printf("Progress callback count....... %d\n", cx.nCb);203    printf("Max time between callbacks.... %d ms\n", (int)cx.mxInterval);204  }205  return 0;206}207