diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-03-04 01:35:10 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-03-04 01:35:10 -0800 |
commit | f3caaf8efd66511eeff194c198e59308c27de54d (patch) | |
tree | 0cb1f2dc360859eed02a1b8f8eae29980fa4ed8e | |
parent | b111bddfcc737b7f4ab854ce823094bcc8a9de48 (diff) | |
download | txr-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.
-rw-r--r-- | arith.c | 14 |
1 files changed, 14 insertions, 0 deletions
@@ -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; |