/ Check-in [dd62d2de]
Login

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

Overview
Comment:Merge trunk with this branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sorter-opt
Files: files | file ages | folders
SHA1:dd62d2de6eb12dc1902d6df050c395b1dcac01b4
User & Date: dan 2016-11-11 18:45:55
Context
2016-11-11
19:08
Avoid storing redundant fields in sorter records when the sort-key and data have fields in common. check-in: b835cf3e user: drh tags: trunk
18:45
Merge trunk with this branch. Closed-Leaf check-in: dd62d2de user: dan tags: sorter-opt
18:08
Reenable the SQLITE_EXPR_REF optimization for "SELECT DISTINCT ... ORDER BY" queries. check-in: 6e2e9d38 user: dan tags: sorter-opt
17:08
Fix a problem with switching from wal to rollback mode when SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE is configured. check-in: 46e00162 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to main.mk.

   507    507   	./srcck1 sqlite3.c
   508    508   
   509    509   fuzzershell$(EXE):	$(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
   510    510   	$(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
   511    511   	  $(FUZZERSHELL_OPT) $(TOP)/tool/fuzzershell.c sqlite3.c \
   512    512   	  $(TLIBS) $(THREADLIB)
   513    513   
   514         -fuzzcheck$(EXE):	$(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
          514  +fuzzcheck$(EXE):	$(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(TOP)/test/ossfuzz.c
   515    515   	$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
   516         -		-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) \
   517         -		$(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS) $(THREADLIB)
          516  +		-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \
          517  +		$(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS) $(THREADLIB)
   518    518   
   519    519   mptester$(EXE):	sqlite3.c $(TOP)/mptest/mptest.c
   520    520   	$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
   521    521   		$(TLIBS) $(THREADLIB)
   522    522   
   523    523   MPTEST1=./mptester$(EXE) mptest1.db $(TOP)/mptest/crash01.test --repeat 20
   524    524   MPTEST2=./mptester$(EXE) mptest2.db $(TOP)/mptest/multiwrite01.test --repeat 20

Changes to src/attach.c.

   321    321   ){
   322    322     int rc;
   323    323     NameContext sName;
   324    324     Vdbe *v;
   325    325     sqlite3* db = pParse->db;
   326    326     int regArgs;
   327    327   
          328  +  if( pParse->nErr ) goto attach_end;
   328    329     memset(&sName, 0, sizeof(NameContext));
   329    330     sName.pParse = pParse;
   330    331   
   331    332     if( 
   332    333         SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
   333    334         SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
   334    335         SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))

Changes to src/pager.c.

  4029   4029     assert( assert_pager_state(pPager) );
  4030   4030     disable_simulated_io_errors();
  4031   4031     sqlite3BeginBenignMalloc();
  4032   4032     pagerFreeMapHdrs(pPager);
  4033   4033     /* pPager->errCode = 0; */
  4034   4034     pPager->exclusiveMode = 0;
  4035   4035   #ifndef SQLITE_OMIT_WAL
  4036         -  sqlite3WalClose(pPager->pWal,db,pPager->ckptSyncFlags,pPager->pageSize,pTmp);
         4036  +  assert( db || pPager->pWal==0 );
         4037  +  sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, pPager->pageSize,
         4038  +      (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp)
         4039  +  );
  4037   4040     pPager->pWal = 0;
  4038   4041   #endif
  4039   4042     pager_reset(pPager);
  4040   4043     if( MEMDB ){
  4041   4044       pager_unlock(pPager);
  4042   4045     }else{
  4043   4046       /* If it is open, sync the journal file before calling UnlockAndRollback.

Changes to src/resolve.c.

   395    395             assert( pExpr->pLeft==0 && pExpr->pRight==0 );
   396    396             assert( pExpr->x.pList==0 );
   397    397             assert( pExpr->x.pSelect==0 );
   398    398             pOrig = pEList->a[j].pExpr;
   399    399             if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
   400    400               sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
   401    401               return WRC_Abort;
          402  +          }
          403  +          if( sqlite3ExprVectorSize(pOrig)!=1 ){
          404  +            sqlite3ErrorMsg(pParse, "row value misused");
          405  +            return WRC_Abort;
   402    406             }
   403    407             resolveAlias(pParse, pEList, j, pExpr, "", nSubquery);
   404    408             cnt = 1;
   405    409             pMatch = 0;
   406    410             assert( zTab==0 && zDb==0 );
   407    411             goto lookupname_end;
   408    412           }
................................................................................
   772    776         }
   773    777         break;
   774    778       }
   775    779       case TK_VARIABLE: {
   776    780         notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
   777    781         break;
   778    782       }
          783  +    case TK_BETWEEN:
   779    784       case TK_EQ:
   780    785       case TK_NE:
   781    786       case TK_LT:
   782    787       case TK_LE:
   783    788       case TK_GT:
   784    789       case TK_GE:
   785    790       case TK_IS:
   786    791       case TK_ISNOT: {
   787    792         int nLeft, nRight;
   788    793         if( pParse->db->mallocFailed ) break;
   789         -      assert( pExpr->pRight!=0 );
   790    794         assert( pExpr->pLeft!=0 );
   791    795         nLeft = sqlite3ExprVectorSize(pExpr->pLeft);
   792         -      nRight = sqlite3ExprVectorSize(pExpr->pRight);
          796  +      if( pExpr->op==TK_BETWEEN ){
          797  +        nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr);
          798  +        if( nRight==nLeft ){
          799  +          nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr);
          800  +        }
          801  +      }else{
          802  +        assert( pExpr->pRight!=0 );
          803  +        nRight = sqlite3ExprVectorSize(pExpr->pRight);
          804  +      }
   793    805         if( nLeft!=nRight ){
   794    806           testcase( pExpr->op==TK_EQ );
   795    807           testcase( pExpr->op==TK_NE );
   796    808           testcase( pExpr->op==TK_LT );
   797    809           testcase( pExpr->op==TK_LE );
   798    810           testcase( pExpr->op==TK_GT );
   799    811           testcase( pExpr->op==TK_GE );
   800    812           testcase( pExpr->op==TK_IS );
   801    813           testcase( pExpr->op==TK_ISNOT );
          814  +        testcase( pExpr->op==TK_BETWEEN );
   802    815           sqlite3ErrorMsg(pParse, "row value misused");
   803    816         }
   804    817         break; 
   805    818       }
   806    819     }
   807    820     return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
   808    821   }

Changes to src/shell.c.

  1212   1212               utf8_printf(p->out, "%s%s", zSep, azCol[i]);
  1213   1213             }
  1214   1214             raw_printf(p->out,")");
  1215   1215           }
  1216   1216           raw_printf(p->out," VALUES(");
  1217   1217         }else if( p->cnt==0 && p->showHeader ){
  1218   1218           for(i=0; i<nArg; i++){
  1219         -          if( i>0 ) utf8_printf(p->out, ",");
         1219  +          if( i>0 ) raw_printf(p->out, ",");
  1220   1220             output_quoted_string(p->out, azCol[i]);
  1221   1221           }
  1222         -        utf8_printf(p->out,"\n");
         1222  +        raw_printf(p->out,"\n");
  1223   1223         }
  1224   1224         p->cnt++;
  1225   1225         for(i=0; i<nArg; i++){
  1226   1226           char *zSep = i>0 ? ",": "";
  1227   1227           if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
  1228   1228             utf8_printf(p->out,"%sNULL",zSep);
  1229   1229           }else if( aiType && aiType[i]==SQLITE_TEXT ){
................................................................................
  3912   3912       if( rc==SQLITE_OK ){
  3913   3913         rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
  3914   3914         sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
  3915   3915         if( rc ){
  3916   3916           utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
  3917   3917         }else{
  3918   3918           utf8_printf(stdout, "%s;\n", zSql);
  3919         -        utf8_printf(stdout, 
         3919  +        raw_printf(stdout,
  3920   3920              "WARNING: writing to an imposter table will corrupt the index!\n"
  3921   3921           );
  3922   3922         }
  3923   3923       }else{
  3924         -      utf8_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
         3924  +      raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
  3925   3925         rc = 1;
  3926   3926       }
  3927   3927       sqlite3_free(zSql);
  3928   3928     }else
  3929   3929   #endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
  3930   3930   
  3931   3931   #ifdef SQLITE_ENABLE_IOTRACE
................................................................................
  4778   4778     }else
  4779   4779   
  4780   4780     /* Begin redirecting output to the file "testcase-out.txt" */
  4781   4781     if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
  4782   4782       output_reset(p);
  4783   4783       p->out = output_file_open("testcase-out.txt");
  4784   4784       if( p->out==0 ){
  4785         -      utf8_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
         4785  +      raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
  4786   4786       }
  4787   4787       if( nArg>=2 ){
  4788   4788         sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
  4789   4789       }else{
  4790   4790         sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
  4791   4791       }
  4792   4792     }else
................................................................................
  5171   5171     if( zSql==0 ) return 1;
  5172   5172     zSql[nSql] = ';';
  5173   5173     zSql[nSql+1] = 0;
  5174   5174     rc = sqlite3_complete(zSql);
  5175   5175     zSql[nSql] = 0;
  5176   5176     return rc;
  5177   5177   }
         5178  +
         5179  +/*
         5180  +** Run a single line of SQL
         5181  +*/
         5182  +static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
         5183  +  int rc;
         5184  +  char *zErrMsg = 0;
         5185  +
         5186  +  open_db(p, 0);
         5187  +  if( p->backslashOn ) resolve_backslashes(zSql);
         5188  +  BEGIN_TIMER;
         5189  +  rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
         5190  +  END_TIMER;
         5191  +  if( rc || zErrMsg ){
         5192  +    char zPrefix[100];
         5193  +    if( in!=0 || !stdin_is_interactive ){
         5194  +      sqlite3_snprintf(sizeof(zPrefix), zPrefix,
         5195  +                       "Error: near line %d:", startline);
         5196  +    }else{
         5197  +      sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
         5198  +    }
         5199  +    if( zErrMsg!=0 ){
         5200  +      utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
         5201  +      sqlite3_free(zErrMsg);
         5202  +      zErrMsg = 0;
         5203  +    }else{
         5204  +      utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
         5205  +    }
         5206  +    return 1;
         5207  +  }else if( p->countChanges ){
         5208  +    raw_printf(p->out, "changes: %3d   total_changes: %d\n",
         5209  +            sqlite3_changes(p->db), sqlite3_total_changes(p->db));
         5210  +  }
         5211  +  return 0;
         5212  +}
         5213  +
  5178   5214   
  5179   5215   /*
  5180   5216   ** Read input from *in and process it.  If *in==0 then input
  5181   5217   ** is interactive - the user is typing it it.  Otherwise, input
  5182   5218   ** is coming from a file or device.  A prompt is issued and history
  5183   5219   ** is saved only if input is interactive.  An interrupt signal will
  5184   5220   ** cause this routine to exit immediately, unless input is interactive.
................................................................................
  5188   5224   static int process_input(ShellState *p, FILE *in){
  5189   5225     char *zLine = 0;          /* A single input line */
  5190   5226     char *zSql = 0;           /* Accumulated SQL text */
  5191   5227     int nLine;                /* Length of current line */
  5192   5228     int nSql = 0;             /* Bytes of zSql[] used */
  5193   5229     int nAlloc = 0;           /* Allocated zSql[] space */
  5194   5230     int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
  5195         -  char *zErrMsg;            /* Error message returned */
  5196   5231     int rc;                   /* Error code */
  5197   5232     int errCnt = 0;           /* Number of errors seen */
  5198   5233     int lineno = 0;           /* Current line number */
  5199   5234     int startline = 0;        /* Line number for start of current input */
  5200   5235   
  5201   5236     while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
  5202   5237       fflush(p->out);
