Index: src/test1.c ================================================================== --- src/test1.c +++ src/test1.c @@ -6602,10 +6602,64 @@ Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); return TCL_OK; } #endif /* SQLITE_USER_AUTHENTICATION */ +/* +** tclcmd: bad_behavior TYPE +** +** Do some things that should trigger a valgrind or -fsanitize=undefined +** warning. This is used to verify that errors and warnings output by those +** tools are detected by the test scripts. +** +** TYPE BEHAVIOR +** 1 Overflow a signed integer +** 2 Jump based on an uninitialized variable +** 3 Read after free +*/ +static int test_bad_behavior( + ClientData clientData, /* Pointer to an integer containing zero */ + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[] /* Command arguments */ +){ + int iType; + int xyz; + int i = *(int*)clientData; + int j; + int w[10]; + int *a; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "TYPE"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &iType) ) return TCL_ERROR; + switch( iType ){ + case 1: { + xyz = 0x7fffff00 - i; + xyz += 0x100; + Tcl_SetObjResult(interp, Tcl_NewIntObj(xyz)); + break; + } + case 2: { + w[1] = 5; + if( w[i]>0 ) w[1]++; + Tcl_SetObjResult(interp, Tcl_NewIntObj(w[1])); + break; + } + case 3: { + a = malloc( sizeof(int)*10 ); + for(j=0; j<10; j++) a[j] = j; + free(a); + Tcl_SetObjResult(interp, Tcl_NewIntObj(a[i])); + break; + } + } + return TCL_OK; +} + + /* ** Register commands with the TCL interpreter. */ int Sqlitetest1_Init(Tcl_Interp *interp){ extern int sqlite3_search_count; @@ -6618,10 +6672,11 @@ extern int sqlite3_hostid_num; #endif extern int sqlite3_max_blobsize; extern int sqlite3BtreeSharedCacheReport(void*, Tcl_Interp*,int,Tcl_Obj*CONST*); + static int iZero = 0; static struct { char *zName; Tcl_CmdProc *xProc; } aCmd[] = { { "db_enter", (Tcl_CmdProc*)db_enter }, @@ -6670,10 +6725,11 @@ static struct { char *zName; Tcl_ObjCmdProc *xProc; void *clientData; } aObjCmd[] = { + { "bad_behavior", test_bad_behavior, (void*)&iZero }, { "sqlite3_connection_pointer", get_sqlite_pointer, 0 }, { "sqlite3_bind_int", test_bind_int, 0 }, { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 }, { "sqlite3_bind_int64", test_bind_int64, 0 }, { "sqlite3_bind_double", test_bind_double, 0 }, Index: test/main.test ================================================================== --- test/main.test +++ test/main.test @@ -518,7 +518,21 @@ # Print the version number so that it can be picked up by releasetest.tcl. # puts [db one {SELECT 'VERSION: ' || sqlite_version() || ' ' || sqlite_source_id();}] + +# Do deliberate failures if the TEST_FAILURE environment variable is set. +# This is done to verify that failure notifications are detected by the +# releasetest.tcl script, or possibly by other scripts involved in automatic +# testing. +# +if {[info exists ::env(TEST_FAILURE)]} { + set res 123 + if {$::env(TEST_FAILURE)==0} {set res 234} + do_test main-99.1 { + bad_behavior $::env(TEST_FAILURE) + set x 123 + } $res +} finish_test Index: test/permutations.test ================================================================== --- test/permutations.test +++ test/permutations.test @@ -121,10 +121,18 @@ if {[info exists ::env(QUICKTEST_OMIT)]} { foreach x [split $::env(QUICKTEST_OMIT) ,] { regsub -all \\y$x\\y $allquicktests {} allquicktests } } + +# If the TEST_FAILURE environment variable is set, it means that we what to +# deliberately provoke test failures in order to test the test infrastructure. +# Only the main.test module is needed for this. +# +if {[info exists ::env(TEST_FAILURE)]} { + set allquicktests main.test +} ############################################################################# # Start of tests # Index: test/releasetest.tcl ================================================================== --- test/releasetest.tcl +++ test/releasetest.tcl @@ -30,16 +30,11 @@ } array set ::Configs { "Default" { -O2 - --disable-amalgamation - } - "Ftrapv" { - -O2 -ftrapv - -DSQLITE_MAX_ATTACHED=125 - -DSQLITE_TCL_DEFAULT_FULLMUTEX=1 + --disable-amalgamation --disable-shared } "Sanitize" { CC=clang -fsanitize=undefined -DSQLITE_ENABLE_STAT4 } @@ -86,10 +81,11 @@ -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_MEMSYS5=1 -DSQLITE_ENABLE_MEMSYS3=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_ENABLE_STAT4 + -DSQLITE_MAX_ATTACHED=125 } "Device-One" { -O2 -DSQLITE_DEBUG=1 -DSQLITE_DEFAULT_AUTOVACUUM=1 @@ -166,10 +162,13 @@ "Valgrind" { -DSQLITE_ENABLE_STAT4 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE } + Fail0 {-O0} + Fail2 {-O0} + Fail3 {-O0} } array set ::Platforms { Linux-x86_64 { "Check-Symbols" checksymbols @@ -179,11 +178,10 @@ "Update-Delete-Limit" test "Extra-Robustness" test "Device-Two" test "No-lookaside" test "Devkit" test - "Ftrapv" test "Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test} "Valgrind" valgrindtest "Default" "threadtest fulltest" "Device-One" fulltest } @@ -203,10 +201,16 @@ "OS-X" "threadtest fulltest" } "Windows NT-intel" { "Default" "mptest fulltestonly" } + Failure-Detection { + Fail0 "TEST_FAILURE=0 test" + Sanitize "TEST_FAILURE=1 test" + Fail2 "TEST_FAILURE=2 valgrindtest" + Fail3 "TEST_FAILURE=3 valgrindtest" + } } # End of configuration section. #########################################################################