Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9c4abca

Browse files
authored
Avoid overflow in to_string for -huge(1)-1 (#667)
1 parent f98f3d3 commit 9c4abca

File tree

2 files changed

+60
-15
lines changed

2 files changed

+60
-15
lines changed

‎src/stdlib_strings_to_string.fypp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ contains
1313
${t1},ドル intent(in) :: value
1414
character(len=*), intent(in), optional :: format
1515
character(len=:), allocatable :: string
16-
16+
1717
character(len=buffer_len) :: buffer
1818
integer :: stat
1919

@@ -43,30 +43,31 @@ contains
4343
#:for k1, t1 in INT_KINDS_TYPES
4444
!> Represent an integer of kind ${k1}$ as character sequence.
4545
pure module function to_string_1_${t1[0]}$_${k1}$(value) result(string)
46-
${t1},ドル intent(in) :: value
46+
integer, parameter :: ik = ${k1}$
47+
integer(ik), intent(in) :: value
4748
character(len=:), allocatable :: string
4849
integer, parameter :: buffer_len = range(value)+2
4950
character(len=buffer_len) :: buffer
5051
integer :: pos
51-
${t1}$ :: n
52-
character(len=1), parameter :: numbers(0:9) = &
53-
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
52+
integer(ik) :: n
53+
character(len=1), parameter :: numbers(-9:0) = &
54+
["9", "8", "7", "6", "5", "4", "3", "2", "1", "0"]
5455

55-
if (value == 0_${k1}$) then
56+
if (value == 0_ik) then
5657
string = numbers(0)
5758
return
5859
end if
5960

60-
n = abs(value)
61+
n = sign(value, -1_ik)
6162
buffer = ""
62-
6363
pos = buffer_len + 1
64-
do while (n > 0_${k1}$)
64+
do while (n < 0_ik)
6565
pos = pos - 1
66-
buffer(pos:pos) = numbers(mod(n, 10_${k1}$))
67-
n = n/10_${k1}$
66+
buffer(pos:pos) = numbers(mod(n, 10_ik))
67+
n = n/10_ik
6868
end do
69-
if (value < 0_${k1}$) then
69+
70+
if (value < 0_ik) then
7071
pos = pos - 1
7172
buffer(pos:pos) = '-'
7273
end if
@@ -78,7 +79,7 @@ contains
7879
${t1},ドル intent(in) :: value
7980
character(len=*), intent(in) :: format
8081
character(len=:), allocatable :: string
81-
82+
8283
character(len=buffer_len) :: buffer
8384
integer :: stat
8485

@@ -106,7 +107,7 @@ contains
106107
${t1},ドル intent(in) :: value
107108
character(len=*), intent(in) :: format
108109
character(len=:), allocatable :: string
109-
110+
110111
character(len=buffer_len) :: buffer
111112
integer :: stat
112113

‎src/tests/string/test_string_to_string.f90

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ subroutine collect_string_to_string(testsuite)
1818
new_unittest("to_string-complex", test_to_string_complex), &
1919
new_unittest("to_string-integer", test_to_string_integer), &
2020
new_unittest("to_string-logical", test_to_string_logical), &
21-
new_unittest("to_string-real", test_to_string_real) &
21+
new_unittest("to_string-real", test_to_string_real), &
22+
new_unittest("to_string-limit-i1", test_string_i1), &
23+
new_unittest("to_string-limit-i2", test_string_i2), &
24+
new_unittest("to_string-limit-i4", test_string_i4), &
25+
new_unittest("to_string-limit-i8", test_string_i8) &
2226
]
2327
end subroutine collect_string_to_string
2428

@@ -146,6 +150,46 @@ subroutine test_to_string_logical(error)
146150
end subroutine test_to_string_logical
147151

148152

153+
subroutine test_string_i1(error)
154+
use stdlib_kinds, only : i1 => int8
155+
156+
!> Error handling
157+
type(error_type), allocatable, intent(out) :: error
158+
159+
call check(error, to_string(-huge(1_i1) - 1_i1), "-128")
160+
end subroutine test_string_i1
161+
162+
163+
subroutine test_string_i2(error)
164+
use stdlib_kinds, only : i2 => int16
165+
166+
!> Error handling
167+
type(error_type), allocatable, intent(out) :: error
168+
169+
call check(error, to_string(-huge(1_i2) - 1_i2), "-32768")
170+
end subroutine test_string_i2
171+
172+
173+
subroutine test_string_i4(error)
174+
use stdlib_kinds, only : i4 => int32
175+
176+
!> Error handling
177+
type(error_type), allocatable, intent(out) :: error
178+
179+
call check(error, to_string(-huge(1_i4) - 1_i4), "-2147483648")
180+
end subroutine test_string_i4
181+
182+
183+
subroutine test_string_i8(error)
184+
use stdlib_kinds, only : i8 => int64
185+
186+
!> Error handling
187+
type(error_type), allocatable, intent(out) :: error
188+
189+
call check(error, to_string(-huge(1_i8) - 1_i8), "-9223372036854775808")
190+
end subroutine test_string_i8
191+
192+
149193
end module test_string_to_string
150194

151195

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /