OLD | NEW |
| (Empty) |
1 # 2001 September 15 | |
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 # | |
12 # This file attempts to check the behavior of the SQLite library in | |
13 # an out-of-memory situation. When compiled with -DSQLITE_DEBUG=1, | |
14 # the SQLite library accepts a special command (sqlite3_memdebug_fail N C) | |
15 # which causes the N-th malloc to fail. This special feature is used | |
16 # to see what happens in the library if a malloc were to really fail | |
17 # due to an out-of-memory situation. | |
18 # | |
19 # $Id: malloc.test,v 1.81 2009/06/24 13:13:45 drh Exp $ | |
20 | |
21 set testdir [file dirname $argv0] | |
22 source $testdir/tester.tcl | |
23 set ::testprefix malloc | |
24 | |
25 | |
26 # Only run these tests if memory debugging is turned on. | |
27 # | |
28 source $testdir/malloc_common.tcl | |
29 if {!$MEMDEBUG} { | |
30 puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." | |
31 finish_test | |
32 return | |
33 } | |
34 | |
35 # Do a couple of memory dumps just to exercise the memory dump logic | |
36 # that that we can say that we have. | |
37 # | |
38 puts stderr "This is a test. Ignore the error that follows:" | |
39 sqlite3_memdebug_dump $testdir | |
40 puts "Memory dump to file memdump.txt..." | |
41 sqlite3_memdebug_dump memdump.txt | |
42 | |
43 ifcapable bloblit&&subquery { | |
44 do_malloc_test 1 -tclprep { | |
45 db close | |
46 } -tclbody { | |
47 if {[catch {sqlite3 db test.db}]} { | |
48 error "out of memory" | |
49 } | |
50 sqlite3_extended_result_codes db 1 | |
51 } -sqlbody { | |
52 DROP TABLE IF EXISTS t1; | |
53 CREATE TABLE t1( | |
54 a int, b float, c double, d text, e varchar(20), | |
55 primary key(a,b,c) | |
56 ); | |
57 CREATE INDEX i1 ON t1(a,b); | |
58 INSERT INTO t1 VALUES(1,2.3,4.5,'hi',x'746865726500'); | |
59 INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder'); | |
60 SELECT * FROM t1; | |
61 SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0; | |
62 DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1); | |
63 SELECT count(*), group_concat(e) FROM t1; | |
64 SELECT b FROM t1 ORDER BY 1 COLLATE nocase; | |
65 } | |
66 } | |
67 | |
68 # Ensure that no file descriptors were leaked. | |
69 do_test malloc-1.X { | |
70 catch {db close} | |
71 set sqlite_open_file_count | |
72 } {0} | |
73 | |
74 ifcapable subquery { | |
75 do_malloc_test 2 -sqlbody { | |
76 CREATE TABLE t1(a int, b int default 'abc', c int default 1); | |
77 CREATE INDEX i1 ON t1(a,b); | |
78 INSERT INTO t1 VALUES(1,1,'99 abcdefghijklmnopqrstuvwxyz'); | |
79 INSERT INTO t1 VALUES(2,4,'98 abcdefghijklmnopqrstuvwxyz'); | |
80 INSERT INTO t1 VALUES(3,9,'97 abcdefghijklmnopqrstuvwxyz'); | |
81 INSERT INTO t1 VALUES(4,16,'96 abcdefghijklmnopqrstuvwxyz'); | |
82 INSERT INTO t1 VALUES(5,25,'95 abcdefghijklmnopqrstuvwxyz'); | |
83 INSERT INTO t1 VALUES(6,36,'94 abcdefghijklmnopqrstuvwxyz'); | |
84 SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1; | |
85 UPDATE t1 SET b=b||b||b||b; | |
86 UPDATE t1 SET b=a WHERE a in (10,12,22); | |
87 INSERT INTO t1(c,b,a) VALUES(20,10,5); | |
88 INSERT INTO t1 SELECT * FROM t1 | |
89 WHERE a IN (SELECT a FROM t1 WHERE a<10); | |
90 DELETE FROM t1 WHERE a>=10; | |
91 DROP INDEX i1; | |
92 DELETE FROM t1; | |
93 } | |
94 } | |
95 | |
96 # Ensure that no file descriptors were leaked. | |
97 do_test malloc-2.X { | |
98 catch {db close} | |
99 set sqlite_open_file_count | |
100 } {0} | |
101 | |
102 do_malloc_test 3 -sqlbody { | |
103 BEGIN TRANSACTION; | |
104 CREATE TABLE t1(a int, b int, c int); | |
105 CREATE INDEX i1 ON t1(a,b); | |
106 INSERT INTO t1 VALUES(1,1,99); | |
107 INSERT INTO t1 VALUES(2,4,98); | |
108 INSERT INTO t1 VALUES(3,9,97); | |
109 INSERT INTO t1 VALUES(4,16,96); | |
110 INSERT INTO t1 VALUES(5,25,95); | |
111 INSERT INTO t1 VALUES(6,36,94); | |
112 INSERT INTO t1(c,b,a) VALUES(20,10,5); | |
113 DELETE FROM t1 WHERE a>=10; | |
114 DROP INDEX i1; | |
115 DELETE FROM t1; | |
116 ROLLBACK; | |
117 } | |
118 | |
119 | |
120 # Ensure that no file descriptors were leaked. | |
121 do_test malloc-3.X { | |
122 catch {db close} | |
123 set sqlite_open_file_count | |
124 } {0} | |
125 | |
126 ifcapable subquery { | |
127 do_malloc_test 4 -sqlbody { | |
128 BEGIN TRANSACTION; | |
129 CREATE TABLE t1(a int, b int, c int); | |
130 CREATE INDEX i1 ON t1(a,b); | |
131 INSERT INTO t1 VALUES(1,1,99); | |
132 INSERT INTO t1 VALUES(2,4,98); | |
133 INSERT INTO t1 VALUES(3,9,97); | |
134 INSERT INTO t1 VALUES(4,16,96); | |
135 INSERT INTO t1 VALUES(5,25,95); | |
136 INSERT INTO t1 VALUES(6,36,94); | |
137 UPDATE t1 SET b=a WHERE a in (10,12,22); | |
138 INSERT INTO t1 SELECT * FROM t1 | |
139 WHERE a IN (SELECT a FROM t1 WHERE a<10); | |
140 DROP INDEX i1; | |
141 DELETE FROM t1; | |
142 COMMIT; | |
143 } | |
144 } | |
145 | |
146 # Ensure that no file descriptors were leaked. | |
147 do_test malloc-4.X { | |
148 catch {db close} | |
149 set sqlite_open_file_count | |
150 } {0} | |
151 | |
152 ifcapable trigger { | |
153 do_malloc_test 5 -sqlbody { | |
154 BEGIN TRANSACTION; | |
155 CREATE TABLE t1(a,b); | |
156 CREATE TABLE t2(x,y); | |
157 CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN new.a = 2 BEGIN | |
158 INSERT INTO t2(x,y) VALUES(new.rowid,1); | |
159 INSERT INTO t2(x,y) SELECT * FROM t2; | |
160 INSERT INTO t2 SELECT * FROM t2; | |
161 UPDATE t2 SET y=y+1 WHERE x=new.rowid; | |
162 SELECT 123; | |
163 DELETE FROM t2 WHERE x=new.rowid; | |
164 END; | |
165 INSERT INTO t1(a,b) VALUES(2,3); | |
166 COMMIT; | |
167 } | |
168 } | |
169 | |
170 # Ensure that no file descriptors were leaked. | |
171 do_test malloc-5.X { | |
172 catch {db close} | |
173 set sqlite_open_file_count | |
174 } {0} | |
175 | |
176 ifcapable vacuum { | |
177 do_malloc_test 6 -sqlprep { | |
178 BEGIN TRANSACTION; | |
179 CREATE TABLE t1(a); | |
180 INSERT INTO t1 VALUES(1); | |
181 INSERT INTO t1 SELECT a*2 FROM t1; | |
182 INSERT INTO t1 SELECT a*2 FROM t1; | |
183 INSERT INTO t1 SELECT a*2 FROM t1; | |
184 INSERT INTO t1 SELECT a*2 FROM t1; | |
185 INSERT INTO t1 SELECT a*2 FROM t1; | |
186 INSERT INTO t1 SELECT a*2 FROM t1; | |
187 INSERT INTO t1 SELECT a*2 FROM t1; | |
188 INSERT INTO t1 SELECT a*2 FROM t1; | |
189 INSERT INTO t1 SELECT a*2 FROM t1; | |
190 INSERT INTO t1 SELECT a*2 FROM t1; | |
191 DELETE FROM t1 where rowid%5 = 0; | |
192 COMMIT; | |
193 } -sqlbody { | |
194 VACUUM; | |
195 } | |
196 } | |
197 | |
198 autoinstall_test_functions | |
199 do_malloc_test 7 -sqlprep { | |
200 CREATE TABLE t1(a, b); | |
201 INSERT INTO t1 VALUES(1, 2); | |
202 INSERT INTO t1 VALUES(3, 4); | |
203 INSERT INTO t1 VALUES(5, 6); | |
204 INSERT INTO t1 VALUES(7, randstr(1200,1200)); | |
205 } -sqlbody { | |
206 SELECT min(a) FROM t1 WHERE a<6 GROUP BY b; | |
207 SELECT a FROM t1 WHERE a<6 ORDER BY a; | |
208 SELECT b FROM t1 WHERE a>6; | |
209 } | |
210 | |
211 # This block is designed to test that some malloc failures that may | |
212 # occur in vdbeapi.c. Specifically, if a malloc failure that occurs | |
213 # when converting UTF-16 text to integers and real numbers is handled | |
214 # correctly. | |
215 # | |
216 # This is done by retrieving a string from the database engine and | |
217 # manipulating it using the sqlite3_column_*** APIs. This doesn't | |
218 # actually return an error to the user when a malloc() fails.. That | |
219 # could be viewed as a bug. | |
220 # | |
221 # These tests only run if UTF-16 support is compiled in. | |
222 # | |
223 ifcapable utf16 { | |
224 set ::STMT {} | |
225 do_malloc_test 8 -tclprep { | |
226 set sql "SELECT '[string repeat abc 20]', '[string repeat def 20]', ?" | |
227 set ::STMT [sqlite3_prepare db $sql -1 X] | |
228 sqlite3_step $::STMT | |
229 if { $::tcl_platform(byteOrder)=="littleEndian" } { | |
230 set ::bomstr "\xFF\xFE" | |
231 } else { | |
232 set ::bomstr "\xFE\xFF" | |
233 } | |
234 append ::bomstr [encoding convertto unicode "123456789_123456789_123456789"] | |
235 } -tclbody { | |
236 sqlite3_column_text16 $::STMT 0 | |
237 sqlite3_column_int $::STMT 0 | |
238 sqlite3_column_text16 $::STMT 1 | |
239 sqlite3_column_double $::STMT 1 | |
240 set rc [sqlite3_reset $::STMT] | |
241 if {$rc eq "SQLITE_NOMEM"} {error "out of memory"} | |
242 sqlite3_bind_text16 $::STMT 1 $::bomstr 60 | |
243 #catch {sqlite3_finalize $::STMT} | |
244 #if {[lindex [sqlite_malloc_stat] 2]<=0} { | |
245 # error "out of memory" | |
246 #} | |
247 } -cleanup { | |
248 if {$::STMT!=""} { | |
249 sqlite3_finalize $::STMT | |
250 set ::STMT {} | |
251 } | |
252 } | |
253 } | |
254 | |
255 # This block tests that malloc() failures that occur whilst commiting | |
256 # a multi-file transaction are handled correctly. | |
257 # | |
258 do_malloc_test 9 -sqlprep { | |
259 ATTACH 'test2.db' as test2; | |
260 CREATE TABLE abc1(a, b, c); | |
261 CREATE TABLE test2.abc2(a, b, c); | |
262 } -sqlbody { | |
263 BEGIN; | |
264 INSERT INTO abc1 VALUES(1, 2, 3); | |
265 INSERT INTO abc2 VALUES(1, 2, 3); | |
266 COMMIT; | |
267 } | |
268 | |
269 # This block tests malloc() failures that occur while opening a | |
270 # connection to a database. | |
271 do_malloc_test 10 -tclprep { | |
272 catch {db2 close} | |
273 db close | |
274 forcedelete test.db test.db-journal | |
275 sqlite3 db test.db | |
276 sqlite3_extended_result_codes db 1 | |
277 db eval {CREATE TABLE abc(a, b, c)} | |
278 } -tclbody { | |
279 db close | |
280 sqlite3 db2 test.db | |
281 sqlite3_extended_result_codes db2 1 | |
282 db2 eval {SELECT * FROM sqlite_master} | |
283 db2 close | |
284 } | |
285 | |
286 # This block tests malloc() failures that occur within calls to | |
287 # sqlite3_create_function(). | |
288 do_malloc_test 11 -tclbody { | |
289 set rc [sqlite3_create_function db] | |
290 if {[string match $rc SQLITE_OK]} { | |
291 set rc [sqlite3_create_aggregate db] | |
292 } | |
293 if {[string match $rc SQLITE_NOMEM]} { | |
294 error "out of memory" | |
295 } | |
296 } | |
297 | |
298 do_malloc_test 12 -tclbody { | |
299 set sql16 [encoding convertto unicode "SELECT * FROM sqlite_master"] | |
300 append sql16 "\00\00" | |
301 set ::STMT [sqlite3_prepare16 db $sql16 -1 DUMMY] | |
302 sqlite3_finalize $::STMT | |
303 } | |
304 | |
305 # Test malloc errors when replaying two hot journals from a 2-file | |
306 # transaction. | |
307 ifcapable crashtest&&attach { | |
308 do_malloc_test 13 -tclprep { | |
309 set rc [crashsql -delay 1 -file test2.db { | |
310 ATTACH 'test2.db' as aux; | |
311 PRAGMA cache_size = 10; | |
312 BEGIN; | |
313 CREATE TABLE aux.t2(a, b, c); | |
314 CREATE TABLE t1(a, b, c); | |
315 COMMIT; | |
316 }] | |
317 if {$rc!="1 {child process exited abnormally}"} { | |
318 error "Wrong error message: $rc" | |
319 } | |
320 } -tclbody { | |
321 db eval {ATTACH 'test2.db' as aux;} | |
322 set rc [catch {db eval { | |
323 SELECT * FROM t1; | |
324 SELECT * FROM t2; | |
325 }} err] | |
326 if {$rc && $err!="no such table: t1"} { | |
327 error $err | |
328 } | |
329 } | |
330 } | |
331 | |
332 if {$tcl_platform(platform)!="windows"} { | |
333 do_malloc_test 14 -tclprep { | |
334 catch {db close} | |
335 sqlite3 db2 test2.db | |
336 sqlite3_extended_result_codes db2 1 | |
337 db2 eval { | |
338 PRAGMA journal_mode = DELETE; /* For inmemory_journal permutation */ | |
339 PRAGMA synchronous = 0; | |
340 CREATE TABLE t1(a, b); | |
341 INSERT INTO t1 VALUES(1, 2); | |
342 BEGIN; | |
343 INSERT INTO t1 VALUES(3, 4); | |
344 } | |
345 forcecopy test2.db test.db | |
346 forcecopy test2.db-journal test.db-journal | |
347 db2 close | |
348 } -tclbody { | |
349 sqlite3 db test.db | |
350 sqlite3_extended_result_codes db 1 | |
351 | |
352 # If an out-of-memory occurs within a call to a VFS layer function during | |
353 # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit | |
354 # [5668] for details. | |
355 set rc [catch {db eval { SELECT * FROM t1 }} msg] | |
356 if {$msg eq "database disk image is malformed"} { set msg "out of memory" } | |
357 if {$rc} { error $msg } | |
358 set msg | |
359 } | |
360 } | |
361 | |
362 proc string_compare {a b} { | |
363 return [string compare $a $b] | |
364 } | |
365 | |
366 # Test for malloc() failures in sqlite3_create_collation() and | |
367 # sqlite3_create_collation16(). | |
368 # | |
369 ifcapable utf16 { | |
370 do_malloc_test 15 -start 4 -tclbody { | |
371 db collate string_compare string_compare | |
372 if {[catch {add_test_collate db 1 1 1} msg]} { | |
373 if {$msg=="SQLITE_NOMEM"} {set msg "out of memory"} | |
374 error $msg | |
375 } | |
376 | |
377 db complete {SELECT "hello """||'world"' [microsoft], * FROM anicetable;} | |
378 db complete {-- Useful comment} | |
379 | |
380 execsql { | |
381 CREATE TABLE t1(a, b COLLATE string_compare); | |
382 INSERT INTO t1 VALUES(10, 'string'); | |
383 INSERT INTO t1 VALUES(10, 'string2'); | |
384 } | |
385 } | |
386 } | |
387 | |
388 # Also test sqlite3_complete(). There are (currently) no malloc() | |
389 # calls in this function, but test anyway against future changes. | |
390 # | |
391 do_malloc_test 16 -tclbody { | |
392 db complete {SELECT "hello """||'world"' [microsoft], * FROM anicetable;} | |
393 db complete {-- Useful comment} | |
394 db eval { | |
395 SELECT * FROM sqlite_master; | |
396 } | |
397 } | |
398 | |
399 # Test handling of malloc() failures in sqlite3_open16(). | |
400 # | |
401 ifcapable utf16 { | |
402 do_malloc_test 17 -tclbody { | |
403 set DB2 0 | |
404 set STMT 0 | |
405 | |
406 # open database using sqlite3_open16() | |
407 set filename [encoding convertto unicode test.db] | |
408 append filename "\x00\x00" | |
409 set DB2 [sqlite3_open16 $filename -unused] | |
410 if {0==$DB2} { | |
411 error "out of memory" | |
412 } | |
413 sqlite3_extended_result_codes $DB2 1 | |
414 | |
415 # Prepare statement | |
416 set rc [catch {sqlite3_prepare $DB2 {SELECT * FROM sqlite_master} -1 X} msg] | |
417 if {[sqlite3_errcode $DB2] eq "SQLITE_IOERR+12"} { | |
418 error "out of memory" | |
419 } | |
420 if {[regexp ".*automatic extension loading.*" [sqlite3_errmsg $DB2]]} { | |
421 error "out of memory" | |
422 } | |
423 if {$rc} { | |
424 error [string range $msg 4 end] | |
425 } | |
426 set STMT $msg | |
427 | |
428 # Finalize statement | |
429 set rc [sqlite3_finalize $STMT] | |
430 if {$rc!="SQLITE_OK"} { | |
431 error [sqlite3_errmsg $DB2] | |
432 } | |
433 set STMT 0 | |
434 | |
435 # Close database | |
436 set rc [sqlite3_close $DB2] | |
437 if {$rc!="SQLITE_OK"} { | |
438 error [sqlite3_errmsg $DB2] | |
439 } | |
440 set DB2 0 | |
441 } -cleanup { | |
442 if {$STMT!="0"} { | |
443 sqlite3_finalize $STMT | |
444 } | |
445 if {$DB2!="0"} { | |
446 set rc [sqlite3_close $DB2] | |
447 } | |
448 } | |
449 } | |
450 | |
451 # Test handling of malloc() failures in sqlite3_errmsg16(). | |
452 # | |
453 ifcapable utf16 { | |
454 do_malloc_test 18 -tclprep { | |
455 catch { | |
456 db eval "SELECT [string repeat longcolumnname 10] FROM sqlite_master" | |
457 } | |
458 } -tclbody { | |
459 set utf16 [sqlite3_errmsg16 [sqlite3_connection_pointer db]] | |
460 binary scan $utf16 c* bytes | |
461 if {[llength $bytes]==0} { | |
462 error "out of memory" | |
463 } | |
464 } | |
465 } | |
466 | |
467 # This test is aimed at coverage testing. Specificly, it is supposed to | |
468 # cause a malloc() only used when converting between the two utf-16 | |
469 # encodings to fail (i.e. little-endian->big-endian). It only actually | |
470 # hits this malloc() on little-endian hosts. | |
471 # | |
472 set static_string "\x00h\x00e\x00l\x00l\x00o" | |
473 for {set l 0} {$l<10} {incr l} { | |
474 append static_string $static_string | |
475 } | |
476 append static_string "\x00\x00" | |
477 do_malloc_test 19 -tclprep { | |
478 execsql { | |
479 PRAGMA encoding = "UTF16be"; | |
480 CREATE TABLE abc(a, b, c); | |
481 } | |
482 } -tclbody { | |
483 unset -nocomplain ::STMT | |
484 set r [catch { | |
485 set ::STMT [sqlite3_prepare db {SELECT ?} -1 DUMMY] | |
486 sqlite3_bind_text16 -static $::STMT 1 $static_string 112 | |
487 } msg] | |
488 if {$r} {error [string range $msg 4 end]} | |
489 set msg | |
490 } -cleanup { | |
491 if {[info exists ::STMT]} { | |
492 sqlite3_finalize $::STMT | |
493 } | |
494 } | |
495 unset static_string | |
496 | |
497 # Make sure SQLITE_NOMEM is reported out on an ATTACH failure even | |
498 # when the malloc failure occurs within the nested parse. | |
499 # | |
500 ifcapable attach { | |
501 do_malloc_test 20 -tclprep { | |
502 db close | |
503 forcedelete test2.db test2.db-journal | |
504 sqlite3 db test2.db | |
505 sqlite3_extended_result_codes db 1 | |
506 db eval {CREATE TABLE t1(x);} | |
507 db close | |
508 } -tclbody { | |
509 if {[catch {sqlite3 db test.db}]} { | |
510 error "out of memory" | |
511 } | |
512 sqlite3_extended_result_codes db 1 | |
513 } -sqlbody { | |
514 ATTACH DATABASE 'test2.db' AS t2; | |
515 SELECT * FROM t1; | |
516 DETACH DATABASE t2; | |
517 } | |
518 } | |
519 | |
520 # Test malloc failure whilst installing a foreign key. | |
521 # | |
522 ifcapable foreignkey { | |
523 do_malloc_test 21 -sqlbody { | |
524 CREATE TABLE abc(a, b, c, FOREIGN KEY(a) REFERENCES abc(b)) | |
525 } | |
526 } | |
527 | |
528 # Test malloc failure in an sqlite3_prepare_v2() call. | |
529 # | |
530 do_malloc_test 22 -tclbody { | |
531 set ::STMT "" | |
532 set r [catch { | |
533 set ::STMT [ | |
534 sqlite3_prepare_v2 db "SELECT * FROM sqlite_master" -1 DUMMY | |
535 ] | |
536 } msg] | |
537 if {$r} {error [string range $msg 4 end]} | |
538 } -cleanup { | |
539 if {$::STMT ne ""} { | |
540 sqlite3_finalize $::STMT | |
541 set ::STMT "" | |
542 } | |
543 } | |
544 | |
545 ifcapable {pager_pragmas} { | |
546 # This tests a special case - that an error that occurs while the pager | |
547 # is trying to recover from error-state in exclusive-access mode works. | |
548 # | |
549 do_malloc_test 23 -tclprep { | |
550 db eval { | |
551 PRAGMA cache_size = 10; | |
552 PRAGMA locking_mode = exclusive; | |
553 BEGIN; | |
554 CREATE TABLE abc(a, b, c); | |
555 CREATE INDEX abc_i ON abc(a, b, c); | |
556 INSERT INTO abc | |
557 VALUES(randstr(100,100), randstr(100,100), randstr(100,100)); | |
558 INSERT INTO abc | |
559 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; | |
560 INSERT INTO abc | |
561 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; | |
562 INSERT INTO abc | |
563 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; | |
564 INSERT INTO abc | |
565 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; | |
566 INSERT INTO abc | |
567 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; | |
568 COMMIT; | |
569 } | |
570 | |
571 # This puts the pager into error state. | |
572 # | |
573 db eval BEGIN | |
574 db eval {UPDATE abc SET a = 0 WHERE oid%2} | |
575 set ::sqlite_io_error_pending 10 | |
576 catch {db eval {ROLLBACK}} msg | |
577 | |
578 } -tclbody { | |
579 # If an out-of-memory occurs within a call to a VFS layer function during | |
580 # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit | |
581 # [5668] for details. | |
582 set rc [catch {db eval { SELECT * FROM abc LIMIT 10 }} msg] | |
583 if {$msg eq "database disk image is malformed"} { set msg "out of memory" } | |
584 if {$rc} { error $msg } | |
585 set msg | |
586 } -cleanup { | |
587 set e [db eval {PRAGMA integrity_check}] | |
588 if {$e ne "ok"} {error $e} | |
589 } | |
590 } | |
591 | |
592 ifcapable compound { | |
593 do_malloc_test 24 -sqlprep { | |
594 CREATE TABLE t1(a, b, c) | |
595 } -sqlbody { | |
596 SELECT 1 FROM t1 UNION SELECT 2 FROM t1 ORDER BY 1 | |
597 } | |
598 } | |
599 | |
600 ifcapable view&&trigger { | |
601 do_malloc_test 25 -sqlprep { | |
602 CREATE TABLE t1(a, b, c); | |
603 CREATE VIEW v1 AS SELECT * FROM t1; | |
604 CREATE TRIGGER v1t1 INSTEAD OF DELETE ON v1 BEGIN SELECT 1; END; | |
605 CREATE TRIGGER v1t2 INSTEAD OF INSERT ON v1 BEGIN SELECT 1; END; | |
606 CREATE TRIGGER v1t3 INSTEAD OF UPDATE ON v1 BEGIN SELECT 1; END; | |
607 } -sqlbody { | |
608 DELETE FROM v1 WHERE a = 1; | |
609 INSERT INTO v1 VALUES(1, 2, 3); | |
610 UPDATE v1 SET a = 1 WHERE b = 2; | |
611 } | |
612 } | |
613 | |
614 do_malloc_test 25 -sqlprep { | |
615 CREATE TABLE abc(a, b, c); | |
616 CREATE INDEX i1 ON abc(a, b); | |
617 INSERT INTO abc VALUES(1, 2, 3); | |
618 INSERT INTO abc VALUES(4, 5, 6); | |
619 } -tclbody { | |
620 # For each UPDATE executed, the cursor used for the SELECT statement | |
621 # must be "saved". Because the cursor is open on an index, this requires | |
622 # a malloc() to allocate space to save the index key. This test case is | |
623 # aimed at testing the response of the library to a failure in that | |
624 # particular malloc() call. | |
625 db eval {SELECT a FROM abc ORDER BY a} { | |
626 db eval {UPDATE abc SET b = b - 1 WHERE a = $a} | |
627 } | |
628 } | |
629 | |
630 # This test is designed to test a specific juncture in the sqlite code. | |
631 # The database set up by -sqlprep script contains a single table B-Tree | |
632 # of height 2. In the -tclbody script, the existing database connection | |
633 # is closed and a new one opened and used to insert a new row into the | |
634 # table B-Tree. By using a new connection, the outcome of a malloc() | |
635 # failure while seeking to the right-hand side of the B-Tree to insert | |
636 # a new record can be tested. | |
637 # | |
638 do_malloc_test 26 -sqlprep { | |
639 BEGIN; | |
640 CREATE TABLE t1(a, b); | |
641 INSERT INTO t1 VALUES(1, randomblob(210)); | |
642 INSERT INTO t1 VALUES(1, randomblob(210)); | |
643 INSERT INTO t1 VALUES(1, randomblob(210)); | |
644 INSERT INTO t1 VALUES(1, randomblob(210)); | |
645 INSERT INTO t1 VALUES(1, randomblob(210)); | |
646 COMMIT; | |
647 } -tclbody { | |
648 db close | |
649 sqlite3 db test.db | |
650 db eval { INSERT INTO t1 VALUES(1, randomblob(210)) } | |
651 } | |
652 | |
653 # Test that no memory is leaked following a malloc() failure in | |
654 # sqlite3_initialize(). | |
655 # | |
656 do_malloc_test 27 -tclprep { | |
657 db close | |
658 sqlite3_shutdown | |
659 } -tclbody { | |
660 set rc [sqlite3_initialize] | |
661 if {$rc == "SQLITE_NOMEM"} { | |
662 error "out of memory" | |
663 } | |
664 } | |
665 autoinstall_test_functions | |
666 | |
667 # Test that malloc failures that occur while processing INDEXED BY | |
668 # clauses are handled correctly. | |
669 do_malloc_test 28 -sqlprep { | |
670 CREATE TABLE t1(a, b); | |
671 CREATE INDEX i1 ON t1(a); | |
672 CREATE VIEW v1 AS SELECT * FROM t1 INDEXED BY i1 WHERE a = 10; | |
673 } -sqlbody { | |
674 SELECT * FROM t1 INDEXED BY i1 ORDER BY a; | |
675 SELECT * FROM v1; | |
676 } | |
677 | |
678 do_malloc_test 29 -sqlprep { | |
679 CREATE TABLE t1(a TEXT, b TEXT); | |
680 } -sqlbody { | |
681 INSERT INTO t1 VALUES(1, -234); | |
682 INSERT INTO t1 SELECT * FROM t1 UNION ALL SELECT * FROM t1; | |
683 } | |
684 | |
685 do_malloc_test 30 -tclprep { | |
686 db eval { | |
687 CREATE TABLE t1(x PRIMARY KEY); | |
688 INSERT INTO t1 VALUES(randstr(500,500)); | |
689 INSERT INTO t1 VALUES(randstr(500,500)); | |
690 INSERT INTO t1 VALUES(randstr(500,500)); | |
691 } | |
692 db close | |
693 sqlite3 db test.db | |
694 | |
695 # The DELETE command in the following block moves the overflow pages that | |
696 # are part of the primary key index to the free-list. But it does not | |
697 # actually load the content of the pages. This leads to the peculiar | |
698 # situation where cache entries exist, but are not populated with data. | |
699 # They are populated next time they are requested by the b-tree layer. | |
700 # | |
701 db eval { | |
702 BEGIN; | |
703 DELETE FROM t1; | |
704 ROLLBACK; | |
705 } | |
706 } -sqlbody { | |
707 -- This statement requires the 'no-content' pages loaded by the DELETE | |
708 -- statement above. When requesting the pages, the content is loaded | |
709 -- from the database file. The point of this test case is to test handling | |
710 -- of malloc errors (including SQLITE_IOERR_NOMEM errors) when loading | |
711 -- the content. | |
712 SELECT * FROM t1 ORDER BY x; | |
713 } | |
714 | |
715 # After committing a transaction in persistent-journal mode, if a journal | |
716 # size limit is configured SQLite may attempt to truncate the journal file. | |
717 # This test verifies the libraries response to a malloc() failure during | |
718 # this operation. | |
719 # | |
720 do_malloc_test 31 -sqlprep { | |
721 PRAGMA journal_mode = persist; | |
722 PRAGMA journal_size_limit = 1024; | |
723 CREATE TABLE t1(a PRIMARY KEY, b); | |
724 } -sqlbody { | |
725 INSERT INTO t1 VALUES(1, 2); | |
726 } | |
727 | |
728 # When written, this test provoked an obscure change-counter bug. | |
729 # | |
730 # If, when running in exclusive mode, a malloc() failure occurs | |
731 # after the database file change-counter has been written but | |
732 # before the transaction has been committed, then the transaction | |
733 # is automatically rolled back. However, internally the | |
734 # Pager.changeCounterDone flag was being left set. This means | |
735 # that if the same connection attempts another transaction following | |
736 # the malloc failure and rollback, the change counter will not | |
737 # be updated. This could corrupt another processes cache. | |
738 # | |
739 do_malloc_test 32 -tclprep { | |
740 # Build a small database containing an indexed table. | |
741 # | |
742 db eval { | |
743 PRAGMA locking_mode = normal; | |
744 BEGIN; | |
745 CREATE TABLE t1(a PRIMARY KEY, b); | |
746 INSERT INTO t1 VALUES(1, 'one'); | |
747 INSERT INTO t1 VALUES(2, 'two'); | |
748 INSERT INTO t1 VALUES(3, 'three'); | |
749 COMMIT; | |
750 PRAGMA locking_mode = exclusive; | |
751 } | |
752 | |
753 # Open a second database connection. Load the table (but not index) | |
754 # into the second connections pager cache. | |
755 # | |
756 sqlite3 db2 test.db | |
757 db2 eval { | |
758 PRAGMA locking_mode = normal; | |
759 SELECT b FROM t1; | |
760 } | |
761 | |
762 } -tclbody { | |
763 # Running in exclusive mode, perform a database transaction that | |
764 # modifies both the database table and index. For iterations where | |
765 # the malloc failure occurs after updating the change counter but | |
766 # before committing the transaction, this should result in the | |
767 # transaction being rolled back but the changeCounterDone flag | |
768 # left set. | |
769 # | |
770 db eval { UPDATE t1 SET a = a + 3 } | |
771 } -cleanup { | |
772 | |
773 # Perform another transaction using the first connection. Unlock | |
774 # the database after doing so. If this is one of the right iterations, | |
775 # then this should result in the database contents being updated but | |
776 # the change-counter left as it is. | |
777 # | |
778 db eval { | |
779 PRAGMA locking_mode = normal; | |
780 UPDATE t1 SET a = a + 3; | |
781 } | |
782 | |
783 # Now do an integrity check with the second connection. The second | |
784 # connection still has the database table in its cache. If this is | |
785 # one of the magic iterations and the change counter was not modified, | |
786 # then it won't realize that the cached data is out of date. Since | |
787 # the cached data won't match the up to date index data read from | |
788 # the database file, the integrity check should fail. | |
789 # | |
790 set zRepeat "transient" | |
791 if {$::iRepeat} {set zRepeat "persistent"} | |
792 do_test malloc-32.$zRepeat.${::n}.integrity { | |
793 execsql {PRAGMA integrity_check} db2 | |
794 } {ok} | |
795 db2 close | |
796 } | |
797 | |
798 # The following two OOM tests verify that OOM handling works in the | |
799 # code used to optimize "SELECT count(*) FROM <tbl>". | |
800 # | |
801 do_malloc_test 33 -tclprep { | |
802 db eval { PRAGMA cache_size = 10 } | |
803 db transaction { | |
804 db eval { CREATE TABLE abc(a, b) } | |
805 for {set i 0} {$i<500} {incr i} { | |
806 db eval {INSERT INTO abc VALUES(randstr(100,100), randstr(1000,1000))} | |
807 } | |
808 } | |
809 } -sqlbody { | |
810 SELECT count(*) FROM abc; | |
811 } | |
812 do_malloc_test 34 -tclprep { | |
813 db eval { PRAGMA cache_size = 10 } | |
814 db transaction { | |
815 db eval { CREATE TABLE abc(a PRIMARY KEY, b) } | |
816 for {set i 0} {$i<500} {incr i} { | |
817 db eval {INSERT INTO abc VALUES(randstr(100,100), randstr(1000,1000))} | |
818 } | |
819 } | |
820 } -sqlbody { | |
821 SELECT count(*) FROM abc; | |
822 } | |
823 | |
824 proc f {args} { error "Quite a long error!" } | |
825 do_malloc_test 35 -tclprep { | |
826 db func f f | |
827 set ::STMT [sqlite3_prepare db "SELECT f()" -1 DUMMY] | |
828 sqlite3_step $::STMT | |
829 } -tclbody { | |
830 sqlite3_finalize $::STMT | |
831 } -cleanup { | |
832 # At one point an assert( !db->mallocFailed ) could fail in the following | |
833 # call to sqlite3_errmsg(). Because sqlite3_finalize() had failed to clear | |
834 # the flag before returning. | |
835 sqlite3_errmsg16 db | |
836 } | |
837 | |
838 do_malloc_test 36 -sqlprep { | |
839 CREATE TABLE t1(a, b); | |
840 INSERT INTO t1 VALUES(1, 2); | |
841 INSERT INTO t1 VALUES(3, 4); | |
842 } -sqlbody { | |
843 SELECT test_agg_errmsg16(), group_concat(a) FROM t1 | |
844 } | |
845 | |
846 # At one point, if an OOM occurred immediately after obtaining a shared lock | |
847 # on the database file, the file remained locked. This test case ensures | |
848 # that bug has been fixed.i | |
849 if {[db eval {PRAGMA locking_mode}]!="exclusive"} { | |
850 do_malloc_test 37 -tclprep { | |
851 sqlite3 db2 test.db | |
852 execsql { | |
853 CREATE TABLE t1(a, b); | |
854 INSERT INTO t1 VALUES(1, 2); | |
855 } db2 | |
856 } -sqlbody { | |
857 SELECT * FROM t1; | |
858 } -cleanup { | |
859 # Try to write to the database using connection [db2]. If connection [db] | |
860 # has correctly released the shared lock, this write attempt should | |
861 # succeed. If [db] has not released the lock, this should hit an | |
862 # SQLITE_BUSY error. | |
863 do_test malloc-36.$zRepeat.${::n}.unlocked { | |
864 execsql {INSERT INTO t1 VALUES(3, 4)} db2 | |
865 } {} | |
866 db2 close | |
867 } | |
868 catch { db2 close } | |
869 } | |
870 | |
871 | |
872 # Test that if an OOM error occurs, aux-data is still correctly destroyed. | |
873 # This test case was causing either a memory-leak or an assert() failure | |
874 # at one point, depending on the configuration. | |
875 # | |
876 do_malloc_test 39 -tclprep { | |
877 sqlite3 db test.db | |
878 } -sqlbody { | |
879 SELECT test_auxdata('abc', 'def'); | |
880 } -cleanup { | |
881 db close | |
882 } | |
883 | |
884 reset_db | |
885 add_test_utf16bin_collate db | |
886 do_execsql_test 40.1 { | |
887 CREATE TABLE t1(a); | |
888 INSERT INTO t1 VALUES('fghij'); | |
889 INSERT INTO t1 VALUES('pqrst'); | |
890 INSERT INTO t1 VALUES('abcde'); | |
891 INSERT INTO t1 VALUES('uvwxy'); | |
892 INSERT INTO t1 VALUES('klmno'); | |
893 } | |
894 do_execsql_test 40.2 { | |
895 SELECT * FROM t1 ORDER BY 1 COLLATE utf16bin; | |
896 } {abcde fghij klmno pqrst uvwxy} | |
897 do_faultsim_test 40.3 -faults oom-trans* -body { | |
898 execsql { | |
899 SELECT * FROM t1 ORDER BY 1 COLLATE utf16bin; | |
900 } | |
901 } -test { | |
902 faultsim_test_result {0 {abcde fghij klmno pqrst uvwxy}} | |
903 faultsim_integrity_check | |
904 } | |
905 | |
906 reset_db | |
907 add_test_utf16bin_collate db | |
908 set big [string repeat x 200] | |
909 do_execsql_test 41.1 { | |
910 DROP TABLE IF EXISTS t1; | |
911 CREATE TABLE t1(a COLLATE utf16bin); | |
912 INSERT INTO t1 VALUES('fghij' || $::big); | |
913 INSERT INTO t1 VALUES('pqrst' || $::big); | |
914 INSERT INTO t1 VALUES('abcde' || $::big); | |
915 INSERT INTO t1 VALUES('uvwxy' || $::big); | |
916 INSERT INTO t1 VALUES('klmno' || $::big); | |
917 CREATE INDEX i1 ON t1(a); | |
918 } | |
919 do_faultsim_test 41.2 -faults oom* -body { | |
920 execsql { SELECT * FROM t1 WHERE a = ('abcde' || $::big)} | |
921 } -test { | |
922 faultsim_test_result [list 0 "abcde$::big"] | |
923 faultsim_integrity_check | |
924 } | |
925 | |
926 # Ensure that no file descriptors were leaked. | |
927 do_test malloc-99.X { | |
928 catch {db close} | |
929 set sqlite_open_file_count | |
930 } {0} | |
931 | |
932 puts open-file-count=$sqlite_open_file_count | |
933 finish_test | |
OLD | NEW |