Blame tool/fuzzershell.c

Packit 87b942
/*
Packit 87b942
** 2015-04-17
Packit 87b942
**
Packit 87b942
** The author disclaims copyright to this source code.  In place of
Packit 87b942
** a legal notice, here is a blessing:
Packit 87b942
**
Packit 87b942
**    May you do good and not evil.
Packit 87b942
**    May you find forgiveness for yourself and forgive others.
Packit 87b942
**    May you share freely, never taking more than you give.
Packit 87b942
**
Packit 87b942
*************************************************************************
Packit 87b942
**
Packit 87b942
** This is a utility program designed to aid running the SQLite library
Packit 87b942
** against an external fuzzer, such as American Fuzzy Lop (AFL)
Packit 87b942
** (http://lcamtuf.coredump.cx/afl/).  Basically, this program reads
Packit 87b942
** SQL text from standard input and passes it through to SQLite for evaluation,
Packit 87b942
** just like the "sqlite3" command-line shell.  Differences from the
Packit 87b942
** command-line shell:
Packit 87b942
**
Packit 87b942
**    (1)  The complex "dot-command" extensions are omitted.  This
Packit 87b942
**         prevents the fuzzer from discovering that it can run things
Packit 87b942
**         like ".shell rm -rf ~"
Packit 87b942
**
Packit 87b942
**    (2)  The database is opened with the SQLITE_OPEN_MEMORY flag so that
Packit 87b942
**         no disk I/O from the database is permitted.  The ATTACH command
Packit 87b942
**         with a filename still uses an in-memory database.
Packit 87b942
**
Packit 87b942
**    (3)  The main in-memory database can be initialized from a template
Packit 87b942
**         disk database so that the fuzzer starts with a database containing
Packit 87b942
**         content.
Packit 87b942
**
Packit 87b942
**    (4)  The eval() SQL function is added, allowing the fuzzer to do 
Packit 87b942
**         interesting recursive operations.
Packit 87b942
**
Packit 87b942
**    (5)  An error is raised if there is a memory leak.
Packit 87b942
**
Packit 87b942
** The input text can be divided into separate test cases using comments
Packit 87b942
** of the form:
Packit 87b942
**
Packit 87b942
**       |****<...>****|
Packit 87b942
**
Packit 87b942
** where the "..." is arbitrary text. (Except the "|" should really be "/".
Packit 87b942
** "|" is used here to avoid compiler errors about nested comments.)
Packit 87b942
** A separate in-memory SQLite database is created to run each test case.
Packit 87b942
** This feature allows the "queue" of AFL to be captured into a single big
Packit 87b942
** file using a command like this:
Packit 87b942
**
Packit 87b942
**    (for i in id:*; do echo '|****<'$i'>****|'; cat $i; done) >~/all-queue.txt
Packit 87b942
**
Packit 87b942
** (Once again, change the "|" to "/") Then all elements of the AFL queue
Packit 87b942
** can be run in a single go (for regression testing, for example) by typing:
Packit 87b942
**
Packit 87b942
**    fuzzershell -f ~/all-queue.txt
Packit 87b942
**
Packit 87b942
** After running each chunk of SQL, the database connection is closed.  The
Packit 87b942
** program aborts if the close fails or if there is any unfreed memory after
Packit 87b942
** the close.
Packit 87b942
**
Packit 87b942
** New test cases can be appended to all-queue.txt at any time.  If redundant
Packit 87b942
** test cases are added, they can be eliminated by running:
Packit 87b942
**
Packit 87b942
**    fuzzershell -f ~/all-queue.txt --unique-cases ~/unique-cases.txt
Packit 87b942
*/
Packit 87b942
#include <stdio.h>
Packit 87b942
#include <stdlib.h>
Packit 87b942
#include <string.h>
Packit 87b942
#include <stdarg.h>
Packit 87b942
#include <ctype.h>
Packit 87b942
#include "sqlite3.h"
Packit 87b942
#define ISDIGIT(X) isdigit((unsigned char)(X))
Packit 87b942
Packit 87b942
/*
Packit 87b942
** All global variables are gathered into the "g" singleton.
Packit 87b942
*/
Packit 87b942
struct GlobalVars {
Packit 87b942
  const char *zArgv0;              /* Name of program */
Packit 87b942
  sqlite3_mem_methods sOrigMem;    /* Original memory methods */
Packit 87b942
  sqlite3_mem_methods sOomMem;     /* Memory methods with OOM simulator */
Packit 87b942
  int iOomCntdown;                 /* Memory fails on 1 to 0 transition */
Packit 87b942
  int nOomFault;                   /* Increments for each OOM fault */
Packit 87b942
  int bOomOnce;                    /* Fail just once if true */
Packit 87b942
  int bOomEnable;                  /* True to enable OOM simulation */
Packit 87b942
  int nOomBrkpt;                   /* Number of calls to oomFault() */
Packit 87b942
  char zTestName[100];             /* Name of current test */
Packit 87b942
} g;
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Maximum number of iterations for an OOM test
Packit 87b942
*/
Packit 87b942
#ifndef OOM_MAX
Packit 87b942
# define OOM_MAX 625
Packit 87b942
#endif
Packit 87b942
Packit 87b942
/*
Packit 87b942
** This routine is called when a simulated OOM occurs.  It exists as a
Packit 87b942
** convenient place to set a debugger breakpoint.
Packit 87b942
*/
Packit 87b942
static void oomFault(void){
Packit 87b942
  g.nOomBrkpt++; /* Prevent oomFault() from being optimized out */
Packit 87b942
}
Packit 87b942
Packit 87b942
Packit 87b942
/* Versions of malloc() and realloc() that simulate OOM conditions */
Packit 87b942
static void *oomMalloc(int nByte){
Packit 87b942
  if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){
Packit 87b942
    g.iOomCntdown--;
Packit 87b942
    if( g.iOomCntdown==0 ){
Packit 87b942
      if( g.nOomFault==0 ) oomFault();
Packit 87b942
      g.nOomFault++;
Packit 87b942
      if( !g.bOomOnce ) g.iOomCntdown = 1;
Packit 87b942
      return 0;
Packit 87b942
    }
Packit 87b942
  }
Packit 87b942
  return g.sOrigMem.xMalloc(nByte);
Packit 87b942
}
Packit 87b942
static void *oomRealloc(void *pOld, int nByte){
Packit 87b942
  if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){
Packit 87b942
    g.iOomCntdown--;
Packit 87b942
    if( g.iOomCntdown==0 ){
Packit 87b942
      if( g.nOomFault==0 ) oomFault();
Packit 87b942
      g.nOomFault++;
Packit 87b942
      if( !g.bOomOnce ) g.iOomCntdown = 1;
Packit 87b942
      return 0;
Packit 87b942
    }
Packit 87b942
  }
Packit 87b942
  return g.sOrigMem.xRealloc(pOld, nByte);
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Print an error message and abort in such a way to indicate to the
Packit 87b942
** fuzzer that this counts as a crash.
Packit 87b942
*/
Packit 87b942
static void abendError(const char *zFormat, ...){
Packit 87b942
  va_list ap;
Packit 87b942
  if( g.zTestName[0] ){
Packit 87b942
    fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName);
Packit 87b942
  }else{
Packit 87b942
    fprintf(stderr, "%s: ", g.zArgv0);
Packit 87b942
  }
Packit 87b942
  va_start(ap, zFormat);
Packit 87b942
  vfprintf(stderr, zFormat, ap);
Packit 87b942
  va_end(ap);
Packit 87b942
  fprintf(stderr, "\n");
Packit 87b942
  abort();
Packit 87b942
}
Packit 87b942
/*
Packit 87b942
** Print an error message and quit, but not in a way that would look
Packit 87b942
** like a crash.
Packit 87b942
*/
Packit 87b942
static void fatalError(const char *zFormat, ...){
Packit 87b942
  va_list ap;
Packit 87b942
  if( g.zTestName[0] ){
Packit 87b942
    fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName);
Packit 87b942
  }else{
Packit 87b942
    fprintf(stderr, "%s: ", g.zArgv0);
Packit 87b942
  }
Packit 87b942
  va_start(ap, zFormat);
