summaryrefslogtreecommitdiffstats
path: root/arith.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-03-04 01:35:10 -0800
committerKaz Kylheku <kaz@kylheku.com>2021-03-04 01:35:10 -0800
commitf3caaf8efd66511eeff194c198e59308c27de54d (patch)
tree0cb1f2dc360859eed02a1b8f8eae29980fa4ed8e /arith.c
parentb111bddfcc737b7f4ab854ce823094bcc8a9de48 (diff)
downloadtxr-f3caaf8efd66511eeff194c198e59308c27de54d.tar.gz
txr-f3caaf8efd66511eeff194c198e59308c27de54d.tar.bz2
txr-f3caaf8efd66511eeff194c198e59308c27de54d.zip
math: defend against locale decimal separator.
The int_flo function also has a sensitivity to locale because the bignum handling is text-based, involving printing a floating-point value, and then assuming it contains a period decimal separator. * arith.c (int_flo): If CONFIG_LOCALE_TOLERANCE is enabled, look for dec_point rather than '.' in the formatted number. When matching and destructuring the number with sscanf, don't look for the '.' character, but rather a complemented character set which can maching nothing but the separator, whatever that is.
Diffstat (limited to 'arith.c')
-rw-r--r--arith.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/arith.c b/arith.c
index 9b940e0c..3d484550 100644
--- a/arith.c
+++ b/arith.c
@@ -2943,6 +2943,19 @@ val int_flo(val f)
self, nao);
have_exp = (strchr(text, 'e') != 0);
+
+#if CONFIG_LOCALE_TOLERANCE
+ have_point = (strchr(text, dec_point) != 0);
+
+ if (have_exp && have_point)
+ sscanf(text, "%127[-0-9]%*1[^0-9e]%127[0-9]e%d", mint, mfrac, &exp);
+ else if (have_exp)
+ sscanf(text, "%127[-0-9]e%d", mint, &exp);
+ else if (have_point)
+ sscanf(text, "%127[-0-9]%*1[^0-9]*[%127[0-9]", mint, mfrac);
+ else
+ return int_str(string_utf8(text), nil);
+#else
have_point = (strchr(text, '.') != 0);
if (have_exp && have_point)
@@ -2953,6 +2966,7 @@ val int_flo(val f)
sscanf(text, "%127[-0-9].%127[0-9]", mint, mfrac);
else
return int_str(string_utf8(text), nil);
+#endif
if (have_exp && exp < 0)
return zero;