Fix a problem causing the recovery extension to use excessive memory and CPU time...
[sqlite.git] / test / zipfile2.test
blob987e4f0cfdc81962e41df701b0c5301ede9d580d
1 # 2018 January 30
3 # The author disclaims copyright to this source code.  In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
13 package require Tcl 8.6
15 set testdir [file dirname $argv0]
16 source $testdir/tester.tcl
17 set testprefix zipfile2
19 ifcapable !vtab {
20   finish_test; return
22 if {[catch {load_static_extension db zipfile} error]} {
23   puts "Skipping zipfile2 tests, hit load error: $error"
24   finish_test; return
27 proc blobliteral {str} {
28   set concat [string map {" " "" "\n" ""} $str]
29   return "X'$concat'"
32 proc blob {str} {
33   binary decode hex $str
36 proc findall {needle haystack} {
37   set L [list]
38   set start 0
39   while { [set idx [string first $needle $haystack $start]]>=0 } {
40     lappend L $idx
41     set start [expr $idx+1]
42   }
43   set L
46 do_execsql_test 1.0 {
47   CREATE VIRTUAL TABLE aaa USING zipfile('testzip');
48   CREATE VIRTUAL TABLE bbb USING zipfile("testzip");
49   CREATE VIRTUAL TABLE ccc USING zipfile(`testzip`);
50   CREATE VIRTUAL TABLE ddd USING zipfile([testzip]);
51   CREATE VIRTUAL TABLE eee USING zipfile(testzip);
52   CREATE VIRTUAL TABLE fff USING zipfile('test''zip');
55 do_test 2.0 {
56   forcedelete testdir
57   file mkdir testdir
58   execsql { CREATE VIRTUAL TABLE hhh USING zipfile('testdir') }
59   lindex [catchsql { 
60     SELECT * FROM hhh;
61     INSERT INTO hhh(name, data) VALUES('1.txt', 'file data');
62   }] 0 
63 } 1
66 set archive {
67   504B0304140000080000D4A52BEC09F3B6E0110000001100000005000900612E
68   747874555405000140420F00636F6E74656E7473206F6620612E747874504B03
69   04140000080000D4A52BECD98916A7110000001100000005000900622E747874
70   555405000140420F00636F6E74656E7473206F6620622E747874504B01021E03
71   140000080000D4A52BEC09F3B6E0110000001100000005000900000000000000
72   0000A48100000000612E747874555405000140420F00504B01021E0314000008
73   0000D4A52BECD98916A71100000011000000050009000000000000000000A481
74   3D000000622E747874555405000140420F00504B050600000000020002007800
75   00007A0000000000
78 if 0 {
79   # This test is broken - the archive generated is slightly different
80   # depending on the zlib version used.
81   do_execsql_test 3.1 {
82     WITH contents(name,mtime,data) AS (
83         VALUES('a.txt', 1000000, 'contents of a.txt') UNION ALL
84         VALUES('b.txt', 1000000, 'contents of b.txt')
85     ) SELECT quote( zipfile(name,NULL,mtime,data) ) FROM contents;
86   } [blobliteral $archive]
90 set blob [blob $archive]
91 do_execsql_test 3.2 {
92   SELECT name,mtime,data FROM zipfile($blob)
93 } {
94   a.txt 1000000 {contents of a.txt} 
95   b.txt 1000000 {contents of b.txt}
98 # Corrupt each of the 0x50 0x4B (ascii "PK") headers in the file
99 # Test that in each case this causes an error.
101 set L [findall 504B $archive]
102 for {set i 0} {$i < [llength $L]} {incr i} {
103   set idx [lindex $L $i]
104   set a [string replace $archive $idx [expr $idx+3] 0000]
105   set blob [blob $a]
106   do_catchsql_test 3.3.$i {
107     SELECT name,mtime,data FROM zipfile($blob)
108   } {/1 .*/}
111 # Change the "extra info id" for all extended-timestamp fields.
112 set L [findall 5554 $archive]
113 for {set i 0} {$i < [llength $L]} {incr i} {
114   set idx [lindex $L $i]
115   set a [string replace $archive $idx [expr $idx+3] 1234]
116   set blob [blob $a]
117   do_execsql_test 3.4.$i {
118     SELECT name,data FROM zipfile($blob)
119   } {
120     a.txt {contents of a.txt} 
121     b.txt {contents of b.txt}
122   }
125 for {set i 0} {$i < [llength $L]} {incr i} {
126   set idx [lindex $L $i]
127   set a [string replace $archive [expr $idx+8] [expr $idx+9] 00]
128   set blob [blob $a]
129   do_execsql_test 3.5.$i {
130     SELECT name,data FROM zipfile($blob)
131   } {
132     a.txt {contents of a.txt} 
133     b.txt {contents of b.txt}
134   }
137 # set blob [db one {
138 #   WITH contents(name,mtime,data) AS (
139 #     VALUES('a.txt', 1000000, 'aaaaaaaaaaaaaaaaaaaaaaa')
140 #   ) SELECT quote( zipfile(name,NULL,mtime,data) ) FROM contents;
141 # }]
142 # set blob [string range $blob 2 end]
143 # set blob [string range $blob 0 end-1]
144 # while {[string length $blob]>0} {
145 #   puts [string range $blob 0 63]
146 #   set blob [string range $blob 64 end]
147 # }
148 # exit
150 set archive2 {
151   504B0304140000080800D4A52BEC08F54C6E050000001700000005000900612E
152   747874555405000140420F004B4CC40A00504B01021E03140000080800D4A52B
153   EC08F54C6E0500000017000000050009000000000000000000A4810000000061
154   2E747874555405000140420F00504B050600000000010001003C000000310000
155   000000
157 set blob [blob $archive2]
158 do_execsql_test 4.0 {
159   SELECT name,mtime,data,method FROM zipfile($blob)
160 } {
161   a.txt 1000000 aaaaaaaaaaaaaaaaaaaaaaa 8
164 set L [findall 17000000 $archive2]
165 set a $archive2
166 foreach i $L { set a [string replace $a $i [expr $i+7] 16000000] }
167 set blob [blob $a]
168 do_catchsql_test 4.1 {
169   SELECT name,mtime,data,method FROM zipfile($blob)
170 } {1 {inflate() failed (0)}}
172 # Check the response to an unknown compression method (set data to NULL).
173 set blob [blob [string map {0800 0900} $archive2]]
174 do_execsql_test 4.2 {
175   SELECT name,mtime,data IS NULL,method FROM zipfile($blob)
176 } {a.txt 1000000 1 9}
178 # Corrupt the EOCDS signature bytes in various ways.
179 foreach {tn sub} {
180   1 {504B0500}
181   2 {504B0006}
182   3 {50000506}
183   4 {004B0506}
184 } {
185   set blob [blob [string map [list 504B0506 $sub] $archive2]]
186   do_catchsql_test 4.3.$tn {
187     SELECT * FROM zipfile($blob)
188   } {1 {cannot find end of central directory record}}
191 #-------------------------------------------------------------------------
192 # Test that a zero-length file with a '/' at the end is treated as
193 # a directory (data IS NULL). Even if the mode doesn't indicate
194 # that it is a directory.
196 do_test 5.0 {
197   set blob [db one {
198     WITH c(n, d) AS (
199       SELECT 'notadir', ''
200     )
201     SELECT zipfile(n, d) FROM c
202  }]
204   set hex [binary encode hex $blob]
205   set hex [string map {6e6f7461646972 6e6f746164692f} $hex] 
206   set blob2 [binary decode hex $hex]
208   execsql { SELECT name, data IS NULL FROM zipfile($blob2) }
209 } {notadi/ 1}
211 #-------------------------------------------------------------------------
212 # Test that duplicate entries may not be created using UPDATE
213 # statements.
215 forcedelete test.zip
216 do_execsql_test 6.0 {
217   CREATE VIRTUAL TABLE temp.zip USING zipfile('test.zip'); 
218   INSERT INTO temp.zip (name,data) VALUES ('test1','test'); 
219   INSERT INTO temp.zip (name,data) VALUES ('test2','test'); 
221 do_catchsql_test 6.1 {
222   UPDATE temp.zip SET name='test1' WHERE name='test2'
223 } {1 {duplicate name: "test1"}}
225 forcedelete test.zip
226 do_catchsql_test 6.2 {
227   DROP TABLE zip;
228   CREATE VIRTUAL TABLE temp.zip USING zipfile('test.zip'); 
229   INSERT INTO temp.zip (name,data) VALUES ('test','test'); 
230   UPDATE  temp.zip set name=name||'new' where name='test'; 
231   INSERT INTO temp.zip (name,data) VALUES ('test','test'); 
232   UPDATE  temp.zip set name=name||'new' where name='test'; 
233 } {1 {duplicate name: "testnew"}}
235 forcedelete test.zip
236 do_execsql_test 6.3 {
237   INSERT INTO temp.zip (name,data) VALUES ('test1','test'); 
238   INSERT INTO temp.zip (name,data) VALUES ('test2','test'); 
239   UPDATE OR REPLACE zip SET name='test2' WHERE name='test1';
240   SELECT name FROM zip;
241 } {test2}
243 finish_test