From 158e5ca75909b721c1967059fa811067ad232b58 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Wed, 11 Feb 2004 13:03:58 +0000 Subject: [PATCH] Specia:Asksql security fix, Special:Asksql query timeout feature --- includes/Database.php | 18 +++++++++++++++++- includes/DefaultSettings.php | 1 + includes/OutputPage.php | 8 ++++---- includes/SpecialAsksql.php | 19 ++++++++++++------- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/includes/Database.php b/includes/Database.php index 60069171af..3d24642256 100644 --- a/includes/Database.php +++ b/includes/Database.php @@ -173,7 +173,8 @@ class Database { } else { wfDebug("SQL ERROR: " . mysql_error( $this->mConn ) . "\n"); if ( $this->mOut ) { - $this->mOut->databaseError( $fname ); // calls wfAbruptExit() + // this calls wfAbruptExit() + $this->mOut->databaseError( $fname, $this ); } } } @@ -385,6 +386,21 @@ class Database { $this->mDatabase = $db; mysql_select_db( $db, $this->mConn ); } + + function startTimer( $timeout ) + { + $thisdir = dirname( getenv( "SCRIPT_FILENAME" ) ); + $tid = mysql_thread_id( $this->mConn ); + $this->mTimerProc = popen( "php $thisdir/killthread.php $timeout $tid &", "w" ); + } + + function stopTimer() + { + if ( $this->mTimerProc ) { + pclose( $this->mTimerProc ); + } + } + } #------------------------------------------------------------------------------ diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 52664664a7..45b862a769 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -40,6 +40,7 @@ $wgDBsqlpassword = "sqlpass"; $wgDBminWordLen = 4; $wgDBtransactions = false; # Set to true if using InnoDB tables $wgDBmysql4 = false; # Set to true to use enhanced fulltext search +$wgSqlTimeout = 30; # Database load balancer $wgDBservers = false; # e.g. array("larousse", "pliny") diff --git a/includes/OutputPage.php b/includes/OutputPage.php index ac7d6575a8..998489e73d 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -465,7 +465,7 @@ class OutputPage { $this->returnToMain(); } - function databaseError( $fname ) + function databaseError( $fname, &$conn ) { global $wgUser, $wgCommandLineMode; @@ -479,10 +479,10 @@ class OutputPage { $msg = wfMsgNoDB( "dberrortext" ); } - $msg = str_replace( "$1", htmlspecialchars( wfLastDBquery() ), $msg ); + $msg = str_replace( "$1", htmlspecialchars( $conn->lastQuery() ), $msg ); $msg = str_replace( "$2", htmlspecialchars( $fname ), $msg ); - $msg = str_replace( "$3", wfLastErrno(), $msg ); - $msg = str_replace( "$4", htmlspecialchars( wfLastError() ), $msg ); + $msg = str_replace( "$3", $conn->lastErrno(), $msg ); + $msg = str_replace( "$4", htmlspecialchars( $conn->lastError() ), $msg ); if ( $wgCommandLineMode || !is_object( $wgUser )) { print "$msg\n"; diff --git a/includes/SpecialAsksql.php b/includes/SpecialAsksql.php index 2cc45bc91e..8b8d4acc53 100644 --- a/includes/SpecialAsksql.php +++ b/includes/SpecialAsksql.php @@ -60,7 +60,7 @@ class SqlQueryForm { { global $wgOut, $wgUser, $wgServer, $wgScript, $wgArticlePath, $wgLang; global $wpSqlQuery; - global $wgDBsqluser, $wgDBsqlpassword; + global $wgDBserver, $wgDBsqluser, $wgDBsqlpassword, $wgDBname, $wgSqlTimeout; # Use a limit, folks! $wpSqlQuery = trim( $wpSqlQuery ); @@ -68,19 +68,24 @@ class SqlQueryForm { and !preg_match( "/LIMIT/i", $wpSqlQuery ) ) { $wpSqlQuery .= " LIMIT 100"; } - $connection = wfGetDB( $wgDBsqluser, $wgDBsqlpassword ); + $conn = Database::newFromParams( $wgDBserver, $wgDBsqluser, $wgDBsqlpassword, $wgDBname ); + $this->logQuery( $wpSqlQuery ); - $res = wfQuery( $wpSqlQuery, DB_WRITE, "SpecialAsksql::doSubmit" ); + + # Start timer, will kill the DB thread in $wgSqlTimeout seconds + $conn->startTimer( $wgSqlTimeout ); + $res = $conn->query( $wpSqlQuery, "SpecialAsksql::doSubmit" ); + $conn->stopTimer(); $this->logFinishedQuery(); $n = 0; - @$n = wfNumFields( $res ); + @$n = $conn->numFields( $res ); $titleList = false; if ( $n ) { $k = array(); for ( $x = 0; $x < $n; ++$x ) { - array_push( $k, wfFieldName( $res, $x ) ); + array_push( $k, $conn->fieldName( $res, $x ) ); } if ( $n == 2 && in_array( "cur_title", $k ) && in_array( "cur_namespace", $k ) ) { @@ -88,10 +93,10 @@ class SqlQueryForm { } $a = array(); - while ( $s = wfFetchObject( $res ) ) { + while ( $s = $conn->fetchObject( $res ) ) { array_push( $a, $s ); } - wfFreeResult( $res ); + $conn->freeResult( $res ); if ( $titleList ) { $r = ""; -- 2.20.1