/ Check-in [ab0a96ca]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Enhance fuzzershell to support multiple blocks of SQL, each run in its own private in-memory database.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ab0a96ca73cfe92d5a837c71c148e8361f42acc3
User & Date: drh 2015-04-20 12:50:13
Context
2015-04-20
13:59
Fix an obscure memory leak in sqlite3Stat4ProbeFree() check-in: c72abbe2 user: drh tags: trunk
12:50
Enhance fuzzershell to support multiple blocks of SQL, each run in its own private in-memory database. check-in: ab0a96ca user: drh tags: trunk
01:13
Add an ALWAYS() around a new branch that was made unreachable by an even newer change. check-in: 592c0104 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to tool/fuzzershell.c.

    27     27   **
    28     28   **    (3)  The main in-memory database can be initialized from a template
    29     29   **         disk database so that the fuzzer starts with a database containing
    30     30   **         content.
    31     31   **
    32     32   **    (4)  The eval() SQL function is added, allowing the fuzzer to do 
    33     33   **         interesting recursive operations.
           34  +**
           35  +** 2015-04-20: The input text can be divided into separate SQL chunks using
           36  +** lines of the form:
           37  +**
           38  +**       |****<...>****|
           39  +**
           40  +** where the "..." is arbitrary text, except the "|" should really be "/".
           41  +** ("|" is used here to avoid compiler warnings about nested comments.)
           42  +** Each such SQL comment is printed as it is encountered.  A separate 
           43  +** in-memory SQLite database is created to run each chunk of SQL.  This
           44  +** feature allows the "queue" of AFL to be captured into a single big
           45  +** file using a command like this:
           46  +**
           47  +**    (for i in id:*; do echo '|****<'$i'>****|'; cat $i; done) >~/all-queue.txt
           48  +**
           49  +** (Once again, change the "|" to "/") Then all elements of the AFL queue
           50  +** can be run in a single go (for regression testing, for example, by typing:
           51  +**
           52  +**    fuzzershell -f ~/all-queue.txt >out.txt
           53  +**
           54  +** After running each chunk of SQL, the database connection is closed.  The
           55  +** program aborts if the close fails or if there is any unfreed memory after
           56  +** the close.
    34     57   */
    35     58   #include <stdio.h>
    36     59   #include <stdlib.h>
    37     60   #include <string.h>
    38     61   #include <stdarg.h>
    39     62   #include "sqlite3.h"
    40     63   
................................................................................
   214    237     char *zIn = 0;          /* Input text */
   215    238     int nAlloc = 0;         /* Number of bytes allocated for zIn[] */
   216    239     int nIn = 0;            /* Number of bytes of zIn[] used */
   217    240     size_t got;             /* Bytes read from input */
   218    241     FILE *in = stdin;       /* Where to read SQL text from */
   219    242     int rc = SQLITE_OK;     /* Result codes from API functions */
   220    243     int i;                  /* Loop counter */
          244  +  int iNext;              /* Next block of SQL */
   221    245     sqlite3 *db;            /* Open database */
   222         -  sqlite3 *dbInit;        /* On-disk database used to initialize the in-memory db */
          246  +  sqlite3 *dbInit = 0;    /* On-disk database used to initialize the in-memory db */
   223    247     const char *zInitDb = 0;/* Name of the initialization database file */
   224    248     char *zErrMsg = 0;      /* Error message returned from sqlite3_exec() */
   225    249   
   226    250     g.zArgv0 = argv[0];
   227    251     for(i=1; i<argc; i++){
   228    252       const char *z = argv[i];
   229    253       if( z[0]=='-' ){
................................................................................
   246    270           abendError("unknown option: %s", argv[i]);
   247    271         }
   248    272       }else{
   249    273         abendError("unknown argument: %s", argv[i]);
   250    274       }
   251    275     }
   252    276     sqlite3_config(SQLITE_CONFIG_LOG, shellLog, 0);
          277  +  while( !feof(in) ){
          278  +    nAlloc += nAlloc+1000;
          279  +    zIn = realloc(zIn, nAlloc);
          280  +    if( zIn==0 ) fatalError("out of memory");
          281  +    got = fread(zIn+nIn, 1, nAlloc-nIn-1, in); 
          282  +    nIn += (int)got;
          283  +    zIn[nIn] = 0;
          284  +    if( got==0 ) break;
          285  +  }
          286  +  if( zInitDb ){
          287  +    rc = sqlite3_open_v2(zInitDb, &dbInit, SQLITE_OPEN_READONLY, 0);
          288  +    if( rc!=SQLITE_OK ){
          289  +      abendError("unable to open initialization database \"%s\"", zInitDb);
          290  +    }
          291  +  }
          292  +  for(i=0; i<nIn; i=iNext){
          293  +    char cSaved;
          294  +    if( strncmp(&zIn[i], "/****<",6)==0 ){
          295  +      char *z = strstr(&zIn[i], ">****/");
          296  +      if( z ){
          297  +        z += 6;
          298  +        printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
          299  +        i += (int)(z-&zIn[i]);
          300  +      }
          301  +    }
          302  +    for(iNext=i; iNext<nIn && strncmp(&zIn[iNext],"/****<",6)!=0; iNext++){}
          303  +    
   253    304     rc = sqlite3_open_v2(
   254    305       "main.db", &db,
   255    306       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
   256    307       0);
   257    308     if( rc!=SQLITE_OK ){
   258    309       abendError("Unable to open the in-memory database");
   259    310     }
   260    311     if( zInitDb ){
   261    312       sqlite3_backup *pBackup;
   262         -    rc = sqlite3_open_v2(zInitDb, &dbInit, SQLITE_OPEN_READONLY, 0);
   263         -    if( rc!=SQLITE_OK ){
   264         -      abendError("unable to open initialization database \"%s\"", zInitDb);
   265         -    }
   266    313       pBackup = sqlite3_backup_init(db, "main", dbInit, "main");
   267    314       rc = sqlite3_backup_step(pBackup, -1);
   268    315       if( rc!=SQLITE_DONE ){
   269         -      abendError("attempt to initialize the in-memory database failed (rc=%d)",rc);
          316  +        abendError("attempt to initialize the in-memory database failed (rc=%d)",
          317  +                   rc);
   270    318       }
   271    319       sqlite3_backup_finish(pBackup);
   272         -    sqlite3_close(dbInit);
   273    320     }
   274    321     sqlite3_trace(db, traceCallback, 0);
   275    322     sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
   276    323     sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
   277         -  while( !feof(in) ){
   278         -    nAlloc += 1000;
   279         -    zIn = sqlite3_realloc(zIn, nAlloc);
   280         -    if( zIn==0 ) fatalError("out of memory");
   281         -    got = fread(zIn+nIn, 1, nAlloc-nIn-1, in); 
   282         -    nIn += (int)got;
   283         -    zIn[nIn] = 0;
   284         -    if( got==0 ) break;
   285         -  }
   286         -  printf("INPUT (%d bytes): [%s]\n", nIn, zIn);
   287         -  rc = sqlite3_exec(db, zIn, execCallback, 0, &zErrMsg);
          324  +    sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
          325  +
          326  +    cSaved = zIn[iNext];
          327  +    zIn[iNext] = 0;
          328  +    printf("INPUT (offset: %d, size: %d): [%s]\n",
          329  +            i, (int)strlen(&zIn[i]), &zIn[i]);
          330  +    rc = sqlite3_exec(db, &zIn[i], execCallback, 0, &zErrMsg);
          331  +    zIn[iNext] = cSaved;
          332  +
   288    333     printf("RESULT-CODE: %d\n", rc);
   289    334     if( zErrMsg ){
   290    335       printf("ERROR-MSG: [%s]\n", zErrMsg);
   291    336       sqlite3_free(zErrMsg);
   292    337     }
   293         -  return rc!=SQLITE_OK;
          338  +    rc = sqlite3_close(db);
          339  +    if( rc ){
          340  +      abendError("sqlite3_close() failed with rc=%d", rc);
          341  +    }
          342  +    if( sqlite3_memory_used()>0 ){
          343  +      abendError("memory in use after close: %lld bytes", sqlite3_memory_used());
          344  +    }
          345  +  }
          346  +  free(zIn);
          347  +  return 0;
   294    348   }