xref: /sqlite-3.40.0/test/fuzz.test (revision db83f823)
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