github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/malloc.test (about)

     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" && [atomic_batch_write test.db]==0} {
   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  reset_db
   927  do_execsql_test 42.0 {
   928    CREATE TABLE t1(x INTEGER PRIMARY KEY, y, z);
   929    CREATE TABLE t2(a, b);
   930    CREATE VIEW a002 AS SELECT *, sum(b) AS m FROM t2 GROUP BY a;
   931  }
   932  faultsim_save_and_close
   933  do_faultsim_test 42 -faults oom-tran* -prep {
   934    faultsim_restore_and_reopen
   935    execsql { SELECT * FROM sqlite_master }
   936  } -body {
   937    execsql {
   938      SELECT t1.z, a002.m
   939      FROM t1 JOIN a002 ON t1.y=a002.m
   940      WHERE t1.x IN (1,2,3);
   941    }
   942  } -test {
   943    faultsim_test_result {0 {}}
   944  }
   945  
   946  
   947  # Ensure that no file descriptors were leaked.
   948  do_test malloc-99.X {
   949    catch {db close}
   950    set sqlite_open_file_count
   951  } {0}
   952  
   953  puts open-file-count=$sqlite_open_file_count
   954  finish_test