................................................................................
  5248   5283       }else{
  5249   5284         zSql[nSql++] = '\n';
  5250   5285         memcpy(zSql+nSql, zLine, nLine+1);
  5251   5286         nSql += nLine;
  5252   5287       }
  5253   5288       if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
  5254   5289                   && sqlite3_complete(zSql) ){
  5255         -      p->cnt = 0;
  5256         -      open_db(p, 0);
  5257         -      if( p->backslashOn ) resolve_backslashes(zSql);
  5258         -      BEGIN_TIMER;
  5259         -      rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
  5260         -      END_TIMER;
  5261         -      if( rc || zErrMsg ){
  5262         -        char zPrefix[100];
  5263         -        if( in!=0 || !stdin_is_interactive ){
  5264         -          sqlite3_snprintf(sizeof(zPrefix), zPrefix,
  5265         -                           "Error: near line %d:", startline);
  5266         -        }else{
  5267         -          sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
  5268         -        }
  5269         -        if( zErrMsg!=0 ){
  5270         -          utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
  5271         -          sqlite3_free(zErrMsg);
  5272         -          zErrMsg = 0;
  5273         -        }else{
  5274         -          utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
  5275         -        }
  5276         -        errCnt++;
  5277         -      }else if( p->countChanges ){
  5278         -        raw_printf(p->out, "changes: %3d   total_changes: %d\n",
  5279         -                sqlite3_changes(p->db), sqlite3_total_changes(p->db));
  5280         -      }
         5290  +      errCnt += runOneSqlLine(p, zSql, in, startline);
  5281   5291         nSql = 0;
  5282   5292         if( p->outCount ){
  5283   5293           output_reset(p);
  5284   5294           p->outCount = 0;
  5285   5295         }
  5286   5296       }else if( nSql && _all_whitespace(zSql) ){
  5287   5297         if( p->echoOn ) printf("%s\n", zSql);
  5288   5298         nSql = 0;
  5289   5299       }
  5290   5300     }
  5291         -  if( nSql ){
  5292         -    if( !_all_whitespace(zSql) ){
  5293         -      utf8_printf(stderr, "Error: incomplete SQL: %s\n", zSql);
  5294         -      errCnt++;
  5295         -    }
         5301  +  if( nSql && !_all_whitespace(zSql) ){
         5302  +    runOneSqlLine(p, zSql, in, startline);
  5296   5303     }
  5297   5304     free(zSql);
  5298   5305     free(zLine);
  5299   5306     return errCnt>0;
  5300   5307   }
  5301   5308   
  5302   5309   /*

Changes to src/wal.c.

  1939   1939       ** ordinary, rollback-mode locking methods, this guarantees that the
  1940   1940       ** connection associated with this log file is the only connection to
  1941   1941       ** the database. In this case checkpoint the database and unlink both
  1942   1942       ** the wal and wal-index files.
  1943   1943       **
  1944   1944       ** The EXCLUSIVE lock is not released before returning.
  1945   1945       */
  1946         -    if( (db->flags & SQLITE_NoCkptOnClose)==0 
         1946  +    if( zBuf!=0
  1947   1947        && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE))
  1948   1948       ){
  1949   1949         if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
  1950   1950           pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
  1951   1951         }
  1952   1952         rc = sqlite3WalCheckpoint(pWal, db, 
  1953   1953             SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0

Added test/bestindex4.test.

            1  +# 2016 November 11
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# Test the virtual table interface. In particular the xBestIndex
           12  +# method.
           13  +#
           14  +
           15  +set testdir [file dirname $argv0]
           16  +source $testdir/tester.tcl
           17  +set testprefix bestindex4
           18  +
           19  +ifcapable !vtab {
           20  +  finish_test
           21  +  return
           22  +}
           23  +
           24  +#-------------------------------------------------------------------------
           25  +# Virtual table callback for a virtual table named $tbl.
           26  +#
           27  +# The table created is:
           28  +#
           29  +#      "CREATE TABLE t1 (id, host, class)"
           30  +#
           31  +# The virtual table supports == operators on a subset of its columns. The
           32  +# exact subset depends on the value of bitmask paramater $param.
           33  +#
           34  +#   0x01 - == on "id" supported
           35  +#   0x02 - == on "host" supported
           36  +#   0x04 - == on "class" supported
           37  +#
           38  +# $param also supports the following bits:
           39  +#
           40  +#   0x08 - ignore the "usable" flag (malfunction)
           41  +#
           42  +#
           43  +#  
           44  +proc vtab_cmd {param method args} {
           45  +  switch -- $method {
           46  +    xConnect {
           47  +      return "CREATE TABLE t1(id TEXT, host TEXT, class TEXT)"
           48  +    }
           49  +
           50  +    xBestIndex {
           51  +      foreach {clist orderby mask} $args {}
           52  +
           53  +      set ret [list]
           54  +
           55  +      set use use
           56  +
           57  +
           58  +      for {set i 0} {$i < [llength $clist]} {incr i} {
           59  +        array unset C
           60  +        array set C [lindex $clist $i]
           61  +        if { ($C(usable) || ($param & 0x08)) 
           62  +          && $C(op)=="eq" && ($param & 1<<$C(column))
           63  +        } {
           64  +          lappend ret $use $i
           65  +          break
           66  +        }
           67  +      }
           68  +
           69  +      set score 1000000
           70  +      if {$ret!=""} {
           71  +        set score [expr $score / [llength $ret]]
           72  +      }
           73  +      lappend ret cost $score rows $score
           74  +
           75  +      return $ret
           76  +    }
           77  +
           78  +    xFilter {
           79  +    }
           80  +  }
           81  +  return ""
           82  +}
           83  +
           84  +register_tcl_module db
           85  +
           86  +for {set param1 0} {$param1<16} {incr param1} {
           87  +  for {set param2 0} {$param2<16} {incr param2} {
           88  +    reset_db
           89  +    register_tcl_module db
           90  +    do_execsql_test 1.$param1.$param2.1 "
           91  +      CREATE VIRTUAL TABLE t1 USING tcl('vtab_cmd $param1');
           92  +      CREATE VIRTUAL TABLE t2 USING tcl('vtab_cmd $param2');
           93  +    "
           94  +
           95  +    foreach {tn sql} {
           96  +      2 "select t1.id as ID from t1, t2 where t1.id=t2.host and t2.class='xx'"
           97  +      3 {
           98  +        select t1.id as ID from t1, t2 where t2.class ='xx' and t2.id = t1.host
           99  +      }
          100  +      4 {
          101  +        select t1.id as ID from t1, t2 where t1.host = t2.id and t2. class ='xx'
          102  +      }
          103  +    } {
          104  +
          105  +      if {($param1 & 0x08)==0 && ($param2 & 0x08)==0} {
          106  +
          107  +        do_execsql_test 1.$param1.$param2.$tn.a $sql {}
          108  +
          109  +      } else {
          110  +        do_test 1.$param1.$param2.$tn.b {
          111  +          catchsql $sql
          112  +            set {} {}
          113  +        } {}
          114  +      }
          115  +    }
          116  +
          117  +  }
          118  +}
          119  +
          120  +finish_test
          121  +

Changes to test/fuzz-oss1.test.

  1993   1993   "nao:Property14"."ID" AND "9_u" IS NOT NULL AND "10_u" IS NOT
  1994   1994   NULL AND ("9_u" COLLATE NOCASE = ? COLLATE NOCASE))) FROM (SELECT
  1995   1995   "nco:PersonContact1"."ID" AS "1_u" FROM "nco:PersonContact" AS
  1996   1996   "nco:PersonContact1") ORDER BY "1_u";
  1997   1997     }
  1998   1998   } {/.* Goto .*/}
  1999   1999   
         2000  +# Crash reported by OSS-FUZZ on 2016-11-10
         2001  +do_catchsql_test fuzz-oss1-detach {
         2002  +  DETACH x IS #1;
         2003  +} {1 {near "#1": syntax error}}
  2000   2004   
  2001   2005   finish_test

