Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a segfault in the sessions module that could follow an OOM. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sessions |
Files: | files | file ages | folders |
SHA1: |
09985fa6b60a0bf38e23bbccd4d8e1d1 |
User & Date: | dan 2014-09-27 18:18:32.969 |
Context
2014-09-27
| ||
19:51 | Merge recent trunk changes (performance enhancements) into the sessions branch. (check-in: 497367cb57 user: drh tags: sessions) | |
18:18 | Fix a segfault in the sessions module that could follow an OOM. (check-in: 09985fa6b6 user: dan tags: sessions) | |
16:33 | Fix a segfault in the streaming API functions triggered by a very long table name. (check-in: d2642543ee user: dan tags: sessions) | |
Changes
Changes to ext/session/session9.test.
︙ | ︙ | |||
196 197 198 199 200 201 202 203 204 205 206 207 208 209 | SELECT * FROM t2; } } {one {value one} {value one} one} do_test 3.3.1 { list [catch {sqlite3changeset_apply db $::ccdel1 conflict_handler} msg] $msg } {1 SQLITE_CONSTRAINT} do_test 3.3.2 { list [catch {sqlite3changeset_apply db $::ccdel2 conflict_handler} msg] $msg } {1 SQLITE_CONSTRAINT} do_test 3.3.4.1 { list [catch {sqlite3changeset_apply db $::ccdel conflict_handler} msg] $msg } {0 {}} | > | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | SELECT * FROM t2; } } {one {value one} {value one} one} do_test 3.3.1 { list [catch {sqlite3changeset_apply db $::ccdel1 conflict_handler} msg] $msg } {1 SQLITE_CONSTRAINT} do_test 3.3.2 { list [catch {sqlite3changeset_apply db $::ccdel2 conflict_handler} msg] $msg } {1 SQLITE_CONSTRAINT} do_test 3.3.4.1 { list [catch {sqlite3changeset_apply db $::ccdel conflict_handler} msg] $msg } {0 {}} |
︙ | ︙ | |||
246 247 248 249 250 251 252 253 254 | } do_catchsql_test 4.3.2 { INSERT INTO c1 VALUES(1, 'x') } {1 {UNIQUE constraint failed: c1.a}} do_catchsql_test 4.3.3 { COMMIT } {0 {}} do_catchsql_test 4.3.4 { BEGIN ; COMMIT } {0 {}} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | } do_catchsql_test 4.3.2 { INSERT INTO c1 VALUES(1, 'x') } {1 {UNIQUE constraint failed: c1.a}} do_catchsql_test 4.3.3 { COMMIT } {0 {}} do_catchsql_test 4.3.4 { BEGIN ; COMMIT } {0 {}} #-------------------------------------------------------------------- # Test that if a DELETE change cannot be applied due to an # SQLITE_CONSTRAINT error thrown by a trigger program, things do not # go awry. drop_all_tables reset_db do_execsql_test 5.1 { CREATE TABLE x1(x PRIMARY KEY, y); CREATE TABLE x2(x PRIMARY KEY, y); INSERT INTO x2 VALUES(1, 1); INSERT INTO x1 VALUES(1, 1); } set ::cc [changeset_from_sql { DELETE FROM x1; }] do_execsql_test 5.2 { INSERT INTO x1 VALUES(1, 1); CREATE TRIGGER tr1 AFTER DELETE ON x1 BEGIN INSERT INTO x2 VALUES(old.x, old.y); END; } {} proc conflict_handler {args} { return "ABORT" } do_test 5.3 { list [catch {sqlite3changeset_apply db $::cc conflict_handler} msg] $msg } {1 SQLITE_ABORT} do_execsql_test 5.4 { SELECT * FROM X1; } {1 1} finish_test |
Changes to ext/session/sessionA.test.
1 2 3 4 5 6 7 8 9 10 11 | # 2013 July 04 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # | | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # 2013 July 04 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # This file tests that filter callbacks work as required. # if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl |
︙ | ︙ | |||
59 60 61 62 63 64 65 | execsql { SELECT * FROM t1; SELECT * FROM t2; SELECT * FROM t3; } db2 } {a b e f} | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | execsql { SELECT * FROM t1; SELECT * FROM t2; SELECT * FROM t3; } db2 } {a b e f} #------------------------------------------------------------------------- # Test that filter callbacks passed to sqlite3changeset_apply() are # invoked correctly. # reset_db do_execsql_test 3.1 { CREATE TABLE t1(a PRIMARY KEY, b); CREATE TABLE t2(x PRIMARY KEY, y); } do_test 3.2 { execsql BEGIN set ::cs [changeset_from_sql { INSERT INTO t1 VALUES(1, 2); INSERT INTO t2 VALUES('x', 'y'); }] execsql ROLLBACK set {} {} } {} proc filter {x y} { return [string equal $x $y] } do_test 3.3 { sqlite3changeset_apply db $::cs {} [list filter t1] execsql { SELECT * FROM t1; SELECT * FROM t2; } } {1 2} do_test 3.4 { execsql { DELETE FROM t1 } sqlite3changeset_apply db $::cs {} [list filter t2] execsql { SELECT * FROM t1; SELECT * FROM t2; } } {x y} finish_test |
Changes to ext/session/sessionfault.test.
︙ | ︙ | |||
280 281 282 283 284 285 286 287 288 289 290 291 292 293 | foreach c " {UPDATE t2 0 X. {i 1 t $::abc} {{} {} t abc}} {UPDATE t2 0 X. {i 2 t $::def} {{} {} t def}} " { lappend y $c } if {$x != $y} { error "changeset no good" } } } #------------------------------------------------------------------------- # Test that OOM errors in sqlite3changeset_concat() are handled correctly. # catch {db close} forcedelete test.db sqlite3 db test.db | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | foreach c " {UPDATE t2 0 X. {i 1 t $::abc} {{} {} t abc}} {UPDATE t2 0 X. {i 2 t $::def} {{} {} t def}} " { lappend y $c } if {$x != $y} { error "changeset no good" } } } catch {db close} catch {db2 close} forcedelete test.db sqlite3 db test.db set abc [string repeat abc 256] set def [string repeat def 256] execsql " CREATE TABLE t2(a PRIMARY KEY, b); INSERT INTO t2 VALUES(1, '$abc'); " set changeset [changeset_from_sql " INSERT INTO t2 VALUES(2, '$def'); DELETE FROM t2 WHERE a = 1; "] db close do_faultsim_test 5.3 -faults oom-tra* -body { set ::inverse [sqlite3changeset_invert $::changeset] set {} {} } -test { faultsim_test_result {0 {}} {1 SQLITE_NOMEM} if {$testrc==0} { set x [list] sqlite3session_foreach c $::inverse { lappend x $c } foreach c " {INSERT t2 0 X. {} {i 1 t $::abc}} {DELETE t2 0 X. {i 2 t $::def} {}} " { lappend y $c } if {$x != $y} { error "changeset no good" } } } #------------------------------------------------------------------------- # Test that OOM errors in sqlite3changeset_concat() are handled correctly. # catch {db close} forcedelete test.db sqlite3 db test.db |
︙ | ︙ | |||
511 512 513 514 515 516 517 | if {$testrc==0} { if {[db one {SELECT b=$bigstr||'x' FROM t1}]==0} { error "data does not look right" } } } | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 | if {$testrc==0} { if {[db one {SELECT b=$bigstr||'x' FROM t1}]==0} { error "data does not look right" } } } #------------------------------------------------------------------------- # Test an OOM with an sqlite3changeset_apply() filter callback. # reset_db do_test 11.prep { execsql { CREATE TABLE t1(a PRIMARY KEY, b); CREATE TABLE t2(x PRIMARY KEY, y); BEGIN; } set ::cs [changeset_from_sql { INSERT INTO t1 VALUES(1, 2); INSERT INTO t2 VALUES('x', 'y'); }] execsql ROLLBACK set {} {} } {} proc filter {x} { return [string equal t1 $x] } faultsim_save_and_close do_faultsim_test 11 -faults oom-tra* -prep { faultsim_restore_and_reopen } -body { sqlite3changeset_apply db $::cs {} filter } -test { faultsim_test_result {0 {}} {1 SQLITE_NOMEM} if {$testrc==0} { if {[db eval {SELECT * FROM t1 UNION ALL SELECT * FROM t2}] != "1 2"} { error "data does not look right" } } } finish_test |
Changes to ext/session/sqlite3session.c.
︙ | ︙ | |||
3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 | /* If an xFilter() callback was specified, invoke it now. If the ** xFilter callback returns zero, skip this table. If it returns ** non-zero, proceed. */ schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew))); if( schemaMismatch ){ zTab = sqlite3_mprintf("%s", zNew); nTab = (int)strlen(zTab); sApply.azCol = (const char **)zTab; }else{ sqlite3changeset_pk(pIter, &abPK, 0); rc = sessionTableInfo( db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK ); | > > > > | 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 | /* If an xFilter() callback was specified, invoke it now. If the ** xFilter callback returns zero, skip this table. If it returns ** non-zero, proceed. */ schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew))); if( schemaMismatch ){ zTab = sqlite3_mprintf("%s", zNew); if( zTab==0 ){ rc = SQLITE_NOMEM; break; } nTab = (int)strlen(zTab); sApply.azCol = (const char **)zTab; }else{ sqlite3changeset_pk(pIter, &abPK, 0); rc = sessionTableInfo( db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK ); |
︙ | ︙ |