Added tests from issue 7608 comments.

Fixed "_" only and no digits. Now returns an error since this is effectively passing nothing to the parser.
This commit is contained in:
Jeffrey Ward committed 2026-10-07 21:28:43 -04:00
1 parent b6f29d5f5d
commit c2684b43cb
2 files changed
+82 -16

No files matched your search

+32 -16
View File
@@ -93,7 +93,7 @@ parse_i64_of_base :: proc(str: string, base: int, n: ^int = nil) -> (value: i64,
}
i := 0
i, digits := 0, 0
for r in s {
if r == '_' {
i += 1
@@ -116,9 +116,11 @@ parse_i64_of_base :: proc(str: string, base: int, n: ^int = nil) -> (value: i64,
value = value*i64(base) + v
}
i += 1
digits += 1
}
s = s[i:]
ok = len(s) == 0
// Underscores are only separators; at least one digit is required.
ok = len(s) == 0 && digits > 0
return
}
/*
@@ -180,7 +182,7 @@ parse_i64_maybe_prefixed :: proc(str: string, n: ^int = nil) -> (value: i64, ok:
}
i := 0
i, digits := 0, 0
for r in s {
if r == '_' {
i += 1
@@ -203,9 +205,11 @@ parse_i64_maybe_prefixed :: proc(str: string, n: ^int = nil) -> (value: i64, ok:
value = value*base + v
}
i += 1
digits += 1
}
s = s[i:]
ok = len(s) == 0
// Underscores are only separators; at least one digit is required.
ok = len(s) == 0 && digits > 0
return
}
//
@@ -252,7 +256,7 @@ parse_u64_of_base :: proc(str: string, base: int, n: ^int = nil) -> (value: u64,
s = s[1:]
}
i := 0
i, digits := 0, 0
for r in s {
if r == '_' {
i += 1
@@ -267,10 +271,12 @@ parse_u64_of_base :: proc(str: string, base: int, n: ^int = nil) -> (value: u64,
}
value = value*u64(base) + v
i += 1
digits += 1
}
s = s[i:]
ok = len(s) == 0
// Underscores are only separators; at least one digit is required.
ok = len(s) == 0 && digits > 0
return
}
/*
@@ -327,7 +333,7 @@ parse_u64_maybe_prefixed :: proc(str: string, n: ^int = nil) -> (value: u64, ok:
}
}
i := 0
i, digits := 0, 0
for r in s {
if r == '_' {
i += 1
@@ -342,10 +348,12 @@ parse_u64_maybe_prefixed :: proc(str: string, n: ^int = nil) -> (value: u64, ok:
}
value = value*base + v
i += 1
digits += 1
}
s = s[i:]
ok = len(s) == 0
// Underscores are only separators; at least one digit is required.
ok = len(s) == 0 && digits > 0
return
}
//
@@ -487,7 +495,7 @@ parse_i128_of_base :: proc(str: string, base: int, n: ^int = nil) -> (value: i12
}
i := 0
i, digits := 0, 0
for r in s {
if r == '_' {
i += 1
@@ -510,9 +518,11 @@ parse_i128_of_base :: proc(str: string, base: int, n: ^int = nil) -> (value: i12
value = value*i128(base) + v
}
i += 1
digits += 1
}
s = s[i:]
ok = len(s) == 0
// Underscores are only separators; at least one digit is required.
ok = len(s) == 0 && digits > 0
return
}
/*
@@ -574,7 +584,7 @@ parse_i128_maybe_prefixed :: proc(str: string, n: ^int = nil) -> (value: i128, o
}
i := 0
i, digits := 0, 0
for r in s {
if r == '_' {
i += 1
@@ -597,9 +607,11 @@ parse_i128_maybe_prefixed :: proc(str: string, n: ^int = nil) -> (value: i128, o
value = value*base + v
}
i += 1
digits += 1
}
s = s[i:]
ok = len(s) == 0
// Underscores are only separators; at least one digit is required.
ok = len(s) == 0 && digits > 0
return
}
//
@@ -645,7 +657,7 @@ parse_u128_of_base :: proc(str: string, base: int, n: ^int = nil) -> (value: u12
s = s[1:]
}
i := 0
i, digits := 0, 0
for r in s {
if r == '_' {
i += 1
@@ -660,10 +672,12 @@ parse_u128_of_base :: proc(str: string, base: int, n: ^int = nil) -> (value: u12
}
value = value*u128(base) + v
i += 1
digits += 1
}
s = s[i:]
ok = len(s) == 0
// Underscores are only separators; at least one digit is required.
ok = len(s) == 0 && digits > 0
return
}
/*
@@ -717,7 +731,7 @@ parse_u128_maybe_prefixed :: proc(str: string, n: ^int = nil) -> (value: u128, o
}
}
i := 0
i, digits := 0, 0
for r in s {
if r == '_' {
i += 1
@@ -732,10 +746,12 @@ parse_u128_maybe_prefixed :: proc(str: string, n: ^int = nil) -> (value: u128, o
}
value = value*base + v
i += 1
digits += 1
}
s = s[i:]
ok = len(s) == 0
// Underscores are only separators; at least one digit is required.
ok = len(s) == 0 && digits > 0
return
}
//
+50
View File
@@ -268,6 +268,56 @@ test_parse_int_overflow :: proc(t: ^testing.T) {
_, ok = strconv.parse_uint("18446744073709551616")
testing.expect_value(t, ok, false)
}
{
// Cases reported in issue #7608.
_, ok := strconv.parse_u64("36893488147419103232")
testing.expect_value(t, ok, false)
_, ok = strconv.parse_u64("18446744073709551616", 10)
testing.expect_value(t, ok, false)
_, ok = strconv.parse_u64_maybe_prefixed("0xffffffffffffffffff")
testing.expect_value(t, ok, false)
_, ok = strconv.parse_int("99999999999999999999")
testing.expect_value(t, ok, false)
}
}
@(test)
test_parse_int_underscore_only :: proc(t: ^testing.T) {
for s in ([]string{"_", "__", "+_", "-_", "0x_", "0b__"}) {
_, ok_i64 := strconv.parse_i64(s)
testing.expectf(t, !ok_i64, "parse_i64(%q) should fail", s)
_, ok_u64 := strconv.parse_u64(s)
testing.expectf(t, !ok_u64, "parse_u64(%q) should fail", s)
_, ok_i128 := strconv.parse_i128(s)
testing.expectf(t, !ok_i128, "parse_i128(%q) should fail", s)
_, ok_u128 := strconv.parse_u128(s)
testing.expectf(t, !ok_u128, "parse_u128(%q) should fail", s)
_, ok_int := strconv.parse_int(s)
testing.expectf(t, !ok_int, "parse_int(%q) should fail", s)
_, ok_uint := strconv.parse_uint(s)
testing.expectf(t, !ok_uint, "parse_uint(%q) should fail", s)
}
for s in ([]string{"_", "__", "+_", "-_"}) {
_, ok_i64 := strconv.parse_i64(s, 10)
testing.expectf(t, !ok_i64, "parse_i64(%q, 10) should fail", s)
_, ok_u64 := strconv.parse_u64(s, 10)
testing.expectf(t, !ok_u64, "parse_u64(%q, 10) should fail", s)
_, ok_i128 := strconv.parse_i128(s, 10)
testing.expectf(t, !ok_i128, "parse_i128(%q, 10) should fail", s)
_, ok_u128 := strconv.parse_u128(s, 10)
testing.expectf(t, !ok_u128, "parse_u128(%q, 10) should fail", s)
}
// Underscores alongside at least one digit are still accepted.
v, ok := strconv.parse_u64("_1_")
testing.expect_value(t, v, 1)
testing.expect_value(t, ok, true)
v, ok = strconv.parse_u64("0x_ff")
testing.expect_value(t, v, 0xff)
testing.expect_value(t, ok, true)
iv, iok := strconv.parse_i64("-1_000", 10)
testing.expect_value(t, iv, -1000)
testing.expect_value(t, iok, true)
}
test_float_hex :: proc(t: ^testing.T) {