Packit 87b942
  vfprintf(stderr, zFormat, ap);
Packit 87b942
  va_end(ap);
Packit 87b942
  fprintf(stderr, "\n");
Packit 87b942
  exit(1);
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Evaluate some SQL.  Abort if unable.
Packit 87b942
*/
Packit 87b942
static void sqlexec(sqlite3 *db, const char *zFormat, ...){
Packit 87b942
  va_list ap;
Packit 87b942
  char *zSql;
Packit 87b942
  char *zErrMsg = 0;
Packit 87b942
  int rc;
Packit 87b942
  va_start(ap, zFormat);
Packit 87b942
  zSql = sqlite3_vmprintf(zFormat, ap);
Packit 87b942
  va_end(ap);
Packit 87b942
  rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
Packit 87b942
  if( rc ) abendError("failed sql [%s]: %s", zSql, zErrMsg);
Packit 87b942
  sqlite3_free(zSql);
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** This callback is invoked by sqlite3_log().
Packit 87b942
*/
Packit 87b942
static void shellLog(void *pNotUsed, int iErrCode, const char *zMsg){
Packit 87b942
  printf("LOG: (%d) %s\n", iErrCode, zMsg);
Packit 87b942
  fflush(stdout);
Packit 87b942
}
Packit 87b942
static void shellLogNoop(void *pNotUsed, int iErrCode, const char *zMsg){
Packit 87b942
  return;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** This callback is invoked by sqlite3_exec() to return query results.
Packit 87b942
*/
Packit 87b942
static int execCallback(void *NotUsed, int argc, char **argv, char **colv){
Packit 87b942
  int i;
Packit 87b942
  static unsigned cnt = 0;
Packit 87b942
  printf("ROW #%u:\n", ++cnt);
Packit 87b942
  if( argv ){
Packit 87b942
    for(i=0; i
Packit 87b942
      printf(" %s=", colv[i]);
Packit 87b942
      if( argv[i] ){
Packit 87b942
        printf("[%s]\n", argv[i]);
Packit 87b942
      }else{
Packit 87b942
        printf("NULL\n");
Packit 87b942
      }
Packit 87b942
    }
Packit 87b942
  }
Packit 87b942
  fflush(stdout);
Packit 87b942
  return 0;
Packit 87b942
}
Packit 87b942
static int execNoop(void *NotUsed, int argc, char **argv, char **colv){
Packit 87b942
  return 0;
Packit 87b942
}
Packit 87b942
Packit 87b942
#ifndef SQLITE_OMIT_TRACE
Packit 87b942
/*
Packit 87b942
** This callback is invoked by sqlite3_trace() as each SQL statement
Packit 87b942
** starts.
Packit 87b942
*/
Packit 87b942
static void traceCallback(void *NotUsed, const char *zMsg){
Packit 87b942
  printf("TRACE: %s\n", zMsg);
Packit 87b942
  fflush(stdout);
Packit 87b942
}
Packit 87b942
static void traceNoop(void *NotUsed, const char *zMsg){
Packit 87b942
  return;
Packit 87b942
}
Packit 87b942
#endif
Packit 87b942
Packit 87b942
/***************************************************************************
Packit 87b942
** String accumulator object
Packit 87b942
*/
Packit 87b942
typedef struct Str Str;
Packit 87b942
struct Str {
Packit 87b942
  char *z;                /* The string.  Memory from malloc() */
Packit 87b942
  sqlite3_uint64 n;       /* Bytes of input used */
Packit 87b942
  sqlite3_uint64 nAlloc;  /* Bytes allocated to z[] */
Packit 87b942
  int oomErr;             /* OOM error has been seen */
Packit 87b942
};
Packit 87b942
Packit 87b942
/* Initialize a Str object */
Packit 87b942
static void StrInit(Str *p){
Packit 87b942
  memset(p, 0, sizeof(*p));
Packit 87b942
}
Packit 87b942
Packit 87b942
/* Append text to the end of a Str object */
Packit 87b942
static void StrAppend(Str *p, const char *z){
Packit 87b942
  sqlite3_uint64 n = strlen(z);
Packit 87b942
  if( p->n + n >= p->nAlloc ){
Packit 87b942
    char *zNew;
Packit 87b942
    sqlite3_uint64 nNew;
Packit 87b942
    if( p->oomErr ) return;
Packit 87b942
    nNew = p->nAlloc*2 + 100 + n;
Packit 87b942
    zNew = sqlite3_realloc(p->z, (int)nNew);
Packit 87b942
    if( zNew==0 ){
Packit 87b942
      sqlite3_free(p->z);
Packit 87b942
      memset(p, 0, sizeof(*p));
Packit 87b942
      p->oomErr = 1;
Packit 87b942
      return;
Packit 87b942
    }
Packit 87b942
    p->z = zNew;
Packit 87b942
    p->nAlloc = nNew;
Packit 87b942
  }
Packit 87b942
  memcpy(p->z + p->n, z, (size_t)n);
Packit 87b942
  p->n += n;
Packit 87b942
  p->z[p->n] = 0;
Packit 87b942
}
Packit 87b942
Packit 87b942
/* Return the current string content */
Packit 87b942
static char *StrStr(Str *p){
Packit 87b942
 return p->z;
Packit 87b942
}
Packit 87b942
Packit 87b942
/* Free the string */
Packit 87b942
static void StrFree(Str *p){
Packit 87b942
  sqlite3_free(p->z);
Packit 87b942
  StrInit(p);
Packit 87b942
}
Packit 87b942
Packit 87b942
/***************************************************************************
Packit 87b942
** eval() implementation copied from ../ext/misc/eval.c
Packit 87b942
*/
Packit 87b942
/*
Packit 87b942
** Structure used to accumulate the output
Packit 87b942
*/
Packit 87b942
struct EvalResult {
Packit 87b942
  char *z;               /* Accumulated output */
Packit 87b942
  const char *zSep;      /* Separator */
Packit 87b942
  int szSep;             /* Size of the separator string */
Packit 87b942
  sqlite3_int64 nAlloc;  /* Number of bytes allocated for z[] */
Packit 87b942
  sqlite3_int64 nUsed;   /* Number of bytes of z[] actually used */
Packit 87b942
};
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Callback from sqlite_exec() for the eval() function.
Packit 87b942
*/
Packit 87b942
static int callback(void *pCtx, int argc, char **argv, char **colnames){
Packit 87b942
  struct EvalResult *p = (struct EvalResult*)pCtx;
Packit 87b942
  int i; 
Packit 87b942
  for(i=0; i
Packit 87b942
    const char *z = argv[i] ? argv[i] : "";
Packit 87b942
    size_t sz = strlen(z);
Packit 87b942
    if( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){
Packit 87b942
      char *zNew;
Packit 87b942
      p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
Packit 87b942
      /* Using sqlite3_realloc64() would be better, but it is a recent
Packit 87b942
      ** addition and will cause a segfault if loaded by an older version
Packit 87b942
      ** of SQLite.  */
Packit 87b942
      zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0;
Packit 87b942
      if( zNew==0 ){
Packit 87b942
        sqlite3_free(p->z);
Packit 87b942
        memset(p, 0, sizeof(*p));
Packit 87b942
        return 1;
Packit 87b942
      }
Packit 87b942
      p->z = zNew;
Packit 87b942
    }
Packit 87b942
    if( p->nUsed>0 ){
Packit 87b942
      memcpy(&p->z[p->nUsed], p->zSep, p->szSep);
Packit 87b942
      p->nUsed += p->szSep;
Packit 87b942
    }
Packit 87b942
    memcpy(&p->z[p->nUsed], z, sz);
Packit 87b942
    p->nUsed += sz;
Packit 87b942
  }
Packit 87b942
  return 0;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Implementation of the eval(X) and eval(X,Y) SQL functions.
Packit 87b942
**
Packit 87b942
** Evaluate the SQL text in X.  Return the results, using string
Packit 87b942
** Y as the separator.  If Y is omitted, use a single space character.
Packit 87b942
*/
Packit 87b942
static void sqlEvalFunc(
Packit 87b942
  sqlite3_context *context,
Packit 87b942
  int argc,
Packit 87b942
  sqlite3_value **argv
Packit 87b942
){
Packit 87b942
  const char *zSql;
Packit 87b942
  sqlite3 *db;
Packit 87b942
  char *zErr = 0;
Packit 87b942
  int rc;
Packit 87b942
  struct EvalResult x;
Packit 87b942
Packit 87b942
  memset(&x, 0, sizeof(x));
Packit 87b942
  x.zSep = " ";
Packit 87b942
  zSql = (const char*)sqlite3_value_text(argv[0]);
Packit 87b942
  if( zSql==0 ) return;
Packit 87b942
  if( argc>1 ){
Packit 87b942
    x.zSep = (const char*)sqlite3_value_text(argv[1]);
Packit 87b942
    if( x.zSep==0 ) return;
Packit 87b942
  }
Packit 87b942
  x.szSep = (int)strlen(x.zSep);
Packit 87b942
  db = sqlite3_context_db_handle(context);
Packit 87b942
  rc = sqlite3_exec(db, zSql, callback, &x, &zErr);
Packit 87b942
  if( rc!=SQLITE_OK ){
Packit 87b942
    sqlite3_result_error(context, zErr, -1);
Packit 87b942
    sqlite3_free(zErr);
Packit 87b942
  }else if( x.zSep==0 ){
Packit 87b942
    sqlite3_result_error_nomem(context);
Packit 87b942
    sqlite3_free(x.z);
Packit 87b942
  }else{
Packit 87b942
    sqlite3_result_text(context, x.z, (int)x.nUsed, sqlite3_free);
Packit 87b942
  }
Packit 87b942
}
Packit 87b942
/* End of the eval() implementation
Packit 87b942
******************************************************************************/
Packit 87b942
Packit 87b942
/******************************************************************************
Packit 87b942
** The generate_series(START,END,STEP) eponymous table-valued function.
Packit 87b942
**
Packit 87b942
** This code is copy/pasted from ext/misc/series.c in the SQLite source tree.
Packit 87b942
*/
Packit 87b942
/* series_cursor is a subclass of sqlite3_vtab_cursor which will
Packit 87b942
** serve as the underlying representation of a cursor that scans
Packit 87b942
** over rows of the result
Packit 87b942
*/
Packit 87b942
typedef struct series_cursor series_cursor;
Packit 87b942
struct series_cursor {
Packit 87b942
  sqlite3_vtab_cursor base;  /* Base class - must be first */
Packit 87b942
  int isDesc;                /* True to count down rather than up */
Packit 87b942
  sqlite3_int64 iRowid;      /* The rowid */
Packit 87b942
  sqlite3_int64 iValue;      /* Current value ("value") */
Packit 87b942
  sqlite3_int64 mnValue;     /* Mimimum value ("start") */
Packit 87b942
  sqlite3_int64 mxValue;     /* Maximum value ("stop") */
Packit 87b942
  sqlite3_int64 iStep;       /* Increment ("step") */
Packit 87b942
};
Packit 87b942
Packit 87b942
/*
Packit 87b942
** The seriesConnect() method is invoked to create a new
Packit 87b942
** series_vtab that describes the generate_series virtual table.
Packit 87b942
**
Packit 87b942
** Think of this routine as the constructor for series_vtab objects.
Packit 87b942
**
Packit 87b942
** All this routine needs to do is:
Packit 87b942
**
Packit 87b942
**    (1) Allocate the series_vtab object and initialize all fields.
Packit 87b942
**
Packit 87b942
**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
Packit 87b942
**        result set of queries against generate_series will look like.
Packit 87b942
*/
Packit 87b942
static int seriesConnect(
Packit 87b942
  sqlite3 *db,
Packit 87b942
  void *pAux,
Packit 87b942
  int argc, const char *const*argv,
Packit 87b942
  sqlite3_vtab **ppVtab,
Packit 87b942
  char **pzErr
Packit 87b942
){
Packit 87b942
  sqlite3_vtab *pNew;
Packit 87b942
  int rc;
Packit 87b942
Packit 87b942
/* Column numbers */
Packit 87b942
#define SERIES_COLUMN_VALUE 0
Packit 87b942
#define SERIES_COLUMN_START 1
Packit 87b942
#define SERIES_COLUMN_STOP  2
Packit 87b942
#define SERIES_COLUMN_STEP  3
Packit 87b942
Packit 87b942
  rc = sqlite3_declare_vtab(db,
Packit 87b942
     "CREATE TABLE x(value,start hidden,stop hidden,step hidden)");
Packit 87b942
  if( rc==SQLITE_OK ){
Packit 87b942
    pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
Packit 87b942
    if( pNew==0 ) return SQLITE_NOMEM;
Packit 87b942
    memset(pNew, 0, sizeof(*pNew));
Packit 87b942
  }
Packit 87b942
  return rc;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** This method is the destructor for series_cursor objects.
Packit 87b942
*/
Packit 87b942
static int seriesDisconnect(sqlite3_vtab *pVtab){
Packit 87b942
  sqlite3_free(pVtab);
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Constructor for a new series_cursor object.
Packit 87b942
*/
Packit 87b942
static int seriesOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
Packit 87b942
  series_cursor *pCur;
Packit 87b942
  pCur = sqlite3_malloc( sizeof(*pCur) );
Packit 87b942
  if( pCur==0 ) return SQLITE_NOMEM;
Packit 87b942
  memset(pCur, 0, sizeof(*pCur));
Packit 87b942
  *ppCursor = &pCur->base;
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Destructor for a series_cursor.
Packit 87b942
*/
Packit 87b942
static int seriesClose(sqlite3_vtab_cursor *cur){
Packit 87b942
  sqlite3_free(cur);
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Advance a series_cursor to its next row of output.
Packit 87b942
*/
Packit 87b942
static int seriesNext(sqlite3_vtab_cursor *cur){
Packit 87b942
  series_cursor *pCur = (series_cursor*)cur;
Packit 87b942
  if( pCur->isDesc ){
Packit 87b942
    pCur->iValue -= pCur->iStep;
Packit 87b942
  }else{
Packit 87b942
    pCur->iValue += pCur->iStep;
Packit 87b942
  }
Packit 87b942
  pCur->iRowid++;
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Return values of columns for the row at which the series_cursor
Packit 87b942
** is currently pointing.
Packit 87b942
*/
Packit 87b942
static int seriesColumn(
Packit 87b942
  sqlite3_vtab_cursor *cur,   /* The cursor */
Packit 87b942
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
Packit 87b942
  int i                       /* Which column to return */
Packit 87b942
){
Packit 87b942
  series_cursor *pCur = (series_cursor*)cur;
Packit 87b942
  sqlite3_int64 x = 0;
Packit 87b942
  switch( i ){
Packit 87b942
    case SERIES_COLUMN_START:  x = pCur->mnValue; break;
Packit 87b942
    case SERIES_COLUMN_STOP:   x = pCur->mxValue; break;
Packit 87b942
    case SERIES_COLUMN_STEP:   x = pCur->iStep;   break;
Packit 87b942
    default:                   x = pCur->iValue;  break;
Packit 87b942
  }
Packit 87b942
  sqlite3_result_int64(ctx, x);
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Return the rowid for the current row.  In this implementation, the
Packit 87b942
** rowid is the same as the output value.
Packit 87b942
*/
Packit 87b942
static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
Packit 87b942
  series_cursor *pCur = (series_cursor*)cur;
Packit 87b942
  *pRowid = pCur->iRowid;
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Return TRUE if the cursor has been moved off of the last
Packit 87b942
** row of output.
Packit 87b942
*/
Packit 87b942
static int seriesEof(sqlite3_vtab_cursor *cur){
Packit 87b942
  series_cursor *pCur = (series_cursor*)cur;
Packit 87b942
  if( pCur->isDesc ){
Packit 87b942
    return pCur->iValue < pCur->mnValue;
Packit 87b942
  }else{
Packit 87b942
    return pCur->iValue > pCur->mxValue;
Packit 87b942
  }
Packit 87b942
}
Packit 87b942
Packit 87b942
/* True to cause run-time checking of the start=, stop=, and/or step= 
Packit 87b942
** parameters.  The only reason to do this is for testing the
Packit 87b942
** constraint checking logic for virtual tables in the SQLite core.
Packit 87b942
*/
Packit 87b942
#ifndef SQLITE_SERIES_CONSTRAINT_VERIFY
Packit 87b942
# define SQLITE_SERIES_CONSTRAINT_VERIFY 0
Packit 87b942
#endif
Packit 87b942
Packit 87b942
/*
Packit 87b942
** This method is called to "rewind" the series_cursor object back
Packit 87b942
** to the first row of output.  This method is always called at least
Packit 87b942
** once prior to any call to seriesColumn() or seriesRowid() or 
Packit 87b942
** seriesEof().
Packit 87b942
**
Packit 87b942
** The query plan selected by seriesBestIndex is passed in the idxNum
Packit 87b942
** parameter.  (idxStr is not used in this implementation.)  idxNum
Packit 87b942
** is a bitmask showing which constraints are available:
Packit 87b942
**
Packit 87b942
**    1:    start=VALUE
Packit 87b942
**    2:    stop=VALUE
Packit 87b942
**    4:    step=VALUE
Packit 87b942
**
Packit 87b942
** Also, if bit 8 is set, that means that the series should be output
Packit 87b942
** in descending order rather than in ascending order.
Packit 87b942
**
Packit 87b942
** This routine should initialize the cursor and position it so that it
Packit 87b942
** is pointing at the first row, or pointing off the end of the table
Packit 87b942
** (so that seriesEof() will return true) if the table is empty.
Packit 87b942
*/
Packit 87b942
static int seriesFilter(
Packit 87b942
  sqlite3_vtab_cursor *pVtabCursor, 
Packit 87b942
  int idxNum, const char *idxStr,
Packit 87b942
  int argc, sqlite3_value **argv
Packit 87b942
){
Packit 87b942
  series_cursor *pCur = (series_cursor *)pVtabCursor;
Packit 87b942
  int i = 0;
Packit 87b942
  if( idxNum & 1 ){
Packit 87b942
    pCur->mnValue = sqlite3_value_int64(argv[i++]);
Packit 87b942
  }else{
Packit 87b942
    pCur->mnValue = 0;
Packit 87b942
  }
Packit 87b942
  if( idxNum & 2 ){
Packit 87b942
    pCur->mxValue = sqlite3_value_int64(argv[i++]);
Packit 87b942
  }else{
Packit 87b942
    pCur->mxValue = 0xffffffff;
Packit 87b942
  }
Packit 87b942
  if( idxNum & 4 ){
Packit 87b942
    pCur->iStep = sqlite3_value_int64(argv[i++]);
Packit 87b942
    if( pCur->iStep<1 ) pCur->iStep = 1;
Packit 87b942
  }else{
Packit 87b942
    pCur->iStep = 1;
Packit 87b942
  }
Packit 87b942
  if( idxNum & 8 ){
Packit 87b942
    pCur->isDesc = 1;
Packit 87b942
    pCur->iValue = pCur->mxValue;
Packit 87b942
    if( pCur->iStep>0 ){
Packit 87b942
      pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep;
Packit 87b942
    }
Packit 87b942
  }else{
Packit 87b942
    pCur->isDesc = 0;
Packit 87b942
    pCur->iValue = pCur->mnValue;
Packit 87b942
  }
Packit 87b942
  pCur->iRowid = 1;
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** SQLite will invoke this method one or more times while planning a query
Packit 87b942
** that uses the generate_series virtual table.  This routine needs to create
Packit 87b942
** a query plan for each invocation and compute an estimated cost for that
Packit 87b942
** plan.
Packit 87b942
**
Packit 87b942
** In this implementation idxNum is used to represent the
Packit 87b942
** query plan.  idxStr is unused.
Packit 87b942
**
Packit 87b942
** The query plan is represented by bits in idxNum:
Packit 87b942
**
Packit 87b942
**  (1)  start = $value  -- constraint exists
Packit 87b942
**  (2)  stop = $value   -- constraint exists
Packit 87b942
**  (4)  step = $value   -- constraint exists
Packit 87b942
**  (8)  output in descending order
Packit 87b942
*/
Packit 87b942
static int seriesBestIndex(
Packit 87b942
  sqlite3_vtab *tab,
Packit 87b942
  sqlite3_index_info *pIdxInfo
Packit 87b942
){
Packit 87b942
  int i;                 /* Loop over constraints */
Packit 87b942
  int idxNum = 0;        /* The query plan bitmask */
Packit 87b942
  int startIdx = -1;     /* Index of the start= constraint, or -1 if none */
Packit 87b942
  int stopIdx = -1;      /* Index of the stop= constraint, or -1 if none */
Packit 87b942
  int stepIdx = -1;      /* Index of the step= constraint, or -1 if none */
Packit 87b942
  int nArg = 0;          /* Number of arguments that seriesFilter() expects */
Packit 87b942
Packit 87b942
  const struct sqlite3_index_constraint *pConstraint;
Packit 87b942
  pConstraint = pIdxInfo->aConstraint;
Packit 87b942
  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
Packit 87b942
    if( pConstraint->usable==0 ) continue;
Packit 87b942
    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
Packit 87b942
    switch( pConstraint->iColumn ){
Packit 87b942
      case SERIES_COLUMN_START:
Packit 87b942
        startIdx = i;
Packit 87b942
        idxNum |= 1;
Packit 87b942
        break;
Packit 87b942
      case SERIES_COLUMN_STOP:
Packit 87b942
        stopIdx = i;
Packit 87b942
        idxNum |= 2;
Packit 87b942
        break;
Packit 87b942
      case SERIES_COLUMN_STEP:
Packit 87b942
        stepIdx = i;
Packit 87b942
        idxNum |= 4;
Packit 87b942
        break;
Packit 87b942
    }
Packit 87b942
  }
Packit 87b942
  if( startIdx>=0 ){
Packit 87b942
    pIdxInfo->aConstraintUsage[startIdx].argvIndex = ++nArg;
Packit 87b942
    pIdxInfo->aConstraintUsage[startIdx].omit= !SQLITE_SERIES_CONSTRAINT_VERIFY;
Packit 87b942
  }
Packit 87b942
  if( stopIdx>=0 ){
Packit 87b942
    pIdxInfo->aConstraintUsage[stopIdx].argvIndex = ++nArg;
Packit 87b942
    pIdxInfo->aConstraintUsage[stopIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
Packit 87b942
  }
Packit 87b942
  if( stepIdx>=0 ){
Packit 87b942
    pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg;
Packit 87b942
    pIdxInfo->aConstraintUsage[stepIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
Packit 87b942
  }
Packit 87b942
  if( (idxNum & 3)==3 ){
Packit 87b942
    /* Both start= and stop= boundaries are available.  This is the 
Packit 87b942
    ** the preferred case */
Packit 87b942
    pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
Packit 87b942
    pIdxInfo->estimatedRows = 1000;
Packit 87b942
    if( pIdxInfo->nOrderBy==1 ){
Packit 87b942
      if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8;
Packit 87b942
      pIdxInfo->orderByConsumed = 1;
Packit 87b942
    }
Packit 87b942
  }else{
Packit 87b942
    /* If either boundary is missing, we have to generate a huge span
Packit 87b942
    ** of numbers.  Make this case very expensive so that the query
Packit 87b942
    ** planner will work hard to avoid it. */
Packit 87b942
    pIdxInfo->estimatedCost = (double)2147483647;
Packit 87b942
    pIdxInfo->estimatedRows = 2147483647;
Packit 87b942
  }
Packit 87b942
  pIdxInfo->idxNum = idxNum;
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** This following structure defines all the methods for the 
Packit 87b942
** generate_series virtual table.
Packit 87b942
*/
Packit 87b942
static sqlite3_module seriesModule = {
Packit 87b942
  0,                         /* iVersion */
Packit 87b942
  0,                         /* xCreate */
Packit 87b942
  seriesConnect,             /* xConnect */
Packit 87b942
  seriesBestIndex,           /* xBestIndex */
Packit 87b942
  seriesDisconnect,          /* xDisconnect */
Packit 87b942
  0,                         /* xDestroy */
Packit 87b942
  seriesOpen,                /* xOpen - open a cursor */
Packit 87b942
  seriesClose,               /* xClose - close a cursor */
Packit 87b942
  seriesFilter,              /* xFilter - configure scan constraints */
Packit 87b942
  seriesNext,                /* xNext - advance a cursor */
Packit 87b942
  seriesEof,                 /* xEof - check for end of scan */
Packit 87b942
  seriesColumn,              /* xColumn - read data */
Packit 87b942
  seriesRowid,               /* xRowid - read data */
Packit 87b942
  0,                         /* xUpdate */
Packit 87b942
  0,                         /* xBegin */
Packit 87b942
  0,                         /* xSync */
Packit 87b942
  0,                         /* xCommit */
Packit 87b942
  0,                         /* xRollback */
Packit 87b942
  0,                         /* xFindMethod */
Packit 87b942
  0,                         /* xRename */
Packit 87b942
};
Packit 87b942
/* END the generate_series(START,END,STEP) implementation
Packit 87b942
*********************************************************************************/
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Print sketchy documentation for this utility program
Packit 87b942
*/
Packit 87b942
static void showHelp(void){
Packit 87b942
  printf("Usage: %s [options] ?FILE...?\n", g.zArgv0);
Packit 87b942
  printf(
Packit 87b942
"Read SQL text from FILE... (or from standard input if FILE... is omitted)\n"
Packit 87b942
"and then evaluate each block of SQL contained therein.\n"
Packit 87b942
"Options:\n"
Packit 87b942
"  --autovacuum          Enable AUTOVACUUM mode\n"
Packit 87b942
"  --database FILE       Use database FILE instead of an in-memory database\n"
Packit 87b942
"  --disable-lookaside   Turn off lookaside memory\n"
Packit 87b942
"  --heap SZ MIN         Memory allocator uses SZ bytes & min allocation MIN\n"
Packit 87b942
"  --help                Show this help text\n"    
Packit 87b942
"  --lookaside N SZ      Configure lookaside for N slots of SZ bytes each\n"
Packit 87b942
"  --oom                 Run each test multiple times in a simulated OOM loop\n"
Packit 87b942
"  --pagesize N          Set the page size to N\n"
Packit 87b942
"  --pcache N SZ         Configure N pages of pagecache each of size SZ bytes\n"
Packit 87b942
"  -q                    Reduced output\n"
Packit 87b942
"  --quiet               Reduced output\n"
Packit 87b942
"  --scratch N SZ        Configure scratch memory for N slots of SZ bytes each\n"
Packit 87b942
"  --unique-cases FILE   Write all unique test cases to FILE\n"
Packit 87b942
"  --utf16be             Set text encoding to UTF-16BE\n"
Packit 87b942
"  --utf16le             Set text encoding to UTF-16LE\n"
Packit 87b942
"  -v                    Increased output\n"
Packit 87b942
"  --verbose             Increased output\n"
Packit 87b942
  );
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Return the value of a hexadecimal digit.  Return -1 if the input
Packit 87b942
** is not a hex digit.
Packit 87b942
*/
Packit 87b942
static int hexDigitValue(char c){
Packit 87b942
  if( c>='0' && c<='9' ) return c - '0';
Packit 87b942
  if( c>='a' && c<='f' ) return c - 'a' + 10;
Packit 87b942
  if( c>='A' && c<='F' ) return c - 'A' + 10;
Packit 87b942
  return -1;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Interpret zArg as an integer value, possibly with suffixes.
Packit 87b942
*/
Packit 87b942
static int integerValue(const char *zArg){
Packit 87b942
  sqlite3_int64 v = 0;
Packit 87b942
  static const struct { char *zSuffix; int iMult; } aMult[] = {
Packit 87b942
    { "KiB", 1024 },
Packit 87b942
    { "MiB", 1024*1024 },
Packit 87b942
    { "GiB", 1024*1024*1024 },
Packit 87b942
    { "KB",  1000 },
Packit 87b942
    { "MB",  1000000 },
Packit 87b942
    { "GB",  1000000000 },
Packit 87b942
    { "K",   1000 },
Packit 87b942
    { "M",   1000000 },
Packit 87b942
    { "G",   1000000000 },
Packit 87b942
  };
Packit 87b942
  int i;
Packit 87b942
  int isNeg = 0;
Packit 87b942
  if( zArg[0]=='-' ){
Packit 87b942
    isNeg = 1;
Packit 87b942
    zArg++;
Packit 87b942
  }else if( zArg[0]=='+' ){
Packit 87b942
    zArg++;
Packit 87b942
  }
Packit 87b942
  if( zArg[0]=='0' && zArg[1]=='x' ){
Packit 87b942
    int x;
Packit 87b942
    zArg += 2;
Packit 87b942
    while( (x = hexDigitValue(zArg[0]))>=0 ){
Packit 87b942
      v = (v<<4) + x;
Packit 87b942
      zArg++;
Packit 87b942
    }
Packit 87b942
  }else{
Packit 87b942
    while( ISDIGIT(zArg[0]) ){
Packit 87b942
      v = v*10 + zArg[0] - '0';
Packit 87b942
      zArg++;
Packit 87b942
    }
Packit 87b942
  }
Packit 87b942
  for(i=0; i
Packit 87b942
    if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
Packit 87b942
      v *= aMult[i].iMult;
Packit 87b942
      break;
Packit 87b942
    }
Packit 87b942
  }
Packit 87b942
  if( v>0x7fffffff ) abendError("parameter too large - max 2147483648");
Packit 87b942
  return (int)(isNeg? -v : v);
Packit 87b942
}
Packit 87b942
Packit 87b942
/* Return the current wall-clock time */
Packit 87b942
static sqlite3_int64 timeOfDay(void){
Packit 87b942
  static sqlite3_vfs *clockVfs = 0;
Packit 87b942
  sqlite3_int64 t;
Packit 87b942
  if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
Packit 87b942
  if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){
Packit 87b942
    clockVfs->xCurrentTimeInt64(clockVfs, &t);
Packit 87b942
  }else{
Packit 87b942
    double r;
Packit 87b942
    clockVfs->xCurrentTime(clockVfs, &r);
Packit 87b942
    t = (sqlite3_int64)(r*86400000.0);
Packit 87b942
  }
Packit 87b942
  return t;
Packit 87b942
}
Packit 87b942
Packit 87b942
int main(int argc, char **argv){
Packit 87b942
  char *zIn = 0;                /* Input text */
Packit 87b942
  int nAlloc = 0;               /* Number of bytes allocated for zIn[] */
Packit 87b942
  int nIn = 0;                  /* Number of bytes of zIn[] used */
Packit 87b942
  size_t got;                   /* Bytes read from input */
Packit 87b942
  int rc = SQLITE_OK;           /* Result codes from API functions */
Packit 87b942
  int i;                        /* Loop counter */
Packit 87b942
  int iNext;                    /* Next block of SQL */
Packit 87b942
  sqlite3 *db;                  /* Open database */
Packit 87b942
  char *zErrMsg = 0;            /* Error message returned from sqlite3_exec() */
Packit 87b942
  const char *zEncoding = 0;    /* --utf16be or --utf16le */
Packit 87b942
  int nHeap = 0, mnHeap = 0;    /* Heap size from --heap */
Packit 87b942
  int nLook = 0, szLook = 0;    /* --lookaside configuration */
Packit 87b942
  int nPCache = 0, szPCache = 0;/* --pcache configuration */
Packit 87b942
  int nScratch = 0, szScratch=0;/* --scratch configuration */
Packit 87b942
  int pageSize = 0;             /* Desired page size.  0 means default */
Packit 87b942
  void *pHeap = 0;              /* Allocated heap space */
Packit 87b942
  void *pLook = 0;              /* Allocated lookaside space */
Packit 87b942
  void *pPCache = 0;            /* Allocated storage for pcache */
Packit 87b942
  void *pScratch = 0;           /* Allocated storage for scratch */
Packit 87b942
  int doAutovac = 0;            /* True for --autovacuum */
Packit 87b942
  char *zSql;                   /* SQL to run */
Packit 87b942
  char *zToFree = 0;            /* Call sqlite3_free() on this afte running zSql */
Packit 87b942
  int verboseFlag = 0;          /* --verbose or -v flag */
Packit 87b942
  int quietFlag = 0;            /* --quiet or -q flag */
Packit 87b942
  int nTest = 0;                /* Number of test cases run */
Packit 87b942
  int multiTest = 0;            /* True if there will be multiple test cases */
Packit 87b942
  int lastPct = -1;             /* Previous percentage done output */
Packit 87b942
  sqlite3 *dataDb = 0;          /* Database holding compacted input data */
Packit 87b942
  sqlite3_stmt *pStmt = 0;      /* Statement to insert testcase into dataDb */
Packit 87b942
  const char *zDataOut = 0;     /* Write compacted data to this output file */
Packit 87b942
  int nHeader = 0;              /* Bytes of header comment text on input file */
Packit 87b942
  int oomFlag = 0;              /* --oom */
Packit 87b942
  int oomCnt = 0;               /* Counter for the OOM loop */
Packit 87b942
  char zErrBuf[200];            /* Space for the error message */
Packit 87b942
  const char *zFailCode;        /* Value of the TEST_FAILURE environment var */
Packit 87b942
  const char *zPrompt;          /* Initial prompt when large-file fuzzing */
Packit 87b942
  int nInFile = 0;              /* Number of input files to read */
Packit 87b942
  char **azInFile = 0;          /* Array of input file names */
Packit 87b942
  int jj;                       /* Loop counter for azInFile[] */
Packit 87b942
  sqlite3_int64 iBegin;         /* Start time for the whole program */
Packit 87b942
  sqlite3_int64 iStart, iEnd;   /* Start and end-times for a test case */
Packit 87b942
  const char *zDbName = 0;      /* Name of an on-disk database file to open */
Packit 87b942
Packit 87b942
  iBegin = timeOfDay();
Packit 87b942
  sqlite3_shutdown();
Packit 87b942
  zFailCode = getenv("TEST_FAILURE");
Packit 87b942
  g.zArgv0 = argv[0];
Packit 87b942
  zPrompt = "<stdin>";
Packit 87b942
  for(i=1; i
Packit 87b942
    const char *z = argv[i];
Packit 87b942
    if( z[0]=='-' ){
Packit 87b942
      z++;
Packit 87b942
      if( z[0]=='-' ) z++;
Packit 87b942
      if( strcmp(z,"autovacuum")==0 ){
Packit 87b942
        doAutovac = 1;
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"database")==0 ){
Packit 87b942
        if( i>=argc-1 ) abendError("missing argument on %s\n", argv[i]);
Packit 87b942
        zDbName = argv[i+1];
Packit 87b942
        i += 1;
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"disable-lookaside")==0 ){
Packit 87b942
        nLook = 1;
Packit 87b942
        szLook = 0;
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z, "f")==0 && i+1
Packit 87b942
        i++;
Packit 87b942
        goto addNewInFile;
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"heap")==0 ){
Packit 87b942
        if( i>=argc-2 ) abendError("missing arguments on %s\n", argv[i]);
Packit 87b942
        nHeap = integerValue(argv[i+1]);
Packit 87b942
        mnHeap = integerValue(argv[i+2]);
Packit 87b942
        i += 2;
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"help")==0 ){
Packit 87b942
        showHelp();
Packit 87b942
        return 0;
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"lookaside")==0 ){
Packit 87b942
        if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
Packit 87b942
        nLook = integerValue(argv[i+1]);
Packit 87b942
        szLook = integerValue(argv[i+2]);
Packit 87b942
        i += 2;
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"oom")==0 ){
Packit 87b942
        oomFlag = 1;
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"pagesize")==0 ){
Packit 87b942
        if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
Packit 87b942
        pageSize = integerValue(argv[++i]);
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"pcache")==0 ){
Packit 87b942
        if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
Packit 87b942
        nPCache = integerValue(argv[i+1]);
Packit 87b942
        szPCache = integerValue(argv[i+2]);
Packit 87b942
        i += 2;
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
Packit 87b942
        quietFlag = 1;
Packit 87b942
        verboseFlag = 0;
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"scratch")==0 ){
Packit 87b942
        if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
Packit 87b942
        nScratch = integerValue(argv[i+1]);
Packit 87b942
        szScratch = integerValue(argv[i+2]);
Packit 87b942
        i += 2;
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z, "unique-cases")==0 ){
Packit 87b942
        if( i>=argc-1 ) abendError("missing arguments on %s", argv[i]);
Packit 87b942
        if( zDataOut ) abendError("only one --minimize allowed");
Packit 87b942
        zDataOut = argv[++i];
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"utf16le")==0 ){
Packit 87b942
        zEncoding = "utf16le";
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"utf16be")==0 ){
Packit 87b942
        zEncoding = "utf16be";
Packit 87b942
      }else
Packit 87b942
      if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
Packit 87b942
        quietFlag = 0;
Packit 87b942
        verboseFlag = 1;
Packit 87b942
      }else
Packit 87b942
      {
Packit 87b942
        abendError("unknown option: %s", argv[i]);
Packit 87b942
      }
Packit 87b942
    }else{
Packit 87b942
      addNewInFile:
Packit 87b942
      nInFile++;
Packit 87b942
      azInFile = realloc(azInFile, sizeof(azInFile[0])*nInFile);
Packit 87b942
      if( azInFile==0 ) abendError("out of memory");
Packit 87b942
      azInFile[nInFile-1] = argv[i];
Packit 87b942
    }
Packit 87b942
  }
Packit 87b942
Packit 87b942
  /* Do global SQLite initialization */
Packit 87b942
  sqlite3_config(SQLITE_CONFIG_LOG, verboseFlag ? shellLog : shellLogNoop, 0);
Packit 87b942
  if( nHeap>0 ){
Packit 87b942
    pHeap = malloc( nHeap );
Packit 87b942
    if( pHeap==0 ) fatalError("cannot allocate %d-byte heap\n", nHeap);
Packit 87b942
    rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
Packit 87b942
    if( rc ) abendError("heap configuration failed: %d\n", rc);
Packit 87b942
  }
Packit 87b942
  if( oomFlag ){
Packit 87b942
    sqlite3_config(SQLITE_CONFIG_GETMALLOC, &g.sOrigMem);
Packit 87b942
    g.sOomMem = g.sOrigMem;
Packit 87b942
    g.sOomMem.xMalloc = oomMalloc;
Packit 87b942
    g.sOomMem.xRealloc = oomRealloc;
Packit 87b942
    sqlite3_config(SQLITE_CONFIG_MALLOC, &g.sOomMem);
Packit 87b942
  }
