xref: /sqlite-3.40.0/test/fuzz.test (revision d908f5ab)
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.5 2007/05/11 07:08:29 danielk1977 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 ( SELECT zeroblob(1000) FROM (
139      SELECT * FROM (SELECT 'first') ORDER BY NOT 'in')
140    )
141  }
142} [execsql {SELECT zeroblob(1000)}]
143
144#----------------------------------------------------------------
145# Test some fuzzily generated expressions.
146#
147for {set ii 0} {$ii < 2000} {incr ii} {
148  do_test fuzz-2.1.$ii {
149    set ::expr [Expr]
150    set rc [catch {execsql "SELECT $::expr"} msg]
151    set e [expr {
152      $rc == 0 ||
153      $msg eq "parser stack overflow" ||
154      0 == [string first "ORDER BY column number" $msg]
155    }]
156    if {$e == 0} {
157      puts ""
158      puts "SELECT $::expr"
159      puts $msg
160    }
161    set e
162  } {1}
163}
164
165do_test fuzz-3.1 {
166  execsql {
167    CREATE TABLE abc(a, b, c);
168    CREATE TABLE def(d, e, f);
169    CREATE TABLE ghi(g, h, i);
170  }
171} {}
172set ::TableList [list abc def ghi]
173
174#----------------------------------------------------------------
175# Test some fuzzily generated SELECT statements.
176#
177for {set ii 0} {$ii < 2000} {incr ii} {
178  do_test fuzz-2.2.$ii {
179    set ::select [Select]
180    set rc [catch {execsql $::select} msg]
181    set e [expr {$rc == 0 || $msg eq "parser stack overflow"}]
182    set e [expr {
183      $rc == 0 ||
184      $msg eq "parser stack overflow" ||
185      0 == [string first "ORDER BY column number" $msg]
186    }]
187    if {$e == 0} {
188      puts ""
189      puts $::select
190      puts $msg
191    }
192    set e
193  } {1}
194}
195
196finish_test
197