Skip to content

Commit 52c5eec

Browse files
authored
Merge pull request RustPython#1725 from youknowone/fix-parse-number
parse_number can raise error about length
2 parents 8272e47 + 1c2b01f commit 52c5eec

File tree

2 files changed

+17
-14
lines changed

2 files changed

+17
-14
lines changed

Lib/test/test_types.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,8 @@ def test(f, format_spec, result):
563563
test(12345.6, "1=20", '111111111111112345.6')
564564
test(12345.6, "*=20", '*************12345.6')
565565

566-
@unittest.skip("TODO: RUSTPYTHON")
566+
# TODO: RUSTPYTHON
567+
@unittest.expectedFailure
567568
def test_format_spec_errors(self):
568569
# int, float, and string all share the same format spec
569570
# mini-language parser.

vm/src/format.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -155,16 +155,17 @@ fn parse_fill_and_align(text: &str) -> (Option<char>, Option<FormatAlign>, &str)
155155
}
156156
}
157157

158-
fn parse_number(text: &str) -> (Option<usize>, &str) {
158+
fn parse_number(text: &str) -> Result<(Option<usize>, &str), &'static str> {
159159
let num_digits: usize = get_num_digits(text);
160160
if num_digits == 0 {
161-
return (None, text);
161+
return Ok((None, text));
162+
}
163+
if let Ok(num) = text[..num_digits].parse::<usize>() {
164+
Ok((Some(num), &text[num_digits..]))
165+
} else {
166+
// NOTE: this condition is different from CPython
167+
Err("Too many decimal digits in format string")
162168
}
163-
// This should never fail
164-
(
165-
Some(text[..num_digits].parse::<usize>().unwrap()),
166-
&text[num_digits..],
167-
)
168169
}
169170

170171
fn parse_sign(text: &str) -> (Option<FormatSign>, &str) {
@@ -193,19 +194,19 @@ fn parse_zero(text: &str) -> (bool, &str) {
193194
}
194195
}
195196

196-
fn parse_precision(text: &str) -> (Option<usize>, &str) {
197+
fn parse_precision(text: &str) -> Result<(Option<usize>, &str), &'static str> {
197198
let mut chars = text.chars();
198-
match chars.next() {
199+
Ok(match chars.next() {
199200
Some('.') => {
200-
let (size, remaining) = parse_number(&chars.as_str());
201+
let (size, remaining) = parse_number(&chars.as_str())?;
201202
if size.is_some() {
202203
(size, remaining)
203204
} else {
204205
(None, text)
205206
}
206207
}
207208
_ => (None, text),
208-
}
209+
})
209210
}
210211

211212
fn parse_grouping_option(text: &str) -> (Option<FormatGrouping>, &str) {
@@ -239,14 +240,15 @@ fn parse_format_type(text: &str) -> (Option<FormatType>, &str) {
239240
}
240241

241242
fn parse_format_spec(text: &str) -> Result<FormatSpec, &'static str> {
243+
// get_integer in CPython
242244
let (preconversor, after_preconversor) = parse_preconversor(text);
243245
let (mut fill, mut align, after_align) = parse_fill_and_align(after_preconversor);
244246
let (sign, after_sign) = parse_sign(after_align);
245247
let (alternate_form, after_alternate_form) = parse_alternate_form(after_sign);
246248
let (zero, after_zero) = parse_zero(after_alternate_form);
247-
let (width, after_width) = parse_number(after_zero);
249+
let (width, after_width) = parse_number(after_zero)?;
248250
let (grouping_option, after_grouping_option) = parse_grouping_option(after_width);
249-
let (precision, after_precision) = parse_precision(after_grouping_option);
251+
let (precision, after_precision) = parse_precision(after_grouping_option)?;
250252
let (format_type, after_format_type) = parse_format_type(after_precision);
251253
if !after_format_type.is_empty() {
252254
return Err("Invalid format specifier");

0 commit comments

Comments
 (0)