Changes to test/fuzzcheck.c.

    76     76   
    77     77   
    78     78   #ifdef __unix__
    79     79   # include <signal.h>
    80     80   # include <unistd.h>
    81     81   #endif
    82     82   
           83  +#ifdef SQLITE_OSS_FUZZ
           84  +# include <stddef.h>
           85  +# include <stdint.h>
           86  +#endif
           87  +
    83     88   /*
    84     89   ** Files in the virtual file system.
    85     90   */
    86     91   typedef struct VFile VFile;
    87     92   struct VFile {
    88     93     char *zFilename;        /* Filename.  NULL for delete-on-close. From malloc() */
    89     94     int sz;                 /* Size of the file in bytes */
................................................................................
   790    795   "  -q|--quiet           Reduced output\n"
   791    796   "  --limit-mem N        Limit memory used by test SQLite instance to N bytes\n"
   792    797   "  --limit-vdbe         Panic if any test runs for more than 100,000 cycles\n"
   793    798   "  --load-sql ARGS...   Load SQL scripts fro files into SOURCE-DB\n"
   794    799   "  --load-db ARGS...    Load template databases from files into SOURCE_DB\n"
   795    800   "  -m TEXT              Add a description to the database\n"
   796    801   "  --native-vfs         Use the native VFS for initially empty database files\n"
          802  +"  --oss-fuzz           Enable OSS-FUZZ testing\n"
   797    803   "  --rebuild            Rebuild and vacuum the database file\n"
   798    804   "  --result-trace       Show the results of each SQL command\n"
   799    805   "  --sqlid N            Use only SQL where sqlid=N\n"
   800    806   "  --timeout N          Abort if any single test needs more than N seconds\n"
   801    807   "  -v|--verbose         Increased output.  Repeat for more output.\n"
   802    808     );
   803    809   }
