diff options
author | Isaac Bennetch <bennetch@gmail.com> | 2016-11-24 19:03:58 +0300 |
---|---|---|
committer | Isaac Bennetch <bennetch@gmail.com> | 2016-11-24 19:03:58 +0300 |
commit | 253894e2995ae4175f4429bf5cdaedfb6a722988 (patch) | |
tree | 7fbb8780941acfa4ad44e1a355ece5a96ac319e7 | |
parent | 637d55bb4459ffceae9a5d0be36ab022ac583e10 (diff) | |
parent | 5daee71272efd87a24fe58f90303e82a5b6caf6d (diff) |
Resolve merge conflicts with ChangeLogRELEASE_4_6_5
Signed-off-by: Isaac Bennetch <bennetch@gmail.com>
30 files changed, 197 insertions, 79 deletions
@@ -1,7 +1,7 @@ phpMyAdmin - ChangeLog ====================== -4.6.5 (not yet released) +4.6.5 (2016-11-24) - issue Remove potentionally license problematic sRGB profile - issue #12459 Display read only fields as read only when editing - issue #12384 Fix expanding of navigation pane when clicking on database @@ -93,6 +93,20 @@ phpMyAdmin - ChangeLog - issue #12361 Fix self SQL injection in table-specific privileges - issue #12698 Add link to release notes and download on new version notification - issue #12712 Error when trying to setup replication (fatal error in call to an old PMA_DBI_connect function) +- issue [security] Unsafe generation of $cfg['blowfish_secret'], see PMASA-2016-58 +- issue [security] phpMyAdmin's phpinfo functionality is removed, see PMASA-2016-59 +- issue [security] AllowRoot and allow/deny rule bypass with specially-crafted username, see PMASA-2016-60 +- issue [security] Username matching weaknesses with allow/deny rules, see PMASA-2016-61 +- issue [security] Possible to bypass logout timeout, see PMASA-2016-62 +- issue [security] Full path disclosure (FPD) weaknesses, see PMASA-2016-63 +- issue [security] Multiple XSS weaknesses, see PMASA-2016-64 +- issue [security] Multiple denial-of-service (DOS) vulnerabilities, see PMASA-2016-65 +- issue [security] Possible to bypass white-list protection for URL redirection, see PMASA-2016-66 +- issue [security] BBCode injection to login page, see PMASA-2016-67 +- issue [security] Denial-of-service (DOS) vulnerability in table partitioning, see PMASA-2016-68 +- issue [security] Multiple SQL injection vulnerabilities, see PMASA-2016-69 +- issue [security] Incorrect serialized string parsing, see PMASA-2016-70 +- issue [security] CSRF token not stripped from the URL, see PMASA-2016-71 4.6.4 (2016-08-16) - issue [security] Weaknesses with cookie encryption, see PMASA-2016-29 @@ -1,7 +1,7 @@ phpMyAdmin - Readme =================== -Version 4.6.5-dev +Version 4.6.5 A web interface for MySQL and MariaDB. diff --git a/doc/conf.py b/doc/conf.py index e87f80a90c..48317aeb16 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -51,7 +51,7 @@ copyright = u'2012 - 2016, The phpMyAdmin devel team' # built documents. # # The short X.Y version. -version = '4.6.5-dev' +version = '4.6.5' # The full version, including alpha/beta/rc tags. release = version diff --git a/import.php b/import.php index b6db86fc00..9f41389712 100644 --- a/import.php +++ b/import.php @@ -616,8 +616,8 @@ if ($GLOBALS['PMA_recoding_engine'] != PMA_CHARSET_NONE && isset($charset_of_fil // Something to skip? (because timeout has passed) if (! $error && isset($_POST['skip'])) { - $original_skip = $skip = $_POST['skip']; - while ($skip > 0) { + $original_skip = $skip = intval($_POST['skip']); + while ($skip > 0 && ! $finished) { PMA_importGetNextChunk($skip < $read_limit ? $skip : $read_limit); // Disable read progressivity, otherwise we eat all memory! $read_multiply = 1; @@ -389,7 +389,7 @@ PMA_printListItem( PMA_printListItem( __('Official Homepage'), 'li_pma_homepage', - PMA_linkURL('https://www.phpMyAdmin.net/'), + PMA_linkURL('https://www.phpmyadmin.net/'), null, '_blank' ); diff --git a/js/config.js b/js/config.js index d3d0c5f840..7a0f4bf53f 100644 --- a/js/config.js +++ b/js/config.js @@ -625,9 +625,9 @@ AJAX.registerOnload('config.js', function () { var tab_check_fnc = function () { if (location.hash != prev_hash) { prev_hash = location.hash; - if (location.hash.match(/^#tab_[a-zA-Z0-9_]+/)) { + if (prev_hash.match(/^#tab_[a-zA-Z0-9_]+$/)) { // session ID is sometimes appended here - var hash = location.hash.substr(5).split('&')[0]; + var hash = prev_hash.substr(5).split('&')[0]; if ($('#' + hash).length) { setTab(hash); } diff --git a/js/microhistory.js b/js/microhistory.js index 60bb207147..4263cd0eef 100644 --- a/js/microhistory.js +++ b/js/microhistory.js @@ -280,15 +280,16 @@ PMA_SetUrlHash = (function (jQuery, window) { /** * Start initialisation */ - if (window.location.hash.substring(0, 8) == '#PMAURL-') { + var urlhash = window.location.hash; + if (urlhash.substring(0, 8) == '#PMAURL-') { // We have a valid hash, let's redirect the user // to the page that it's pointing to - var colon_position = window.location.hash.indexOf(':'); - var questionmark_position = window.location.hash.indexOf('?'); + var colon_position = urlhash.indexOf(':'); + var questionmark_position = urlhash.indexOf('?'); if (colon_position != -1 && questionmark_position != -1 && colon_position < questionmark_position) { - var hash_url = window.location.hash.substring(colon_position + 1, questionmark_position); + var hash_url = urlhash.substring(colon_position + 1, questionmark_position); if (PMA_gotoWhitelist.indexOf(hash_url) != -1) { - window.location = window.location.hash.substring( + window.location = urlhash.substring( colon_position + 1 ); } @@ -328,4 +329,4 @@ PMA_SetUrlHash = (function (jQuery, window) { * Publicly exposes a reference to the otherwise private setUrlHash function */ return setUrlHash; -})(jQuery, window);
\ No newline at end of file +})(jQuery, window); diff --git a/libraries/Config.php b/libraries/Config.php index b3dce0e5e7..d5b6a386ab 100644 --- a/libraries/Config.php +++ b/libraries/Config.php @@ -101,7 +101,7 @@ class Config */ public function checkSystem() { - $this->set('PMA_VERSION', '4.6.5-dev'); + $this->set('PMA_VERSION', '4.6.5'); /** * @deprecated */ diff --git a/libraries/DbQbe.php b/libraries/DbQbe.php index d9d1f3ca21..08eb4cc520 100644 --- a/libraries/DbQbe.php +++ b/libraries/DbQbe.php @@ -1940,7 +1940,10 @@ class DbQbe // sets row count $rows = PMA_ifSetOr($_REQUEST['rows'], 0, 'numeric'); $criteriaRowAdd = PMA_ifSetOr($_REQUEST['criteriaRowAdd'], 0, 'numeric'); - $this->_criteria_row_count = max($rows + $criteriaRowAdd, 0); + $this->_criteria_row_count = min( + 100, + max($rows + $criteriaRowAdd, 0) + ); return $criteriaColumnCount; } diff --git a/libraries/Error.php b/libraries/Error.php index b45afef75a..7a0083864e 100644 --- a/libraries/Error.php +++ b/libraries/Error.php @@ -478,7 +478,7 @@ class Error extends Message /* Probably affected by open_basedir */ if ($dest === FALSE) { - return $path; + return basename($path); } $Ahere = explode( diff --git a/libraries/ErrorHandler.php b/libraries/ErrorHandler.php index 0e96f8e026..b3e6cf4ea0 100644 --- a/libraries/ErrorHandler.php +++ b/libraries/ErrorHandler.php @@ -193,16 +193,19 @@ class ErrorHandler $this->errors[$error->getHash()] = $error; switch ($error->getNumber()) { - case E_USER_NOTICE: - case E_USER_WARNING: case E_STRICT: case E_DEPRECATED: case E_NOTICE: case E_WARNING: case E_CORE_WARNING: case E_COMPILE_WARNING: - case E_USER_ERROR: case E_RECOVERABLE_ERROR: + /* Avoid rendering BB code in PHP errors */ + $error->setBBCode(false); + break; + case E_USER_NOTICE: + case E_USER_WARNING: + case E_USER_ERROR: // just collect the error // display is called from outside break; diff --git a/libraries/Message.php b/libraries/Message.php index 1b500aff39..fefd50ff44 100644 --- a/libraries/Message.php +++ b/libraries/Message.php @@ -113,6 +113,14 @@ class Message protected $isDisplayed = false; /** + * Whether to use BB code when displaying. + * + * @access protected + * @var boolean + */ + protected $useBBCode = true; + + /** * Unique id * * @access protected @@ -236,6 +244,7 @@ class Message { $r = new Message('', $type); $r->setMessage($message); + $r->setBBCode(false); return $r; } @@ -393,6 +402,18 @@ class Message } /** + * Set whether we should use BB Code when rendering. + * + * @param boolean $useBBCode Use BB Code? + * + * @return void + */ + public function setBBCode($useBBCode) + { + $this->useBBCode = $useBBCode; + } + + /** * set raw message (overrides string) * * @param string $message A localized string @@ -647,7 +668,9 @@ class Message $message = Message::format($message, $this->getParams()); } - $message = Message::decodeBB($message); + if ($this->useBBCode) { + $message = Message::decodeBB($message); + } foreach ($this->getAddedMessages() as $add_message) { $message .= $add_message; diff --git a/libraries/SavedSearches.php b/libraries/SavedSearches.php index db80ff75d0..9cd652afaa 100644 --- a/libraries/SavedSearches.php +++ b/libraries/SavedSearches.php @@ -160,6 +160,16 @@ class SavedSearches } } + /* Limit amount of rows */ + if (!isset($data['rows'])) { + $data['rows'] = 0; + } else { + $data['rows'] = min( + max(0, intval($data['rows'])), + 100 + ); + } + for ($i = 0; $i <= $data['rows']; $i++) { $data['Or' . $i] = $criterias['Or' . $i]; } diff --git a/libraries/Tracker.php b/libraries/Tracker.php index 8132503bfa..06b77d03b9 100644 --- a/libraries/Tracker.php +++ b/libraries/Tracker.php @@ -144,8 +144,9 @@ class Tracker static public function getLogComment() { $date = date('Y-m-d H:i:s'); + $user = preg_replace('/\s+/', ' ', $GLOBALS['cfg']['Server']['user']); - return "# log " . $date . " " . $GLOBALS['cfg']['Server']['user'] . "\n"; + return "# log " . $date . " " . $user . "\n"; } /** diff --git a/libraries/VersionInformation.php b/libraries/VersionInformation.php index dcfa362991..f256ef70ce 100644 --- a/libraries/VersionInformation.php +++ b/libraries/VersionInformation.php @@ -72,7 +72,7 @@ class VersionInformation CURLOPT_TIMEOUT, $connection_timeout ); - $response = curl_exec($curl_handle); + $response = @curl_exec($curl_handle); } else if (ini_get('allow_url_fopen')) { $context = array( 'http' => array( @@ -81,12 +81,16 @@ class VersionInformation ) ); $context = Util::handleContext($context); - $response = file_get_contents( + $response = @file_get_contents( $file, false, stream_context_create($context) ); } + // Check possible failure of getting data + if ($response === false) { + $response = '{}'; + } } /* Parse response */ diff --git a/libraries/core.lib.php b/libraries/core.lib.php index ffb0540293..cb7161d281 100644 --- a/libraries/core.lib.php +++ b/libraries/core.lib.php @@ -754,10 +754,17 @@ function PMA_linkURL($url) function PMA_isAllowedDomain($url) { $arr = parse_url($url); - // Avoid URLs without hostname or with credentials - if (empty($arr['host']) || ! empty($arr['user']) || ! empty($arr['pass'])) { + // We need host to be set + if (! isset($arr['host']) || strlen($arr['host']) == 0) { return false; } + // We do not want these to be present + $blocked = array('user', 'pass', 'port'); + foreach ($blocked as $part) { + if (isset($arr[$part]) && strlen($arr[$part]) != 0) { + return false; + } + } $domain = $arr["host"]; $domainWhiteList = array( /* Include current domain */ @@ -766,6 +773,7 @@ function PMA_isAllowedDomain($url) 'wiki.phpmyadmin.net', 'www.phpmyadmin.net', 'phpmyadmin.net', 'demo.phpmyadmin.net', 'docs.phpmyadmin.net', + 'demo.phpmyadmin.net', /* mysql.com domains */ 'dev.mysql.com','bugs.mysql.com', /* mariadb domains */ @@ -781,7 +789,7 @@ function PMA_isAllowedDomain($url) /* Following are doubtful ones. */ 'mysqldatabaseadministration.blogspot.com', ); - if (in_array(mb_strtolower($domain), $domainWhiteList)) { + if (in_array($domain, $domainWhiteList)) { return true; } @@ -1014,7 +1022,7 @@ if (! function_exists('hash_hmac')) { /** * Sanitizes MySQL hostname * - * * strips p: prefix + * * strips p: prefix(es) * * @param string $name User given hostname * @@ -1022,14 +1030,32 @@ if (! function_exists('hash_hmac')) { */ function PMA_sanitizeMySQLHost($name) { - if (strtolower(substr($name, 0, 2)) == 'p:') { - return substr($name, 2); + while (strtolower(substr($name, 0, 2)) == 'p:') { + $name = substr($name, 2); } return $name; } /** + * Sanitizes MySQL username + * + * * strips part behind null byte + * + * @param string $name User given username + * + * @return string + */ +function PMA_sanitizeMySQLUser($name) +{ + $position = strpos($name, chr(0)); + if ($position !== false) { + return substr($name, 0, $position); + } + return $name; +} + +/** * Safe unserializer wrapper * * It does not unserialize data containing objects @@ -1062,7 +1088,7 @@ function PMA_safeUnserialize($data) case 's': /* string */ // parse sting length - $strlen = intval($data[$i + 2]); + $strlen = intval(substr($data, $i + 2)); // string start $i = strpos($data, ':', $i + 2); if ($i === false) { diff --git a/libraries/export.lib.php b/libraries/export.lib.php index d8b3fa1bda..7a21795027 100644 --- a/libraries/export.lib.php +++ b/libraries/export.lib.php @@ -18,12 +18,10 @@ use PMA\libraries\ZipFile; */ function PMA_shutdownDuringExport() { - $a = error_get_last(); - if ($a != null && mb_strpos($a['message'], "execution time")) { - //write in partially downloaded file for future reference of user - print_r($a); + $error = error_get_last(); + if ($error != null && mb_strpos($error['message'], "execution time")) { //set session variable to check if there was error while exporting - $_SESSION['pma_export_error'] = $a['message']; + $_SESSION['pma_export_error'] = $error['message']; } } diff --git a/libraries/ip_allow_deny.lib.php b/libraries/ip_allow_deny.lib.php index bd7c84757b..cc74c16b7c 100644 --- a/libraries/ip_allow_deny.lib.php +++ b/libraries/ip_allow_deny.lib.php @@ -194,7 +194,7 @@ function PMA_ipv6MaskTest($test_range, $ip_to_test) if ($is_single) { $range_hex = bin2hex(inet_pton($test_range)); - $result = $ip_hex === $range_hex; + $result = hash_equals($ip_hex, $range_hex); return $result; } @@ -321,7 +321,7 @@ function PMA_allowDeny($type) // check for username if (($rule_data[1] != '%') //wildcarded first - && ($rule_data[1] != $username) + && (! hash_equals($rule_data[1], $username)) ) { continue; } diff --git a/libraries/plugins/AuthenticationPlugin.php b/libraries/plugins/AuthenticationPlugin.php index 33f83f4a63..6063aa98e0 100644 --- a/libraries/plugins/AuthenticationPlugin.php +++ b/libraries/plugins/AuthenticationPlugin.php @@ -114,7 +114,7 @@ abstract class AuthenticationPlugin } else { $dbi_error = $GLOBALS['dbi']->getError(); if (!empty($dbi_error)) { - return PMA_sanitize($dbi_error); + return htmlspecialchars($dbi_error); } elseif (isset($GLOBALS['errno'])) { return '#' . $GLOBALS['errno'] . ' ' . __('Cannot log in to the MySQL server'); @@ -134,4 +134,26 @@ abstract class AuthenticationPlugin public function handlePasswordChange($password) { } + + /** + * Store session access time in session. + * + * Tries to workaround PHP 5 session garbage collection which + * looks at the session file's last modified time + * + * @return void + */ + public function setSessionAccessTime() + { + if (isset($_REQUEST['access_time'])) { + // Ensure access_time is in range <0, LoginCookieValidity + 1> + // to avoid excessive extension of validity. + // + // Negative values can cause session expiry extension + // Too big values can cause overflow and lead to same + $_SESSION['last_access_time'] = time() - min(max(0, intval($_REQUEST['access_time'])), $GLOBALS['cfg']['LoginCookieValidity'] + 1); + } else { + $_SESSION['last_access_time'] = time(); + } + } } diff --git a/libraries/plugins/auth/AuthenticationConfig.php b/libraries/plugins/auth/AuthenticationConfig.php index a98263b94f..77bf980d97 100644 --- a/libraries/plugins/auth/AuthenticationConfig.php +++ b/libraries/plugins/auth/AuthenticationConfig.php @@ -61,13 +61,7 @@ class AuthenticationConfig extends AuthenticationPlugin */ public function authSetUser() { - // try to workaround PHP 5 session garbage collection which - // looks at the session file's last modified time - if (isset($_REQUEST['access_time'])) { - $_SESSION['last_access_time'] = time() - $_REQUEST['access_time']; - } else { - $_SESSION['last_access_time'] = time(); - } + $this->setSessionAccessTime(); return true; } diff --git a/libraries/plugins/auth/AuthenticationCookie.php b/libraries/plugins/auth/AuthenticationCookie.php index 9f9e040206..0d37f4db32 100644 --- a/libraries/plugins/auth/AuthenticationCookie.php +++ b/libraries/plugins/auth/AuthenticationCookie.php @@ -301,7 +301,7 @@ class AuthenticationCookie extends AuthenticationPlugin } // The user just logged in - $GLOBALS['PHP_AUTH_USER'] = $_REQUEST['pma_username']; + $GLOBALS['PHP_AUTH_USER'] = PMA_sanitizeMySQLUser($_REQUEST['pma_username']); $GLOBALS['PHP_AUTH_PW'] = empty($_REQUEST['pma_password']) ? '' : $_REQUEST['pma_password']; @@ -408,14 +408,14 @@ class AuthenticationCookie extends AuthenticationPlugin // Ensures valid authentication mode, 'only_db', bookmark database and // table names and relation table name are used - if ($cfg['Server']['user'] != $GLOBALS['PHP_AUTH_USER']) { + if (! hash_equals($cfg['Server']['user'], $GLOBALS['PHP_AUTH_USER'])) { foreach ($cfg['Servers'] as $idx => $current) { if ($current['host'] == $cfg['Server']['host'] && $current['port'] == $cfg['Server']['port'] && $current['socket'] == $cfg['Server']['socket'] && $current['ssl'] == $cfg['Server']['ssl'] && $current['connect_type'] == $cfg['Server']['connect_type'] - && $current['user'] == $GLOBALS['PHP_AUTH_USER'] + && hash_equals($current['user'], $GLOBALS['PHP_AUTH_USER']) ) { $GLOBALS['server'] = $idx; $cfg['Server'] = $current; @@ -450,11 +450,7 @@ class AuthenticationCookie extends AuthenticationPlugin // Avoid showing the password in phpinfo()'s output unset($GLOBALS['PHP_AUTH_PW']); unset($_SERVER['PHP_AUTH_PW']); - if (isset($_REQUEST['access_time'])) { - $_SESSION['last_access_time'] = time() - $_REQUEST['access_time']; - } else { - $_SESSION['last_access_time'] = time(); - } + $this->setSessionAccessTime(); } /** diff --git a/libraries/plugins/auth/AuthenticationHttp.php b/libraries/plugins/auth/AuthenticationHttp.php index 3f76a130b5..b4c6f92808 100644 --- a/libraries/plugins/auth/AuthenticationHttp.php +++ b/libraries/plugins/auth/AuthenticationHttp.php @@ -165,10 +165,13 @@ class AuthenticationHttp extends AuthenticationPlugin unset($usr_pass); } + // sanitize username + $PHP_AUTH_USER = PMA_sanitizeMySQLUser($PHP_AUTH_USER); + // User logged out -> ensure the new username is not the same $old_usr = isset($_REQUEST['old_usr']) ? $_REQUEST['old_usr'] : ''; - if (!empty($old_usr) - && (isset($PHP_AUTH_USER) && $old_usr == $PHP_AUTH_USER) + if (! empty($old_usr) + && (isset($PHP_AUTH_USER) && hash_equals($old_usr, $PHP_AUTH_USER)) ) { $PHP_AUTH_USER = ''; // -> delete user's choices that were stored in session @@ -202,12 +205,12 @@ class AuthenticationHttp extends AuthenticationPlugin // Ensures valid authentication mode, 'only_db', bookmark database and // table names and relation table name are used - if ($cfg['Server']['user'] != $PHP_AUTH_USER) { + if (! hash_equals($cfg['Server']['user'], $PHP_AUTH_USER)) { $servers_cnt = count($cfg['Servers']); for ($i = 1; $i <= $servers_cnt; $i++) { if (isset($cfg['Servers'][$i]) && ($cfg['Servers'][$i]['host'] == $cfg['Server']['host'] - && $cfg['Servers'][$i]['user'] == $PHP_AUTH_USER) + && hash_equals($cfg['Servers'][$i]['user'], $PHP_AUTH_USER)) ) { $server = $i; $cfg['Server'] = $cfg['Servers'][$i]; @@ -223,9 +226,7 @@ class AuthenticationHttp extends AuthenticationPlugin unset($GLOBALS['PHP_AUTH_PW']); unset($_SERVER['PHP_AUTH_PW']); - // try to workaround PHP 5 session garbage collection which - // looks at the session file's last modified time - $_SESSION['last_access_time'] = time(); + $this->setSessionAccessTime(); return true; } diff --git a/libraries/tbl_partition_definition.inc.php b/libraries/tbl_partition_definition.inc.php index 3f7602bb05..0ec3dc6f0b 100644 --- a/libraries/tbl_partition_definition.inc.php +++ b/libraries/tbl_partition_definition.inc.php @@ -14,17 +14,31 @@ if (!isset($partitionDetails)) { // Extract some partitioning and subpartitioning parameters from the request $partitionParams = array( - 'partition_by', 'partition_expr', 'partition_count', - 'subpartition_by', 'subpartition_expr', 'subpartition_count' + 'partition_by', 'partition_expr', + 'subpartition_by', 'subpartition_expr', ); foreach ($partitionParams as $partitionParam) { $partitionDetails[$partitionParam] = isset($_REQUEST[$partitionParam]) ? $_REQUEST[$partitionParam] : ''; } + if (PMA_isValid($_REQUEST['partition_count'], 'numeric')) { + // MySQL's limit is 8192, so do not allow more + $partition_count = min(intval($_REQUEST['partition_count']), 8192); + } else { + $partition_count = 0; + } + $partitionDetails['partition_count'] = $partition_count; + if (PMA_isValid($_REQUEST['subpartition_count'], 'numeric')) { + // MySQL's limit is 8192, so do not allow more + $subpartition_count = min(intval($_REQUEST['subpartition_count']), 8192); + } else { + $subpartition_count = 0; + } + $partitionDetails['subpartition_count'] = $subpartition_count; + // Only LIST and RANGE type parameters allow subpartitioning - $partitionDetails['can_have_subpartitions'] = isset($_REQUEST['partition_count']) - && $_REQUEST['partition_count'] > 1 + $partitionDetails['can_have_subpartitions'] = $partition_count > 1 && isset($_REQUEST['partition_by']) && ($_REQUEST['partition_by'] == 'RANGE' || $_REQUEST['partition_by'] == 'RANGE COLUMNS' @@ -38,18 +52,17 @@ if (!isset($partitionDetails)) { || $_REQUEST['partition_by'] == 'LIST' || $_REQUEST['partition_by'] == 'LIST COLUMNS'); - if (PMA_isValid($_REQUEST['partition_count'], 'numeric') - && $_REQUEST['partition_count'] > 1 - ) { // Has partitions + // Has partitions + if ($partition_count > 1) { $partitions = isset($_REQUEST['partitions']) ? $_REQUEST['partitions'] : array(); // Remove details of the additional partitions // when number of partitions have been reduced - array_splice($partitions, $_REQUEST['partition_count']); + array_splice($partitions, $partition_count); - for ($i = 0; $i < $_REQUEST['partition_count']; $i++) { + for ($i = 0; $i < $partition_count; $i++) { if (! isset($partitions[$i])) { // Newly added partition $partitions[$i] = array( 'name' => 'p' . $i, @@ -85,11 +98,10 @@ if (!isset($partitionDetails)) { $partition['node_group'] = ''; } - if (PMA_isValid($_REQUEST['subpartition_count'], 'numeric') - && $_REQUEST['subpartition_count'] > 1 + if ($subpartition_count > 1 && $partitionDetails['can_have_subpartitions'] == true ) { // Has subpartitions - $partition['subpartition_count'] = $_REQUEST['subpartition_count']; + $partition['subpartition_count'] = $subpartition_count; if (! isset($partition['subpartitions'])) { $partition['subpartitions'] = array(); @@ -98,9 +110,9 @@ if (!isset($partitionDetails)) { // Remove details of the additional subpartitions // when number of subpartitions have been reduced - array_splice($subpartitions, $_REQUEST['subpartition_count']); + array_splice($subpartitions, $subpartition_count); - for ($j = 0; $j < $_REQUEST['subpartition_count']; $j++) { + for ($j = 0; $j < $subpartition_count; $j++) { if (! isset($subpartitions[$j])) { // Newly added subpartition $subpartitions[$j] = array( 'name' => $partition['name'] . '_s' . $j, diff --git a/libraries/tracking.lib.php b/libraries/tracking.lib.php index b0ee37158e..6e2dace08d 100644 --- a/libraries/tracking.lib.php +++ b/libraries/tracking.lib.php @@ -1186,14 +1186,16 @@ function PMA_exportAsFileDownload($entries) { @ini_set('url_rewriter.tags', ''); + // Replace all multiple whitespaces by a single space + $table = htmlspecialchars(preg_replace('/\s+/', ' ', $_REQUEST['table'])); $dump = "# " . sprintf( - __('Tracking report for table `%s`'), htmlspecialchars($_REQUEST['table']) + __('Tracking report for table `%s`'), $table ) . "\n" . "# " . date('Y-m-d H:i:s') . "\n"; foreach ($entries as $entry) { $dump .= $entry['statement']; } - $filename = 'log_' . htmlspecialchars($_REQUEST['table']) . '.sql'; + $filename = 'log_' . $table . '.sql'; PMA\libraries\Response::getInstance()->disable(); PMA_downloadHeader( $filename, diff --git a/prefs_manage.php b/prefs_manage.php index e17dbba6bc..3d8e9cdfa7 100644 --- a/prefs_manage.php +++ b/prefs_manage.php @@ -173,7 +173,7 @@ if (isset($_POST['submit_export']) $result = PMA_saveUserprefs($cf->getConfigArray()); if ($result === true) { if ($return_url) { - $query = explode('&', parse_url($return_url, PHP_URL_QUERY)); + $query = PMA\libraries\Util::splitURLQuery($return_url); $return_url = parse_url($return_url, PHP_URL_PATH); foreach ($query as $q) { diff --git a/test/classes/ErrorTest.php b/test/classes/ErrorTest.php index ae2aca6b97..fa5c6e9dce 100644 --- a/test/classes/ErrorTest.php +++ b/test/classes/ErrorTest.php @@ -102,7 +102,7 @@ class ErrorTest extends PMATestCase return array( array('./ChangeLog', './ChangeLog'), array(__FILE__, './test/classes/ErrorTest.php'), - array('./NONEXISTING', './NONEXISTING'), + array('./NONEXISTING', 'NONEXISTING'), ); } diff --git a/test/classes/MessageTest.php b/test/classes/MessageTest.php index b330430b5b..203178f09b 100644 --- a/test/classes/MessageTest.php +++ b/test/classes/MessageTest.php @@ -110,6 +110,7 @@ class MessageTest extends PMATestCase { $this->object = new PMA\libraries\Message('', PMA\libraries\Message::ERROR); $this->object->setMessage('test<&>'); + $this->object->setBBCode(false); $this->assertEquals($this->object, PMA\libraries\Message::rawError('test<&>')); } @@ -123,6 +124,7 @@ class MessageTest extends PMATestCase { $this->object = new PMA\libraries\Message('', PMA\libraries\Message::NOTICE); $this->object->setMessage('test<&>'); + $this->object->setBBCode(false); $this->assertEquals($this->object, PMA\libraries\Message::rawNotice('test<&>')); } @@ -136,6 +138,7 @@ class MessageTest extends PMATestCase { $this->object = new PMA\libraries\Message('', PMA\libraries\Message::SUCCESS); $this->object->setMessage('test<&>'); + $this->object->setBBCode(false); $this->assertEquals($this->object, PMA\libraries\Message::rawSuccess('test<&>')); } diff --git a/test/libraries/core/PMA_isAllowedDomain_test.php b/test/libraries/core/PMA_isAllowedDomain_test.php index 586e6bcfb3..9f544c0d9c 100644 --- a/test/libraries/core/PMA_isAllowedDomain_test.php +++ b/test/libraries/core/PMA_isAllowedDomain_test.php @@ -43,6 +43,9 @@ class PMA_isAllowedDomain_test extends PHPUnit_Framework_TestCase array('https://www.phpmyadmin.net/', true), array('http://duckduckgo.com\\@github.com', false), array('https://github.com/', true), + array('https://github.com:123/', false), + array('https://user:pass@github.com:123/', false), + array('https://user:pass@github.com/', false), array('https://server.local/', true), array('./relative/', false), ); diff --git a/test/libraries/core/PMA_safeUnserialize_test.php b/test/libraries/core/PMA_safeUnserialize_test.php index f2710c0792..f589361b93 100644 --- a/test/libraries/core/PMA_safeUnserialize_test.php +++ b/test/libraries/core/PMA_safeUnserialize_test.php @@ -44,6 +44,7 @@ class PMA_safeUnserialize_test extends PHPUnit_Framework_TestCase array('b:0;', false), array('O:1:"a":1:{s:5:"value";s:3:"100";}', null), array('O:8:"stdClass":1:{s:5:"field";O:8:"stdClass":0:{}}', null), + array('a:2:{i:0;s:90:"1234567890;a345678901234567890123456789012345678901234567890123456789012345678901234567890";i:1;O:8:"stdClass":0:{}}', null), array(serialize(array(1, 2, 3)), array(1, 2, 3)), array(serialize('string""'), 'string""'), array(serialize(array('foo' => 'bar')), array('foo' => 'bar')), diff --git a/test/libraries/core/PMA_sanitizeMySQLHost_test.php b/test/libraries/core/PMA_sanitizeMySQLHost_test.php index 1b4404732a..d17ca530d0 100644 --- a/test/libraries/core/PMA_sanitizeMySQLHost_test.php +++ b/test/libraries/core/PMA_sanitizeMySQLHost_test.php @@ -40,6 +40,7 @@ class PMA_sanitizeMySQLHost_test extends PHPUnit_Framework_TestCase { return array( array('p:foo.bar', 'foo.bar'), + array('p:p:foo.bar', 'foo.bar'), array('bar.baz', 'bar.baz'), array('P:example.com', 'example.com'), ); |