Packit 87b942
  if( nLook>0 ){
Packit 87b942
    sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
Packit 87b942
    if( szLook>0 ){
Packit 87b942
      pLook = malloc( nLook*szLook );
Packit 87b942
      if( pLook==0 ) fatalError("out of memory");
Packit 87b942
    }
Packit 87b942
  }
Packit 87b942
  if( nScratch>0 && szScratch>0 ){
Packit 87b942
    pScratch = malloc( nScratch*(sqlite3_int64)szScratch );
Packit 87b942
    if( pScratch==0 ) fatalError("cannot allocate %lld-byte scratch",
Packit 87b942
                                 nScratch*(sqlite3_int64)szScratch);
Packit 87b942
    rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch);
Packit 87b942
    if( rc ) abendError("scratch configuration failed: %d\n", rc);
Packit 87b942
  }
Packit 87b942
  if( nPCache>0 && szPCache>0 ){
Packit 87b942
    pPCache = malloc( nPCache*(sqlite3_int64)szPCache );
Packit 87b942
    if( pPCache==0 ) fatalError("cannot allocate %lld-byte pcache",
Packit 87b942
                                 nPCache*(sqlite3_int64)szPCache);
Packit 87b942
    rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
Packit 87b942
    if( rc ) abendError("pcache configuration failed: %d", rc);
Packit 87b942
  }
