1# 2007 May 10 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# This file implements regression tests for SQLite library. The 12# focus of this file is generating semi-random strings of SQL 13# (a.k.a. "fuzz") and sending it into the parser to try to generate 14# errors. 15# 16# $Id: fuzz.test,v 1.4 2007/05/11 00:20:08 drh Exp $ 17 18set testdir [file dirname $argv0] 19source $testdir/tester.tcl 20 21proc fuzz {TemplateList} { 22 set n [llength $TemplateList] 23 set i [expr {int(rand()*$n)}] 24 return [subst -novar [lindex $TemplateList $i]] 25} 26 27# Returns a string representing an SQL literal. 28# 29proc Literal {} { 30 set TemplateList { 31 456 0 -456 1 -1 32 2147483648 2147483647 2147483649 -2147483647 -2147483648 -2147483649 33 'The' 'first' 'experiments' 'in' 'hardware' 'fault' 'injection' 34 zeroblob(1000) 35 NULL 36 56.1 -56.1 37 123456789.1234567899 38 } 39 fuzz $TemplateList 40} 41 42proc UnaryOp {} { 43 set TemplateList {+ - NOT} 44 fuzz $TemplateList 45} 46 47proc BinaryOp {} { 48 set TemplateList {+ - % * / AND OR LIKE GLOB} 49 fuzz $TemplateList 50} 51 52set ::ExprDepth 0 53proc Expr {} { 54 incr ::ExprDepth 55 56 set TemplateList {[Literal]} 57 if {$::ExprDepth < 100} { 58 lappend TemplateList \ 59 {[Expr] [BinaryOp] [Expr]} \ 60 {[UnaryOp] [Expr]} 61 } 62 if {$::SelectDepth < 10} { 63 lappend TemplateList {([Select 1])} 64 } 65 set res [fuzz $TemplateList] 66 incr ::ExprDepth -1 67 return $res 68} 69 70set ::TableList [list] 71proc Table {} { 72 set TemplateList [concat sqlite_master $::TableList] 73 fuzz $TemplateList 74} 75 76set ::SelectDepth 0 77proc Select {{isExpr 0}} { 78 incr ::SelectDepth 79 set TemplateList { 80 {SELECT [Expr]} 81 } 82 if {$::SelectDepth < 5} { 83 lappend TemplateList \ 84 {SELECT [Expr] FROM ([Select])} \ 85 {SELECT [Expr] FROM [Table]} 86 87 if {0 == $isExpr} { 88 lappend TemplateList \ 89 {SELECT [Expr], [Expr] FROM ([Select]) ORDER BY [Expr]} \ 90 {SELECT * FROM ([Select]) ORDER BY [Expr]} \ 91 } 92 } 93 set res [fuzz $TemplateList] 94 incr ::SelectDepth -1 95 set res 96} 97 98######################################################################## 99 100#---------------------------------------------------------------- 101# These tests caused errors that were first caught by the tests 102# in this file. They are still here. 103do_test fuzz-1.1 { 104 execsql { 105 SELECT 'abc' LIKE X'ABCD'; 106 } 107} {0} 108do_test fuzz-1.2 { 109 execsql { 110 SELECT 'abc' LIKE zeroblob(10); 111 } 112} {0} 113do_test fuzz-1.3 { 114 execsql { 115 SELECT zeroblob(10) LIKE 'abc'; 116 } 117} {0} 118do_test fuzz-1.4 { 119 execsql { 120 SELECT (- -21) % NOT (456 LIKE zeroblob(10)); 121 } 122} {0} 123do_test fuzz-1.5 { 124 execsql { 125 SELECT (SELECT ( 126 SELECT (SELECT -2147483648) FROM (SELECT 1) ORDER BY 1 127 )) 128 } 129} {-2147483648} 130do_test fuzz-1.6 { 131 execsql { 132 SELECT 'abc', zeroblob(1) FROM (SELECT 1) ORDER BY 1 133 } 134} [execsql {SELECT 'abc', zeroblob(1)}] 135 136do_test fuzz-1.7 { 137 execsql { 138 SELECT ( 139 SELECT zeroblob(1000) FROM ( 140 SELECT * FROM (SELECT 'first') ORDER BY NOT 'in' 141 ) 142 ) 143 } 144} {} 145 146#---------------------------------------------------------------- 147# Test some fuzzily generated expressions. 148# 149for {set ii 0} {$ii < 2000} {incr ii} { 150 do_test fuzz-2.1.$ii { 151 set ::expr [Expr] 152 set rc [catch {execsql "SELECT $::expr"} msg] 153 set e [expr { 154 $rc == 0 || 155 $msg eq "parser stack overflow" || 156 0 == [string first "ORDER BY column number" $msg] 157 }] 158 if {$e == 0} { 159 puts "" 160 puts "SELECT $::expr" 161 puts $msg 162 } 163 set e 164 } {1} 165} 166 167do_test fuzz-3.1 { 168 execsql { 169 CREATE TABLE abc(a, b, c); 170 CREATE TABLE def(d, e, f); 171 CREATE TABLE ghi(g, h, i); 172 } 173} {} 174set ::TableList [list abc def ghi] 175 176#---------------------------------------------------------------- 177# Test some fuzzily generated SELECT statements. 178# 179for {set ii 0} {$ii < 2000} {incr ii} { 180 do_test fuzz-2.2.$ii { 181 set ::select [Select] 182 set rc [catch {execsql $::select} msg] 183 set e [expr {$rc == 0 || $msg eq "parser stack overflow"}] 184 set e [expr { 185 $rc == 0 || 186 $msg eq "parser stack overflow" || 187 0 == [string first "ORDER BY column number" $msg] 188 }] 189 if {$e == 0} { 190 puts "" 191 puts $::select 192 puts $msg 193 } 194 set e 195 } {1} 196} 197 198finish_test 199