From 887ed5b9e999db0f6c5d0419b47fc4801803484f Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 24 Nov 2025 12:46:31 +0100 Subject: [PATCH] - `String.to_integer` does not correctly return in some cases where it should #2590. --- lib/std/core/string.c3 | 8 ++--- releasenotes.md | 1 + test/unit/stdlib/core/string_to_int.c3 | 42 ++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 test/unit/stdlib/core/string_to_int.c3 diff --git a/lib/std/core/string.c3 b/lib/std/core/string.c3 index 7ffb8e7e7..d0be62551 100644 --- a/lib/std/core/string.c3 +++ b/lib/std/core/string.c3 @@ -1067,14 +1067,10 @@ macro String.to_integer(self, $Type, int base = 10) { if (is_negative) { - $Type new_value = value * base_used - c; - if (new_value > value) return INTEGER_OVERFLOW?; - value = new_value; + value = value.overflow_mul(base_used).overflow_sub(c) ?? INTEGER_OVERFLOW?!; break; } - $Type new_value = value * base_used + c; - if (new_value < value) return INTEGER_OVERFLOW?; - value = new_value; + value = value.overflow_mul(base_used).overflow_add(c) ?? INTEGER_OVERFLOW?!; }; } return value; diff --git a/releasenotes.md b/releasenotes.md index b51566536..60ba46ad9 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -39,6 +39,7 @@ - With project.json, when overriding with an empty list the base settings would still be used. #2583 - Add sigsegv stacktrace in test and regular errors for Darwin Arm64. #1105 - Incorrect error message when using generic type that isn't imported #2589 +- `String.to_integer` does not correctly return in some cases where it should #2590. ### Stdlib changes - Add `CGFloat` `CGPoint` `CGSize` `CGRect` types to core_foundation (macOS). diff --git a/test/unit/stdlib/core/string_to_int.c3 b/test/unit/stdlib/core/string_to_int.c3 new file mode 100644 index 000000000..7248accdc --- /dev/null +++ b/test/unit/stdlib/core/string_to_int.c3 @@ -0,0 +1,42 @@ +module string_to_int; +import std::io, std::math; + +const N = 2560; +macro String[] m() @const +{ + var $strings = {}; + $foreach $i : math::iota(int[N]): + $strings +++= @sprintf("%s", $i); + $endforeach + return $strings; +} + +macro String[] m2() @const +{ + var $strings = {}; + $foreach $i : math::iota(int[N]): + $strings +++= @sprintf("%s", -$i); + $endforeach + return $strings; +} + +fn void string_to_char() @test +{ + int valid = 0; + foreach (str : m()) + { + char? x = str.to_integer(char); + if (try x) valid++; + } + assert(valid == 256); +} +fn void string_to_ichar() @test +{ + int valid = 0; + foreach (str : m2()) + { + ichar? x = str.to_integer(ichar); + if (try x) valid++; + } + assert(valid == 129); +} \ No newline at end of file