/ Check-in [183c236e]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a crash that can follow an OOM when "all tables" are registered with a session module.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1: 183c236e991faaabdc768e52e926c52cf4a7abc9
User & Date: dan 2011-03-22 16:54:12
Context
2011-03-22
18:45
Add API function sqlite3_preupdate_depth(), for determining the depth of the trigger stack from within a pre-update callback. check-in: bdea7089 user: dan tags: sessions
16:54
Fix a crash that can follow an OOM when "all tables" are registered with a session module. check-in: 183c236e user: dan tags: sessions
15:21
If a NULL pointer is passed to sqlite3session_attach() in place of a table name, attach all database tables to the session object. check-in: e9037e4e user: dan tags: sessions
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/session/sessionfault.test.

30
31
32
33
34
35
36




37
38
39
40
41
42
43
44
..
46
47
48
49
50
51
52


























53
54
55
56
57
58
59
faultsim_save_and_close
db2 close


#-------------------------------------------------------------------------
# Test OOM error handling when collecting and applying a simple changeset.
#




do_faultsim_test pagerfault-1 -faults oom-* -prep {
  catch {db2 close}
  catch {db close}
  faultsim_restore_and_reopen
  sqlite3 db2 test.db2
} -body {
  do_then_apply_sql {
    INSERT INTO t1 VALUES(7, 8, 9);
................................................................................
    DELETE FROM t1 WHERE a = 4;
  }
} -test {
  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
  faultsim_integrity_check
  if {$testrc==0} { compare_db db db2 }
}



























#-------------------------------------------------------------------------
# The following block of tests - pagerfault-2.* - are designed to check 
# the handling of faults in the sqlite3changeset_apply() function.
#
catch {db close}
catch {db2 close}







>
>
>
>
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
faultsim_save_and_close
db2 close


#-------------------------------------------------------------------------
# Test OOM error handling when collecting and applying a simple changeset.
#
# Test 1.1 attaches tables individually by name to the session object. 
# Whereas test 1.2 passes NULL to sqlite3session_attach() to attach all
# tables.
#
do_faultsim_test pagerfault-1.1 -faults oom-* -prep {
  catch {db2 close}
  catch {db close}
  faultsim_restore_and_reopen
  sqlite3 db2 test.db2
} -body {
  do_then_apply_sql {
    INSERT INTO t1 VALUES(7, 8, 9);
................................................................................
    DELETE FROM t1 WHERE a = 4;
  }
} -test {
  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
  faultsim_integrity_check
  if {$testrc==0} { compare_db db db2 }
}

do_faultsim_test pagerfault-1.2 -faults oom-* -prep {
  catch {db2 close}
  catch {db close}
  faultsim_restore_and_reopen
} -body {
  sqlite3session S db main
  S attach *
  execsql {
    INSERT INTO t1 VALUES(7, 8, 9);
    UPDATE t1 SET c = 10 WHERE a = 1;
    DELETE FROM t1 WHERE a = 4;
  }
  set ::changeset [S changeset]
  set {} {}
} -test {
  catch { S delete }
  faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
  faultsim_integrity_check
  if {$testrc==0} { 
    proc xConflict {args} { return "OMIT" }
    sqlite3 db2 test.db2
    sqlite3changeset_apply db2 $::changeset xConflict
    compare_db db db2 
  }
}

#-------------------------------------------------------------------------
# The following block of tests - pagerfault-2.* - are designed to check 
# the handling of faults in the sqlite3changeset_apply() function.
#
catch {db close}
catch {db2 close}

Changes to ext/session/sqlite3session.c.

777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
    if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue;

    for(pTab=pSession->pTable; pTab || pSession->bAutoAttach; pTab=pTab->pNext){
      if( !pTab ){
        /* This branch is taken if table zName has not yet been attached to
        ** this session and the auto-attach flag is set.  */
        pSession->rc = sqlite3session_attach(pSession,zName);
        if( pSession->rc ) continue;
        pTab = pSession->pTable;
        assert( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) );
      }

      if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ){
        sessionPreupdateOneChange(op, pSession, pTab);
        if( op==SQLITE_UPDATE ){







|







777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
    if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue;

    for(pTab=pSession->pTable; pTab || pSession->bAutoAttach; pTab=pTab->pNext){
      if( !pTab ){
        /* This branch is taken if table zName has not yet been attached to
        ** this session and the auto-attach flag is set.  */
        pSession->rc = sqlite3session_attach(pSession,zName);
        if( pSession->rc ) break;
        pTab = pSession->pTable;
        assert( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) );
      }

      if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ){
        sessionPreupdateOneChange(op, pSession, pTab);
        if( op==SQLITE_UPDATE ){