php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77347 switch casting behavior by setlocale(LC_NUMERIC, '') is wrong
Submitted: 2018-12-26 14:32 UTC Modified: 2018-12-26 23:11 UTC
From: spam2 at rhsoft dot net Assigned: cmb (profile)
Status: Duplicate Package: Scripting Engine problem
PHP Version: 7.2.13 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: spam2 at rhsoft dot net
New email:
PHP Version: OS:

 

 [2018-12-26 14:32 UTC] spam2 at rhsoft dot net
Description:
------------
you can disable comments for https://bugs.php.net/bug.php?id=77278 as much as you want - the current behavior of the scriptiung language is plain wrong and this seems have to be fixed even in the past looking at https://bugs.php.net/bug.php?id=17815 and "Workaround for this bug: setlocale(LC_NUMERIC,'C');"

* LC_NUMERIC="de_DE.UTF-8" is the default environment here
* if you call the changing behavior depending on locale
  correct you mustn't silently change it to LC_NUMERIC=C
  to begin with and that code sample would always
  come with , instead .
* but it does not
* it does only after a random setlocale wihtin PHP or some library

[harry@srv-rhsoft:/downloads]$ locale
LANG=de_DE.UTF-8
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC="de_DE.UTF-8"
LC_TIME="de_DE.UTF-8"
LC_COLLATE="de_DE.UTF-8"
LC_MONETARY="de_DE.UTF-8"
LC_MESSAGES="de_DE.UTF-8"
LC_PAPER="de_DE.UTF-8"
LC_NAME="de_DE.UTF-8"
LC_ADDRESS="de_DE.UTF-8"
LC_TELEPHONE="de_DE.UTF-8"
LC_MEASUREMENT="de_DE.UTF-8"
LC_IDENTIFICATION="de_DE.UTF-8"
LC_ALL=

[harry@srv-rhsoft:/downloads]$ php /downloads/casting.php
LC_CTYPE=de_DE.UTF-8;LC_NUMERIC=C;LC_TIME=C;LC_COLLATE=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;LC_IDENTIFICATION=C
OK: 4

de_DE.UTF-8
FAIL: 3,3333333333333

Test script:
---------------
[harry@srv-rhsoft:/downloads]$ cat /downloads/casting.php
<?php declare(strict_types=1);
echo setlocale(LC_ALL, '0'), "\n";
$pages_summary = (string)(10 / 3);
if($pages_summary > (int)$pages_summary)
{
 $pages_summary = (int)$pages_summary + 1;
}
if((int)$pages_summary !== 4)
{
 echo "FAIL: $pages_summary\n";
}
else
{
 echo "OK: $pages_summary\n";
}

echo "\n";

echo setlocale(LC_NUMERIC, ''), "\n";
$pages_summary = (string)(10 / 3);
if($pages_summary > (int)$pages_summary)
{
 $pages_summary = (int)$pages_summary + 1;
}
if((int)$pages_summary !== 4)
{
 echo "FAIL: $pages_summary\n";
}
else
{
 echo "OK: $pages_summary\n";
}

Expected result:
----------------
no change in casting behavior

Actual result:
--------------
don't change internal behavior randomly

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-12-26 14:35 UTC] spam2 at rhsoft dot net
-Summary: switch catsing behavior by setlocale(LC_NUMERIC, '') is wrong +Summary: switch casting behavior by setlocale(LC_NUMERIC, '') is wrong
 [2018-12-26 14:35 UTC] spam2 at rhsoft dot net
fixed typo in summary
 [2018-12-26 15:28 UTC] cmb@php.net
-Status: Open +Status: Duplicate -Assigned To: +Assigned To: cmb
 [2018-12-26 15:28 UTC] cmb@php.net
What are you trying to convey here?  The fact that

  setlocale(LC_NUMERIC, '')

changes the locale setting according to the environment is well
documented[1], and that the decimal separator is locale depending
for float to string casts[2].  Other than that, I can't see how
this bug report isn't a duplicate of bug #77278, where it already
has been explained in detail that:

| PHP converts by locale in one direction (float->string) but not
| in the other direction (string->float). It should be consistent.
| But like @nikic said, this inconsistency is currently the intended
| behavior - not the correct behavior, merely the *intended*
| behavior. It does need to get fixed but it's not a simple thing to
| just do.

To additionally clarify the word “simple” above: of course it is
simple to change the behavior, but that would likely cause a
massive BC break, so we cannot do this for the next minor version,
or even a revision, but would have at least to wait for the next
major PHP version.  And yes, somebody would need to take the time
to walk through the RFC process[3].

[1] <http://php.net/manual/en/function.setlocale.php>
[2] <http://php.net/manual/en/language.types.string.php#language.types.string.casting>
[3] <https://wiki.php.net/rfc/howto>
 [2018-12-26 15:46 UTC] spam2 at rhsoft dot net
well, comments for the other Bugreport are disabled 

can you explain me why for php LC_NUMERIC is set to C while the locale of the session is german other then to prevent that sort of confusion until somebody is touching locale after script start? 

if php would act here consistent I pretty sure would never have written that casting code to begin with because this dumb behavior would have jumped straight in my face all the time and not just by a random library which touched locale 


the float-to-string locale behavior is plain wrong and not that the other direction don't convert back correctly

if one is interest in locale format he is using a format function and not type casting
 [2018-12-26 17:18 UTC] cmb@php.net
> can you explain me why for php LC_NUMERIC is set to C while the
> locale of the session is german other then to prevent that sort of
> confusion until somebody is touching locale after script start? 

PHP's core does not touch any locale settings (so all default to
C), except for LC_TYPE[1].

> if php would act here consistent I pretty sure would never have
> written that casting code to begin with […]

See commit 7e0baa7[2] why initializing LC_ALL might not be the
best idea.

[1] <https://github.com/php/php-src/blob/9882929bfa4422765c1b1fde6a612fa48bfcce2e/main/main.c#L2180>
[2] <http://git.php.net/?p=php-src.git;a=commit;h=7e0baa7a1daa531e39881e59842c88d12e42c901>
 [2018-12-26 17:36 UTC] spam2 at rhsoft dot net
if it don't touch it how can it be C then when the environment is DE
 [2018-12-26 17:53 UTC] spam2 at rhsoft dot net
http://git.php.net/?p=php-src.git;a=commit;h=7e0baa7a1daa531e39881e59842c88d12e42c901 and "Revert Thies' locale patch. It was screwing up language level things" 18 years ago should not have reverted but the "language level things" fixed so that they are *not* get screwed up just because setlocale() exists somewhere left and right in the code
 [2018-12-26 23:11 UTC] cmb@php.net
> if it don't touch it how can it be C then when the environment
> is DE

This is defined by POSIX[1]:

| The POSIX locale is the default global locale at entry to
| main().

(The C locale is equivalent to the POSIX locale.)

POSIX futher elaborates:

| Internationalized programs can initiate language operation
| according to environment variable settings […]

Note the word “can”.

[1] <http://pubs.opengroup.org/onlinepubs/9699919799/functions/setlocale.html>
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 15:01:29 2024 UTC