From: dan Date: Thu, 26 Aug 2010 14:15:37 +0000 (+0000) Subject: Fix a couple of memory leaks in r-tree that can occur following an OOM condition. X-Git-Tag: experimental~113 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=897230eb7ae8307fa51bada2f5d76b74e3227771;p=thirdparty%2Fsqlite.git Fix a couple of memory leaks in r-tree that can occur following an OOM condition. FossilOrigin-Name: 1975a27cdec09e1dad4ca8281a87dd7754c02c3e --- diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 5e11d89266..1e402b8f93 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -2097,6 +2097,7 @@ static int deleteCell(Rtree *, RtreeNode *, int, int); static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){ int rc; + int rc2; RtreeNode *pParent; int iCell; @@ -2106,9 +2107,12 @@ static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){ iCell = nodeParentIndex(pRtree, pNode); pParent = pNode->pParent; pNode->pParent = 0; - if( SQLITE_OK!=(rc = deleteCell(pRtree, pParent, iCell, iHeight+1)) - || SQLITE_OK!=(rc = nodeRelease(pRtree, pParent)) - ){ + rc = deleteCell(pRtree, pParent, iCell, iHeight+1); + rc2 = nodeRelease(pRtree, pParent); + if( rc==SQLITE_OK ){ + rc = rc2; + } + if( rc!=SQLITE_OK ){ return rc; } @@ -2448,12 +2452,15 @@ static int rtreeUpdate( ** in this scenario). */ if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){ + int rc2; RtreeNode *pChild; i64 iChild = nodeGetRowid(pRtree, pRoot, 0); rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); if( rc==SQLITE_OK ){ rc = removeNode(pRtree, pChild, pRtree->iDepth-1); } + rc2 = nodeRelease(pRtree, pChild); + if( rc==SQLITE_OK ) rc = rc2; if( rc==SQLITE_OK ){ pRtree->iDepth--; writeInt16(pRoot->zData, pRtree->iDepth); diff --git a/ext/rtree/rtree1.test b/ext/rtree/rtree1.test index f27cb75801..fe5fa0ae50 100644 --- a/ext/rtree/rtree1.test +++ b/ext/rtree/rtree1.test @@ -13,7 +13,7 @@ # if {![info exists testdir]} { - set testdir [file join [file dirname $argv0] .. .. test] + set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] rtree_util.tcl] source $testdir/tester.tcl diff --git a/ext/rtree/rtree2.test b/ext/rtree/rtree2.test index 4ffa880348..f5d15cc6b9 100644 --- a/ext/rtree/rtree2.test +++ b/ext/rtree/rtree2.test @@ -13,7 +13,7 @@ # if {![info exists testdir]} { - set testdir [file join [file dirname $argv0] .. .. test] + set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] rtree_util.tcl] source $testdir/tester.tcl diff --git a/ext/rtree/rtree3.test b/ext/rtree/rtree3.test index 5761329a6b..a307a1ee5b 100644 --- a/ext/rtree/rtree3.test +++ b/ext/rtree/rtree3.test @@ -14,26 +14,39 @@ # if {![info exists testdir]} { - set testdir [file join [file dirname $argv0] .. .. test] + set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl source $testdir/malloc_common.tcl - ifcapable !rtree { finish_test return } -# Only run these tests if memory debugging is turned on. +# Test summary: +# +# rtree3-1: Test OOM in simple CREATE TABLE, INSERT, DELETE and SELECT +# commands on an almost empty table. +# +# rtree3-2: Test OOM in a DROP TABLE command. +# +# rtree3-3a: Test OOM during a transaction to insert 100 pseudo-random rows. +# +# rtree3-3b: Test OOM during a transaction deleting all entries in the +# database constructed in [rtree3-3a] in pseudo-random order. +# +# rtree3-4a: OOM during "SELECT count(*) FROM ..." on a big table. +# +# rtree3-4b: OOM while deleting rows from a big table. +# +# rtree3-5: Test OOM while inserting rows into a big table. +# +# rtree3-6: Test OOM while deleting all rows of a table, one at a time. +# +# rtree3-7: OOM during an ALTER TABLE RENAME TABLE command. +# +# rtree3-8: Test OOM while registering the r-tree module with sqlite. # -source $testdir/malloc_common.tcl -if {!$MEMDEBUG} { - puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." - finish_test - return -} - -if 1 { do_faultsim_test rtree3-1 -faults oom* -prep { faultsim_delete_and_reopen @@ -96,8 +109,6 @@ do_faultsim_test rtree3-3b -faults oom* -prep { db eval COMMIT } -} - do_test rtree3-4.prep { faultsim_delete_and_reopen execsql { @@ -120,7 +131,7 @@ do_faultsim_test rtree3-4a -faults oom-* -prep { faultsim_test_result {0 1500} } -do_faultsim_test rtree3-4b -faults oom-* -prep { +do_faultsim_test rtree3-4b -faults oom-transient -prep { faultsim_restore_and_reopen } -body { db eval { DELETE FROM rt WHERE ii BETWEEN 1 AND 100 } diff --git a/ext/rtree/rtree4.test b/ext/rtree/rtree4.test index 715473bf02..708d335b06 100644 --- a/ext/rtree/rtree4.test +++ b/ext/rtree/rtree4.test @@ -13,7 +13,7 @@ # if {![info exists testdir]} { - set testdir [file join [file dirname $argv0] .. .. test] + set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl @@ -93,7 +93,7 @@ for {set nDim 1} {$nDim<=5} {incr nDim} { for {set i 1} {$i<$::NROW} {incr i} { # Do a random insert # - do_test rtree-$nDim.2.$i.1 { + do_test rtree4-$nDim.2.$i.1 { set vlist {} for {set j 0} {$j<$nDim} {incr j} { set mn [rand 10000] @@ -113,7 +113,7 @@ for {set nDim 1} {$nDim<=5} {incr nDim} { lappend where mn$j>=$mn mx$j<=$mx } set where "WHERE [join $where { AND }]" - do_test rtree-$nDim.2.$i.2 { + do_test rtree4-$nDim.2.$i.2 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] @@ -126,7 +126,7 @@ for {set nDim 1} {$nDim<=5} {incr nDim} { lappend where mx$j>=$mn mn$j<=$mx } set where "WHERE [join $where { AND }]" - do_test rtree-$nDim.2.$i.3 { + do_test rtree4-$nDim.2.$i.3 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] @@ -143,7 +143,7 @@ for {set nDim 1} {$nDim<=5} {incr nDim} { lappend where mn$j>=$mn mx$j<=$mx } set where "WHERE [join $where { AND }]" - do_test rtree-$nDim.2.$i.3 { + do_test rtree4-$nDim.2.$i.3 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] @@ -160,7 +160,7 @@ for {set nDim 1} {$nDim<=5} {incr nDim} { lappend where mx$j>$mn mn$j<$mx } set where "WHERE [join $where { AND }]" - do_test rtree-$nDim.2.$i.4 { + do_test rtree4-$nDim.2.$i.4 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] @@ -176,7 +176,7 @@ for {set nDim 1} {$nDim<=5} {incr nDim} { lappend where mn$j>=-10000 mx$j<10000 } set where "WHERE [join $where { AND }]" - do_test rtree-$nDim.2.$i.5 { + do_test rtree4-$nDim.2.$i.5 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] @@ -192,7 +192,7 @@ for {set nDim 1} {$nDim<=5} {incr nDim} { lappend where mx$j>-10000 mn$j<=10000 } set where "WHERE [join $where { AND }]" - do_test rtree-$nDim.2.$i.6 { + do_test rtree4-$nDim.2.$i.6 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] @@ -208,7 +208,7 @@ for {set nDim 1} {$nDim<=5} {incr nDim} { lappend where mn$j>=$mn1 mn$j>$mn2 mx$j<$mx1 mx$j<=$mx2 } set where "WHERE [join [scramble $where] { AND }]" - do_test rtree-$nDim.2.$i.7 { + do_test rtree4-$nDim.2.$i.7 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] @@ -224,7 +224,7 @@ for {set nDim 1} {$nDim<=5} {incr nDim} { lappend where mx$j>=$mn1 mx$j>$mn2 mn$j<$mx1 mn$j<=$mx2 } set where "WHERE [join [scramble $where] { AND }]" - do_test rtree-$nDim.2.$i.8 { + do_test rtree4-$nDim.2.$i.8 { list $where [db eval "SELECT id FROM rx $where ORDER BY id"] } [list $where [db eval "SELECT id FROM bx $where ORDER BY id"]] } diff --git a/ext/rtree/rtree5.test b/ext/rtree/rtree5.test index 3620619fc5..ea2946f918 100644 --- a/ext/rtree/rtree5.test +++ b/ext/rtree/rtree5.test @@ -14,7 +14,7 @@ # if {![info exists testdir]} { - set testdir [file join [file dirname $argv0] .. .. test] + set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl diff --git a/ext/rtree/rtree6.test b/ext/rtree/rtree6.test index bab596e015..0a65c15f50 100644 --- a/ext/rtree/rtree6.test +++ b/ext/rtree/rtree6.test @@ -12,7 +12,7 @@ # if {![info exists testdir]} { - set testdir [file join [file dirname $argv0] .. .. test] + set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl diff --git a/ext/rtree/rtree7.test b/ext/rtree/rtree7.test index 5939afda3c..31dae0cd8a 100644 --- a/ext/rtree/rtree7.test +++ b/ext/rtree/rtree7.test @@ -15,7 +15,7 @@ # if {![info exists testdir]} { - set testdir [file join [file dirname $argv0] .. .. test] + set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl diff --git a/ext/rtree/rtree8.test b/ext/rtree/rtree8.test index c3777e8607..9181b9d5f7 100644 --- a/ext/rtree/rtree8.test +++ b/ext/rtree/rtree8.test @@ -12,7 +12,7 @@ # if {![info exists testdir]} { - set testdir [file join [file dirname $argv0] .. .. test] + set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl ifcapable !rtree { finish_test ; return } diff --git a/ext/rtree/tkt3363.test b/ext/rtree/tkt3363.test index f07217141f..db05ed527a 100644 --- a/ext/rtree/tkt3363.test +++ b/ext/rtree/tkt3363.test @@ -13,7 +13,7 @@ # if {![info exists testdir]} { - set testdir [file join [file dirname $argv0] .. .. test] + set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] rtree_util.tcl] source $testdir/tester.tcl diff --git a/manifest b/manifest index 1b2817e948..abb2014d81 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sunreachable\scondition\sfrom\srtree.c. -D 2010-08-26T11:27:23 +C Fix\sa\scouple\sof\smemory\sleaks\sin\sr-tree\sthat\scan\soccur\sfollowing\san\sOOM\scondition. +D 2010-08-26T14:15:38 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 543f91f24cd7fee774ecc0a61c19704c0c3e78fd F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -78,19 +78,19 @@ F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9 F ext/icu/icu.c 850e9a36567bbcce6bd85a4b68243cad8e3c2de2 F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 536070b23d6da289824460a08529f07e638d7c81 +F ext/rtree/rtree.c 2e87d4f44329bfdfb1d074d874b7500e9db83a06 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e -F ext/rtree/rtree1.test 51bb0cd0405970501e63258401ae5ad235a4f468 -F ext/rtree/rtree2.test 47b90f549a59e667e9fb01338956ead6f66c8d9d -F ext/rtree/rtree3.test db7652535e339bbbf5f3909599a088c7daa4be87 -F ext/rtree/rtree4.test 2adce44dc544f6eb570898c8d5270bdf6ca64bd8 -F ext/rtree/rtree5.test 92508f5152a50110af6551fa5b769d1bbd7c4ef3 -F ext/rtree/rtree6.test 903720aaab819764c3693aaac0affe8174104ac8 -F ext/rtree/rtree7.test 6fd29fb8e13795c822f4ceeea92ab5d61c96976d -F ext/rtree/rtree8.test 64b83b163a6997202e11c4226a74e7e52f26e75c +F ext/rtree/rtree1.test dbd4250ac0ad367a262eb9676f7e3080b0368206 +F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba +F ext/rtree/rtree3.test deafc076f639b824466e9f82b39f1601b86dca8e +F ext/rtree/rtree4.test 0061e6f464fd3dc6a79f82454c5a1c3dadbe42af +F ext/rtree/rtree5.test ce3d7ccae2cfd9d2e1052b462424964c9bdcda12 +F ext/rtree/rtree6.test 1ebe0d632a7501cc80ba5a225f028fd4f0fdda08 +F ext/rtree/rtree7.test bcb647b42920b3b5d025846689147778485cc318 +F ext/rtree/rtree8.test e4e291e4cdbc576ac0cfc34c6a75c00b2ee347c3 F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea -F ext/rtree/tkt3363.test 2bf324f7908084a5f463de3109db9c6e607feb1b +F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 @@ -550,7 +550,7 @@ F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806 F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb F test/pcache.test 4118a183908ecaed343a06fcef3ba82e87e0129d F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16 -F test/permutations.test 17498d1219f922d5a6da893a94c4dc7766fb2426 +F test/permutations.test fff338765bb6d9235d385ead4e6d5c9433b6ba05 F test/pragma.test ed78d200f65c6998df51196cb8c39d5300570f24 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea @@ -565,7 +565,7 @@ F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 F test/rollback.test 1a83118ea6db4e7d8c10eaa63871b5e90502ffdc F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81 F test/rowid.test e58e0acef38b527ed1b0b70d3ada588f804af287 -F test/rtree.test dbc0c5113c1d67e5cc44a495d682dda531c83fd4 +F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798 F test/savepoint.test 992d6429b6bce16ac172f7431975044ceaeb0803 F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7 F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec @@ -847,7 +847,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P bee1959dde19ebec20a7ffcb732aee0c8bb2e67d -R 9fb046de4a8191bdd0781857213d3e87 +P 90f40cd36860d3af13ec24575dff7cc1f57ac493 +R a46858ce791434a7e43a1a791bfcb584 U dan -Z 921a91bcff15deea1dac40ed4f714457 +Z 87e2b951218964ab648d9c5a5a463f97 diff --git a/manifest.uuid b/manifest.uuid index 31f9d36ae1..639bbf9da9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -90f40cd36860d3af13ec24575dff7cc1f57ac493 \ No newline at end of file +1975a27cdec09e1dad4ca8281a87dd7754c02c3e \ No newline at end of file diff --git a/test/permutations.test b/test/permutations.test index 086897c468..2c3d0f3737 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -69,6 +69,7 @@ proc test_set {args} { foreach f $a { set t($f) 1 } } else { foreach f $a { array unset t $f } + foreach f $a { array unset t */$f } } } @@ -84,13 +85,17 @@ proc test_set {args} { # set alltests [list] foreach f [glob $testdir/*.test] { lappend alltests [file tail $f] } +foreach f [glob -nocomplain $testdir/../ext/rtree/*.test] { + lappend alltests $f +} + if {$::tcl_platform(platform)!="unix"} { set alltests [test_set $alltests -exclude crash.test crash2.test] } set alltests [test_set $alltests -exclude { all.test async.test quick.test veryquick.test memleak.test permutations.test soak.test fts3.test - mallocAll.test + mallocAll.tes rtree.test }] set allquicktests [test_set $alltests -exclude { @@ -105,7 +110,7 @@ set allquicktests [test_set $alltests -exclude { thread003.test thread004.test thread005.test trans2.test vacuum3.test incrvacuum_ioerr.test autovacuum_crash.test btree8.test shared_err.test vtab_err.test walslow.test walcrash.test - walthread.test + walthread.test rtree3.test }] if {[info exists ::env(QUICKTEST_INCLUDE)]} { set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)] @@ -734,6 +739,11 @@ test_suite "wal" -description { fts3am.test fts3an.test fts3ao.test fts3b.test fts3c.test fts3d.test fts3e.test fts3query.test } + +test_suite "rtree" -description { + All R-tree related tests. Provides coverage of source file rtree.c. +} -files [glob -nocomplain $::testdir/../ext/rtree/*.test] + # End of tests ############################################################################# @@ -759,7 +769,8 @@ proc run_tests {name args} { uplevel $options(-initialize) foreach file [lsort $options(-files)] { - slave_test_file $::testdir/$file + if {[file tail $file] == $file} { set file [file join $::testdir $file] } + slave_test_file $file } uplevel $options(-shutdown) diff --git a/test/rtree.test b/test/rtree.test index cedc6f93dd..b5045746cd 100644 --- a/test/rtree.test +++ b/test/rtree.test @@ -1,3 +1,4 @@ +# 2008 June 23 # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. @@ -6,35 +7,12 @@ #*********************************************************************** # This file runs all rtree related tests. # -# $Id: rtree.test,v 1.3 2009/05/25 14:17:35 drh Exp $ set testdir [file dirname $argv0] -source $testdir/tester.tcl +source $testdir/permutations.test -rename finish_test rtree_finish_test -proc finish_test {} {} - -set RTREE_EXCLUDE { } -if {[info exists G(isquick)] && $G(isquick)} { - set RTREE_EXCLUDE rtree3.test -} -set G(isquick) 1 - -set rtreedir [file join $testdir .. ext rtree] - -foreach testfile [lsort -dictionary [glob -nocomplain $rtreedir/*.test]] { - set tail [file tail $testfile] - if {[lsearch -exact $RTREE_EXCLUDE $tail]>=0} continue - source $testfile - catch {db close} - if {$sqlite_open_file_count>0} { - puts "$tail did not close all files: $sqlite_open_file_count" - fail_test $tail - set sqlite_open_file_count 0 - } +ifcapable rtree { + run_test_suite rtree } -set sqlite_open_file_count 0 -rtree_finish_test -rename finish_test {} -rename rtree_finish_test finish_test +finish_test