From 1756ae10e16dd7a7892d9f4be98fef51b7193183 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 15 Apr 2011 16:03:32 +0000 Subject: [PATCH] Add tests and fixes for OOM handling in sqlite3changeset_concat(). FossilOrigin-Name: df0b2d21dcd81679e55b24866f97568019932983 --- ext/session/session5.test | 41 ++++++++++++++++++-------------- ext/session/session_common.tcl | 6 ++++- ext/session/sessionfault.test | 43 ++++++++++++++++++++++++++++++++++ ext/session/sqlite3session.c | 6 ++++- manifest | 18 +++++++------- manifest.uuid | 2 +- 6 files changed, 86 insertions(+), 30 deletions(-) diff --git a/ext/session/session5.test b/ext/session/session5.test index d2761b3218..9cce67dcc1 100644 --- a/ext/session/session5.test +++ b/ext/session/session5.test @@ -31,12 +31,6 @@ set testprefix session5 # session5-3.*: Schema mismatch errors. # -proc changeset_to_list {c} { - set list [list] - sqlite3session_foreach elem $c { lappend list $elem } - lsort $list -} - proc do_concat_test {tn args} { set subtest 0 @@ -191,20 +185,31 @@ do_concat_test 2.1 { UPDATE abc SET a='one point six' WHERE c = 'three'; } +catch {db close} +forcedelete test.db +sqlite3 db test.db +do_concat_test 2.2 { + CREATE TABLE t1(a, b, PRIMARY KEY(b)); + CREATE TABLE t2(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('string', 1); + INSERT INTO t1 VALUES(4, 2); + INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3); +} { + INSERT INTO t2 VALUES('one', 'two'); + INSERT INTO t2 VALUES(1, NULL); + UPDATE t1 SET a = 5 WHERE a = 2; +} { + DELETE FROM t2 WHERE a = 1; + UPDATE t1 SET a = 4 WHERE a = 2; + INSERT INTO t2 VALUES('x', 'y'); +} + #------------------------------------------------------------------------- # Test that schema incompatibilities are detected correctly. # # session5-3.1: Incompatible number of columns. # session5-3.2: Incompatible PK definition. # -proc sql_to_changeset {sql} { - sqlite3session S db main - S attach * - execsql $sql - set c [S changeset] - S delete - return $c -} do_test 3.1 { db close @@ -212,12 +217,12 @@ do_test 3.1 { sqlite3 db test.db execsql { CREATE TABLE t1(a PRIMARY KEY, b) } - set c1 [sql_to_changeset { INSERT INTO t1 VALUES(1, 2) }] + set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }] execsql { DROP TABLE t1; CREATE TABLE t1(a PRIMARY KEY, b, c); } - set c2 [sql_to_changeset { INSERT INTO t1 VALUES(2, 3, 4) }] + set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3, 4) }] list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg } {1 SQLITE_SCHEMA} @@ -228,12 +233,12 @@ do_test 3.2 { sqlite3 db test.db execsql { CREATE TABLE t1(a PRIMARY KEY, b) } - set c1 [sql_to_changeset { INSERT INTO t1 VALUES(1, 2) }] + set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }] execsql { DROP TABLE t1; CREATE TABLE t1(a, b PRIMARY KEY); } - set c2 [sql_to_changeset { INSERT INTO t1 VALUES(2, 3) }] + set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3) }] list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg } {1 SQLITE_SCHEMA} diff --git a/ext/session/session_common.tcl b/ext/session/session_common.tcl index d5c74fba5c..53870c4027 100644 --- a/ext/session/session_common.tcl +++ b/ext/session/session_common.tcl @@ -128,5 +128,9 @@ proc compare_db {db1 db2} { return "" } - +proc changeset_to_list {c} { + set list [list] + sqlite3session_foreach elem $c { lappend list $elem } + lsort $list +} diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index cf155f4f3d..c21d72fb81 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -251,4 +251,47 @@ do_faultsim_test 5 -faults oom* -body { } } +#------------------------------------------------------------------------- +# Test that OOM errors in sqlite3changeset_concat() are handled correctly. +# +catch {db close} +forcedelete test.db +sqlite3 db test.db +do_execsql_test 5.prep1 { + CREATE TABLE t1(a, b, PRIMARY KEY(b)); + CREATE TABLE t2(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('string', 1); + INSERT INTO t1 VALUES(4, 2); + INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3); +} + +do_test 5.prep2 { + sqlite3session M db main + M attach * + set ::c2 [changeset_from_sql { + INSERT INTO t2 VALUES(randomblob(1000), randomblob(1000)); + INSERT INTO t2 VALUES('one', 'two'); + INSERT INTO t2 VALUES(1, NULL); + UPDATE t1 SET a = 5 WHERE a = 2; + }] + set ::c1 [changeset_from_sql { + DELETE FROM t2 WHERE a = 1; + UPDATE t1 SET a = 4 WHERE a = 2; + INSERT INTO t2 VALUES('x', 'y'); + }] + set ::total [changeset_to_list [M changeset]] + M delete +} {} + +do_faultsim_test 6 -faults oom-* -body { + set ::result [sqlite3changeset_concat $::c1 $::c2] + set {} {} +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + if {$testrc==0} { + set v [changeset_to_list $::result] + if {$v != $::total} { error "result no good" } + } +} + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index b37b1b33f7..41665ce9e9 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -2786,6 +2786,7 @@ static int sessionChangeMerge( nByte = sizeof(SessionChange) + pExist->nRecord + nRec; pNew = (SessionChange *)sqlite3_malloc(nByte); if( !pNew ){ + sqlite3_free(pExist); return SQLITE_NOMEM; } memset(pNew, 0, sizeof(SessionChange)); @@ -2886,7 +2887,10 @@ int sessionConcatChangeset( pTab->zName = (char *)zNew; } - if( sessionGrowHash(pTab) ) break; + if( sessionGrowHash(pTab) ){ + rc = SQLITE_NOMEM; + break; + } iHash = sessionChangeHash(pTab, aRec, pTab->nChange); /* Search for existing entry. If found, remove it from the hash table. diff --git a/manifest b/manifest index 8e07b45dbd..b165b9433c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Have\ssqlite3changeset_concat()\sreturn\sSQLITE_SCHEMA\sif\san\sattempt\sis\smade\sto\sconcatenate\schangesets\sbased\son\sincompatible\sdatabase\sschemas. -D 2011-04-15T15:04:31.042 +C Add\stests\sand\sfixes\sfor\sOOM\shandling\sin\ssqlite3changeset_concat(). +D 2011-04-15T16:03:32.057 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -103,10 +103,10 @@ F ext/session/session1.test 7a92a2a6f531aef1e9764ffb7f983fb8b315376d F ext/session/session2.test c3e5f78d5eb988e35cc2ba9ce3678f706283cfdb F ext/session/session3.test bfa2376db7cbb2ac69496f84d93a8d81b13110d3 F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 -F ext/session/session5.test cbb011a1b2f487d2fe4b014fb6ae3a67e5f7f767 -F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28 -F ext/session/sessionfault.test 2544a2e2ecad56e3c07a32c09799871d243c114c -F ext/session/sqlite3session.c b5293510224e42c50d69a509e6bfaca45defec76 +F ext/session/session5.test 940d77c748808769cac50fb62bb674aa84e472f2 +F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 +F ext/session/sessionfault.test 2766cd620f1793f0e54f1e3859a184bcea55bad4 +F ext/session/sqlite3session.c 08573805932a9db4158f36663e01747d0ff69342 F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf F ext/session/test_session.c f4d1dca94db71ec2177ee61eab51e718e58476d7 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -938,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P ada9efa53a6ea55f89d237cfd530f1d180343e19 -R bdb9eba45cd97b77f78325d72d96c5f4 +P 343b64517d244b75097e38342dc273eb5a52915b +R c818789c65113df118a04c3a29f3e5ba U dan -Z 570068f4f013ca36918b632f2a36093d +Z 7081c2709375635b8446c7ef8a86300e diff --git a/manifest.uuid b/manifest.uuid index 6943cc86d4..72289d19b5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -343b64517d244b75097e38342dc273eb5a52915b \ No newline at end of file +df0b2d21dcd81679e55b24866f97568019932983 \ No newline at end of file