Skip to content

Commit 12f0e2b

Browse files
committed
parse_number can raise error about length
1 parent c335791 commit 12f0e2b

File tree

2 files changed

+17
-12
lines changed

2 files changed

+17
-12
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 & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -155,16 +155,19 @@ 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));
162162
}
163-
// This should never fail
164-
(
163+
if num_digits >= 20 {
164+
// NOTE: this is different from CPython
165+
return Err("Too many decimal digits in format string");
166+
}
167+
Ok((
165168
Some(text[..num_digits].parse::<usize>().unwrap()),
166169
&text[num_digits..],
167-
)
170+
))
168171
}
169172

170173
fn parse_sign(text: &str) -> (Option<FormatSign>, &str) {
@@ -193,19 +196,19 @@ fn parse_zero(text: &str) -> (bool, &str) {
193196
}
194197
}
195198

196-
fn parse_precision(text: &str) -> (Option<usize>, &str) {
199+
fn parse_precision(text: &str) -> Result<(Option<usize>, &str), &'static str> {
197200
let mut chars = text.chars();
198-
match chars.next() {
201+
Ok(match chars.next() {
199202
Some('.') => {
200-
let (size, remaining) = parse_number(&chars.as_str());
203+
let (size, remaining) = parse_number(&chars.as_str())?;
201204
if size.is_some() {
202205
(size, remaining)
203206
} else {
204207
(None, text)
205208
}
206209
}
207210
_ => (None, text),
208-
}
211+
})
209212
}
210213

211214
fn parse_grouping_option(text: &str) -> (Option<FormatGrouping>, &str) {
@@ -239,14 +242,15 @@ fn parse_format_type(text: &str) -> (Option<FormatType>, &str) {
239242
}
240243

241244
fn parse_format_spec(text: &str) -> Result<FormatSpec, &'static str> {
245+
// get_integer in CPython
242246
let (preconversor, after_preconversor) = parse_preconversor(text);
243247
let (mut fill, mut align, after_align) = parse_fill_and_align(after_preconversor);
244248
let (sign, after_sign) = parse_sign(after_align);
245249
let (alternate_form, after_alternate_form) = parse_alternate_form(after_sign);
246250
let (zero, after_zero) = parse_zero(after_alternate_form);
247-
let (width, after_width) = parse_number(after_zero);
251+
let (width, after_width) = parse_number(after_zero)?;
248252
let (grouping_option, after_grouping_option) = parse_grouping_option(after_width);
249-
let (precision, after_precision) = parse_precision(after_grouping_option);
253+
let (precision, after_precision) = parse_precision(after_grouping_option)?;
250254
let (format_type, after_format_type) = parse_format_type(after_precision);
251255
if !after_format_type.is_empty() {
252256
return Err("Invalid format specifier");

0 commit comments

Comments
 (0)