#894802 ksh: parsing of floating-point constants is broken in locales where the decimal point is not "."

#894802#5
Date:
2018-04-04 11:37:04 UTC
From:
To:
--- Please enter the report below this line. ---

Floating point arithmetic no longer works in ksh. Here's how it used to
work:

... and this is how it works now:

The last version which actually supported FP arithmetic was
93u+20120801-1 in Debian 8.
The changelog for Debian 9 lists 4 more updates (93u+20120801-1.1,
93u+20120801-1.2, 93u+20120801-2 and 93u+20120801-3.1), but none of them
mentions any breaking changes.

Debian Release: 9.3
500 stable-updates ftp.ru.debian.org
500 stable security.debian.org
500 stable ftp.ru.debian.org
100 stretch-backports ftp.ru.debian.org
--- Package information. ---
Depends (Version) | Installed
=============================-+-===========
libc6 (>= 2.23) |
binfmt-support |


Package's Recommends field is empty.

Package's Suggests field is empty.

#894802#10
Date:
2018-04-06 09:45:33 UTC
From:
To:
Hello,

The issue is actually locale-dependent:

ksh infers the decimal separator from LC_NUMERIC, and since my locale is
ru_RU.UTF-8,
it expects a comma (,) instead of a dot (.).

Strange thing is, LC_NUMERIC affects neither zsh nor bc -- only ksh.

I believe this behaviour should be at least documented somewhere.

Regards,
Andrey.

#894802#15
Date:
2020-01-24 13:35:34 UTC
From:
To:
Control: retitle -1 ksh: parsing of floating-point constants is broken in locales where the decimal point is not "."

There is documentation, but it does not match the observed behavior.
The man page says under "Arithmetic Evaluation.":

  "Floating point constants follow the ANSI-C programming language
  floating point conventions."

In C, like in many programming languages, the locales do not influence
the syntax of literals, e.g. "1." is the floating-point constant 1
whatever the locale.

However, in CAVEATS, it says:

  "It is a good idea to leave a space after the comma operator in
  arithmetic expressions to prevent the comma from being interpreted
  as the decimal point character in certain locales."

but that's no the main documentation.

I'd rather say that this is a bug in the code (otherwise, hardcoded
constants in scripts would be an issue, in particular), which blindly
use standard library functions in the current locale.

This would also solve the current inconsistency with Turkish locales:

cventin:~> LC_ALL=tr_TR.utf8 ksh
$ echo $((Inf))
inf
$ echo $((ınf))
0

while the lowercase form of "Inf" is "ınf", not "inf", i.e. ksh does
not seem to honor the current locale for infinity.

#894802#32
Date:
2026-06-21 10:52:09 UTC
From:
To:
Thanks for the analysis.

Checking the current state on ksh93u+m (1.0.10-5), the original arithmetic
syntax error is gone, and a '.'  literal in a comma-radix locale produces
an explicit message:

+ ksh -c 'echo $((1./2))'
+ LC_ALL=C
0.5
+ ksh -c 'echo $((1./2))'
+ LC_ALL=de_DE.UTF-8
ksh: 1./2: radix point '.' requires LC_NUMERIC=C
+ ksh -c 'echo $((1,0/2,0))'
+ LC_ALL=de_DE.UTF-8
0,5
+ ksh -c 'echo $((1./2))'
+ LANG=de_DE.UTF-8
+ LC_NUMERIC=C
0.5
+ ksh -c 'echo $((Inf))'
+ LC_ALL=tr_TR.UTF-8
inf
+ ksh -c 'echo $((inf))'
+ LC_ALL=tr_TR.UTF-8
inf
+ ksh -c 'echo $((ınf))'
+ LC_ALL=tr_TR.UTF-8
0

The locale-dependent radix point is intentional and is covered by the
test suite. The workaround is LC_NUMERIC=C.

On the Turkish Inf/NaN point, that recognition happens through ASCII and
is not dependent on LC_NUMERIC and so 'ınf' is not matched by design.
What remains however is a valid documentation gap for which this patch
will be forwarded upstream:
--- a/src/cmd/ksh93/sh.1
+++ b/src/cmd/ksh93/sh.1
@@ -3252,8 +3252,13 @@ double precision floating point
 arithmetic or long double precision floating point for
 systems that provide this data type.
 Floating point constants follow the ANSI C programming language
-floating point conventions.
-The case-insensitive floating point constants
+floating point conventions, except that the radix point character
+is determined by the
+.SM LC_NUMERIC
+locale category; set
+.B LC_NUMERIC=C
+to use a period.
+The ASCII case-insensitive floating point constants
 .B NaN
 and
 .B Inf

 Anuradha

#894802#39
Date:
2026-06-22 13:30:17 UTC
From:
To:
IMHO, this is bad. The interpretation of literals in a source file
(here, a ksh script) should not depend on the current locales.

#894802#44
Date:
2026-06-23 04:27:19 UTC
From:
To:
Agreed with you in principle. To be clear though, this isn't new
or a regression and it has been parsed through the locale-aware
strtold() historically unfortunately, and so changing it would have
backward compatibility concerns.

However, a case could be made whether such behavior could make it
into a portable opt-in without changing the legacy default (POSIX
itself is silent, since shell floating point arithmetic is a ksh
extension), but that would be a discussion that would need to be
had upstream. If you're willing to advocate a case for that, would
you mind opening an enhancement request on
https://github.com/ksh93/ksh/issues?

Also, let me know if you have any concerns with the documentation
fix before I forward it upstream.

thanks,

Anuradha

#894802#49
Date:
2026-06-23 11:59:52 UTC
From:
To:
The bug reporter Andrey ``Bass'' Shcheglov said that there was
a change between Debian 8 and Debian 9. But perhaps he changed
his locale?

Note that this also affects the comma operator when the decimal-point
chracter is the comma (as noted at the end of the ksh93(1) man page,
but a bit incorrectly). However, the comma operator is not specified
by POSIX and is an extension in shells except the basic ones.

See also:
https://www.mail-archive.com/austin-group-l@opengroup.org/msg14429.html

At https://github.com/ksh93/ksh/issues/999 I've mentioned 2 issues
with the ksh93(1) man page:

* "Floating point constants follow the ANSI C programming language
  floating point conventions." This is not correct since C
  floating-point constants do not depend on the current locale.

* "It is a good idea to leave a space after the comma operator in
  arithmetic expressions to prevent the comma from being interpreted
  as the decimal-point character in certain locales." But a space
  *before* the comma operator may also be needed:

$ for s in "1,2" "1, 2" " 1 ,2" "1 , 2" ; do LC_ALL=fr_FR.utf8 ksh93 -c "echo \$(( $s ))" ; done
1,2
ksh93:  1, 2 : arithmetic syntax error
ksh93:   1 ,2 : arithmetic syntax error
2