Skip to content

Commit 8b7158f

Browse files
Make common::repr throw error instead of panic (RustPython#4520)
1 parent 82c1a3a commit 8b7158f

File tree

6 files changed

+25
-14
lines changed

6 files changed

+25
-14
lines changed

common/src/bytes.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
pub fn repr(b: &[u8]) -> String {
1+
use crate::str::ReprOverflowError;
2+
3+
pub fn repr(b: &[u8]) -> Result<String, ReprOverflowError> {
24
repr_with(b, &[], "")
35
}
46

5-
pub fn repr_with(b: &[u8], prefixes: &[&str], suffix: &str) -> String {
7+
pub fn repr_with(b: &[u8], prefixes: &[&str], suffix: &str) -> Result<String, ReprOverflowError> {
68
use std::fmt::Write;
79

810
let mut out_len = 0usize;
@@ -23,8 +25,7 @@ pub fn repr_with(b: &[u8], prefixes: &[&str], suffix: &str) -> String {
2325
0x20..=0x7e => 1,
2426
_ => 4, // \xHH
2527
};
26-
// TODO: OverflowError
27-
out_len = out_len.checked_add(incr).unwrap();
28+
out_len = out_len.checked_add(incr).ok_or(ReprOverflowError)?;
2829
}
2930

3031
let (quote, num_escaped_quotes) = crate::str::choose_quotes_for_repr(squote, dquote);
@@ -57,5 +58,5 @@ pub fn repr_with(b: &[u8], prefixes: &[&str], suffix: &str) -> String {
5758
res.push(quote);
5859
res.push_str(suffix);
5960

60-
res
61+
Ok(res)
6162
}

compiler/ast/src/constant.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::fmt::Error;
2+
13
use num_bigint::BigInt;
24
pub use rustpython_compiler_core::ConversionFlag;
35

@@ -42,7 +44,7 @@ impl std::fmt::Display for Constant {
4244
Constant::None => f.pad("None"),
4345
Constant::Bool(b) => f.pad(if *b { "True" } else { "False" }),
4446
Constant::Str(s) => rustpython_common::str::repr(s).fmt(f),
45-
Constant::Bytes(b) => f.pad(&rustpython_common::bytes::repr(b)),
47+
Constant::Bytes(b) => f.pad(&rustpython_common::bytes::repr(b).map_err(|_err| Error)?),
4648
Constant::Int(i) => i.fmt(f),
4749
Constant::Tuple(tup) => {
4850
if let [elt] = &**tup {

vm/src/builtins/bytearray.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,10 @@ impl PyByteArray {
123123
}
124124

125125
#[pymethod(magic)]
126-
fn repr(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyResult<String> {
126+
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<String> {
127127
let class = zelf.class();
128128
let class_name = class.name();
129-
let s = zelf.inner().repr(Some(&class_name));
130-
Ok(s)
129+
zelf.inner().repr(Some(&class_name), vm)
131130
}
132131

133132
#[pymethod(magic)]

vm/src/builtins/bytes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ impl PyBytes {
116116
)]
117117
impl PyBytes {
118118
#[pymethod(magic)]
119-
pub(crate) fn repr(&self) -> String {
120-
self.inner.repr(None)
119+
pub(crate) fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
120+
self.inner.repr(None, vm)
121121
}
122122

123123
#[pymethod(magic)]

vm/src/bytesinner.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
},
66
byte::bytes_from_object,
77
cformat::cformat_bytes,
8+
convert::ToPyException,
89
function::{ArgIterable, Either, OptionalArg, OptionalOption, PyComparisonValue},
910
identifier,
1011
protocol::PyBuffer,
@@ -246,12 +247,13 @@ impl PyBytesInner {
246247
&self.elements
247248
}
248249

249-
pub fn repr(&self, class_name: Option<&str>) -> String {
250-
if let Some(class_name) = class_name {
250+
pub fn repr(&self, class_name: Option<&str>, vm: &VirtualMachine) -> PyResult<String> {
251+
let repr = if let Some(class_name) = class_name {
251252
rustpython_common::bytes::repr_with(&self.elements, &[class_name, "("], ")")
252253
} else {
253254
rustpython_common::bytes::repr(&self.elements)
254-
}
255+
};
256+
repr.map_err(|err| err.to_pyexception(vm))
255257
}
256258

257259
#[inline]

vm/src/exceptions.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use self::types::{PyBaseException, PyBaseExceptionRef};
22
use crate::builtins::tuple::IntoPyTuple;
33
use crate::common::lock::PyRwLock;
4+
use crate::common::str::ReprOverflowError;
45
use crate::{
56
builtins::{
67
traceback::PyTracebackRef, PyNone, PyStr, PyStrRef, PyTuple, PyTupleRef, PyType, PyTypeRef,
@@ -1621,3 +1622,9 @@ pub(super) mod types {
16211622
"Base class for warnings about encodings."
16221623
}
16231624
}
1625+
1626+
impl ToPyException for ReprOverflowError {
1627+
fn to_pyexception(&self, vm: &VirtualMachine) -> PyBaseExceptionRef {
1628+
vm.new_overflow_error(self.to_string())
1629+
}
1630+
}

0 commit comments

Comments
 (0)