Skip to content

Fix int type casting error with negative base value #1406

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 25, 2019

Conversation

hqsz
Copy link
Contributor

@hqsz hqsz commented Sep 23, 2019

Change base type from u32 to i32

After result

>>>>> print(int(' 1 ', base=-1))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: int() base must be >= 2 and <= 36, or 0

Fixed: #1405

@hqsz
Copy link
Contributor Author

hqsz commented Sep 23, 2019

I want to test ints.py but my pytest does not working :(
does my test method is wrong?

$ pytest ints.py 
======================================== test session starts ========================================
platform linux -- Python 3.6.8, pytest-5.1.3, py-1.8.0, pluggy-0.13.0
rootdir: /home/jsh/RustPython/tests/snippets
collected 0 items                                                                                   

======================================= no tests ran in 0.06s =======================================

@coolreader18
Copy link
Member

Try running it from tests/ and passing snippets/ints.py as an argument.

@hqsz
Copy link
Contributor Author

hqsz commented Sep 24, 2019

I try with above method. but result is same.

$ pwd
/home/jsh/RustPython/tests
$ pytest snippets/ints.py 
============================= test session starts ==============================
platform linux -- Python 3.6.8, pytest-5.1.3, py-1.8.0, pluggy-0.13.0
rootdir: /home/jsh/RustPython/tests
collected 0 items                         
                                    
============================ no tests ran in 0.01s =============================

@coolreader18
Copy link
Member

Hmm, odd. And is just running pytest working?

@@ -704,7 +704,7 @@ struct IntOptions {
#[pyarg(positional_only, optional = true)]
val_options: OptionalArg<PyObjectRef>,
#[pyarg(positional_or_keyword, optional = true)]
base: OptionalArg<u32>,
base: OptionalArg<i32>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't completely fix the problem, it just shifts the range that the problem occurs, because if a PyInt can't fit into a i32 it still overflows. I recommend changing base to be a PyIntRef and passing a &BigInt around instead of an i32.

Copy link
Contributor Author

@hqsz hqsz Sep 24, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for reviewing. I Change base to PyIntRef. And i also add test for minus base and Large value than max of i32.

@hqsz
Copy link
Contributor Author

hqsz commented Sep 24, 2019

Yeah. just running pytest is working, but it execute all test. How can i test only ints.py?

@coolreader18
Copy link
Member

Try pytest -k rustpython_ints

@coolreader18
Copy link
Member

It's tricky because we're not actually running the test snippets with unittest/pytest, we have a custom loader test_snippets.py that loads all of the snippets as functions on a a test case class.

@hqsz
Copy link
Contributor Author

hqsz commented Sep 24, 2019

pytest -k rustpython_ints is working. thank you for your comment.
However, I think other people can ask similar question.
So, how about writing this method to test/README.md?

@hqsz hqsz force-pushed the fix-1405 branch 2 times, most recently from dd81aea to 188e485 Compare September 24, 2019 15:20
Change base type from u32 to PyIntRef

Fixed: RustPython#1405
@@ -105,7 +105,7 @@ where
}

fn get_int(vm: &VirtualMachine, arg: &PyObjectRef) -> PyResult<BigInt> {
objint::to_int(vm, arg, 10)
objint::to_int(vm, arg, &BigInt::from(10))
Copy link
Contributor

@windelbouwman windelbouwman Sep 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to prevent using BigInt here, you can change the signature of to_int to accept an Into<BigInt> instead of bigint itself. This will allow you to call the function with 10 and with a BigInt value as well.

Copy link
Contributor Author

@hqsz hqsz Sep 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@windelbouwman Thank you for reviewing. I agree that change signature of to_int will make to_int function more general.

But I have some questions. When we use base type to u32, we can easily pass the argument because u32 have copy trait. And when we use base type to pyIntRef, we can also pass reference of PyInt by as_bigint method.

But If i changed signature of to_int function. i cannot pass base to to_int function. Because PyInt does not have copy trait. Just simple modifying make this error.

error[E0507]: cannot move out of dereference of `pyobject::PyRef<obj::objint::PyInt>`
   --> vm/src/obj/objint.rs:721:34
    |
721 |                 to_int(vm, &val, base.value)
    |                                  ^^^^^^^^^^ move occurs because value has type `num_bigint::bigint::BigInt`, which does not implement the `Copy` trait

error: aborting due to previous error

And also change base type to BigInt occurs other error.

error[E0277]: the trait bound `num_bigint::bigint::BigInt: pyobject::TryFromObject` is not satisfied
   --> vm/src/obj/objint.rs:702:10
    |
702 | #[derive(FromArgs)]
    |          ^^^^^^^^ the trait `pyobject::TryFromObject` is not implemented for `num_bigint::bigint::BigInt`
    | 
   ::: vm/src/pyobject.rs:953:5
    |
953 |     fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self>;
    |     ---------------------------------------------------------------------------- required by `pyobject::TryFromObject::try_from_object`

Unfortunately, I'm not good at rust. so please give me an opinion. thx

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay, the copy trait is important here. I'm not a rust wizard either, so I think the current situation is probably ok. Maybe other people could have a look at this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the current solution is fine as well, passing an &BigInt rather than an Into<BigInt> removes the need for cloning as well.

@windelbouwman windelbouwman merged commit 51c3f71 into RustPython:master Sep 25, 2019
@hqsz hqsz deleted the fix-1405 branch December 3, 2019 07:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

int type casting with negative base value do not raise valueError
3 participants