Index: Makefile.in ================================================================== --- Makefile.in +++ Makefile.in @@ -315,22 +315,15 @@ $(LTLINK) -o libtclsqlite3.la tclsqlite.lo \ $(LIBOBJ) @TCL_STUB_LIB_SPEC@ $(LIBPTHREAD) \ -rpath $(libdir)/sqlite \ -version-info "8:6:8" -testcli$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h +sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h $(LTLINK) $(READLINE_FLAGS) $(LIBPTHREAD) \ -o $@ $(TOP)/src/shell.c libsqlite3.la \ $(LIBREADLINE) $(TLIBS) -sqlite3$(EXE): $(TOP)/src/shell.c sqlite3.c sqlite3.h - $(LTLINK) $(READLINE_FLAGS) -o $@ \ - -DSQLITE_MAX_SQL_LENGTH=1000000000 \ - -USQLITE_THREADSAFE -DSQLITE_THREADSAFE=0 \ - $(TOP)/src/shell.c sqlite3.c \ - $(LIBREADLINE) $(TLIBS) $(THREADLIB) - # This target creates a directory named "tsrc" and fills it with # copies of all of the C source code and header files needed to # build on the target system. Some of the C source code and header # files are automatically generated. This target takes care of # all that automatic generation. Index: main.mk ================================================================== --- main.mk +++ main.mk @@ -275,22 +275,15 @@ libsqlite3.a: $(LIBOBJ) $(AR) libsqlite3.a $(LIBOBJ) $(RANLIB) libsqlite3.a -testcli$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h +sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h $(TCCX) $(READLINE_FLAGS) -o testcli$(EXE) \ $(TOP)/src/shell.c \ libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB) -sqlite3$(EXE): $(TOP)/src/shell.c sqlite3.c sqlite3.h - $(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) \ - -DSQLITE_MAX_SQL_LENGTH=1000000000 \ - -USQLITE_THREADSAFE -DSQLITE_THREADSAFE=0 \ - $(TOP)/src/shell.c sqlite3.c \ - $(LIBREADLINE) $(TLIBS) $(THREADLIB) - objects: $(LIBOBJ_ORIG) # This target creates a directory named "tsrc" and fills it with # copies of all of the C source code and header files needed to # build on the target system. Some of the C source code and header Index: src/sqliteLimit.h ================================================================== --- src/sqliteLimit.h +++ src/sqliteLimit.h @@ -10,11 +10,11 @@ ** ************************************************************************* ** ** This file defines various limits of what SQLite can process. ** -** @(#) $Id: sqliteLimit.h,v 1.5 2007/12/13 21:54:11 drh Exp $ +** @(#) $Id: sqliteLimit.h,v 1.6 2007/12/17 16:20:07 drh Exp $ */ /* ** The maximum length of a TEXT or BLOB in bytes. This also ** limits the size of a row in a table or index. @@ -47,14 +47,14 @@ # define SQLITE_MAX_COLUMN 2000 #endif /* ** The maximum length of a single SQL statement in bytes. -** The hard limit is 1 million. +** A value of zero means there is no limit. */ #ifndef SQLITE_MAX_SQL_LENGTH -# define SQLITE_MAX_SQL_LENGTH 1000000 +# define SQLITE_MAX_SQL_LENGTH 0 #endif /* ** The maximum depth of an expression tree. This is limited to ** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might Index: src/tokenize.c ================================================================== --- src/tokenize.c +++ src/tokenize.c @@ -13,11 +13,11 @@ ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.136 2007/08/27 23:26:59 drh Exp $ +** $Id: tokenize.c,v 1.137 2007/12/17 16:20:07 drh Exp $ */ #include "sqliteInt.h" #include #include @@ -416,11 +416,11 @@ assert( i>=0 ); pParse->sLastToken.z = (u8*)&zSql[i]; assert( pParse->sLastToken.dyn==0 ); pParse->sLastToken.n = getToken((unsigned char*)&zSql[i],&tokenType); i += pParse->sLastToken.n; - if( i>SQLITE_MAX_SQL_LENGTH ){ + if( SQLITE_MAX_SQL_LENGTH>0 && i>SQLITE_MAX_SQL_LENGTH ){ pParse->rc = SQLITE_TOOBIG; break; } switch( tokenType ){ case TK_SPACE: Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -41,11 +41,11 @@ ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.660 2007/12/13 21:54:11 drh Exp $ +** $Id: vdbe.c,v 1.661 2007/12/17 16:20:07 drh Exp $ */ #include "sqliteInt.h" #include #include "vdbeInt.h" @@ -758,12 +758,10 @@ */ case OP_String8: { /* same as TK_STRING */ assert( pOp->p3!=0 ); pOp->opcode = OP_String; pOp->p1 = strlen(pOp->p3); - assert( SQLITE_MAX_SQL_LENGTH <= SQLITE_MAX_LENGTH ); - assert( pOp->p1 <= SQLITE_MAX_LENGTH ); #ifndef SQLITE_OMIT_UTF16 if( encoding!=SQLITE_UTF8 ){ pTos++; sqlite3VdbeMemSetStr(pTos, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC); @@ -775,23 +773,27 @@ sqlite3_free(pOp->p3); } pOp->p3type = P3_DYNAMIC; pOp->p3 = pTos->z; pOp->p1 = pTos->n; - assert( pOp->p1 <= SQLITE_MAX_LENGTH ); /* Due to SQLITE_MAX_SQL_LENGTH */ + if( pOp->p1>SQLITE_MAX_LENGTH ){ + goto too_big; + } break; } #endif - /* Otherwise fall through to the next case, OP_String */ + if( pOp->p1>SQLITE_MAX_LENGTH ){ + goto too_big; + } + /* Fall through to the next case, OP_String */ } /* Opcode: String P1 * P3 ** ** The string value P3 of length P1 (bytes) is pushed onto the stack. */ case OP_String: { - assert( pOp->p1 <= SQLITE_MAX_LENGTH ); /* Due to SQLITE_MAX_SQL_LENGTH */ pTos++; assert( pOp->p3!=0 ); pTos->flags = MEM_Str|MEM_Static|MEM_Term; pTos->z = pOp->p3; pTos->n = pOp->p1; @@ -821,12 +823,13 @@ ** 'Blob' opcode with a binary blob as P3. */ case OP_HexBlob: { /* same as TK_BLOB */ pOp->opcode = OP_Blob; pOp->p1 = strlen(pOp->p3)/2; - assert( SQLITE_MAX_SQL_LENGTH <= SQLITE_MAX_LENGTH ); - assert( pOp->p1 <= SQLITE_MAX_LENGTH ); + if( pOp->p1>SQLITE_MAX_LENGTH ){ + goto too_big; + } if( pOp->p1 ){ char *zBlob = sqlite3HexToBlob(db, pOp->p3); if( !zBlob ) goto no_mem; if( pOp->p3type==P3_DYNAMIC ){ sqlite3_free(pOp->p3); @@ -853,11 +856,11 @@ ** the blob as P3. This opcode is transformed to an OP_Blob ** the first time it is executed. */ case OP_Blob: { pTos++; - assert( pOp->p1 <= SQLITE_MAX_LENGTH ); /* Due to SQLITE_MAX_SQL_LENGTH */ + assert( pOp->p1 <= SQLITE_MAX_LENGTH ); sqlite3VdbeMemSetStr(pTos, pOp->p3, pOp->p1, 0, 0); pTos->enc = encoding; break; } #endif /* SQLITE_OMIT_BLOB_LITERAL */ Index: test/sqllimits1.test ================================================================== --- test/sqllimits1.test +++ test/sqllimits1.test @@ -10,11 +10,11 @@ #*********************************************************************** # # This file contains tests to verify that the limits defined in # sqlite source file limits.h are enforced. # -# $Id: sqllimits1.test,v 1.20 2007/11/28 22:36:41 drh Exp $ +# $Id: sqllimits1.test,v 1.21 2007/12/17 16:20:07 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Test organization: @@ -138,21 +138,47 @@ catchsql { SELECT group_concat(hex(randomblob(20000))) FROM t4; } } {1 {string or blob too big}} db eval {DROP TABLE t4} + +set ::SQLITE_MAX_SQL_LENGTH 0 +set strvalue [string repeat A $::SQLITE_MAX_LENGTH] +do_test sqllimits-1.16 { + catchsql "SELECT '$strvalue'" +} [list 0 $strvalue] +do_test sqllimits-1.17 { + catchsql "SELECT 'A$strvalue'" +} [list 1 {string or blob too big}] +set blobvalue [string repeat 41 $::SQLITE_MAX_LENGTH] +do_test sqllimits-1.18 { + catchsql "SELECT x'$blobvalue'" +} [list 0 $strvalue] +do_test sqllimits-1.19 { + catchsql "SELECT '41$blobvalue'" +} [list 1 {string or blob too big}] +unset strvalue +unset blobvalue #-------------------------------------------------------------------- # Test cases sqllimits-2.* test that the SQLITE_MAX_SQL_LENGTH limit # is enforced. # do_test sqllimits-2.1 { - set sql "SELECT 1 WHERE 1==1" - set N [expr {$::SQLITE_MAX_SQL_LENGTH / [string length " AND 1==1"]}] - append sql [string repeat " AND 1==1" $N] + set ::SQLITE_MAX_SQL_LENGTH 50000 + set sql "SELECT 1 WHERE 1==1" + set tail " /* A comment to take up space in order to make the string\ + longer without increasing the expression depth */\ + AND 1 == 1" + set N [expr {($::SQLITE_MAX_SQL_LENGTH / [string length $tail])+1}] + append sql [string repeat $tail $N] catchsql $sql } {1 {String or BLOB exceeded size limit}} +do_test sqllimits-2.2 { + set ::SQLITE_MAX_SQL_LENGTH 0 + catchsql $sql +} {0 1} #-------------------------------------------------------------------- # Test cases sqllimits-3.* test that the limit set using the # max_page_count pragma. #