................................................................................
   831    837     int cellSzCkFlag = 0;        /* --cell-size-check */
   832    838     int sqlFuzz = 0;             /* True for SQL fuzz testing. False for DB fuzz */
   833    839     int iTimeout = 120;          /* Default 120-second timeout */
   834    840     int nMem = 0;                /* Memory limit */
   835    841     char *zExpDb = 0;            /* Write Databases to files in this directory */
   836    842     char *zExpSql = 0;           /* Write SQL to files in this directory */
   837    843     void *pHeap = 0;             /* Heap for use by SQLite */
          844  +  int ossFuzz = 0;             /* enable OSS-FUZZ testing */
   838    845   
   839    846     iBegin = timeOfDay();
   840    847   #ifdef __unix__
   841    848     signal(SIGALRM, timeoutHandler);
   842    849   #endif
   843    850     g.zArgv0 = argv[0];
   844    851     zFailCode = getenv("TEST_FAILURE");
................................................................................
   890    897         }else
   891    898         if( strcmp(z,"m")==0 ){
   892    899           if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
   893    900           zMsg = argv[++i];
   894    901         }else
   895    902         if( strcmp(z,"native-vfs")==0 ){
   896    903           nativeFlag = 1;
          904  +      }else
          905  +      if( strcmp(z,"oss-fuzz")==0 ){
          906  +        ossFuzz = 1;
   897    907         }else
   898    908         if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
   899    909           quietFlag = 1;
   900    910           verboseFlag = 0;
   901    911         }else
   902    912         if( strcmp(z,"rebuild")==0 ){
   903    913           rebuildFlag = 1;
................................................................................
  1119   1129             if( amt!=prevAmt ){
  1120   1130               printf(" %d%%", amt*10);
  1121   1131               fflush(stdout);
  1122   1132               prevAmt = amt;
  1123   1133             }
  1124   1134           }
  1125   1135           createVFile("main.db", pDb->sz, pDb->a);
  1126         -        openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
  1127         -        if( nativeFlag && pDb->sz==0 ){
  1128         -          openFlags |= SQLITE_OPEN_MEMORY;
  1129         -          zVfs = 0;
  1130         -        }
  1131         -        rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
  1132         -        if( rc ) fatalError("cannot open inmem database");
  1133         -        if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
  1134         -        setAlarm(iTimeout);
         1136  +        if( ossFuzz ){
         1137  +#ifndef SQLITE_OSS_FUZZ
         1138  +          fatalError("--oss-fuzz not supported: recompile with -DSQLITE_OSS_FUZZ");
         1139  +#else
         1140  +          extern int LLVMFuzzerTestOneInput(const uint8_t*, size_t);
         1141  +          LLVMFuzzerTestOneInput((const uint8_t*)pSql->a, (size_t)pSql->sz);
         1142  +#endif
         1143  +        }else{
         1144  +          openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
         1145  +          if( nativeFlag && pDb->sz==0 ){
         1146  +            openFlags |= SQLITE_OPEN_MEMORY;
         1147  +            zVfs = 0;
         1148  +          }
         1149  +          rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
         1150  +          if( rc ) fatalError("cannot open inmem database");
         1151  +          if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
         1152  +          setAlarm(iTimeout);
  1135   1153   #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  1136         -        if( sqlFuzz || vdbeLimitFlag ){
  1137         -          sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag);
  1138         -        }
         1154  +          if( sqlFuzz || vdbeLimitFlag ){
         1155  +            sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag);
         1156  +          }
  1139   1157   #endif
  1140         -        do{
  1141         -          runSql(db, (char*)pSql->a, runFlags);
  1142         -        }while( timeoutTest );
  1143         -        setAlarm(0);
  1144         -        sqlite3_close(db);
         1158  +          do{
         1159  +            runSql(db, (char*)pSql->a, runFlags);
         1160  +          }while( timeoutTest );
         1161  +          setAlarm(0);
         1162  +          sqlite3_close(db);
         1163  +        }
  1145   1164           if( sqlite3_memory_used()>0 ) fatalError("memory leak");
  1146   1165           reformatVfs();
  1147   1166           nTest++;
  1148   1167           g.zTestName[0] = 0;
  1149   1168   
  1150   1169           /* Simulate an error if the TEST_FAILURE environment variable is "5".
  1151   1170           ** This is used to verify that automated test script really do spot

Changes to test/nockpt.test.

    46     46   do_test 1.10 { file exists test.db-wal } 1
    47     47   do_test 1.11 { file size test.db-wal } [wal_file_size 2 1024]
    48     48   
    49     49   sqlite3 db test.db
    50     50   do_execsql_test 1.12 {
    51     51     SELECT * FROM c1
    52     52   } {1 2 3 4 5 6 7 8 9}
           53  +
           54  +do_execsql_test 1.13 { PRAGMA main.journal_mode } {wal}
           55  +do_test 1.14 { sqlite3_db_config db NO_CKPT_ON_CLOSE 1 } {1}
           56  +do_execsql_test 1.14 { PRAGMA main.journal_mode = delete } {delete}
           57  +do_test 1.15 { file exists test.db-wal } {0}
           58  +
    53     59   
    54     60   
    55     61   finish_test

Added test/ossfuzz.c.

            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  +#include <stdint.h>
            7  +#include "sqlite3.h"
            8  +
            9  +/*
           10  +** Progress handler callback
           11  +*/
           12  +static int progress_handler(void *pReturn) {
           13  +  return *(int*)pReturn;
           14  +}
           15  +
           16  +/*
           17  +** Callback for sqlite3_exec().
           18  +*/
           19  +static int exec_handler(void *pCnt, int argc, char **argv, char **namev){
           20  +  int i;
           21  +  for(i=0; i<argc; i++) sqlite3_free(sqlite3_mprintf("%s", argv[i]));
           22  +  return ((*(int*)pCnt)--)<=0;
           23  +}
           24  +
           25  +/*
           26  +** Main entry point.  The fuzzer invokes this function with each
           27  +** fuzzed input.
           28  +*/
           29  +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
           30  +  int progressArg = 0;     /* 1 causes progress handler abort */
           31  +  int execCnt = 0;         /* Abort row callback when count reaches zero */
           32  +  char *zErrMsg = 0;       /* Error message returned by sqlite_exec() */
           33  +  sqlite3 *db;             /* The database connection */
           34  +  uint8_t uSelector;       /* First byte of input data[] */
           35  +  int rc;                  /* Return code from various interfaces */
           36  +  char *zSql;              /* Zero-terminated copy of data[] */
           37  +
           38  +  if( size<3 ) return 0;   /* Early out if unsufficient data */
           39  +
           40  +  /* Extract the selector byte from the beginning of the input.  But only
           41  +  ** do this if the second byte is a \n.  If the second byte is not \n,
           42  +  ** then use a default selector */
           43  +  if( data[1]=='\n' ){
           44  +    uSelector = data[0];  data += 2; size -= 2;
           45  +  }else{
           46  +    uSelector = 0xfd;
           47  +  }
           48  +
           49  +  /* Open the database connection.  Only use an in-memory database. */
           50  +  rc = sqlite3_open_v2("fuzz.db", &db,
           51  +           SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
           52  +  if( rc ) return 0;
           53  +
           54  +  /* Bit 0 of the selector enables progress callbacks.  Bit 1 is the
           55  +  ** return code from progress callbacks */
           56  +  if( uSelector & 1 ){
           57  +    sqlite3_progress_handler(db, 4, progress_handler, (void*)&progressArg);
           58  +  }
           59  +  uSelector >>= 1;
           60  +  progressArg = uSelector & 1;  uSelector >>= 1;
           61  +
           62  +  /* Bit 2 of the selector enables foreign key constraints */
           63  +  sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc);
           64  +  uSelector >>= 1;
           65  +
           66  +  /* Remaining bits of the selector determine a limit on the number of
           67  +  ** output rows */
           68  +  execCnt = uSelector + 1;
           69  +
           70  +  /* Run the SQL.  The sqlite_exec() interface expects a zero-terminated
           71  +  ** string, so make a copy. */
           72  +  zSql = sqlite3_mprintf("%.*s", (int)size, data);
           73  +  sqlite3_exec(db, zSql, exec_handler, (void*)&execCnt, &zErrMsg);
           74  +
           75  +  /* Cleanup and return */
           76  +  sqlite3_free(zErrMsg);
           77  +  sqlite3_free(zSql);
           78  +  sqlite3_close(db);
           79  +  return 0;
           80  +}

