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 | ccf85499a313ba6a8556f517ffad06c7f80f9687 (patch) | |
tree | 0cb1f2dc360859eed02a1b8f8eae29980fa4ed8e | |
parent | fcd49a77c8afd7881e1503454d58da900cb94ae8 (diff) | |
download | txr-ccf85499a313ba6a8556f517ffad06c7f80f9687.tar.gz txr-ccf85499a313ba6a8556f517ffad06c7f80f9687.tar.bz2 txr-ccf85499a313ba6a8556f517ffad06c7f80f9687.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; |