From cb6dedbe6276387f7deeb864a65457e2c732001b Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 6 Jun 2021 10:19:30 +0200 Subject: [PATCH 1/2] PyList: fix segfault on get_item with negative indices See #1667. --- src/types/list.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/types/list.rs b/src/types/list.rs index 7649d4b259b..c6098e69119 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -70,7 +70,7 @@ impl PyList { /// /// Panics if the index is out of range. pub fn get_item(&self, index: isize) -> &PyAny { - assert!((index.abs() as usize) < self.len()); + assert!(index >= 0 && index < self.len() as isize); unsafe { #[cfg(not(Py_LIMITED_API))] let ptr = ffi::PyList_GET_ITEM(self.as_ptr(), index as Py_ssize_t); @@ -237,6 +237,15 @@ mod test { assert_eq!(7, list.get_item(3).extract::().unwrap()); } + #[test] + #[should_panic] + fn test_get_item_invalid() { + let gil = Python::acquire_gil(); + let py = gil.python(); + let list = PyList::new(py, [2, 3, 5, 7]); + list.get_item(-1); + } + #[test] fn test_set_item() { let gil = Python::acquire_gil(); From 98461a2ef6e66935be7455f3df905799943498ea Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 6 Jun 2021 10:19:42 +0200 Subject: [PATCH 2/2] PyList tests: simplify construction --- CHANGELOG.md | 1 + src/types/list.rs | 35 ++++++++++------------------------- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8825b1ea9bf..3a558cfe9b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fix unneccessary rebuilds when cycling between `cargo check` and `cargo clippy` in a Python virtualenv. [#1557](https://github.com/PyO3/pyo3/pull/1557) - Fix segfault when dereferencing `ffi::PyDateTimeAPI` without the GIL. [#1563](https://github.com/PyO3/pyo3/pull/1563) - Fix memory leak when converting to u128 and i128. [#1638](https://github.com/PyO3/pyo3/pull/1638) +- Fix segfault when calling `PyList::get_item` with negative indices. [#1668](https://github.com/PyO3/pyo3/pull/1668) ## [0.13.2] - 2021-02-12 ### Packaging diff --git a/src/types/list.rs b/src/types/list.rs index c6098e69119..5d981c1aacd 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -206,8 +206,7 @@ mod test { fn test_new() { let gil = Python::acquire_gil(); let py = gil.python(); - let v = vec![2, 3, 5, 7]; - let list = PyList::new(py, &v); + let list = PyList::new(py, &[2, 3, 5, 7]); assert_eq!(2, list.get_item(0).extract::().unwrap()); assert_eq!(3, list.get_item(1).extract::().unwrap()); assert_eq!(5, list.get_item(2).extract::().unwrap()); @@ -218,9 +217,7 @@ mod test { fn test_len() { let gil = Python::acquire_gil(); let py = gil.python(); - let v = vec![1, 2, 3, 4]; - let ob = v.to_object(py); - let list = ::try_from(ob.as_ref(py)).unwrap(); + let list = PyList::new(py, &[1, 2, 3, 4]); assert_eq!(4, list.len()); } @@ -228,9 +225,7 @@ mod test { fn test_get_item() { let gil = Python::acquire_gil(); let py = gil.python(); - let v = vec![2, 3, 5, 7]; - let ob = v.to_object(py); - let list = ::try_from(ob.as_ref(py)).unwrap(); + let list = PyList::new(py, &[2, 3, 5, 7]); assert_eq!(2, list.get_item(0).extract::().unwrap()); assert_eq!(3, list.get_item(1).extract::().unwrap()); assert_eq!(5, list.get_item(2).extract::().unwrap()); @@ -242,7 +237,7 @@ mod test { fn test_get_item_invalid() { let gil = Python::acquire_gil(); let py = gil.python(); - let list = PyList::new(py, [2, 3, 5, 7]); + let list = PyList::new(py, &[2, 3, 5, 7]); list.get_item(-1); } @@ -250,9 +245,7 @@ mod test { fn test_set_item() { let gil = Python::acquire_gil(); let py = gil.python(); - let v = vec![2, 3, 5, 7]; - let ob = v.to_object(py); - let list = ::try_from(ob.as_ref(py)).unwrap(); + let list = PyList::new(py, &[2, 3, 5, 7]); let val = 42i32.to_object(py); assert_eq!(2, list.get_item(0).extract::().unwrap()); list.set_item(0, val).unwrap(); @@ -282,9 +275,7 @@ mod test { fn test_insert() { let gil = Python::acquire_gil(); let py = gil.python(); - let v = vec![2, 3, 5, 7]; - let ob = v.to_object(py); - let list = ::try_from(ob.as_ref(py)).unwrap(); + let list = PyList::new(py, &[2, 3, 5, 7]); let val = 42i32.to_object(py); assert_eq!(4, list.len()); assert_eq!(2, list.get_item(0).extract::().unwrap()); @@ -315,9 +306,7 @@ mod test { fn test_append() { let gil = Python::acquire_gil(); let py = gil.python(); - let v = vec![2]; - let ob = v.to_object(py); - let list = ::try_from(ob.as_ref(py)).unwrap(); + let list = PyList::new(py, &[2]); list.append(3).unwrap(); assert_eq!(2, list.get_item(0).extract::().unwrap()); assert_eq!(3, list.get_item(1).extract::().unwrap()); @@ -344,8 +333,7 @@ mod test { let gil = Python::acquire_gil(); let py = gil.python(); let v = vec![2, 3, 5, 7]; - let ob = v.to_object(py); - let list = ::try_from(ob.as_ref(py)).unwrap(); + let list = PyList::new(py, &v); let mut idx = 0; for el in list.iter() { assert_eq!(v[idx], el.extract::().unwrap()); @@ -358,9 +346,7 @@ mod test { fn test_into_iter() { let gil = Python::acquire_gil(); let py = gil.python(); - let v = vec![1, 2, 3, 4]; - let ob = v.to_object(py); - let list = ::try_from(ob.as_ref(py)).unwrap(); + let list = PyList::new(py, &[1, 2, 3, 4]); for (i, item) in list.iter().enumerate() { assert_eq!((i + 1) as i32, item.extract::().unwrap()); } @@ -371,8 +357,7 @@ mod test { let gil = Python::acquire_gil(); let py = gil.python(); let v = vec![2, 3, 5, 7]; - let ob = v.to_object(py); - let list = ::try_from(ob.as_ref(py)).unwrap(); + let list = PyList::new(py, &v); let v2 = list.as_ref().extract::>().unwrap(); assert_eq!(v, v2); }