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.613 2007/05/10 17:23:12 drh Exp $ +** $Id: vdbe.c,v 1.614 2007/05/10 17:32:48 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include #include @@ -916,11 +916,11 @@ ts = *pFrom; Deephemeralize(pTos); for(i=0; ip1; i++, pFrom++){ Deephemeralize(&pFrom[1]); - assert( (pFrom->flags & MEM_Ephem)==0 ); + assert( (pFrom[1].flags & MEM_Ephem)==0 ); *pFrom = pFrom[1]; if( pFrom->flags & MEM_Short ){ assert( pFrom->flags & (MEM_Str|MEM_Blob) ); assert( pFrom->z==pFrom[1].zShort ); pFrom->z = pFrom->zShort; @@ -2272,19 +2272,21 @@ if( zAffinity ){ applyAffinity(pRec, zAffinity[pRec-pData0], encoding); } if( pRec->flags&MEM_Null ){ containsNull = 1; + } + if( pRec->flags&MEM_Zero && pRec->n>0 ){ + sqlite3VdbeMemExpandBlob(pRec); } serial_type = sqlite3VdbeSerialType(pRec, file_format); len = sqlite3VdbeSerialTypeLen(serial_type); nData += len; nHdr += sqlite3VarintLen(serial_type); if( pRec->flags & MEM_Zero ){ /* Only pure zero-filled BLOBs can be input to this Opcode. ** We do not allow blobs with a prefix and a zero-filled tail. */ - assert( pRec->n==0 ); nZero += pRec->u.i; }else if( len ){ nZero = 0; } } Index: src/vdbeapi.c ================================================================== --- src/vdbeapi.c +++ src/vdbeapi.c @@ -496,13 +496,11 @@ ** The following routines are used to access elements of the current row ** in the result set. */ const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ const void *val; - sqlite3MallocDisallow(); val = sqlite3_value_blob( columnMem(pStmt,i) ); - sqlite3MallocAllow(); return val; } int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes( columnMem(pStmt,i) ); columnMallocFailure(pStmt); Index: test/all.test ================================================================== --- test/all.test +++ test/all.test @@ -8,11 +8,11 @@ # May you share freely, never taking more than you give. # #*********************************************************************** # This file runs all tests. # -# $Id: all.test,v 1.41 2007/05/08 15:59:06 danielk1977 Exp $ +# $Id: all.test,v 1.42 2007/05/10 17:32:48 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl rename finish_test really_finish_test proc finish_test {} { @@ -58,10 +58,11 @@ quick.test malloc.test misuse.test memleak.test sqllimits1.test + fuzz.test } # Files to include in the test. If this list is empty then everything # that is not in the EXCLUDE list is run. # Index: test/fuzz.test ================================================================== --- test/fuzz.test +++ test/fuzz.test @@ -10,11 +10,11 @@ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # -# $Id: fuzz.test,v 1.1 2007/05/10 15:37:53 danielk1977 Exp $ +# $Id: fuzz.test,v 1.2 2007/05/10 17:32:48 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl proc fuzz {TemplateList} { @@ -21,11 +21,13 @@ set n [llength $TemplateList] set i [expr {int(rand()*$n)}] return [subst -novar [lindex $TemplateList $i]] } -proc Value {} { +# Returns a string representing an SQL literal. +# +proc Literal {} { set TemplateList { 456 0 -456 1 -1 2147483648 2147483647 2147483649 -2147483647 -2147483648 -2147483649 'The' 'first' 'experiments' 'in' 'hardware' 'fault' 'injection' zeroblob(1000) @@ -48,37 +50,57 @@ set ::ExprDepth 0 proc Expr {} { incr ::ExprDepth - set TemplateList {[Value]} + set TemplateList {[Literal]} if {$::ExprDepth < 100} { lappend TemplateList \ {[Expr] [BinaryOp] [Expr]} \ - {[UnaryOp] [Expr]} \ - {([Select])} \ - {[Value]} + {[UnaryOp] [Expr]} } if {$::SelectDepth < 10} { - lappend TemplateList {([Select])} + lappend TemplateList {([Select 1])} } set res [fuzz $TemplateList] incr ::ExprDepth -1 return $res } + +set ::TableList [list] +proc Table {} { + set TemplateList [concat sqlite_master $::TableList] + fuzz $TemplateList +} set ::SelectDepth 0 -proc Select {} { +proc Select {{isExpr 0}} { incr ::SelectDepth set TemplateList { {SELECT [Expr]} } + if {$::SelectDepth < 5} { + lappend TemplateList \ + {SELECT [Expr] FROM ([Select])} \ + {SELECT [Expr] FROM [Table]} + + if {0 == $isExpr} { + lappend TemplateList \ + {SELECT [Expr], [Expr] FROM ([Select]) ORDER BY [Expr]} \ + {SELECT * FROM ([Select]) ORDER BY [Expr]} \ + } + } set res [fuzz $TemplateList] incr ::SelectDepth -1 set res } +######################################################################## + +#---------------------------------------------------------------- +# These tests caused errors that were first caught by the tests +# in this file. They are still here. do_test fuzz-1.1 { execsql { SELECT 'abc' LIKE X'ABCD'; } } {0} @@ -95,16 +117,78 @@ do_test fuzz-1.4 { execsql { SELECT (- -21) % NOT (456 LIKE zeroblob(10)); } } {0} +do_test fuzz-1.5 { + execsql { + SELECT (SELECT ( + SELECT (SELECT -2147483648) FROM (SELECT 1) ORDER BY 1 + )) + } +} {-2147483648} +do_test fuzz-1.6 { + execsql { + SELECT 'abc', zeroblob(1) FROM (SELECT 1) ORDER BY 1 + } +} [execsql {SELECT 'abc', zeroblob(1)}] + +do_test fuzz-1.7 { + execsql { +SELECT + (SELECT (SELECT 'fault' / + -2147483648 % - 123456789.1234567899 * (SELECT 'experiments' OR NOT 'first' / 'hardware' FROM (SELECT 2147483647, + (SELECT 'injection') FROM (SELECT 2147483649) ORDER BY + NULL AND (SELECT 'hardware') GLOB 2147483648))) FROM (SELECT * FROM (SELECT (SELECT (SELECT + (SELECT 456 * -2147483648)) LIKE (SELECT (SELECT (SELECT 'fault') - -56.1)) AND -2147483648) FROM (SELECT * FROM (SELECT 2147483648) ORDER BY (SELECT 56.1))) ORDER BY zeroblob(1)) + } +} {} -do_test fuzz-2.1 { - for {set ii 0} {$ii < 2000} {incr ii} { +#---------------------------------------------------------------- +# Test some fuzzily generated expressions. +# +for {set ii 0} {$ii < 2000} {incr ii} { + do_test fuzz-2.1.$ii { set ::expr [Expr] - execsql "SELECT $::expr" + set rc [catch {execsql "SELECT $::expr"} msg] + set e [expr { + $rc == 0 || + $msg eq "parser stack overflow" || + 0 == [string first "ORDER BY column number" $msg] + }] + if {$e == 0} { + puts "" + puts "SELECT $::expr" + puts $msg + } + set e + } {1} +} + +do_test fuzz-3.1 { + execsql { + CREATE TABLE abc(a, b, c); + CREATE TABLE def(d, e, f); + CREATE TABLE ghi(g, h, i); } - set a "" } {} +set ::TableList [list abc def ghi] + +#---------------------------------------------------------------- +# Test some fuzzily generated SELECT statements. +# +for {set ii 0} {$ii < 2000} {incr ii} { + do_test fuzz-2.2.$ii { + set ::select [Select] + set rc [catch {execsql $::select} msg] + set e [expr {$rc == 0 || $msg eq "parser stack overflow"}] + set e [expr { + $rc == 0 || + $msg eq "parser stack overflow" || + 0 == [string first "ORDER BY column number" $msg] + }] + if {$e == 0} { + puts "" + puts $::select + puts $msg + } + set e + } {1} +} finish_test