Bug #77278 [Ver]: floatval(strval(value)) truncates if locale's decimal_point isn't a period
| From: | nikic@php.net | Date: | Mon, 10 Dec 2018 21:29:50 +0000 |
| Subject: | Bug #77278 [Ver]: floatval(strval(value)) truncates if locale's decimal_point isn't a period | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-218379@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=77278&edit=1
ID: 77278
Updated by: nikic@php.net
Reported by: spam2 at rhsoft dot net
Summary: floatval(strval(value)) truncates if locale's
decimal_point isn't a period
Status: Verified
Type: Bug
Package: Scripting Engine problem
PHP Version: Irrelevant
Block user comment: N
Private report: N
New Comment:
I think we should get rid of the locale-dependent float to string cast in PHP 8, but for now this is
working as "intended". We should definitely *not* make string to float cast
locale-sensitive as well, that would only make a bad situation worse.
Previous Comments:
------------------------------------------------------------------------
[2018-12-10 19:37:59] requinix@php.net
var_dump(setlocale(LC_NUMERIC, "de_DE", "German_Germany"));
var_dump(1 / 2); float 0,5
var_dump(strval(1 / 2)); // string "0,5"
var_dump(floatval(strval(1 / 2))); // float 0
------------------------------------------------------------------------
[2018-12-10 18:47:07] spam2 at rhsoft dot net
> but that there's an inconsistency between casting floats
> to strings and strings to floats when it comes to the decimal symbol?
that's exactly the point - oustide of format functions my locale de_DE.UTF-8 normally
don't matter and shouldn't do so but afer a simple tidy call anywhere every following php
code doing type casts on float values becomes a lottery
------------------------------------------------------------------------
[2018-12-10 18:40:04] requinix@php.net
I assume you're not trying to use this bug report for Tidy changing locale but that
there's an inconsistency between casting floats to strings and strings to floats when it comes
to the decimal symbol?
------------------------------------------------------------------------
[2018-12-10 17:36:20] spam2 at rhsoft dot net
standalone sample
<?php declare(strict_types=1);
$host = 'localhost';
$user = 'autotest';
$pwd = '****';
$db = 'autotest';
/** comment out this line and everything is fine with libtidy-5.6.0-2.fc28.x86_64 too */
$tidy = tidy_parse_string('bla', [], 'latin1');
/** that code is completly unrelated to tidy and must not change it's behavior */
$conn = mysqli_init();
mysqli_real_connect($conn, $host, $user, $pwd, $db);
mysqli_query($conn, "DROP TABLE IF EXISTS
tidy_test;");
mysqli_query($conn, "CREATE TABLE IF NOT EXISTS tidy_test (tidy_id
mediumint(7) UNSIGNED NOT NULL AUTO_INCREMENT, tidy_test char(2), PRIMARY KEY
(tidy_id));");
for($i=0; $i<=10; $i++)
{
mysqli_query($conn, "insert into tidy_test (tidy_test) values
('$i');");
}
$result = mysqli_query($conn, "select SQL_CALC_FOUND_ROWS * from
tidy_test");
$count_summary = mysqli_fetch_row(mysqli_query($conn, 'select SQL_NO_CACHE
found_rows()'))[0];
$pages_summary = (string)($count_summary / 3);
echo "PAGES-SUMMARY: $pages_summary\n";
if($pages_summary > (int)$pages_summary)
{
$pages_summary = (int)$pages_summary + 1;
}
echo "PAGES-SUMMARY: $pages_summary\n";
if((int)$pages_summary !== 4)
{
echo "CORRUPTION!\n";
}
else
{
echo "OK\n";
}
mysqli_query($conn, "DROP TABLE IF EXISTS tidy_test;");
?>
------------------------------------------------------------------------
[2018-12-10 16:55:13] spam2 at rhsoft dot net
Description:
------------
i doubt that it is expected behavior when some buggy library seems to play around with LOCALE that
unformatted output of float vars changes from dot to a comma
$pages_summary = (string)($count_summary / 3);
echo "PAGES-SUMMARY: $pages_summary\n";
https://github.com/htacg/tidy-html5/issues/780#issuecomment-445885150
libtidy-5.6.0-2.fc28.x86_64.rpm
[harry@srv-rhsoft:~]$ php /downloads/tidy-debug.php
PAGES-SUMMARY: 3,3333333333333
PAGES-SUMMARY: 3,3333333333333
CORRUPTION!
libtidy-5.4.0-4.fc28.20181003.rh.x86_64.rpm
[harry@srv-rhsoft:~]$ php /downloads/tidy-debug.php
PAGES-SUMMARY: 3.3333333333333
PAGES-SUMMARY: 4
OK
Test script:
---------------
libtidy 5.6 is touching LOCALE somewhere without a proper reset - period
look at the comma instad dot after typecasting a float value
libtidy-5.6.0-2.fc28.x86_64.rpm
[harry@srv-rhsoft:~]$ php /downloads/tidy-debug.php
PAGES-SUMMARY: 3,3333333333333
PAGES-SUMMARY: 3,3333333333333
CORRUPTION!
libtidy-5.4.0-4.fc28.20181003.rh.x86_64.rpm
[harry@srv-rhsoft:~]$ php /downloads/tidy-debug.php
PAGES-SUMMARY: 3.3333333333333
PAGES-SUMMARY: 4
OK
/** comment out this line and everything is fine with libtidy-5.6.0-2.fc28.x86_64 too */
$tidy = tidy_parse_string('bla', [], 'latin1');
/** that code is completly unrelated to tidy and must not change it's behavior */
$conn = mysqli_init();
mysqli_real_connect($conn, $host, $user, $pwd, $db);
$result = mysqli_query($conn, "select SQL_CALC_FOUND_ROWS * from cl_autotest_youtube_items
where yi_cid='1' and yi_aktiv='1' order by yi_sort asc limit 0, 3");
$count_summary = mysqli_fetch_row(mysqli_query($conn, 'select SQL_NO_CACHE
found_rows()'))[0];
$pages_summary = (string)($count_summary / 3);
echo "PAGES-SUMMARY: $pages_summary\n";
if($pages_summary > (int)$pages_summary)
{
$pages_summary = (int)$pages_summary + 1;
}
echo "PAGES-SUMMARY: $pages_summary\n";
if((int)$pages_summary !== 4)
{
echo "CORRUPTION!\n";
}
else
{
echo "OK\n";
}
Expected result:
----------------
PAGES-SUMMARY: 3.3333333333333
PAGES-SUMMARY: 4
Actual result:
--------------
PAGES-SUMMARY: 3,3333333333333
PAGES-SUMMARY: 3,3333333333333
CORRUPTION!
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=77278&edit=1