Packit 87b942
Packit 87b942
  /* If the --unique-cases option was supplied, open the database that will
Packit 87b942
  ** be used to gather unique test cases.
Packit 87b942
  */
Packit 87b942
  if( zDataOut ){
Packit 87b942
    rc = sqlite3_open(":memory:", &dataDb);
Packit 87b942
    if( rc ) abendError("cannot open :memory: database");
Packit 87b942
    rc = sqlite3_exec(dataDb,
Packit 87b942
          "CREATE TABLE testcase(sql BLOB PRIMARY KEY, tm) WITHOUT ROWID;",0,0,0);
Packit 87b942
    if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
Packit 87b942
    rc = sqlite3_prepare_v2(dataDb,
Packit 87b942
          "INSERT OR IGNORE INTO testcase(sql,tm)VALUES(?1,?2)",
Packit 87b942
          -1, &pStmt, 0);
Packit 87b942
    if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
Packit 87b942
  }
Packit 87b942
Packit 87b942
  /* Initialize the input buffer used to hold SQL text */
Packit 87b942
  if( nInFile==0 ) nInFile = 1;
Packit 87b942
  nAlloc = 1000;
Packit 87b942
  zIn = malloc(nAlloc);
Packit 87b942
  if( zIn==0 ) fatalError("out of memory");
