Skip to content

Commit 4739942

Browse files
mbrubeckmarijnh
authored andcommitted
Correct handling of non-numeric chars in parse_buf
Without this fix, int::parse_buf and uint::parse_buf return incorrect results for any strings that contain non-numeric characters. Fixes #1102.
1 parent 6f37acc commit 4739942

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

src/lib/int.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,15 @@ fn parse_buf(buf: [u8], radix: uint) -> int {
112112
}
113113
let n = 0;
114114
while true {
115-
n += (buf[i] - ('0' as u8) as int) * power;
115+
let digit = alt buf[i] as char {
116+
'0' to '9' { buf[i] - ('0' as u8) }
117+
'a' to 'z' { 10u8 + buf[i] - ('a' as u8) }
118+
'A' to 'Z' { 10u8 + buf[i] - ('A' as u8) }
119+
};
120+
if (digit as uint) >= radix {
121+
fail;
122+
}
123+
n += (digit as int) * power;
116124
power *= radix as int;
117125
if i <= start { ret n; }
118126
i -= 1u;

src/lib/uint.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,15 @@ fn parse_buf(buf: [u8], radix: uint) -> uint {
100100
let power = 1u;
101101
let n = 0u;
102102
while true {
103-
n += (buf[i] - ('0' as u8) as uint) * power;
103+
let digit = alt buf[i] as char {
104+
'0' to '9' { buf[i] - ('0' as u8) }
105+
'a' to 'z' { 10u8 + buf[i] - ('a' as u8) }
106+
'A' to 'Z' { 10u8 + buf[i] - ('A' as u8) }
107+
};
108+
if (digit as uint) >= radix {
109+
fail;
110+
}
111+
n += (digit as uint) * power;
104112
power *= radix;
105113
if i == 0u { ret n; }
106114
i -= 1u;

src/test/stdtest/int.rs

+22
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
use std;
33
import std::int;
44
import std::str::eq;
5+
import std::str::bytes;
56

67
#[test]
78
fn test_from_str() {
@@ -18,6 +19,27 @@ fn test_from_str() {
1819
assert(int::from_str("-00100") == -100);
1920
}
2021

22+
#[test]
23+
fn test_parse_buf() {
24+
assert (int::parse_buf(bytes("123"), 10u) == 123);
25+
assert (int::parse_buf(bytes("1001"), 2u) == 9);
26+
assert (int::parse_buf(bytes("123"), 8u) == 83);
27+
assert (int::parse_buf(bytes("123"), 16u) == 291);
28+
assert (int::parse_buf(bytes("ffff"), 16u) == 65535);
29+
assert (int::parse_buf(bytes("FFFF"), 16u) == 65535);
30+
assert (int::parse_buf(bytes("z"), 36u) == 35);
31+
assert (int::parse_buf(bytes("Z"), 36u) == 35);
32+
33+
assert (int::parse_buf(bytes("-123"), 10u) == -123);
34+
assert (int::parse_buf(bytes("-1001"), 2u) == -9);
35+
assert (int::parse_buf(bytes("-123"), 8u) == -83);
36+
assert (int::parse_buf(bytes("-123"), 16u) == -291);
37+
assert (int::parse_buf(bytes("-ffff"), 16u) == -65535);
38+
assert (int::parse_buf(bytes("-FFFF"), 16u) == -65535);
39+
assert (int::parse_buf(bytes("-z"), 36u) == -35);
40+
assert (int::parse_buf(bytes("-Z"), 36u) == -35);
41+
}
42+
2143
#[test]
2244
fn test_to_str() {
2345
assert (eq(int::to_str(0, 10u), "0"));

src/test/stdtest/uint.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,26 @@
33
// -*- rust -*-
44
use std;
55
import std::uint;
6+
import std::str::bytes;
7+
8+
#[test]
9+
fn test_from_str() {
10+
assert (uint::from_str("0") == 0u);
11+
assert (uint::from_str("3") == 3u);
12+
assert (uint::from_str("10") == 10u);
13+
assert (uint::from_str("123456789") == 123456789u);
14+
assert (uint::from_str("00100") == 100u);
15+
}
16+
17+
#[test]
18+
fn test_parse_buf() {
19+
assert (uint::parse_buf(bytes("123"), 10u) == 123u);
20+
assert (uint::parse_buf(bytes("1001"), 2u) == 9u);
21+
assert (uint::parse_buf(bytes("123"), 8u) == 83u);
22+
assert (uint::parse_buf(bytes("123"), 16u) == 291u);
23+
assert (uint::parse_buf(bytes("ffff"), 16u) == 65535u);
24+
assert (uint::parse_buf(bytes("z"), 36u) == 35u);
25+
}
626

727
#[test]
828
fn test_next_power_of_two() {
@@ -53,4 +73,4 @@ fn test_overflows() {
5373
assert (uint::max_value() > 0u);
5474
assert (uint::min_value() <= 0u);
5575
assert (uint::min_value() + uint::max_value() + 1u == 0u);
56-
}
76+
}

0 commit comments

Comments
 (0)