Skip to content

Commit b8f276f

Browse files
authored
Fix OverflowError at collections.rs (RustPython#3815)
1 parent 166c45d commit b8f276f

File tree

4 files changed

+29
-31
lines changed

4 files changed

+29
-31
lines changed

Lib/test/seq_tests.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,6 @@ def __eq__(self, other):
362362

363363
self.assertRaises(BadExc, a.count, BadCmp())
364364

365-
# TODO: RUSTPYTHON
366-
@unittest.expectedFailure
367365
def test_index(self):
368366
u = self.type2test([0, 1])
369367
self.assertEqual(u.index(0), 0)

extra_tests/snippets/stdlib_collections_deque.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from testutils import assert_raises
12
from collections import deque
23
from typing import Deque
34

@@ -93,3 +94,6 @@ class D(deque):
9394

9495
assert repr(D()) == "D([])"
9596
assert repr(D([1, 2, 3])) == "D([1, 2, 3])"
97+
98+
99+
assert_raises(ValueError, lambda: deque().index(10,0,10000000000000000000000000))

vm/src/builtins/tuple.rs

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{PositionIterInternal, PyGenericAlias, PyType, PyTypeRef};
1+
use super::{PositionIterInternal, PyGenericAlias, PyIntRef, PyType, PyTypeRef};
22
use crate::common::{hash::PyHash, lock::PyMutex};
33
use crate::{
44
class::PyClassImpl,
@@ -8,8 +8,8 @@ use crate::{
88
protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods},
99
recursion::ReprGuard,
1010
sequence::SequenceExt,
11+
sliceable::pyint_saturate_index,
1112
sliceable::{SequenceIndex, SliceableSequenceOp},
12-
stdlib::sys,
1313
types::{
1414
AsMapping, AsSequence, Comparable, Constructor, Hashable, IterNext, IterNextIterable,
1515
Iterable, PyComparisonOp, Unconstructible,
@@ -281,24 +281,17 @@ impl PyTuple {
281281
fn index(
282282
&self,
283283
needle: PyObjectRef,
284-
start: OptionalArg<isize>,
285-
stop: OptionalArg<isize>,
284+
start: OptionalArg<PyObjectRef>,
285+
stop: OptionalArg<PyObjectRef>,
286286
vm: &VirtualMachine,
287287
) -> PyResult<usize> {
288-
let mut start = start.into_option().unwrap_or(0);
289-
if start < 0 {
290-
start += self.len() as isize;
291-
if start < 0 {
292-
start = 0;
293-
}
294-
}
295-
let mut stop = stop.into_option().unwrap_or(sys::MAXSIZE);
296-
if stop < 0 {
297-
stop += self.len() as isize;
298-
if stop < 0 {
299-
stop = 0;
300-
}
301-
}
288+
let len = self.len();
289+
let saturate = |obj: PyObjectRef, len| -> PyResult<_> {
290+
obj.try_into_value(vm)
291+
.map(|int: PyIntRef| pyint_saturate_index(int, len))
292+
};
293+
let start = start.map_or(Ok(0), |i| saturate(i, len))?;
294+
let stop = stop.map_or(Ok(len), |i| saturate(i, len))?;
302295
for (index, element) in self
303296
.elements
304297
.iter()

vm/src/stdlib/collections.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod _collections {
55
use crate::{
66
builtins::{
77
IterStatus::{Active, Exhausted},
8-
PositionIterInternal, PyGenericAlias, PyInt, PyTypeRef,
8+
PositionIterInternal, PyGenericAlias, PyInt, PyIntRef, PyTypeRef,
99
},
1010
common::lock::{PyMutex, PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard},
1111
function::{FuncArgs, KwArgs, OptionalArg, PyComparisonValue},
@@ -14,7 +14,7 @@ mod _collections {
1414
recursion::ReprGuard,
1515
sequence::MutObjectSequenceOp,
1616
sliceable,
17-
sliceable::saturate_index,
17+
sliceable::pyint_saturate_index,
1818
types::{
1919
AsSequence, Comparable, Constructor, Hashable, Initializer, IterNext, IterNextIterable,
2020
Iterable, PyComparisonOp, Unhashable,
@@ -157,26 +157,29 @@ mod _collections {
157157
#[pymethod]
158158
fn index(
159159
&self,
160-
obj: PyObjectRef,
161-
start: OptionalArg<isize>,
162-
stop: OptionalArg<isize>,
160+
needle: PyObjectRef,
161+
start: OptionalArg<PyObjectRef>,
162+
stop: OptionalArg<PyObjectRef>,
163163
vm: &VirtualMachine,
164164
) -> PyResult<usize> {
165165
let start_state = self.state.load();
166166

167167
let len = self.len();
168-
let start = start.map(|i| saturate_index(i, len)).unwrap_or(0);
169-
let stop = stop
170-
.map(|i| saturate_index(i, len))
171-
.unwrap_or(isize::MAX as usize);
172-
let index = self.mut_index_range(vm, &obj, start..stop)?;
168+
let saturate = |obj: PyObjectRef, len| -> PyResult<_> {
169+
obj.try_into_value(vm)
170+
.map(|int: PyIntRef| pyint_saturate_index(int, len))
171+
};
172+
let start = start.map_or(Ok(0), |i| saturate(i, len))?;
173+
let stop = stop.map_or(Ok(len), |i| saturate(i, len))?;
174+
let index = self.mut_index_range(vm, &needle, start..stop)?;
173175
if start_state != self.state.load() {
174176
Err(vm.new_runtime_error("deque mutated during iteration".to_owned()))
175177
} else if let Some(index) = index.into() {
176178
Ok(index)
177179
} else {
178180
Err(vm.new_value_error(
179-
obj.repr(vm)
181+
needle
182+
.repr(vm)
180183
.map(|repr| format!("{} is not in deque", repr))
181184
.unwrap_or_else(|_| String::new()),
182185
))

0 commit comments

Comments
 (0)