diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-08-13 02:31:41 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-08-13 02:31:41 -0700 |
commit | d5237f4eaaf569706675693d3a6a8d7449303ae6 (patch) | |
tree | e1d85eba5c85209b8915c37f653111ec1c368055 | |
parent | 2265d0cade2ee95f8a16273e66a7af3d05d34e85 (diff) | |
download | txr-d5237f4eaaf569706675693d3a6a8d7449303ae6.tar.gz txr-d5237f4eaaf569706675693d3a6a8d7449303ae6.tar.bz2 txr-d5237f4eaaf569706675693d3a6a8d7449303ae6.zip |
int-str: 0x bug.
* lib.c (int_str): The problem here is that we are recognizing
and skipping the 0x prefix for all bases. So for instance
(int-str "0x123") produces 123. The correct requirement, and
the intent of the code, is that the C conventions are only
honored if the base is specified as the character #\c. In any
other base, including omitted base defaulting to 10, a leading
zero is just a leading zero, and 0x is a zero followed by the
junk character x. Therefore, if we have any valid base that
isn't #\c, and 0x has been seen, we must return zero. We must
not do this only in the base 16 case.
* tests/016/conv.tl: New file.
-rw-r--r-- | lib.c | 15 | ||||
-rw-r--r-- | tests/016/conv.tl | 50 |
2 files changed, 58 insertions, 7 deletions
@@ -5745,15 +5745,16 @@ val int_str(val str, val base) if (base == chr('c')) { b = (zerox ? 16 : (octzero ? 8 : 10)); - } else if (b == 16) { - /* If base is 16, strtoul and its siblings - still recognize the 0x prefix. We don't want that; - except if base is the character #\c. Otherwise, - it is a zero with trailing junk. */ - if (zerox) - return zero; } else if (b < 2 || b > 36) { uw_throwf(error_s, lit("~a: invalid base ~s"), self, base, nao); + } else if (zerox) { + /* If we have a 0x prefix, and base is not #\c + * then that is just a zero followed by junk. + * We do this check here because wcstol recognizes + * these prefixes even when base isn't zero. + */ + if (zerox) + return zero; } /* TODO: detect if we have wcstoll */ diff --git a/tests/016/conv.tl b/tests/016/conv.tl new file mode 100644 index 00000000..34f5b7c7 --- /dev/null +++ b/tests/016/conv.tl @@ -0,0 +1,50 @@ +(load "../common.tl") + +(each ((b 2..36)) + (mtest + (int-str "" b) nil + (int-str "$" b) nil + (int-str "-" b) nil + (int-str "+" b) nil + (int-str "0" b) 0 + (int-str "00" b) 0 + (int-str "0x" b) 0 + (int-str "0x3" b) 0 + (int-str "0xz" b) 0)) + +(mtest + (int-str "+123") 123 + (int-str "-123") -123 + (int-str "0123") 123 + (int-str "00123") 123 + (int-str "999999999999999999999999999999") 999999999999999999999999999999 + (int-str "+999999999999999999999999999999") 999999999999999999999999999999 + (int-str "-999999999999999999999999999999") -999999999999999999999999999999) + +(let ((c #\c)) + (mtest + (int-str "+123" c) 123 + (int-str "-123" c) -123 + (int-str "0123" c) 83 + (int-str "00123" c) 83 + (int-str "0x123" c) 291 + (int-str "-0x123" c) -291 + (int-str "+0xFFFFFFFFFFFFFFFFFFFF" c) #xFFFFFFFFFFFFFFFFFFFF + (int-str "-0xFFFFFFFFFFFFFFFFFFFF" c) #x-FFFFFFFFFFFFFFFFFFFF)) + +(mtest + (int-str "zZz" 35) nil + (int-str "zZz" 36) 46655 + (int-str "-zZz" 36) -46655 + (int-str "+zZz" 36) 46655 + (int-str "+0zZz" 36) 46655 + (int-str "-0zZz" 36) -46655 + (int-str "0zZz" 36) 46655 + (int-str "1" 36) 1 + (int-str "10" 36) 36 + (int-str "100" 36) 1296 + (int-str "zzzzzzzzzzzzzzzzzzzzzzzz" 36) 22452257707354557240087211123792674815 + (int-str "-zzzzzzzzzzzzzzzzzzzzzzzz" 36) -22452257707354557240087211123792674815 + (int-str "0zzzzzzzzzzzzzzzzzzzzzzzz" 36) 22452257707354557240087211123792674815 + (int-str "-0zzzzzzzzzzzzzzzzzzzzzzzz" 36) -22452257707354557240087211123792674815 + (int-str "+0zzzzzzzzzzzzzzzzzzzzzzzz" 36) 22452257707354557240087211123792674815) |