From 12db02eaf0f6d7451e02d9a529ba0cd93dd8eca0 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Sat, 14 Feb 2026 12:52:21 +0900 Subject: [PATCH] Fix _hashlib --- Cargo.lock | 2 + crates/codegen/src/compile.rs | 4 +- crates/stdlib/Cargo.toml | 4 +- crates/stdlib/src/blake2.rs | 4 +- crates/stdlib/src/hashlib.rs | 389 +++++++++++++++++++++++++++++----- crates/stdlib/src/md5.rs | 2 +- crates/stdlib/src/sha1.rs | 2 +- crates/stdlib/src/sha256.rs | 4 +- crates/stdlib/src/sha3.rs | 12 +- crates/stdlib/src/sha512.rs | 4 +- crates/vm/src/vm/mod.rs | 2 +- 11 files changed, 362 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa661627d..906621e09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3226,6 +3226,7 @@ dependencies = [ "foreign-types-shared", "gethostname", "hex", + "hmac", "indexmap", "itertools 0.14.0", "libc", @@ -3250,6 +3251,7 @@ dependencies = [ "page_size", "parking_lot", "paste", + "pbkdf2", "pem-rfc7468 1.0.0", "phf 0.13.1", "pkcs8", diff --git a/crates/codegen/src/compile.rs b/crates/codegen/src/compile.rs index c13ec694a..c132c0f4b 100644 --- a/crates/codegen/src/compile.rs +++ b/crates/codegen/src/compile.rs @@ -3717,7 +3717,7 @@ impl Compiler { // Compile kwdefaults and build dict for (arg, default) in &kw_with_defaults { self.emit_load_const(ConstantData::Str { - value: arg.name.as_str().into(), + value: self.mangle(arg.name.as_str()).into_owned().into(), }); self.compile_expression(default)?; } @@ -6983,7 +6983,7 @@ impl Compiler { let default_kw_count = kw_with_defaults.len(); for (arg, default) in &kw_with_defaults { self.emit_load_const(ConstantData::Str { - value: arg.name.as_str().into(), + value: self.mangle(arg.name.as_str()).into_owned().into(), }); self.compile_expression(default)?; } diff --git a/crates/stdlib/Cargo.toml b/crates/stdlib/Cargo.toml index d0da89d42..0fed25e8b 100644 --- a/crates/stdlib/Cargo.toml +++ b/crates/stdlib/Cargo.toml @@ -61,12 +61,14 @@ rand_core = { workspace = true } mt19937 = "3.1" # Crypto: -digest = "0.10.3" +digest = "0.10.7" md-5 = "0.10.1" sha-1 = "0.10.0" sha2 = "0.10.2" sha3 = "0.10.1" blake2 = "0.10.4" +hmac = "0.12" +pbkdf2 = { version = "0.12", features = ["hmac"] } ## unicode stuff unicode_names2 = { workspace = true } diff --git a/crates/stdlib/src/blake2.rs b/crates/stdlib/src/blake2.rs index 5d2e991b9..53687c702 100644 --- a/crates/stdlib/src/blake2.rs +++ b/crates/stdlib/src/blake2.rs @@ -9,11 +9,11 @@ mod _blake2 { #[pyfunction] fn blake2b(args: BlakeHashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_blake2b(args).into_pyobject(vm)) + Ok(local_blake2b(args, vm)?.into_pyobject(vm)) } #[pyfunction] fn blake2s(args: BlakeHashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_blake2s(args).into_pyobject(vm)) + Ok(local_blake2s(args, vm)?.into_pyobject(vm)) } } diff --git a/crates/stdlib/src/hashlib.rs b/crates/stdlib/src/hashlib.rs index eeb87b90e..5a2a55b93 100644 --- a/crates/stdlib/src/hashlib.rs +++ b/crates/stdlib/src/hashlib.rs @@ -1,4 +1,7 @@ -// spell-checker:ignore usedforsecurity HASHXOF +// spell-checker:ignore usedforsecurity HASHXOF hashopenssl dklen +// NOTE: Function names like `openssl_md5` match CPython's `_hashopenssl.c` interface +// for compatibility, but the implementation uses pure Rust crates (md5, sha2, etc.), +// not OpenSSL. pub(crate) use _hashlib::module_def; @@ -7,7 +10,9 @@ pub mod _hashlib { use crate::common::lock::PyRwLock; use crate::vm::{ Py, PyObjectRef, PyPayload, PyResult, VirtualMachine, - builtins::{PyBytes, PyStrRef, PyTypeRef, PyValueError}, + builtins::{ + PyBaseExceptionRef, PyBytes, PyFrozenSet, PyStr, PyStrRef, PyTypeRef, PyValueError, + }, class::StaticType, convert::ToPyObject, function::{ArgBytesLike, ArgStrOrBytesLike, FuncArgs, OptionalArg}, @@ -17,17 +22,59 @@ pub mod _hashlib { use digest::{DynDigest, core_api::BlockSizeUser}; use digest::{ExtendableOutput, Update}; use dyn_clone::{DynClone, clone_trait_object}; + use hmac::Mac; use md5::Md5; use sha1::Sha1; use sha2::{Sha224, Sha256, Sha384, Sha512}; use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128, Shake256}; + const HASH_ALGORITHMS: &[&str] = &[ + "md5", + "sha1", + "sha224", + "sha256", + "sha384", + "sha512", + "sha3_224", + "sha3_256", + "sha3_384", + "sha3_512", + "shake_128", + "shake_256", + "blake2b", + "blake2s", + ]; + + #[pyattr] + const _GIL_MINSIZE: usize = 2048; + #[pyattr] #[pyexception(name = "UnsupportedDigestmodError", base = PyValueError, impl)] #[derive(Debug)] #[repr(transparent)] pub struct UnsupportedDigestmodError(PyValueError); + #[pyattr] + fn openssl_md_meth_names(vm: &VirtualMachine) -> PyObjectRef { + PyFrozenSet::from_iter( + vm, + HASH_ALGORITHMS.iter().map(|n| vm.ctx.new_str(*n).into()), + ) + .expect("failed to create openssl_md_meth_names frozenset") + .into_ref(&vm.ctx) + .into() + } + + #[pyattr] + fn _constructors(vm: &VirtualMachine) -> PyObjectRef { + let dict = vm.ctx.new_dict(); + for name in HASH_ALGORITHMS { + let s = vm.ctx.new_str(*name); + dict.set_item(&*s, s.clone().into(), vm).unwrap(); + } + dict.into() + } + #[derive(FromArgs, Debug)] #[allow(unused)] struct NewHashArgs { @@ -37,15 +84,19 @@ pub mod _hashlib { data: OptionalArg, #[pyarg(named, default = true)] usedforsecurity: bool, + #[pyarg(named, optional)] + string: OptionalArg, } #[derive(FromArgs)] #[allow(unused)] pub struct BlakeHashArgs { - #[pyarg(positional, optional)] + #[pyarg(any, optional)] pub data: OptionalArg, #[pyarg(named, default = true)] usedforsecurity: bool, + #[pyarg(named, optional)] + pub string: OptionalArg, } impl From for BlakeHashArgs { @@ -53,6 +104,7 @@ pub mod _hashlib { Self { data: args.data, usedforsecurity: args.usedforsecurity, + string: args.string, } } } @@ -61,16 +113,19 @@ pub mod _hashlib { #[allow(unused)] pub struct HashArgs { #[pyarg(any, optional)] - pub string: OptionalArg, + pub data: OptionalArg, #[pyarg(named, default = true)] usedforsecurity: bool, + #[pyarg(named, optional)] + pub string: OptionalArg, } impl From for HashArgs { fn from(args: NewHashArgs) -> Self { Self { - string: args.data, + data: args.data, usedforsecurity: args.usedforsecurity, + string: args.string, } } } @@ -118,6 +173,91 @@ pub mod _hashlib { } } + #[derive(FromArgs)] + #[allow(unused)] + struct HmacDigestArgs { + #[pyarg(positional)] + key: ArgBytesLike, + #[pyarg(positional)] + msg: ArgBytesLike, + #[pyarg(positional)] + digest: PyObjectRef, + } + + #[derive(FromArgs)] + #[allow(unused)] + struct Pbkdf2HmacArgs { + #[pyarg(any)] + hash_name: PyStrRef, + #[pyarg(any)] + password: ArgBytesLike, + #[pyarg(any)] + salt: ArgBytesLike, + #[pyarg(any)] + iterations: i64, + #[pyarg(any, optional)] + dklen: OptionalArg, + } + + fn resolve_data( + data: OptionalArg, + string: OptionalArg, + vm: &VirtualMachine, + ) -> PyResult> { + match (data.into_option(), string.into_option()) { + (Some(d), None) => Ok(OptionalArg::Present(d)), + (None, Some(s)) => Ok(OptionalArg::Present(s)), + (None, None) => Ok(OptionalArg::Missing), + (Some(_), Some(_)) => Err(vm.new_type_error( + "'data' and 'string' are mutually exclusive \ + and support for 'string' keyword parameter \ + is slated for removal in a future version." + .to_owned(), + )), + } + } + + fn resolve_digestmod(digestmod: &PyObjectRef, vm: &VirtualMachine) -> PyResult { + if let Some(name) = digestmod.downcast_ref::() { + return Ok(name.as_str().to_lowercase()); + } + if let Ok(name_obj) = digestmod.get_attr("__name__", vm) + && let Some(name) = name_obj.downcast_ref::() + && let Some(algo) = name.as_str().strip_prefix("openssl_") + { + return Ok(algo.to_owned()); + } + Err(vm.new_exception_msg( + UnsupportedDigestmodError::static_type().to_owned(), + "unsupported digestmod".to_owned(), + )) + } + + fn hash_digest_size(name: &str) -> Option { + match name { + "md5" => Some(16), + "sha1" => Some(20), + "sha224" => Some(28), + "sha256" => Some(32), + "sha384" => Some(48), + "sha512" => Some(64), + "sha3_224" => Some(28), + "sha3_256" => Some(32), + "sha3_384" => Some(48), + "sha3_512" => Some(64), + "blake2b" => Some(64), + "blake2s" => Some(32), + _ => None, + } + } + + fn unsupported_hash(name: &str, vm: &VirtualMachine) -> PyBaseExceptionRef { + vm.new_exception_msg( + UnsupportedDigestmodError::static_type().to_owned(), + format!("unsupported hash type {name}"), + ) + } + #[pyattr] #[pyclass(module = "_hashlib", name = "HASH")] #[derive(PyPayload)] @@ -309,93 +449,163 @@ pub mod _hashlib { #[pyfunction(name = "new")] fn hashlib_new(args: NewHashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; match args.name.as_str().to_lowercase().as_str() { - "md5" => Ok(local_md5(args.into()).into_pyobject(vm)), - "sha1" => Ok(local_sha1(args.into()).into_pyobject(vm)), - "sha224" => Ok(local_sha224(args.into()).into_pyobject(vm)), - "sha256" => Ok(local_sha256(args.into()).into_pyobject(vm)), - "sha384" => Ok(local_sha384(args.into()).into_pyobject(vm)), - "sha512" => Ok(local_sha512(args.into()).into_pyobject(vm)), - "sha3_224" => Ok(local_sha3_224(args.into()).into_pyobject(vm)), - "sha3_256" => Ok(local_sha3_256(args.into()).into_pyobject(vm)), - "sha3_384" => Ok(local_sha3_384(args.into()).into_pyobject(vm)), - "sha3_512" => Ok(local_sha3_512(args.into()).into_pyobject(vm)), - "shake_128" => Ok(local_shake_128(args.into()).into_pyobject(vm)), - "shake_256" => Ok(local_shake_256(args.into()).into_pyobject(vm)), - "blake2b" => Ok(local_blake2b(args.into()).into_pyobject(vm)), - "blake2s" => Ok(local_blake2s(args.into()).into_pyobject(vm)), + "md5" => Ok(PyHasher::new("md5", HashWrapper::new::(data)).into_pyobject(vm)), + "sha1" => Ok(PyHasher::new("sha1", HashWrapper::new::(data)).into_pyobject(vm)), + "sha224" => { + Ok(PyHasher::new("sha224", HashWrapper::new::(data)).into_pyobject(vm)) + } + "sha256" => { + Ok(PyHasher::new("sha256", HashWrapper::new::(data)).into_pyobject(vm)) + } + "sha384" => { + Ok(PyHasher::new("sha384", HashWrapper::new::(data)).into_pyobject(vm)) + } + "sha512" => { + Ok(PyHasher::new("sha512", HashWrapper::new::(data)).into_pyobject(vm)) + } + "sha3_224" => { + Ok(PyHasher::new("sha3_224", HashWrapper::new::(data)).into_pyobject(vm)) + } + "sha3_256" => { + Ok(PyHasher::new("sha3_256", HashWrapper::new::(data)).into_pyobject(vm)) + } + "sha3_384" => { + Ok(PyHasher::new("sha3_384", HashWrapper::new::(data)).into_pyobject(vm)) + } + "sha3_512" => { + Ok(PyHasher::new("sha3_512", HashWrapper::new::(data)).into_pyobject(vm)) + } + "shake_128" => Ok( + PyHasherXof::new("shake_128", HashXofWrapper::new_shake_128(data)) + .into_pyobject(vm), + ), + "shake_256" => Ok( + PyHasherXof::new("shake_256", HashXofWrapper::new_shake_256(data)) + .into_pyobject(vm), + ), + "blake2b" => Ok( + PyHasher::new("blake2b", HashWrapper::new::(data)).into_pyobject(vm), + ), + "blake2s" => Ok( + PyHasher::new("blake2s", HashWrapper::new::(data)).into_pyobject(vm), + ), other => Err(vm.new_value_error(format!("Unknown hashing algorithm: {other}"))), } } #[pyfunction(name = "openssl_md5")] - pub fn local_md5(args: HashArgs) -> PyHasher { - PyHasher::new("md5", HashWrapper::new::(args.string)) + pub fn local_md5(args: HashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasher::new("md5", HashWrapper::new::(data))) } #[pyfunction(name = "openssl_sha1")] - pub fn local_sha1(args: HashArgs) -> PyHasher { - PyHasher::new("sha1", HashWrapper::new::(args.string)) + pub fn local_sha1(args: HashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasher::new("sha1", HashWrapper::new::(data))) } #[pyfunction(name = "openssl_sha224")] - pub fn local_sha224(args: HashArgs) -> PyHasher { - PyHasher::new("sha224", HashWrapper::new::(args.string)) + pub fn local_sha224(args: HashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasher::new("sha224", HashWrapper::new::(data))) } #[pyfunction(name = "openssl_sha256")] - pub fn local_sha256(args: HashArgs) -> PyHasher { - PyHasher::new("sha256", HashWrapper::new::(args.string)) + pub fn local_sha256(args: HashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasher::new("sha256", HashWrapper::new::(data))) } #[pyfunction(name = "openssl_sha384")] - pub fn local_sha384(args: HashArgs) -> PyHasher { - PyHasher::new("sha384", HashWrapper::new::(args.string)) + pub fn local_sha384(args: HashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasher::new("sha384", HashWrapper::new::(data))) } #[pyfunction(name = "openssl_sha512")] - pub fn local_sha512(args: HashArgs) -> PyHasher { - PyHasher::new("sha512", HashWrapper::new::(args.string)) + pub fn local_sha512(args: HashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasher::new("sha512", HashWrapper::new::(data))) } #[pyfunction(name = "openssl_sha3_224")] - pub fn local_sha3_224(args: HashArgs) -> PyHasher { - PyHasher::new("sha3_224", HashWrapper::new::(args.string)) + pub fn local_sha3_224(args: HashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasher::new( + "sha3_224", + HashWrapper::new::(data), + )) } #[pyfunction(name = "openssl_sha3_256")] - pub fn local_sha3_256(args: HashArgs) -> PyHasher { - PyHasher::new("sha3_256", HashWrapper::new::(args.string)) + pub fn local_sha3_256(args: HashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasher::new( + "sha3_256", + HashWrapper::new::(data), + )) } #[pyfunction(name = "openssl_sha3_384")] - pub fn local_sha3_384(args: HashArgs) -> PyHasher { - PyHasher::new("sha3_384", HashWrapper::new::(args.string)) + pub fn local_sha3_384(args: HashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasher::new( + "sha3_384", + HashWrapper::new::(data), + )) } #[pyfunction(name = "openssl_sha3_512")] - pub fn local_sha3_512(args: HashArgs) -> PyHasher { - PyHasher::new("sha3_512", HashWrapper::new::(args.string)) + pub fn local_sha3_512(args: HashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasher::new( + "sha3_512", + HashWrapper::new::(data), + )) } #[pyfunction(name = "openssl_shake_128")] - pub fn local_shake_128(args: HashArgs) -> PyHasherXof { - PyHasherXof::new("shake_128", HashXofWrapper::new_shake_128(args.string)) + pub fn local_shake_128(args: HashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasherXof::new( + "shake_128", + HashXofWrapper::new_shake_128(data), + )) } #[pyfunction(name = "openssl_shake_256")] - pub fn local_shake_256(args: HashArgs) -> PyHasherXof { - PyHasherXof::new("shake_256", HashXofWrapper::new_shake_256(args.string)) + pub fn local_shake_256(args: HashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasherXof::new( + "shake_256", + HashXofWrapper::new_shake_256(data), + )) } #[pyfunction(name = "openssl_blake2b")] - pub fn local_blake2b(args: BlakeHashArgs) -> PyHasher { - PyHasher::new("blake2b", HashWrapper::new::(args.data)) + pub fn local_blake2b(args: BlakeHashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasher::new( + "blake2b", + HashWrapper::new::(data), + )) } #[pyfunction(name = "openssl_blake2s")] - pub fn local_blake2s(args: BlakeHashArgs) -> PyHasher { - PyHasher::new("blake2s", HashWrapper::new::(args.data)) + pub fn local_blake2s(args: BlakeHashArgs, vm: &VirtualMachine) -> PyResult { + let data = resolve_data(args.data, args.string, vm)?; + Ok(PyHasher::new( + "blake2s", + HashWrapper::new::(data), + )) + } + + #[pyfunction] + fn get_fips_mode() -> i32 { + 0 } #[pyfunction] @@ -434,7 +644,6 @@ pub mod _hashlib { #[pyfunction] fn hmac_new(args: NewHMACHashArgs, vm: &VirtualMachine) -> PyResult { - // Raise UnsupportedDigestmodError so Python's hmac.py falls back to pure-Python implementation let _ = args; Err(vm.new_exception_msg( UnsupportedDigestmodError::static_type().to_owned(), @@ -442,12 +651,94 @@ pub mod _hashlib { )) } + #[pyfunction] + fn hmac_digest(args: HmacDigestArgs, vm: &VirtualMachine) -> PyResult { + let name = resolve_digestmod(&args.digest, vm)?; + + let key_buf = args.key.borrow_buf(); + let msg_buf = args.msg.borrow_buf(); + + macro_rules! do_hmac { + ($hash_ty:ty) => {{ + let mut mac = as Mac>::new_from_slice(&key_buf) + .map_err(|_| vm.new_value_error("invalid key length".to_owned()))?; + Mac::update(&mut mac, &msg_buf); + Ok(mac.finalize().into_bytes().to_vec().into()) + }}; + } + + match name.as_str() { + "md5" => do_hmac!(Md5), + "sha1" => do_hmac!(Sha1), + "sha224" => do_hmac!(Sha224), + "sha256" => do_hmac!(Sha256), + "sha384" => do_hmac!(Sha384), + "sha512" => do_hmac!(Sha512), + "sha3_224" => do_hmac!(Sha3_224), + "sha3_256" => do_hmac!(Sha3_256), + "sha3_384" => do_hmac!(Sha3_384), + "sha3_512" => do_hmac!(Sha3_512), + _ => Err(unsupported_hash(&name, vm)), + } + } + + #[pyfunction] + fn pbkdf2_hmac(args: Pbkdf2HmacArgs, vm: &VirtualMachine) -> PyResult { + let name = args.hash_name.as_str().to_lowercase(); + + if args.iterations < 1 { + return Err(vm.new_value_error("iteration value must be greater than 0.".to_owned())); + } + let rounds = u32::try_from(args.iterations) + .map_err(|_| vm.new_overflow_error("iteration value is too great.".to_owned()))?; + + let dklen: usize = match args.dklen.into_option() { + Some(obj) if vm.is_none(&obj) => { + hash_digest_size(&name).ok_or_else(|| unsupported_hash(&name, vm))? + } + Some(obj) => { + let len: i64 = obj.try_into_value(vm)?; + if len < 1 { + return Err(vm.new_value_error("key length must be greater than 0.".to_owned())); + } + usize::try_from(len).map_err(|_| { + vm.new_overflow_error("key length is too great.".to_owned()) + })? + } + None => hash_digest_size(&name).ok_or_else(|| unsupported_hash(&name, vm))?, + }; + + let password_buf = args.password.borrow_buf(); + let salt_buf = args.salt.borrow_buf(); + let mut dk = vec![0u8; dklen]; + + macro_rules! do_pbkdf2 { + ($hash_ty:ty) => {{ + pbkdf2::pbkdf2_hmac::<$hash_ty>(&password_buf, &salt_buf, rounds, &mut dk); + Ok(dk.into()) + }}; + } + + match name.as_str() { + "md5" => do_pbkdf2!(Md5), + "sha1" => do_pbkdf2!(Sha1), + "sha224" => do_pbkdf2!(Sha224), + "sha256" => do_pbkdf2!(Sha256), + "sha384" => do_pbkdf2!(Sha384), + "sha512" => do_pbkdf2!(Sha512), + "sha3_224" => do_pbkdf2!(Sha3_224), + "sha3_256" => do_pbkdf2!(Sha3_256), + "sha3_384" => do_pbkdf2!(Sha3_384), + "sha3_512" => do_pbkdf2!(Sha3_512), + _ => Err(unsupported_hash(&name, vm)), + } + } + pub trait ThreadSafeDynDigest: DynClone + DynDigest + Sync + Send {} impl ThreadSafeDynDigest for T where T: DynClone + DynDigest + Sync + Send {} clone_trait_object!(ThreadSafeDynDigest); - /// Generic wrapper patching around the hashing libraries. #[derive(Clone)] pub struct HashWrapper { block_size: usize, diff --git a/crates/stdlib/src/md5.rs b/crates/stdlib/src/md5.rs index 11923b165..2ff6cd24f 100644 --- a/crates/stdlib/src/md5.rs +++ b/crates/stdlib/src/md5.rs @@ -7,6 +7,6 @@ mod _md5 { #[pyfunction] fn md5(args: HashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_md5(args).into_pyobject(vm)) + Ok(local_md5(args, vm)?.into_pyobject(vm)) } } diff --git a/crates/stdlib/src/sha1.rs b/crates/stdlib/src/sha1.rs index 28d4bcbbe..3e3d4928c 100644 --- a/crates/stdlib/src/sha1.rs +++ b/crates/stdlib/src/sha1.rs @@ -7,6 +7,6 @@ mod _sha1 { #[pyfunction] fn sha1(args: HashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_sha1(args).into_pyobject(vm)) + Ok(local_sha1(args, vm)?.into_pyobject(vm)) } } diff --git a/crates/stdlib/src/sha256.rs b/crates/stdlib/src/sha256.rs index bf4a39373..b4c26dc0d 100644 --- a/crates/stdlib/src/sha256.rs +++ b/crates/stdlib/src/sha256.rs @@ -5,12 +5,12 @@ mod _sha256 { #[pyfunction] fn sha224(args: HashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_sha224(args).into_pyobject(vm)) + Ok(local_sha224(args, vm)?.into_pyobject(vm)) } #[pyfunction] fn sha256(args: HashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_sha256(args).into_pyobject(vm)) + Ok(local_sha256(args, vm)?.into_pyobject(vm)) } pub(crate) fn module_exec(vm: &VirtualMachine, module: &Py) -> PyResult<()> { diff --git a/crates/stdlib/src/sha3.rs b/crates/stdlib/src/sha3.rs index e7342d0dd..0eb2dfa84 100644 --- a/crates/stdlib/src/sha3.rs +++ b/crates/stdlib/src/sha3.rs @@ -10,31 +10,31 @@ mod _sha3 { #[pyfunction] fn sha3_224(args: HashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_sha3_224(args).into_pyobject(vm)) + Ok(local_sha3_224(args, vm)?.into_pyobject(vm)) } #[pyfunction] fn sha3_256(args: HashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_sha3_256(args).into_pyobject(vm)) + Ok(local_sha3_256(args, vm)?.into_pyobject(vm)) } #[pyfunction] fn sha3_384(args: HashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_sha3_384(args).into_pyobject(vm)) + Ok(local_sha3_384(args, vm)?.into_pyobject(vm)) } #[pyfunction] fn sha3_512(args: HashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_sha3_512(args).into_pyobject(vm)) + Ok(local_sha3_512(args, vm)?.into_pyobject(vm)) } #[pyfunction] fn shake_128(args: HashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_shake_128(args).into_pyobject(vm)) + Ok(local_shake_128(args, vm)?.into_pyobject(vm)) } #[pyfunction] fn shake_256(args: HashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_shake_256(args).into_pyobject(vm)) + Ok(local_shake_256(args, vm)?.into_pyobject(vm)) } } diff --git a/crates/stdlib/src/sha512.rs b/crates/stdlib/src/sha512.rs index 303c0067d..b7c6f02ed 100644 --- a/crates/stdlib/src/sha512.rs +++ b/crates/stdlib/src/sha512.rs @@ -5,12 +5,12 @@ mod _sha512 { #[pyfunction] fn sha384(args: HashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_sha384(args).into_pyobject(vm)) + Ok(local_sha384(args, vm)?.into_pyobject(vm)) } #[pyfunction] fn sha512(args: HashArgs, vm: &VirtualMachine) -> PyResult { - Ok(local_sha512(args).into_pyobject(vm)) + Ok(local_sha512(args, vm)?.into_pyobject(vm)) } pub(crate) fn module_exec(vm: &VirtualMachine, module: &Py) -> PyResult<()> { diff --git a/crates/vm/src/vm/mod.rs b/crates/vm/src/vm/mod.rs index 934c79b2e..10409d943 100644 --- a/crates/vm/src/vm/mod.rs +++ b/crates/vm/src/vm/mod.rs @@ -397,7 +397,7 @@ impl VirtualMachine { )?; let mode = if write { "w" } else { "r" }; stdio.set_attr("mode", self.ctx.new_str(mode), self)?; - Ok(stdio) + Ok::<_, self::PyBaseExceptionRef>(stdio) }; // Sandbox stdio: lightweight wrapper using Rust's std::io directly