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.53 2007/11/28 22:36:41 drh Exp $ 20 21set testdir [file dirname $argv0] 22source $testdir/tester.tcl 23 24# Only run these tests if memory debugging is turned on. 25# 26ifcapable !memdebug { 27 puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." 28 finish_test 29 return 30} 31 32source $testdir/malloc_common.tcl 33 34ifcapable bloblit&&subquery { 35 do_malloc_test 1 -tclprep { 36 db close 37 } -tclbody { 38 if {[catch {sqlite3 db test.db}]} { 39 error "out of memory" 40 } 41 sqlite3_extended_result_codes db 1 42 } -sqlbody { 43 DROP TABLE IF EXISTS t1; 44 CREATE TABLE t1( 45 a int, b float, c double, d text, e varchar(20), 46 primary key(a,b,c) 47 ); 48 CREATE INDEX i1 ON t1(a,b); 49 INSERT INTO t1 VALUES(1,2.3,4.5,'hi',x'746865726500'); 50 INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder'); 51 SELECT * FROM t1; 52 SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0; 53 DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1); 54 SELECT count(*), group_concat(e) FROM t1; 55 } 56} 57 58# Ensure that no file descriptors were leaked. 59do_test malloc-1.X { 60 catch {db close} 61 set sqlite_open_file_count 62} {0} 63 64ifcapable subquery { 65 do_malloc_test 2 -sqlbody { 66 CREATE TABLE t1(a int, b int default 'abc', c int default 1); 67 CREATE INDEX i1 ON t1(a,b); 68 INSERT INTO t1 VALUES(1,1,'99 abcdefghijklmnopqrstuvwxyz'); 69 INSERT INTO t1 VALUES(2,4,'98 abcdefghijklmnopqrstuvwxyz'); 70 INSERT INTO t1 VALUES(3,9,'97 abcdefghijklmnopqrstuvwxyz'); 71 INSERT INTO t1 VALUES(4,16,'96 abcdefghijklmnopqrstuvwxyz'); 72 INSERT INTO t1 VALUES(5,25,'95 abcdefghijklmnopqrstuvwxyz'); 73 INSERT INTO t1 VALUES(6,36,'94 abcdefghijklmnopqrstuvwxyz'); 74 SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1; 75 UPDATE t1 SET b=b||b||b||b; 76 UPDATE t1 SET b=a WHERE a in (10,12,22); 77 INSERT INTO t1(c,b,a) VALUES(20,10,5); 78 INSERT INTO t1 SELECT * FROM t1 79 WHERE a IN (SELECT a FROM t1 WHERE a<10); 80 DELETE FROM t1 WHERE a>=10; 81 DROP INDEX i1; 82 DELETE FROM t1; 83 } 84} 85 86# Ensure that no file descriptors were leaked. 87do_test malloc-2.X { 88 catch {db close} 89 set sqlite_open_file_count 90} {0} 91 92do_malloc_test 3 -sqlbody { 93 BEGIN TRANSACTION; 94 CREATE TABLE t1(a int, b int, c int); 95 CREATE INDEX i1 ON t1(a,b); 96 INSERT INTO t1 VALUES(1,1,99); 97 INSERT INTO t1 VALUES(2,4,98); 98 INSERT INTO t1 VALUES(3,9,97); 99 INSERT INTO t1 VALUES(4,16,96); 100 INSERT INTO t1 VALUES(5,25,95); 101 INSERT INTO t1 VALUES(6,36,94); 102 INSERT INTO t1(c,b,a) VALUES(20,10,5); 103 DELETE FROM t1 WHERE a>=10; 104 DROP INDEX i1; 105 DELETE FROM t1; 106 ROLLBACK; 107} 108 109 110# Ensure that no file descriptors were leaked. 111do_test malloc-3.X { 112 catch {db close} 113 set sqlite_open_file_count 114} {0} 115 116ifcapable subquery { 117 do_malloc_test 4 -sqlbody { 118 BEGIN TRANSACTION; 119 CREATE TABLE t1(a int, b int, c int); 120 CREATE INDEX i1 ON t1(a,b); 121 INSERT INTO t1 VALUES(1,1,99); 122 INSERT INTO t1 VALUES(2,4,98); 123 INSERT INTO t1 VALUES(3,9,97); 124 INSERT INTO t1 VALUES(4,16,96); 125 INSERT INTO t1 VALUES(5,25,95); 126 INSERT INTO t1 VALUES(6,36,94); 127 UPDATE t1 SET b=a WHERE a in (10,12,22); 128 INSERT INTO t1 SELECT * FROM t1 129 WHERE a IN (SELECT a FROM t1 WHERE a<10); 130 DROP INDEX i1; 131 DELETE FROM t1; 132 COMMIT; 133 } 134} 135 136# Ensure that no file descriptors were leaked. 137do_test malloc-4.X { 138 catch {db close} 139 set sqlite_open_file_count 140} {0} 141 142ifcapable trigger { 143 do_malloc_test 5 -sqlbody { 144 BEGIN TRANSACTION; 145 CREATE TABLE t1(a,b); 146 CREATE TABLE t2(x,y); 147 CREATE TRIGGER r1 AFTER INSERT ON t1 WHEN new.a = 2 BEGIN 148 INSERT INTO t2(x,y) VALUES(new.rowid,1); 149 INSERT INTO t2(x,y) SELECT * FROM t2; 150 INSERT INTO t2 SELECT * FROM t2; 151 UPDATE t2 SET y=y+1 WHERE x=new.rowid; 152 SELECT 123; 153 DELETE FROM t2 WHERE x=new.rowid; 154 END; 155 INSERT INTO t1(a,b) VALUES(2,3); 156 COMMIT; 157 } 158} 159 160# Ensure that no file descriptors were leaked. 161do_test malloc-5.X { 162 catch {db close} 163 set sqlite_open_file_count 164} {0} 165 166ifcapable vacuum { 167 do_malloc_test 6 -sqlprep { 168 BEGIN TRANSACTION; 169 CREATE TABLE t1(a); 170 INSERT INTO t1 VALUES(1); 171 INSERT INTO t1 SELECT a*2 FROM t1; 172 INSERT INTO t1 SELECT a*2 FROM t1; 173 INSERT INTO t1 SELECT a*2 FROM t1; 174 INSERT INTO t1 SELECT a*2 FROM t1; 175 INSERT INTO t1 SELECT a*2 FROM t1; 176 INSERT INTO t1 SELECT a*2 FROM t1; 177 INSERT INTO t1 SELECT a*2 FROM t1; 178 INSERT INTO t1 SELECT a*2 FROM t1; 179 INSERT INTO t1 SELECT a*2 FROM t1; 180 INSERT INTO t1 SELECT a*2 FROM t1; 181 DELETE FROM t1 where rowid%5 = 0; 182 COMMIT; 183 } -sqlbody { 184 VACUUM; 185 } 186} 187 188do_malloc_test 7 -sqlprep { 189 CREATE TABLE t1(a, b); 190 INSERT INTO t1 VALUES(1, 2); 191 INSERT INTO t1 VALUES(3, 4); 192 INSERT INTO t1 VALUES(5, 6); 193 INSERT INTO t1 VALUES(7, randstr(1200,1200)); 194} -sqlbody { 195 SELECT min(a) FROM t1 WHERE a<6 GROUP BY b; 196 SELECT a FROM t1 WHERE a<6 ORDER BY a; 197 SELECT b FROM t1 WHERE a>6; 198} 199 200# This block is designed to test that some malloc failures that may 201# occur in vdbeapi.c. Specifically, if a malloc failure that occurs 202# when converting UTF-16 text to integers and real numbers is handled 203# correctly. 204# 205# This is done by retrieving a string from the database engine and 206# manipulating it using the sqlite3_column_*** APIs. This doesn't 207# actually return an error to the user when a malloc() fails.. That 208# could be viewed as a bug. 209# 210# These tests only run if UTF-16 support is compiled in. 211# 212ifcapable utf16 { 213 set ::STMT {} 214 do_malloc_test 8 -tclprep { 215 set sql "SELECT '[string repeat abc 20]', '[string repeat def 20]', ?" 216 set ::STMT [sqlite3_prepare db $sql -1 X] 217 sqlite3_step $::STMT 218 if { $::tcl_platform(byteOrder)=="littleEndian" } { 219 set ::bomstr "\xFF\xFE" 220 } else { 221 set ::bomstr "\xFE\xFF" 222 } 223 append ::bomstr [encoding convertto unicode "123456789_123456789_12345678"] 224 } -tclbody { 225 sqlite3_column_text16 $::STMT 0 226 sqlite3_column_int $::STMT 0 227 sqlite3_column_text16 $::STMT 1 228 sqlite3_column_double $::STMT 1 229 set rc [sqlite3_reset $::STMT] 230 if {$rc eq "SQLITE_NOMEM"} {error "out of memory"} 231 sqlite3_bind_text16 $::STMT 1 $::bomstr 60 232 #catch {sqlite3_finalize $::STMT} 233 #if {[lindex [sqlite_malloc_stat] 2]<=0} { 234 # error "out of memory" 235 #} 236 } -cleanup { 237 if {$::STMT!=""} { 238 sqlite3_finalize $::STMT 239 set ::STMT {} 240 } 241 } 242} 243 244# This block tests that malloc() failures that occur whilst commiting 245# a multi-file transaction are handled correctly. 246# 247do_malloc_test 9 -sqlprep { 248 ATTACH 'test2.db' as test2; 249 CREATE TABLE abc1(a, b, c); 250 CREATE TABLE test2.abc2(a, b, c); 251} -sqlbody { 252 BEGIN; 253 INSERT INTO abc1 VALUES(1, 2, 3); 254 INSERT INTO abc2 VALUES(1, 2, 3); 255 COMMIT; 256} 257 258# This block tests malloc() failures that occur while opening a 259# connection to a database. 260do_malloc_test 10 -tclprep { 261 catch {db2 close} 262 db close 263 file delete -force test.db test.db-journal 264 sqlite3 db test.db 265 sqlite3_extended_result_codes db 1 266 db eval {CREATE TABLE abc(a, b, c)} 267} -tclbody { 268 db close 269 sqlite3 db2 test.db 270 sqlite3_extended_result_codes db2 1 271 db2 eval {SELECT * FROM sqlite_master} 272 db2 close 273} 274 275# This block tests malloc() failures that occur within calls to 276# sqlite3_create_function(). 277do_malloc_test 11 -tclbody { 278 set rc [sqlite3_create_function db] 279 if {[string match $rc SQLITE_OK]} { 280 set rc [sqlite3_create_aggregate db] 281 } 282 if {[string match $rc SQLITE_NOMEM]} { 283 error "out of memory" 284 } 285} 286 287do_malloc_test 12 -tclbody { 288 set sql16 [encoding convertto unicode "SELECT * FROM sqlite_master"] 289 append sql16 "\00\00" 290 set ::STMT [sqlite3_prepare16 db $sql16 -1 DUMMY] 291 sqlite3_finalize $::STMT 292} 293 294# Test malloc errors when replaying two hot journals from a 2-file 295# transaction. 296ifcapable crashtest&&attach { 297 do_malloc_test 13 -tclprep { 298 set rc [crashsql -delay 1 -file test2.db { 299 ATTACH 'test2.db' as aux; 300 PRAGMA cache_size = 10; 301 BEGIN; 302 CREATE TABLE aux.t2(a, b, c); 303 CREATE TABLE t1(a, b, c); 304 COMMIT; 305 }] 306 if {$rc!="1 {child process exited abnormally}"} { 307 error "Wrong error message: $rc" 308 } 309 } -tclbody { 310 db eval {ATTACH 'test2.db' as aux;} 311 set rc [catch {db eval { 312 SELECT * FROM t1; 313 SELECT * FROM t2; 314 }} err] 315 if {$rc && $err!="no such table: t1"} { 316 error $err 317 } 318 } 319} 320 321if {$tcl_platform(platform)!="windows"} { 322 do_malloc_test 14 -tclprep { 323 catch {db close} 324 sqlite3 db2 test2.db 325 sqlite3_extended_result_codes db2 1 326 db2 eval { 327 PRAGMA synchronous = 0; 328 CREATE TABLE t1(a, b); 329 INSERT INTO t1 VALUES(1, 2); 330 BEGIN; 331 INSERT INTO t1 VALUES(3, 4); 332 } 333 copy_file test2.db test.db 334 copy_file test2.db-journal test.db-journal 335 db2 close 336 } -tclbody { 337 sqlite3 db test.db 338 sqlite3_extended_result_codes db 1 339 db eval { 340 SELECT * FROM t1; 341 } 342 } 343} 344 345proc string_compare {a b} { 346 return [string compare $a $b] 347} 348 349# Test for malloc() failures in sqlite3_create_collation() and 350# sqlite3_create_collation16(). 351# 352ifcapable utf16 { 353 do_malloc_test 15 -start 4 -tclbody { 354 db collate string_compare string_compare 355 if {[catch {add_test_collate db 1 1 1} msg]} { 356 if {$msg=="SQLITE_NOMEM"} {set msg "out of memory"} 357 error $msg 358 } 359 360 db complete {SELECT "hello """||'world"' [microsoft], * FROM anicetable;} 361 db complete {-- Useful comment} 362 363 execsql { 364 CREATE TABLE t1(a, b COLLATE string_compare); 365 INSERT INTO t1 VALUES(10, 'string'); 366 INSERT INTO t1 VALUES(10, 'string2'); 367 } 368 } 369} 370 371# Also test sqlite3_complete(). There are (currently) no malloc() 372# calls in this function, but test anyway against future changes. 373# 374do_malloc_test 16 -tclbody { 375 db complete {SELECT "hello """||'world"' [microsoft], * FROM anicetable;} 376 db complete {-- Useful comment} 377 db eval { 378 SELECT * FROM sqlite_master; 379 } 380} 381 382# Test handling of malloc() failures in sqlite3_open16(). 383# 384ifcapable utf16 { 385 do_malloc_test 17 -tclbody { 386 set DB2 0 387 set STMT 0 388 389 # open database using sqlite3_open16() 390 set filename [encoding convertto unicode test.db] 391 append filename "\x00\x00" 392 set DB2 [sqlite3_open16 $filename -unused] 393 if {0==$DB2} { 394 error "out of memory" 395 } 396 sqlite3_extended_result_codes $DB2 1 397 398 # Prepare statement 399 set rc [catch {sqlite3_prepare $DB2 {SELECT * FROM sqlite_master} -1 X} msg] 400 if {[sqlite3_errcode $DB2] eq "SQLITE_IOERR+12"} { 401 error "out of memory" 402 } 403 if {$rc} { 404 error [string range $msg 4 end] 405 } 406 set STMT $msg 407 408 # Finalize statement 409 set rc [sqlite3_finalize $STMT] 410 if {$rc!="SQLITE_OK"} { 411 error [sqlite3_errmsg $DB2] 412 } 413 set STMT 0 414 415 # Close database 416 set rc [sqlite3_close $DB2] 417 if {$rc!="SQLITE_OK"} { 418 error [sqlite3_errmsg $DB2] 419 } 420 set DB2 0 421 } -cleanup { 422 if {$STMT!="0"} { 423 sqlite3_finalize $STMT 424 } 425 if {$DB2!="0"} { 426 set rc [sqlite3_close $DB2] 427 } 428 } 429} 430 431# Test handling of malloc() failures in sqlite3_errmsg16(). 432# 433ifcapable utf16 { 434 do_malloc_test 18 -tclprep { 435 catch { 436 db eval "SELECT [string repeat longcolumnname 10] FROM sqlite_master" 437 } 438 } -tclbody { 439 set utf16 [sqlite3_errmsg16 [sqlite3_connection_pointer db]] 440 binary scan $utf16 c* bytes 441 if {[llength $bytes]==0} { 442 error "out of memory" 443 } 444 } 445} 446 447# This test is aimed at coverage testing. Specificly, it is supposed to 448# cause a malloc() only used when converting between the two utf-16 449# encodings to fail (i.e. little-endian->big-endian). It only actually 450# hits this malloc() on little-endian hosts. 451# 452set static_string "\x00h\x00e\x00l\x00l\x00o" 453for {set l 0} {$l<10} {incr l} { 454 append static_string $static_string 455} 456append static_string "\x00\x00" 457do_malloc_test 19 -tclprep { 458 execsql { 459 PRAGMA encoding = "UTF16be"; 460 CREATE TABLE abc(a, b, c); 461 } 462} -tclbody { 463 unset -nocomplain ::STMT 464 set r [catch { 465 set ::STMT [sqlite3_prepare db {SELECT ?} -1 DUMMY] 466 sqlite3_bind_text16 -static $::STMT 1 $static_string 112 467 } msg] 468 if {$r} {error [string range $msg 4 end]} 469 set msg 470} -cleanup { 471 if {[info exists ::STMT]} { 472 sqlite3_finalize $::STMT 473 } 474} 475unset static_string 476 477# Make sure SQLITE_NOMEM is reported out on an ATTACH failure even 478# when the malloc failure occurs within the nested parse. 479# 480ifcapable attach { 481 do_malloc_test 20 -tclprep { 482 db close 483 file delete -force test2.db test2.db-journal 484 sqlite3 db test2.db 485 sqlite3_extended_result_codes db 1 486 db eval {CREATE TABLE t1(x);} 487 db close 488 } -tclbody { 489 if {[catch {sqlite3 db test.db}]} { 490 error "out of memory" 491 } 492 sqlite3_extended_result_codes db 1 493 } -sqlbody { 494 ATTACH DATABASE 'test2.db' AS t2; 495 SELECT * FROM t1; 496 DETACH DATABASE t2; 497 } 498} 499 500# Test malloc failure whilst installing a foreign key. 501# 502ifcapable foreignkey { 503 do_malloc_test 21 -sqlbody { 504 CREATE TABLE abc(a, b, c, FOREIGN KEY(a) REFERENCES abc(b)) 505 } 506} 507 508# Test malloc failure in an sqlite3_prepare_v2() call. 509# 510do_malloc_test 22 -tclbody { 511 set ::STMT "" 512 set r [catch { 513 set ::STMT [ 514 sqlite3_prepare_v2 db "SELECT * FROM sqlite_master" -1 DUMMY 515 ] 516 } msg] 517 if {$r} {error [string range $msg 4 end]} 518} -cleanup { 519 if {$::STMT ne ""} { 520 sqlite3_finalize $::STMT 521 set ::STMT "" 522 } 523} 524 525ifcapable {pager_pragmas} { 526 # This tests a special case - that an error that occurs while the pager 527 # is trying to recover from error-state in exclusive-access mode works. 528 # 529 do_malloc_test 23 -tclprep { 530 db eval { 531 PRAGMA cache_size = 10; 532 PRAGMA locking_mode = exclusive; 533 BEGIN; 534 CREATE TABLE abc(a, b, c); 535 CREATE INDEX abc_i ON abc(a, b, c); 536 INSERT INTO abc 537 VALUES(randstr(100,100), randstr(100,100), randstr(100,100)); 538 INSERT INTO abc 539 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; 540 INSERT INTO abc 541 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; 542 INSERT INTO abc 543 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; 544 INSERT INTO abc 545 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; 546 INSERT INTO abc 547 SELECT randstr(100,100), randstr(100,100), randstr(100,100) FROM abc; 548 COMMIT; 549 } 550 551 # This puts the pager into error state. 552 # 553 db eval BEGIN 554 db eval {UPDATE abc SET a = 0 WHERE oid%2} 555 set ::sqlite_io_error_pending 10 556 catch {db eval {ROLLBACK}} msg 557 558 } -sqlbody { 559 SELECT * FROM abc LIMIT 10; 560 } -cleanup { 561 set e [db eval {PRAGMA integrity_check}] 562 if {$e ne "ok"} {error $e} 563 } 564} 565 566# Ensure that no file descriptors were leaked. 567do_test malloc-99.X { 568 catch {db close} 569 set sqlite_open_file_count 570} {0} 571 572puts open-file-count=$sqlite_open_file_count 573finish_test 574