Merge pull request #112 from Vlad-Shcherbina/patch-3

Disallow str/float to int conversions #108
This commit is contained in:
Nikolay Kim 2018-02-11 09:37:28 -08:00 committed by GitHub
commit 0874c243ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 36 deletions

View File

@ -98,9 +98,5 @@ mod test {
num_to_py_object_and_back!(to_from_f64, f64, f64); num_to_py_object_and_back!(to_from_f64, f64, f64);
num_to_py_object_and_back!(to_from_f32, f32, f32); num_to_py_object_and_back!(to_from_f32, f32, f32);
num_to_py_object_and_back!(float_to_i32, f64, i32);
num_to_py_object_and_back!(float_to_u32, f64, u32);
num_to_py_object_and_back!(float_to_i64, f64, i64);
num_to_py_object_and_back!(float_to_u64, f64, u64);
num_to_py_object_and_back!(int_to_float, i32, f64); num_to_py_object_and_back!(int_to_float, i32, f64);
} }

View File

@ -46,10 +46,17 @@ macro_rules! int_fits_c_long(
} }
} }
pyobject_extract!(obj to $rust_type => { pyobject_extract!(obj to $rust_type => {
let val = unsafe { ffi::PyLong_AsLong(obj.as_ptr()) }; let ptr = obj.as_ptr();
if val == -1 && PyErr::occurred(obj.py()) { let val = unsafe {
return Err(PyErr::fetch(obj.py())); let num = ffi::PyNumber_Index(ptr);
} if num.is_null() {
Err(PyErr::fetch(obj.py()))
} else {
let val = err_if_invalid_value(obj.py(), -1, ffi::PyLong_AsLong(num));
ffi::Py_DECREF(num);
val
}
}?;
match cast::<c_long, $rust_type>(val) { match cast::<c_long, $rust_type>(val) {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(exc::OverflowError.into()) None => Err(exc::OverflowError.into())
@ -96,7 +103,7 @@ fn err_if_invalid_value<T: PartialEq>
} }
macro_rules! int_convert_u64_or_i64 ( macro_rules! int_convert_u64_or_i64 (
($rust_type:ty, $pylong_from_ll_or_ull:expr, $pylong_as_ull_or_ull:expr) => ( ($rust_type:ty, $pylong_from_ll_or_ull:expr, $pylong_as_ll_or_ull:expr) => (
impl ToPyObject for $rust_type { impl ToPyObject for $rust_type {
#[inline] #[inline]
fn to_object(&self, py: Python) -> PyObject { fn to_object(&self, py: Python) -> PyObject {
@ -118,15 +125,13 @@ macro_rules! int_convert_u64_or_i64 (
{ {
let ptr = ob.as_ptr(); let ptr = ob.as_ptr();
unsafe { unsafe {
if ffi::PyLong_Check(ptr) != 0 { let num = ffi::PyNumber_Index(ptr);
err_if_invalid_value(ob.py(), !0, $pylong_as_ull_or_ull(ptr)) if num.is_null() {
Err(PyErr::fetch(ob.py()))
} else { } else {
let num = ffi::PyNumber_Long(ptr); let result = err_if_invalid_value(ob.py(), !0, $pylong_as_ll_or_ull(num));
if num.is_null() { ffi::Py_DECREF(num);
Err(PyErr::fetch(ob.py())) result
} else {
err_if_invalid_value(ob.py(), !0, $pylong_as_ull_or_ull(num))
}
} }
} }
} }
@ -171,29 +176,55 @@ mod test {
use python::Python; use python::Python;
use conversion::ToPyObject; use conversion::ToPyObject;
macro_rules! num_to_py_object_and_back ( macro_rules! test_common (
($func_name:ident, $t1:ty, $t2:ty) => ( ($test_mod_name:ident, $t:ty) => (
#[test] mod $test_mod_name {
fn $func_name() { use super::*;
let gil = Python::acquire_gil(); use objects::exc;
let py = gil.python();
let val = 123 as $t1; #[test]
let obj = val.to_object(py); fn from_py_string_type_error() {
assert_eq!(obj.extract::<$t2>(py).unwrap(), val as $t2); let gil = Python::acquire_gil();
let py = gil.python();
let obj = ("123").to_object(py);
let err = obj.extract::<$t>(py).unwrap_err();
assert!(err.is_instance::<exc::TypeError>(py));
}
#[test]
fn from_py_float_type_error() {
let gil = Python::acquire_gil();
let py = gil.python();
let obj = (12.3).to_object(py);
let err = obj.extract::<$t>(py).unwrap_err();
assert!(err.is_instance::<exc::TypeError>(py));
}
#[test]
fn to_py_object_and_back() {
let gil = Python::acquire_gil();
let py = gil.python();
let val = 123 as $t;
let obj = val.to_object(py);
assert_eq!(obj.extract::<$t>(py).unwrap(), val as $t);
}
} }
) )
); );
num_to_py_object_and_back!(to_from_i8, i8, i8); test_common!(i8, i8);
num_to_py_object_and_back!(to_from_u8, u8, u8); test_common!(u8, u8);
num_to_py_object_and_back!(to_from_i16, i16, i16); test_common!(i16, i16);
num_to_py_object_and_back!(to_from_u16, u16, u16); test_common!(u16, u16);
num_to_py_object_and_back!(to_from_i32, i32, i32); test_common!(i32, i32);
num_to_py_object_and_back!(to_from_u32, u32, u32); test_common!(u32, u32);
num_to_py_object_and_back!(to_from_i64, i64, i64); test_common!(i64, i64);
num_to_py_object_and_back!(to_from_u64, u64, u64); test_common!(u64, u64);
num_to_py_object_and_back!(to_from_isize, isize, isize); test_common!(isize, isize);
num_to_py_object_and_back!(to_from_usize, usize, usize); test_common!(usize, usize);
#[test] #[test]
fn test_u32_max() { fn test_u32_max() {