From df29d8ae4100841ecdb59fdfdd29b76f9a28661d Mon Sep 17 00:00:00 2001 From: Deven Bansod Date: Thu, 25 Aug 2016 19:36:35 +0530 Subject: [PATCH 01/14] Add appr. escaping for $cfg options 'hide_db' and 'only_db' These can lead to SQL injection. Fix #12497 Signed-off-by: Deven Bansod --- libraries/navigation/nodes/Node.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/navigation/nodes/Node.php b/libraries/navigation/nodes/Node.php index 0e186c6498..de6b1d2d62 100644 --- a/libraries/navigation/nodes/Node.php +++ b/libraries/navigation/nodes/Node.php @@ -721,7 +721,9 @@ class Node if (!empty($GLOBALS['cfg']['Server']['hide_db'])) { $whereClause .= "AND " . Util::backquote($columnName) - . " NOT REGEXP '" . $GLOBALS['cfg']['Server']['hide_db'] . "' "; + . " NOT REGEXP '" + . Util::sqlAddSlashes($GLOBALS['cfg']['Server']['hide_db'], true) + . "' "; } if (!empty($GLOBALS['cfg']['Server']['only_db'])) { @@ -735,7 +737,7 @@ class Node foreach ($GLOBALS['cfg']['Server']['only_db'] as $each_only_db) { $subClauses[] = " " . Util::backquote($columnName) . " LIKE '" - . $each_only_db . "' "; + . Util::sqlAddSlashes($each_only_db, true) . "' "; } $whereClause .= implode("OR", $subClauses) . ") "; } From d0b8281e84f30d0c1a5a48b73752e8b1bce29b1a Mon Sep 17 00:00:00 2001 From: Deven Bansod Date: Thu, 25 Aug 2016 19:42:18 +0530 Subject: [PATCH 02/14] ChangeLog entry for #12497 Signed-off-by: Deven Bansod --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 843ed25048..7dc6cf9114 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,7 @@ phpMyAdmin - ChangeLog - issue #12485 Do not show warning about short blowfish_secret if none is set - issue #12251 Fixed random logouts due to wrong cookie path - issue #12480 Fixed editing of ENUM/SET/DECIMAL fields structure +- issue #12497 Missing escaping of configuration used in SQL (hide_db and only_db) 4.6.4 (2016-08-16) - issue [security] Weaknesses with cookie encryption, see PMASA-2016-29 From 96f5f101cc6db57abaea88f4ff5015f1839a2c8e Mon Sep 17 00:00:00 2001 From: Deven Bansod Date: Thu, 25 Aug 2016 23:25:19 +0530 Subject: [PATCH 03/14] Add error checking in reading the advisory_rules file If the file does not exist or if it is not readable by PHP, it can return FALSE. In such cases, we should print a user-friendly message and return from parsing the rules file. Fix #12476 Signed-off-by: Deven Bansod --- libraries/Advisor.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libraries/Advisor.php b/libraries/Advisor.php index 59742b2f6c..cfe4fa65e5 100644 --- a/libraries/Advisor.php +++ b/libraries/Advisor.php @@ -455,10 +455,20 @@ class Advisor */ public static function parseRulesFile() { - $file = file('libraries/advisory_rules.txt', FILE_IGNORE_NEW_LINES); + $filename = 'libraries/advisory_rules.txt'; + $file = file($filename, FILE_IGNORE_NEW_LINES); + $errors = array(); $rules = array(); $lines = array(); + + if ($file === FALSE) { + $errors[] = __( + 'Error in reading file: The file \'' . $filename .'\' does not exist or is not readable' + ); + return array('rules' => $rules, 'lines' => $lines, 'errors' => $errors); + } + $ruleSyntax = array( 'name', 'formula', 'test', 'issue', 'recommendation', 'justification' ); From b3e7f10f2ed8949512b623cac4055de86fe368fc Mon Sep 17 00:00:00 2001 From: Deven Bansod Date: Thu, 25 Aug 2016 23:59:29 +0530 Subject: [PATCH 04/14] Check if the indices are present and map to a string value Fix #12477 The indices may not be present in the json_decode result, or might not be strings Signed-off-by: Deven Bansod --- libraries/common.inc.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 9ec0fc32cd..3c6134afcf 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -455,9 +455,15 @@ PMA_setGlobalDbOrTable('table'); */ if (PMA_isValid($_REQUEST['selected_recent_table'])) { $recent_table = json_decode($_REQUEST['selected_recent_table'], true); - $GLOBALS['db'] = $recent_table['db']; + + $GLOBALS['db'] + = (array_key_exists('db', $recent_table) && is_string($recent_table['db'])) ? + $recent_table['db'] : ''; $GLOBALS['url_params']['db'] = $GLOBALS['db']; - $GLOBALS['table'] = $recent_table['table']; + + $GLOBALS['table'] + = (array_key_exists('table', $recent_table) && is_string($recent_table['table'])) ? + $recent_table['table'] : ''; $GLOBALS['url_params']['table'] = $GLOBALS['table']; } From d7181d1b5a35bf91053d74babf1a3cef666d894e Mon Sep 17 00:00:00 2001 From: Deven Bansod Date: Fri, 26 Aug 2016 00:04:19 +0530 Subject: [PATCH 05/14] ChangeLog entries for #12476 and #12477 Signed-off-by: Deven Bansod --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7dc6cf9114..413e3f6b6e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,8 @@ phpMyAdmin - ChangeLog - issue #12251 Fixed random logouts due to wrong cookie path - issue #12480 Fixed editing of ENUM/SET/DECIMAL fields structure - issue #12497 Missing escaping of configuration used in SQL (hide_db and only_db) +- issue #12476 Add error checking in reading advisory rules file +- issue #12477 Add checking missing elements and confirming element types from json_decode 4.6.4 (2016-08-16) - issue [security] Weaknesses with cookie encryption, see PMASA-2016-29 From ad5187383d35c1bace5f3e53afe1449848cbf93d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= Date: Sat, 27 Aug 2016 09:12:46 +0200 Subject: [PATCH 06/14] Automatically save SQL query in browser local storage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ..when available rather than in cookie as we do not want to send huge cookies with SQL query there and back. Issue #12251 Issue phpmyadmin/docker#32 Signed-off-by: Michal Čihař --- ChangeLog | 1 + js/functions.js | 4 +++- js/sql.js | 27 +++++++++++++++++++-------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 413e3f6b6e..c0488b0478 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,7 @@ phpMyAdmin - ChangeLog - issue #12497 Missing escaping of configuration used in SQL (hide_db and only_db) - issue #12476 Add error checking in reading advisory rules file - issue #12477 Add checking missing elements and confirming element types from json_decode +- issue #12251 Automatically save SQL query in browser local storage rather than in cookie 4.6.4 (2016-08-16) - issue [security] Weaknesses with cookie encryption, see PMASA-2016-29 diff --git a/js/functions.js b/js/functions.js index 0304126695..bace1bf56d 100644 --- a/js/functions.js +++ b/js/functions.js @@ -1164,7 +1164,9 @@ function insertQuery(queryType) } return; } else if (queryType == "saved") { - if ($.cookie('auto_saved_sql')) { + if (isStorageSupported('localStorage') && typeof window.localStorage.auto_saved_sql != 'undefined') { + setQuery(window.localStorage.auto_saved_sql); + } else if ($.cookie('auto_saved_sql')) { setQuery($.cookie('auto_saved_sql')); } else { PMA_ajaxShowMessage(PMA_messages.strNoAutoSavedQuery); diff --git a/js/sql.js b/js/sql.js index 8a8ee57320..c379420d31 100644 --- a/js/sql.js +++ b/js/sql.js @@ -36,6 +36,23 @@ function PMA_urlencode(str) } } +/** + * Saves SQL query in local storage or cooie + * + * @param string SQL query + * @return void + */ +function PMA_autosaveSQL(query) +{ + if (query) { + if (isStorageSupported('localStorage')) { + window.localStorage.auto_saved_sql = query; + } else { + $.cookie('auto_saved_sql', query); + } + } +} + /** * Get the field name for the current field. Required to construct the query * for grid editing @@ -135,17 +152,11 @@ AJAX.registerOnload('sql.js', function () { $(function () { if (codemirror_editor) { codemirror_editor.on('change', function () { - var query = codemirror_editor.getValue(); - if (query) { - $.cookie('auto_saved_sql', query); - } + PMA_autosaveSQL(codemirror_editor.getValue()); }); } else { $('#sqlquery').on('input propertychange', function () { - var query = $('#sqlquery').val(); - if (query) { - $.cookie('auto_saved_sql', query); - } + PMA_autosaveSQL($('#sqlquery').val()); }); } }); From efe97b150066dc7f0882885c2c5e43860ff7df98 Mon Sep 17 00:00:00 2001 From: Isaac Bennetch Date: Sat, 27 Aug 2016 11:45:37 -0400 Subject: [PATCH 07/14] Unable to edit transformations, issue 12292 Signed-off-by: Isaac Bennetch --- ChangeLog | 1 + templates/columns_definitions/transformation_option.phtml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index c0488b0478..77b2c1f9e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,6 +17,7 @@ phpMyAdmin - ChangeLog - issue #12476 Add error checking in reading advisory rules file - issue #12477 Add checking missing elements and confirming element types from json_decode - issue #12251 Automatically save SQL query in browser local storage rather than in cookie +- issue #12292 Unable to edit transformations 4.6.4 (2016-08-16) - issue [security] Weaknesses with cookie encryption, see PMASA-2016-29 diff --git a/templates/columns_definitions/transformation_option.phtml b/templates/columns_definitions/transformation_option.phtml index 91d97ca1a0..bb19e3f0b9 100644 --- a/templates/columns_definitions/transformation_option.phtml +++ b/templates/columns_definitions/transformation_option.phtml @@ -5,5 +5,5 @@ size="16" class="textfield" value="" /> \ No newline at end of file + htmlspecialchars($mime_map[$columnMeta['Field']][$options_key]) + : '' ?>" /> From 38ce0c9d445c0187115267c0d86db62df4849f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= Date: Sun, 28 Aug 2016 10:29:10 +0200 Subject: [PATCH 08/14] Remove unused paramenter when connecting to MySQLi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #12502 Signed-off-by: Michal Čihař --- ChangeLog | 1 + libraries/dbi/DBIMysqli.php | 10 +++------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 77b2c1f9e4..79fa66e378 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,7 @@ phpMyAdmin - ChangeLog - issue #12477 Add checking missing elements and confirming element types from json_decode - issue #12251 Automatically save SQL query in browser local storage rather than in cookie - issue #12292 Unable to edit transformations +- issue #12502 Remove unused paramenter when connecting to MySQLi 4.6.4 (2016-08-16) - issue [security] Weaknesses with cookie encryption, see PMASA-2016-29 diff --git a/libraries/dbi/DBIMysqli.php b/libraries/dbi/DBIMysqli.php index 0b98c85218..f310d9c85b 100644 --- a/libraries/dbi/DBIMysqli.php +++ b/libraries/dbi/DBIMysqli.php @@ -64,7 +64,6 @@ class DBIMysqli implements DBIExtension * @param string $host mysql hostname * @param string $user mysql user name * @param string $password mysql user password - * @param string $dbname database name * @param int $server_port server port * @param string $server_socket server socket * @param int $client_flags client flags of connection @@ -73,7 +72,7 @@ class DBIMysqli implements DBIExtension * @return bool */ private function _realConnect( - $link, $host, $user, $password, $dbname, $server_port, + $link, $host, $user, $password, $server_port, $server_socket, $client_flags = null, $persistent = false ) { global $cfg; @@ -89,7 +88,7 @@ class DBIMysqli implements DBIExtension $host, $user, $password, - $dbname, + '', $server_port, $server_socket ); @@ -99,7 +98,7 @@ class DBIMysqli implements DBIExtension $host, $user, $password, - $dbname, + '', $server_port, $server_socket, $client_flags @@ -185,7 +184,6 @@ class DBIMysqli implements DBIExtension $cfg['Server']['host'], $user, $password, - false, $server_port, $server_socket, $client_flags @@ -201,7 +199,6 @@ class DBIMysqli implements DBIExtension $cfg['Server']['host'], $user, '', - false, $server_port, $server_socket, $client_flags @@ -213,7 +210,6 @@ class DBIMysqli implements DBIExtension $server['host'], $user, $password, - false, $server_port, $server_socket ); From ee1878d3caad4c938a252d993d7583e66ad09d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= Date: Tue, 30 Aug 2016 14:04:55 +0200 Subject: [PATCH 09/14] Extend .gitignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #12515 Signed-off-by: Michal Čihař --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6841414751..52a98f192f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ # Upload/save dirs /upload/ /save/ +/tmp/ # For setup script /config/ # ctags @@ -22,8 +23,9 @@ phpmyadmin.wpj .idea .netbeans *.sw[op] -# IIS files +# Web server files web.config +.htaccess # Locales /locale/ # Backups From e16af0866d31dc175de44c89759494313bb12b85 Mon Sep 17 00:00:00 2001 From: Diego Bemquerer Castro Date: Mon, 29 Aug 2016 00:25:03 +0000 Subject: [PATCH 10/14] Translated using Weblate (Portuguese (Brazil)) Currently translated at 93.1% (2987 of 3206 strings) [CI skip] --- po/pt_BR.po | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/po/pt_BR.po b/po/pt_BR.po index 983d9e5522..5d0df4e01c 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -4,8 +4,8 @@ msgstr "" "Project-Id-Version: phpMyAdmin 4.6.5-dev\n" "Report-Msgid-Bugs-To: translators@phpmyadmin.net\n" "POT-Creation-Date: 2016-08-17 11:29+0200\n" -"PO-Revision-Date: 2016-08-22 02:16+0000\n" -"Last-Translator: Lucius Gaitán \n" +"PO-Revision-Date: 2016-08-29 00:24+0000\n" +"Last-Translator: Diego Bemquerer Castro \n" "Language-Team: Portuguese (Brazil) " "\n" "Language: pt_BR\n" @@ -3694,8 +3694,9 @@ msgid "Unknown error in file upload." msgstr "Erro desconhecido no carregamento do arquivo." #: libraries/File.php:424 +#, fuzzy msgid "File is a symbolic link" -msgstr "" +msgstr "O arquivo é um link simbólico" #: libraries/File.php:470 msgid "Error moving the uploaded file, see [doc@faq1-11]FAQ 1.11[/doc]." From d24dd24b750c879bfc35dadb2df988c97b3954c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= Date: Tue, 30 Aug 2016 14:08:47 +0200 Subject: [PATCH 11/14] Ensure unlim_num_rows is numberic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #12516 Signed-off-by: Michal Čihař --- libraries/Util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Util.php b/libraries/Util.php index 7b65f5a770..538fe808cf 100644 --- a/libraries/Util.php +++ b/libraries/Util.php @@ -4672,7 +4672,7 @@ class Util ->render( array( 'pos' => $pos, - 'unlim_num_rows' => $_REQUEST['unlim_num_rows'], + 'unlim_num_rows' => intval($_REQUEST['unlim_num_rows']), 'rows' => $rows, 'sql_query' => $sql_query, ) From a3d811571a9312d7125b1e79311a8399d0951a1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= Date: Tue, 30 Aug 2016 14:14:02 +0200 Subject: [PATCH 12/14] Fix ', // used in libraries/Util.php '[dochelpicon]' => PMA\libraries\Util::getImage('b_help.png', __('Documentation')), ); From f3babbb945ec54f55969e16191f3f2e9a13a2f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= Date: Tue, 30 Aug 2016 14:48:42 +0200 Subject: [PATCH 13/14] Correctly calculate string length MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #12517 Signed-off-by: Michal Čihař --- libraries/Linter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Linter.php b/libraries/Linter.php index 422141e615..ed53ce2187 100644 --- a/libraries/Linter.php +++ b/libraries/Linter.php @@ -51,7 +51,7 @@ class Linter // (which is actually a new line) aren't going to be processed at // all. $len = ($str instanceof UtfString) ? - $str->length() : strlen($len); + $str->length() : strlen($str); $lines = array(0); for ($i = 0; $i < $len; ++$i) { From f3ca367efa5a44161ca6fa3a2a9fa3b9ed24cbb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= Date: Tue, 30 Aug 2016 15:45:53 +0200 Subject: [PATCH 14/14] Fix number formatting with different settings of precision in PHP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fixed Util::formatNumber to avoid rounding issues to mess up display - force precision = 14 to ensure we get sane behavior With precision set to higher value many things do not behave as expected producing strange numbers in various places. For example with precision=19 you get: php > echo round(1.2, 2); 1.199999999999999956 Fixes #12303 Signed-off-by: Michal Čihař --- ChangeLog | 1 + libraries/Util.php | 16 +++---- libraries/common.inc.php | 7 +++ test/bootstrap-dist.php | 7 +++ .../common/PMA_formatNumberByteDown_test.php | 45 ++++++++++++++++--- 5 files changed, 60 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index 79fa66e378..5e2f3532e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -19,6 +19,7 @@ phpMyAdmin - ChangeLog - issue #12251 Automatically save SQL query in browser local storage rather than in cookie - issue #12292 Unable to edit transformations - issue #12502 Remove unused paramenter when connecting to MySQLi +- issue #12303 Fix number formatting with different settings of precision in PHP 4.6.4 (2016-08-16) - issue [security] Weaknesses with cookie encryption, see PMASA-2016-29 diff --git a/libraries/Util.php b/libraries/Util.php index 538fe808cf..5e2a4a3c5b 100644 --- a/libraries/Util.php +++ b/libraries/Util.php @@ -1604,17 +1604,13 @@ class Util $value = round($value / (self::pow(1000, $d, 'pow') / $dh)) /$dh; $unit = $units[$d]; - // If we don't want any zeros after the comma just add the thousand separator - if ($noTrailingZero) { - $localizedValue = self::localizeNumber( - preg_replace('/(?<=\d)(?=(\d{3})+(?!\d))/', ',', $value) - ); - } else { - //number_format is not multibyte safe, str_replace is safe - $localizedValue = self::localizeNumber( - number_format($value, $digits_right) - ); + // number_format is not multibyte safe, str_replace is safe + $formattedValue = number_format($value, $digits_right); + // If we don't want any zeros, remove them now + if ($noTrailingZero && strpos($formattedValue, '.') !== false) { + $formattedValue = preg_replace('/\.?0+$/', '', $formattedValue); } + $localizedValue = self::localizeNumber($formattedValue); if ($originalValue != 0 && floatval($value) == 0) { return ' <' . self::localizeNumber((1 / self::pow(10, $digits_right))) diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 3c6134afcf..0a04b5e618 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -107,6 +107,13 @@ PMA_checkExtensions(); ini_set('default_charset', 'utf-8'); mb_internal_encoding('utf-8'); +/** + * Set precision to sane value, with higher values + * things behave slightly unexpectedly, for example + * round(1.2, 2) returns 1.199999999999999956. + */ +ini_set('precision', 14); + /** * the relation lib, tracker needs it */ diff --git a/test/bootstrap-dist.php b/test/bootstrap-dist.php index 1b2e45059f..0188e49b05 100644 --- a/test/bootstrap-dist.php +++ b/test/bootstrap-dist.php @@ -6,6 +6,13 @@ * @package PhpMyAdmin-test */ +/** + * Set precision to sane value, with higher values + * things behave slightly unexpectedly, for example + * round(1.2, 2) returns 1.199999999999999956. + */ +ini_set('precision', 14); + // Let PHP complain about all errors error_reporting(E_ALL); diff --git a/test/libraries/common/PMA_formatNumberByteDown_test.php b/test/libraries/common/PMA_formatNumberByteDown_test.php index 138db8c49d..604e59b3e3 100644 --- a/test/libraries/common/PMA_formatNumberByteDown_test.php +++ b/test/libraries/common/PMA_formatNumberByteDown_test.php @@ -70,6 +70,30 @@ class PMA_FormatNumberByteDown_Test extends PHPUnit_Framework_TestCase array(0.003, 3, 3, '3 m'), array(-0.003, 6, 0, '-3,000 µ'), array(100.98, 0, 2, '100.98'), + array(21010101, 0, 2, '21,010,101.00'), + array(20000, 2, 2, '20 k'), + array(20011, 2, 2, '20.01 k'), + ); + } + + /** + * Core test for formatNumber + * + * + * @param float $a Value to format + * @param int $b Sensitiveness + * @param int $c Number of decimals to retain + * @param array $d Expected value + * + * @return void + */ + private function assertFormatNumber($a, $b, $c, $d) + { + $this->assertEquals( + $d, + (string) PMA\libraries\Util::formatNumber( + $a, $b, $c, false + ) ); } @@ -87,12 +111,21 @@ class PMA_FormatNumberByteDown_Test extends PHPUnit_Framework_TestCase */ public function testFormatNumber($a, $b, $c, $d) { - $this->assertEquals( - $d, - (string) PMA\libraries\Util::formatNumber( - $a, $b, $c, false - ) - ); + $this->assertFormatNumber($a, $b, $c, $d); + + // Test with various precisions + $old_precision = ini_get('precision'); + ini_set('precision', 20); + $this->assertFormatNumber($a, $b, $c, $d); + ini_set('precision', 14); + $this->assertFormatNumber($a, $b, $c, $d); + ini_set('precision', 10); + $this->assertFormatNumber($a, $b, $c, $d); + ini_set('precision', 5); + $this->assertFormatNumber($a, $b, $c, $d); + ini_set('precision', -1); + $this->assertFormatNumber($a, $b, $c, $d); + ini_set('precision', $old_precision); } /**