Index: src/ctime.c ================================================================== --- src/ctime.c +++ src/ctime.c @@ -152,10 +152,13 @@ #if SQLITE_ENABLE_UNLOCK_NOTIFY "ENABLE_UNLOCK_NOTIFY", #endif #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT "ENABLE_UPDATE_DELETE_LIMIT", +#endif +#if defined(SQLITE_ENABLE_URI_00_ERROR) + "ENABLE_URI_00_ERROR", #endif #if SQLITE_HAS_CODEC "HAS_CODEC", #endif #if HAVE_ISNAN || SQLITE_HAVE_ISNAN Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -2613,10 +2613,11 @@ int octet = (sqlite3HexToInt(zUri[iIn++]) << 4); octet += sqlite3HexToInt(zUri[iIn++]); assert( octet>=0 && octet<256 ); if( octet==0 ){ +#ifndef SQLITE_ENABLE_URI_00_ERROR /* This branch is taken when "%00" appears within the URI. In this ** case we ignore all text in the remainder of the path, name or ** value currently being parsed. So ignore the current character ** and skip to the next "?", "=" or "&", as appropriate. */ while( (c = zUri[iIn])!=0 && c!='#' @@ -2625,10 +2626,16 @@ && (eState!=2 || c!='&') ){ iIn++; } continue; +#else + /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */ + *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri"); + rc = SQLITE_ERROR; + goto parse_uri_out; +#endif } c = octet; }else if( eState==1 && (c=='&' || c=='=') ){ if( zFile[iOut-1]==0 ){ /* An empty option name. Ignore this option altogether. */ Index: src/test_config.c ================================================================== --- src/test_config.c +++ src/test_config.c @@ -711,10 +711,16 @@ #ifdef SQLITE_ENABLE_SQLLOG Tcl_SetVar2(interp, "sqlite_options", "sqllog", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "sqllog", "0", TCL_GLOBAL_ONLY); #endif + +#ifdef SQLITE_ENABLE_URI_00_ERROR + Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "0", TCL_GLOBAL_ONLY); +#endif #define LINKVAR(x) { \ static const int cv_ ## x = SQLITE_ ## x; \ Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \ TCL_LINK_INT | TCL_LINK_READ_ONLY); } Index: test/uri.test ================================================================== --- test/uri.test +++ test/uri.test @@ -52,10 +52,14 @@ 16 file://localhostPWD/test.db%3Fhello test.db?hello } { ifcapable !curdir { if {$tn==3} break } + + ifcapable uri_00_error { + if {[string first %00 $uri]>=0} continue + } if {$tcl_platform(platform)=="windows"} { # # NOTE: Due to limits on legal characters for file names imposed by # Windows, we must skip the final two tests here (i.e. the @@ -121,10 +125,14 @@ 12 file:test.db?&&&&&&&&hello=world&&&&&&& {hello world} 13 test.db?&&&&&&&&hello=world&&&&&&& {} 14 http:test.db?hello&world {} } { + + ifcapable uri_00_error { + if {[string first %00 $uri]>=0} continue + } if {$tcl_platform(platform) == "windows" && $tn>12} { continue } ADDED test/uri2.test Index: test/uri2.test ================================================================== --- /dev/null +++ test/uri2.test @@ -0,0 +1,63 @@ +# 2016 October 26 +# +# 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. +# +#*********************************************************************** +# +# Tests for SQLITE_ENABLE_URI_00_ERROR builds. + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +ifcapable !uri_00_error { + finish_test + return +} + +set testprefix uri2 +db close +sqlite3_shutdown +sqlite3_config_uri 1 + +foreach {tn uri} { + 1 file:test.db%00trailing + 2 file:test.db?%00trailing=1 + 3 file:test.db?trailing=1%00 + 4 file:test.db?trailing=1&abc%00def + 5 file:test.db?trailing=1&abc%00def +} { + do_test 1.$tn.1 { + set rc [catch { sqlite3 db $uri } msg] + list $rc $msg + } {1 {unexpected %00 in uri}} + + do_test 1.$tn.2 { + set DB2 [sqlite3_open $uri] + sqlite3_errcode $DB2 + } {SQLITE_ERROR} + + catch { sqlite3_close $DB2 } + + do_test 1.$tn.2 { + sqlite3 db "" + catchsql { ATTACH $uri AS aux } + } {1 {unexpected %00 in uri}} + + do_test 1.$tn.3 { + sqlite3_errcode db + } {SQLITE_ERROR} + + catch { db close } +} + +reset_db +do_test 2.0 { + expr {[lsearch [execsql {PRAGMA compile_options}] ENABLE_URI_00_ERROR] >= 0} +} 1 + +finish_test