Changes to test/rowvalue.test.

   261    261   do_execsql_test 12.1 {
   262    262     DROP TABLE IF EXISTS t1;
   263    263     CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2);
   264    264     DROP TABLE IF EXISTS t2;
   265    265     CREATE TABLE t2(x,y); INSERT INTO t2 VALUES(3,4);
   266    266     SELECT *,'x' FROM t1 LEFT JOIN t2 ON (a,b)=(x,y);
   267    267   } {1 2 {} {} x}
          268  +
          269  +
          270  +foreach {tn sql} {
          271  +  0 "SELECT (1,2) AS x WHERE x=3"
          272  +  1 "SELECT (1,2) BETWEEN 1 AND 2"
          273  +  2 "SELECT 1 BETWEEN (1,2) AND 2"
          274  +  3 "SELECT 2 BETWEEN 1 AND (1,2)"
          275  +  4 "SELECT (1,2) FROM (SELECT 1) ORDER BY 1"
          276  +  5 "SELECT (1,2) FROM (SELECT 1) GROUP BY 1"
          277  +} {
          278  +  do_catchsql_test 13.$tn $sql {1 {row value misused}}
          279  +}
          280  +
   268    281   
   269    282   finish_test

Changes to test/shell3.test.

    92     92     catchcmd "foo.db" "CREATE TABLE t1(a); DROP TABLE t1;"
    93     93   } {0 {}}
    94     94   do_test shell3-2.6 {
    95     95     catchcmd "foo.db" ".tables"
    96     96   } {0 {}}
    97     97   do_test shell3-2.7 {
    98     98     catchcmd "foo.db" "CREATE TABLE"
    99         -} {1 {Error: incomplete SQL: CREATE TABLE}}
           99  +} {1 {Error: near line 1: near "TABLE": syntax error}}
   100    100   
   101    101   finish_test