8000 Panic in hash wrapping when user hash returns oversized int · Issue #6550 · RustPython/RustPython · GitHub
[go: up one dir, main page]

Skip to content

Panic in hash wrapping when user hash returns oversized int #6550

@jackfromeast

Description

@jackfromeast

What happened?

Calling hash() on an object whose __hash__ returns an oversized integer (e.g., 1 << 63) causes a panic in hash_wrapper. The wrapper attempts to convert the BigInt to i64, then falls back to % u64::MAX, but that remainder can still be outside i64 and leads to unwrap() on None instead of raising a Python exception or normalizing safely.

Proof of Concept:

class Evil:
    def __hash__(self):
        return 1 << 63

hash(Evil())
Affected Versions
RustPython Version Status Exit Code
Python 3.13.0alpha (heads/main-dirty:21300f689, Dec 13 2025, 22:16:49) [RustPython 0.4.0 with rustc 1.90.0-nightly (11ad40bb8 2025-06-28)] Panic 1
Vulnerable Code
fn hash_wrapper(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyHash> {
    let hash_obj = vm.call_special_method(zelf, identifier!(vm, __hash__), ())?;
    let py_int = hash_obj
        .downcast_ref::<PyInt>()
        .ok_or_else(|| vm.new_type_error("__hash__ method should return an integer"))?;
    let big_int = py_int.as_bigint();
    let hash: PyHash = big_int
        .to_i64()
        .unwrap_or_else(|| (big_int % BigInt::from(u64::MAX)).to_i64().unwrap()); // Bug: u64::MAX should be i64::Max
    Ok(hash)
}
Rust Output
thread 'main' panicked at crates/vm/src/types/slot.rs:369:72:
called `Option::unwrap()` on a `None` value
stack backtrace:
   0: __rustc::rust_begin_unwind
             at /rustc/11ad40bb839ca16f74784b4ab72596ad85587298/library/std/src/panicking.rs:697:5
   1: core::panicking::panic_fmt
             at /rustc/11ad40bb839ca16f74784b4ab72596ad85587298/library/core/src/panicking.rs:75:14
   2: core::panicking::panic
             at /rustc/11ad40bb839ca16f74784b4ab72596ad85587298/library/core/src/panicking.rs:145:5
   3: core::option::unwrap_failed
             at /rustc/11ad40bb839ca16f74784b4ab72596ad85587298/library/core/src/option.rs:2072:5
   4: core::option::Option<T>::unwrap
             at /home/jackfromeast/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:1005:21
   5: rustpython_vm::types::slot::hash_wrapper::{{closure}}
             at ./crates/vm/src/types/slot.rs:369:72
   6: core::option::Option<T>::unwrap_or_else
             at /home/jackfromeast/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:1050:21
   7: rustpython_vm::types::slot::hash_wrapper
             at ./crates/vm/src/types/slot.rs:369:10
   8: rustpython_vm::protocol::object::<impl rustpython_vm::object::core::PyObject>::hash
             at ./crates/vm/src/protocol/object.rs:663:20
   9: rustpython_vm::stdlib::builtins::builtins::hash
             at ./crates/vm/src/stdlib/builtins.rs:440:13
  10: core::ops::function::Fn::call
             at /home/jackfromeast/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:79:5
  11: rustpython_vm::function::builtin::<impl rustpython_vm::function::builtin::sealed::PyNativeFnInternal<(rustpython_vm::function::builtin::OwnedParam<T1>,),R,rustpython_vm::vm::VirtualMachine> for F>::call_
             at ./crates/vm/src/function/builtin.rs:126:17
  12: <F as rustpython_vm::function::builtin::IntoPyNativeFn<(T,R,VM)>>::call
             at ./crates/vm/src/function/builtin.rs:92:14
  13: rustpython_vm::function::builtin::into_func::{{closure}}
             at ./crates/vm/src/function/builtin.rs:50:40
  14: <rustpython_vm::builtins::builtin_func::PyNativeFunction as rustpython_vm::types::slot::Callable>::call
             at ./crates/vm/src/builtins/builtin_func.rs:73:9
  15: rustpython_vm::types::slot::Callable::slot_call
             at ./crates/vm/src/types/slot.rs:1028:9
  16: rustpython_vm::protocol::callable::PyCallable::invoke
             at ./crates/vm/src/protocol/callable.rs:52:22
  17: rustpython_vm::protocol::callable::<impl rustpython_vm::object::core::PyObject>::call_with_args
             at ./crates/vm/src/protocol/callable.rs:33:18
  18: rustpython_vm::protocol::callable::<impl rustpython_vm::object::core::PyObject>::call
             at ./crates/vm/src/protocol/callable.rs:22:14
  19: rustpython_vm::frame::ExecutingFrame::execute_call
             at ./crates/vm/src/frame.rs:1880:30
  20: rustpython_vm::frame::ExecutingFrame::execute_instruction
             at ./crates/vm/src/frame.rs:667:22
  21: rustpython_vm::frame::ExecutingFrame::run
             at ./crates/vm/src/frame.rs:372:31
  22: rustpython_vm::frame::<impl rustpython_vm::object::core::Py<rustpython_vm::frame::Frame>>::run::{{closure}}
             at ./crates/vm/src/frame.rs:247:40
  23: rustpython_vm::frame::<impl rustpython_vm::object::core::Py<rustpython_vm::frame::Frame>>::with_exec
             at ./crates/vm/src/frame.rs:242:9
  24: rustpython_vm::frame::<impl rustpython_vm::object::core::Py<rustpython_vm::frame::Frame>>::run
             at ./crates/vm/src/frame.rs:247:14
  25: rustpython_vm::vm::VirtualMachine::run_frame::{{closure}}
             at ./crates/vm/src/vm/mod.rs:467:44
  26: rustpython_vm::vm::VirtualMachine::with_frame::{{closure}}
             at ./crates/vm/src/vm/mod.rs:495:26
  27: rustpython_vm::vm::VirtualMachine::with_recursion
             at ./crates/vm/src/vm/mod.rs:483:22
  28: rustpython_vm::vm::VirtualMachine::with_frame
             at ./crates/vm/src/vm/mod.rs:493:14
  29: rustpython_vm::vm::VirtualMachine::run_frame
             at ./crates/vm/src/vm/mod.rs:467:20
  30: rustpython_vm::vm::VirtualMac
6308
hine::run_code_obj
             at ./crates/vm/src/vm/mod.rs:442:14
  31: rustpython_vm::vm::compile::<impl rustpython_vm::vm::VirtualMachine>::run_simple_file
             at ./crates/vm/src/vm/compile.rs:93:26
  32: rustpython_vm::vm::compile::<impl rustpython_vm::vm::VirtualMachine>::run_any_file
             at ./crates/vm/src/vm/compile.rs:57:14
  33: rustpython_vm::vm::compile::<impl rustpython_vm::vm::VirtualMachine>::run_script
             at ./crates/vm/src/vm/compile.rs:50:14
  34: rustpython::run_rustpython
             at ./src/lib.rs:231:16
  35: rustpython::run::{{closure}}
             at ./src/lib.rs:112:41
  36: rustpython_vm::vm::interpreter::Interpreter::run::{{closure}}
             at ./crates/vm/src/vm/interpreter.rs:103:35
  37: rustpython_vm::vm::interpreter::Interpreter::enter::{{closure}}
             at ./crates/vm/src/vm/interpreter.rs:72:39
  38: scoped_tls::ScopedKey<T>::set
             at /home/jackfromeast/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scoped-tls-1.0.1/src/lib.rs:137:9
  39: rustpython_vm::vm::thread::enter_vm::{{closure}}
             at ./crates/vm/src/vm/thread.rs:30:20
  40: std::thread::local::LocalKey<T>::try_with
             at /home/jackfromeast/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:315:12
  41: std::thread::local::LocalKey<T>::with
             at /home/jackfromeast/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:279:20
  42: rustpython_vm::vm::thread::enter_vm
             at ./crates/vm/src/vm/thread.rs:27:14
  43: rustpython_vm::vm::interpreter::Interpreter::enter
             at ./crates/vm/src/vm/interpreter.rs:72:9
  44: rustpython_vm::vm::interpreter::Interpreter::run
             at ./crates/vm/src/vm/interpreter.rs:103:24
  45: rustpython::run
             at ./src/lib.rs:112:27
  46: rustpython::main
             at ./src/main.rs:2:5
  47: core::ops::function::FnOnce::call_once
             at /home/jackfromeast/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
CPython Output
(No output)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0