Packit 87b942
Packit 87b942
  /* Loop over all input files */
Packit 87b942
  for(jj=0; jj
Packit 87b942
Packit 87b942
    /* Read the complete content of the next input file into zIn[] */
Packit 87b942
    FILE *in;
Packit 87b942
    if( azInFile ){
Packit 87b942
      int j, k;
Packit 87b942
      in = fopen(azInFile[jj],"rb");
Packit 87b942
      if( in==0 ){
Packit 87b942
        abendError("cannot open %s for reading", azInFile[jj]);
Packit 87b942
      }
Packit 87b942
      zPrompt = azInFile[jj];
Packit 87b942
      for(j=k=0; zPrompt[j]; j++) if( zPrompt[j]=='/' ) k = j+1;
Packit 87b942
      zPrompt += k;
Packit 87b942
    }else{
Packit 87b942
      in = stdin;
Packit 87b942
      zPrompt = "<stdin>";
Packit 87b942
    }
Packit 87b942
    while( !feof(in) ){
Packit 87b942
      got = fread(zIn+nIn, 1, nAlloc-nIn-1, in); 
Packit 87b942
      nIn += (int)got;
Packit 87b942
      zIn[nIn] = 0;
Packit 87b942
      if( got==0 ) break;
Packit 87b942
      if( nAlloc - nIn - 1 < 100 ){
Packit 87b942
        nAlloc += nAlloc+1000;
Packit 87b942
        zIn = realloc(zIn, nAlloc);
Packit 87b942
        if( zIn==0 ) fatalError("out of memory");
Packit 87b942
      }
Packit 87b942
    }
Packit 87b942
    if( in!=stdin ) fclose(in);
Packit 87b942
    lastPct = -1;
Packit 87b942
Packit 87b942
    /* Skip initial lines of the input file that begin with "#" */
Packit 87b942
    for(i=0; i
Packit 87b942
      if( zIn[i]!='#' ) break;
Packit 87b942
      for(iNext=i+1; iNext
Packit 87b942
    }
Packit 87b942
    nHeader = i;
Packit 87b942
Packit 87b942
    /* Process all test cases contained within the input file.
Packit 87b942
    */
Packit 87b942
    for(; i
Packit 87b942
      char cSaved;
Packit 87b942
      if( strncmp(&zIn[i], "/****<",6)==0 ){
Packit 87b942
        char *z = strstr(&zIn[i], ">****/");
Packit 87b942
        if( z ){
Packit 87b942
          z += 6;
Packit 87b942
          sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "%.*s", 
Packit 87b942
                           (int)(z-&zIn[i]) - 12, &zIn[i+6]);
Packit 87b942
          if( verboseFlag ){
Packit 87b942
            printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
Packit 87b942
            fflush(stdout);
Packit 87b942
          }
Packit 87b942
          i += (int)(z-&zIn[i]);
Packit 87b942
          multiTest = 1;
Packit 87b942
        }
Packit 87b942
      }
Packit 87b942
      for(iNext=i; iNext
Packit 87b942
      cSaved = zIn[iNext];
Packit 87b942
      zIn[iNext] = 0;
Packit 87b942
Packit 87b942
Packit 87b942
      /* Print out the SQL of the next test case is --verbose is enabled
Packit 87b942
      */
Packit 87b942
      zSql = &zIn[i];
Packit 87b942
      if( verboseFlag ){
Packit 87b942
        printf("INPUT (offset: %d, size: %d): [%s]\n",
Packit 87b942
                i, (int)strlen(&zIn[i]), &zIn[i]);
Packit 87b942
      }else if( multiTest && !quietFlag ){
Packit 87b942
        if( oomFlag ){
Packit 87b942
          printf("%s\n", g.zTestName);
Packit 87b942
        }else{
Packit 87b942
          int pct = (10*iNext)/nIn;
Packit 87b942
          if( pct!=lastPct ){
Packit 87b942
            if( lastPct<0 ) printf("%s:", zPrompt);
Packit 87b942
            printf(" %d%%", pct*10);
Packit 87b942
            lastPct = pct;
Packit 87b942
          }
Packit 87b942
        }
Packit 87b942
      }else if( nInFile>1 ){
Packit 87b942
        printf("%s\n", zPrompt);
Packit 87b942
      }
Packit 87b942
      fflush(stdout);
Packit 87b942
Packit 87b942
      /* Run the next test case.  Run it multiple times in --oom mode
Packit 87b942
      */
Packit 87b942
      if( oomFlag ){
Packit 87b942
        oomCnt = g.iOomCntdown = 1;
Packit 87b942
        g.nOomFault = 0;
Packit 87b942
        g.bOomOnce = 1;
Packit 87b942
        if( verboseFlag ){
Packit 87b942
          printf("Once.%d\n", oomCnt);
Packit 87b942
          fflush(stdout);
Packit 87b942
        }
Packit 87b942
      }else{
Packit 87b942
        oomCnt = 0;
Packit 87b942
      }
Packit 87b942
      do{
Packit 87b942
        Str sql;
Packit 87b942
        StrInit(&sql;;
Packit 87b942
        if( zDbName ){
Packit 87b942
          rc = sqlite3_open_v2(zDbName, &db, SQLITE_OPEN_READWRITE, 0);
Packit 87b942
          if( rc!=SQLITE_OK ){
Packit 87b942
            abendError("Cannot open database file %s", zDbName);
Packit 87b942
          }
Packit 87b942
        }else{
Packit 87b942
          rc = sqlite3_open_v2(
Packit 87b942
            "main.db", &db,
Packit 87b942
            SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
Packit 87b942
            0);
Packit 87b942
          if( rc!=SQLITE_OK ){
Packit 87b942
            abendError("Unable to open the in-memory database");
Packit 87b942
          }
Packit 87b942
        }
Packit 87b942
        if( pLook ){
Packit 87b942
          rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook);
Packit 87b942
          if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc);
Packit 87b942
        }
Packit 87b942
    #ifndef SQLITE_OMIT_TRACE
Packit 87b942
        sqlite3_trace(db, verboseFlag ? traceCallback : traceNoop, 0);
Packit 87b942
    #endif
Packit 87b942
        sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
Packit 87b942
        sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
Packit 87b942
        sqlite3_create_module(db, "generate_series", &seriesModule, 0);
Packit 87b942
        sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
Packit 87b942
        if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding);
Packit 87b942
        if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
Packit 87b942
        if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
Packit 87b942
        iStart = timeOfDay();
Packit 87b942
Packit 87b942
        /* If using an input database file and that database contains a table
Packit 87b942
        ** named "autoexec" with a column "sql", then replace the input SQL
Packit 87b942
        ** with the concatenated text of the autoexec table.  In this way,
Packit 87b942
        ** if the database file is the input being fuzzed, the SQL text is
Packit 87b942
        ** fuzzed at the same time. */
Packit 87b942
        if( sqlite3_table_column_metadata(db,0,"autoexec","sql",0,0,0,0,0)==0 ){
Packit 87b942
          sqlite3_stmt *pStmt2;
Packit 87b942
          rc = sqlite3_prepare_v2(db,"SELECT sql FROM autoexec",-1,&pStmt2,0);
Packit 87b942
          if( rc==SQLITE_OK ){
Packit 87b942
            while( sqlite3_step(pStmt2)==SQLITE_ROW ){
Packit 87b942
              StrAppend(&sql, (const char*)sqlite3_column_text(pStmt2, 0));
Packit 87b942
              StrAppend(&sql, "\n");
Packit 87b942
            }
Packit 87b942
          }
Packit 87b942
          sqlite3_finalize(pStmt2);
Packit 87b942
          zSql = StrStr(&sql;;
Packit 87b942
        }
Packit 87b942
Packit 87b942
        g.bOomEnable = 1;
Packit 87b942
        if( verboseFlag ){
Packit 87b942
          zErrMsg = 0;
Packit 87b942
          rc = sqlite3_exec(db, zSql, execCallback, 0, &zErrMsg);
Packit 87b942
          if( zErrMsg ){
Packit 87b942
            sqlite3_snprintf(sizeof(zErrBuf),zErrBuf,"%z", zErrMsg);
Packit 87b942
            zErrMsg = 0;
Packit 87b942
          }
Packit 87b942
        }else {
Packit 87b942
          rc = sqlite3_exec(db, zSql, execNoop, 0, 0);
Packit 87b942
        }
Packit 87b942
        g.bOomEnable = 0;
Packit 87b942
        iEnd = timeOfDay();
Packit 87b942
        StrFree(&sql;;
Packit 87b942
        rc = sqlite3_close(db);
Packit 87b942
        if( rc ){
Packit 87b942
          abendError("sqlite3_close() failed with rc=%d", rc);
Packit 87b942
        }
Packit 87b942
        if( !zDataOut && sqlite3_memory_used()>0 ){
Packit 87b942
          abendError("memory in use after close: %lld bytes",sqlite3_memory_used());
Packit 87b942
        }
Packit 87b942
        if( oomFlag ){
Packit 87b942
          /* Limit the number of iterations of the OOM loop to OOM_MAX.  If the
Packit 87b942
          ** first pass (single failure) exceeds 2/3rds of OOM_MAX this skip the
Packit 87b942
          ** second pass (continuous failure after first) completely. */
Packit 87b942
          if( g.nOomFault==0 || oomCnt>OOM_MAX ){
Packit 87b942
            if( g.bOomOnce && oomCnt<=(OOM_MAX*2/3) ){
Packit 87b942
              oomCnt = g.iOomCntdown = 1;
Packit 87b942
              g.bOomOnce = 0;
Packit 87b942
            }else{
Packit 87b942
              oomCnt = 0;
Packit 87b942
            }
Packit 87b942
          }else{
Packit 87b942
            g.iOomCntdown = ++oomCnt;
Packit 87b942
            g.nOomFault = 0;
Packit 87b942
          }
Packit 87b942
          if( oomCnt ){
Packit 87b942
            if( verboseFlag ){
Packit 87b942
              printf("%s.%d\n", g.bOomOnce ? "Once" : "Multi", oomCnt);
Packit 87b942
              fflush(stdout);
Packit 87b942
            }
Packit 87b942
            nTest++;
Packit 87b942
          }
Packit 87b942
        }
Packit 87b942
      }while( oomCnt>0 );
Packit 87b942
Packit 87b942
      /* Store unique test cases in the in the dataDb database if the
Packit 87b942
      ** --unique-cases flag is present
Packit 87b942
      */
Packit 87b942
      if( zDataOut ){
Packit 87b942
        sqlite3_bind_blob(pStmt, 1, &zIn[i], iNext-i, SQLITE_STATIC);
Packit 87b942
        sqlite3_bind_int64(pStmt, 2, iEnd - iStart);
Packit 87b942
        rc = sqlite3_step(pStmt);
Packit 87b942
        if( rc!=SQLITE_DONE ) abendError("%s", sqlite3_errmsg(dataDb));
Packit 87b942
        sqlite3_reset(pStmt);
Packit 87b942
      }
Packit 87b942
Packit 87b942
      /* Free the SQL from the current test case
Packit 87b942
      */
Packit 87b942
      if( zToFree ){
Packit 87b942
        sqlite3_free(zToFree);
Packit 87b942
        zToFree = 0;
Packit 87b942
      }
Packit 87b942
      zIn[iNext] = cSaved;
Packit 87b942
Packit 87b942
      /* Show test-case results in --verbose mode
Packit 87b942
      */
Packit 87b942
      if( verboseFlag ){
Packit 87b942
        printf("RESULT-CODE: %d\n", rc);
Packit 87b942
        if( zErrMsg ){
Packit 87b942
          printf("ERROR-MSG: [%s]\n", zErrBuf);
Packit 87b942
        }
Packit 87b942
        fflush(stdout);
Packit 87b942
      }
Packit 87b942
Packit 87b942
      /* Simulate an error if the TEST_FAILURE environment variable is "5".
Packit 87b942
      ** This is used to verify that automated test script really do spot
Packit 87b942
      ** errors that occur in this test program.
Packit 87b942
      */
Packit 87b942
      if( zFailCode ){
Packit 87b942
        if( zFailCode[0]=='5' && zFailCode[1]==0 ){
Packit 87b942
          abendError("simulated failure");
Packit 87b942
        }else if( zFailCode[0]!=0 ){
Packit 87b942
          /* If TEST_FAILURE is something other than 5, just exit the test
Packit 87b942
          ** early */
Packit 87b942
          printf("\nExit early due to TEST_FAILURE being set");
Packit 87b942
          break;
Packit 87b942
        }
Packit 87b942
      }
Packit 87b942
    }
Packit 87b942
    if( !verboseFlag && multiTest && !quietFlag && !oomFlag ) printf("\n");
Packit 87b942
  }
Packit 87b942
Packit 87b942
  /* Report total number of tests run
Packit 87b942
  */
Packit 87b942
  if( nTest>1 && !quietFlag ){
Packit 87b942
    sqlite3_int64 iElapse = timeOfDay() - iBegin;
Packit 87b942
    printf("%s: 0 errors out of %d tests in %d.%03d seconds\nSQLite %s %s\n",
Packit 87b942
           g.zArgv0, nTest, (int)(iElapse/1000), (int)(iElapse%1000),
Packit 87b942
           sqlite3_libversion(), sqlite3_sourceid());
Packit 87b942
  }
Packit 87b942
Packit 87b942
  /* Write the unique test cases if the --unique-cases flag was used
Packit 87b942
  */
Packit 87b942
  if( zDataOut ){
Packit 87b942
    int n = 0;
Packit 87b942
    FILE *out = fopen(zDataOut, "wb");
Packit 87b942
    if( out==0 ) abendError("cannot open %s for writing", zDataOut);
Packit 87b942
    if( nHeader>0 ) fwrite(zIn, nHeader, 1, out);
Packit 87b942
    sqlite3_finalize(pStmt);
Packit 87b942
    rc = sqlite3_prepare_v2(dataDb, "SELECT sql, tm FROM testcase ORDER BY tm, sql",
Packit 87b942
                            -1, &pStmt, 0);
Packit 87b942
    if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
Packit 87b942
    while( sqlite3_step(pStmt)==SQLITE_ROW ){
Packit 87b942
      fprintf(out,"/****<%d:%dms>****/", ++n, sqlite3_column_int(pStmt,1));
Packit 87b942
      fwrite(sqlite3_column_blob(pStmt,0),sqlite3_column_bytes(pStmt,0),1,out);
Packit 87b942
    }
Packit 87b942
    fclose(out);
Packit 87b942
    sqlite3_finalize(pStmt);
Packit 87b942
    sqlite3_close(dataDb);
Packit 87b942
  }
Packit 87b942
Packit 87b942
  /* Clean up and exit.
Packit 87b942
  */
Packit 87b942
  free(azInFile);
Packit 87b942
  free(zIn);
Packit 87b942
  free(pHeap);
Packit 87b942
  free(pLook);
Packit 87b942
  free(pScratch);
Packit 87b942
  free(pPCache);
Packit 87b942
  return 0;
Packit 87b942
}