From 2ea6c3247e7270e26c904452bc7d05862601a1cb Mon Sep 17 00:00:00 2001 From: Corey Bonnell Date: Sun, 13 Oct 2024 23:14:15 -0400 Subject: [PATCH 1/6] Update to latest PyO3 --- Cargo.toml | 4 +- pyproject.toml | 1 + src/asn1_type.rs | 218 ++++++++++++++++++++++++----------------------- src/decoder.rs | 125 ++++++++++++++------------- src/lib.rs | 76 +++++++++-------- src/tag.rs | 19 +++-- 6 files changed, 232 insertions(+), 211 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c647fb2..a3098cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyasn1-fasder" -version = "0.1.2" +version = "0.1.3" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -9,7 +9,7 @@ name = "pyasn1_fasder" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.20.3", features = ["num-bigint"] } +pyo3 = { version = "0.22.4", features = ["abi3", "num-bigint"] } der = { version = "0.7.8", features = ["oid"] } num-bigint = "0.4.6" itertools = "0.13.0" diff --git a/pyproject.toml b/pyproject.toml index fa55c63..7589957 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] dynamic = ["version"] dependencies = [ diff --git a/src/asn1_type.rs b/src/asn1_type.rs index eb43a74..c08f78f 100644 --- a/src/asn1_type.rs +++ b/src/asn1_type.rs @@ -1,33 +1,33 @@ -use pyo3::{intern, IntoPy, PyAny, PyErr, PyObject, PyResult}; -use pyo3::types::{IntoPyDict, PyBytes, PyDict, PySet, PyTuple}; +use crate::decoder::DecodeStep; +use crate::{decode_der_rec, decode_explicit, decoder, get_chosen_spec, tag, NativeHelperModule, TAGSET_ATTR}; use der::asn1::{ObjectIdentifier, PrintableStringRef}; use itertools::Itertools; -use crate::{decode_der_rec, decode_explicit, decoder, get_chosen_spec, NativeHelperModule, tag, TAGSET_ATTR}; -use crate::decoder::DecodeStep; +use pyo3::prelude::PyAnyMethods; +use pyo3::types::{IntoPyDict, PyBool, PyBytes, PyDict, PySet, PyString, PyTuple}; +use pyo3::{intern, Bound, IntoPy, PyAny, PyErr, PyResult}; const CONSTRUCTED_SET_COMPONENT_KWARGS: &str = "_CONSTRUCTED_SET_COMPONENT_KWARGS"; const CHOICE_SET_COMPONENT_KWARGS: &str = "_CHOICE_SET_COMPONENT_KWARGS"; - -fn create_value_args(value: &PyAny) -> &PyTuple { - PyTuple::new(value.py(), vec![value]) +fn create_value_args<'py>(value: Bound<'py, PyAny>) -> Bound<'py, PyTuple> { + PyTuple::new_bound(value.py(), vec![value]) } -fn clone_asn1_schema_obj<'py>(asn1_schema_obj: &'py PyAny, args: &PyTuple, kwargs: Option<&PyDict>) -> PyResult<&'py PyAny> { - asn1_schema_obj.call_method(intern![asn1_schema_obj.py(), "clone"], args, kwargs) +fn clone_asn1_schema_obj<'py>(asn1_schema_obj: &Bound<'py, PyAny>, args: Bound, kwargs: Option>) -> PyResult> { + asn1_schema_obj.call_method(intern![asn1_schema_obj.py(), "clone"], args, kwargs.as_ref()) } -pub trait Decoder<'py> { - fn verify_raw(self: &Self) -> PyResult<()> { +pub trait Decoder<'a, 'py> { + fn verify_raw(self: &'a Self) -> PyResult<()> { Ok(()) } - fn decode(self: &Self) -> PyResult<&'py PyAny>; + fn decode(self: &'a Self) -> PyResult> where 'py: 'a; - fn verify_decoded(self: &Self, _asn1_value: &PyAny) -> PyResult<()> { + fn verify_decoded(self: &'a Self, _asn1_value: &Bound<'py, PyAny>) -> PyResult<()> { Ok(()) } } @@ -43,7 +43,7 @@ impl<'py> BooleanDecoder<'py> { } } -impl<'py> Decoder<'py> for BooleanDecoder<'py> { +impl<'a, 'py> Decoder<'a, 'py> for BooleanDecoder<'py> { fn verify_raw(&self) -> PyResult<()> { if self.step.tag().format() != tag::FORMAT_SIMPLE { return Err(self.step.create_error("Invalid BOOLEAN value format")); @@ -62,7 +62,7 @@ impl<'py> Decoder<'py> for BooleanDecoder<'py> { } } - fn decode(&self) -> PyResult<&'py PyAny> { + fn decode(&'a self) -> PyResult> where 'py: 'a { let py = self.step.asn1_spec().py(); let mapped_int_bool: u8 = match self.step.value_substrate()[0] { @@ -70,9 +70,9 @@ impl<'py> Decoder<'py> for BooleanDecoder<'py> { _ => 1, }; - let py_value: PyObject = mapped_int_bool.into_py(py); + let py_value = mapped_int_bool.into_py(py).bind(py).clone(); - clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(py_value.as_ref(py)), None) + clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(py_value), None) } } @@ -88,7 +88,7 @@ impl<'py> IntegerDecoder<'py> { } } -impl<'py> Decoder<'py> for IntegerDecoder<'py> { +impl<'a, 'py> Decoder<'a, 'py> for IntegerDecoder<'py> { fn verify_raw(self: &Self) -> PyResult<()> { if self.step.tag().format() != tag::FORMAT_SIMPLE { return Err(self.step.create_error(&format!("Invalid {} value format", self.type_name))); @@ -108,10 +108,11 @@ impl<'py> Decoder<'py> for IntegerDecoder<'py> { Ok(()) } - fn decode(self: &Self) -> PyResult<&'py PyAny> { + fn decode(self: &'a Self) -> PyResult> where 'py: 'a { let py = self.step.asn1_spec().py(); - let py_value = num_bigint::BigInt::from_signed_bytes_be(self.step.value_substrate()).into_py(py).into_ref(py); + let binding = num_bigint::BigInt::from_signed_bytes_be(self.step.value_substrate()).into_py(py); + let py_value = binding.bind(py).clone(); clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(py_value), None) } @@ -138,7 +139,7 @@ impl<'py> BitStringDecoder<'py> { } } -impl<'py> Decoder<'py> for BitStringDecoder<'py> { +impl<'a, 'py> Decoder<'a, 'py> for BitStringDecoder<'py> { fn verify_raw(self: &Self) -> PyResult<()> { if self.step.tag().format() != tag::FORMAT_SIMPLE { return Err(self.step.create_error("Invalid BIT STRING value format")); @@ -165,7 +166,7 @@ impl<'py> Decoder<'py> for BitStringDecoder<'py> { return Err(self.step.create_error("Non-zero trailer value in BIT STRING")); } - if self.step.asn1_spec().getattr(intern![self.step.asn1_spec().py(), "namedValues"]).unwrap().is_true().unwrap() { + if self.step.asn1_spec().getattr(intern![self.step.asn1_spec().py(), "namedValues"])?.is_truthy()? { let last_octet = value_substrate[value_substrate_len - 1]; return self.check_named_bit_string(trailer_bit_count, last_octet) @@ -175,15 +176,16 @@ impl<'py> Decoder<'py> for BitStringDecoder<'py> { Ok(()) } - fn decode(self: &Self) -> PyResult<&'py PyAny> { + fn decode(self: &'a Self) -> PyResult> where 'py: 'a { let py = self.step.asn1_spec().py(); let value = self.step.asn1_spec().call_method( - intern![py, "fromOctetString"], create_value_args(PyBytes::new(py, &self.step.value_substrate()[1..])), - Some([ - (intern![py, "internalFormat"], true.into_py(py).as_ref(py)), - (intern![py, "padding"], self.step.value_substrate()[0].into_py(py).as_ref(py))] - .into_py_dict(py)) + intern![py, "fromOctetString"], create_value_args(PyBytes::new_bound(py, &self.step.value_substrate()[1..]).into_any()), + Some(&[ + (intern![py, "internalFormat"], PyBool::new_bound(py, true).as_any()), + (intern![py, "padding"], self.step.value_substrate()[0].into_py(py).bind(py))] + .into_py_dict_bound(py) + ) )?; clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(value), None) @@ -202,7 +204,7 @@ impl<'py> OctetStringDecoder<'py> { } -impl<'py> Decoder<'py> for OctetStringDecoder<'py> { +impl<'a, 'py> Decoder<'a, 'py> for OctetStringDecoder<'py> { fn verify_raw(self: &Self) -> PyResult<()> { match self.step.tag().format() { @@ -211,10 +213,10 @@ impl<'py> Decoder<'py> for OctetStringDecoder<'py> { } } - fn decode(self: &Self) -> PyResult<&'py PyAny> { + fn decode(self: &'a Self) -> PyResult> where 'py: 'a { let py = self.step.asn1_spec().py(); - clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(PyBytes::new(py, self.step.value_substrate())), None) + clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(PyBytes::new_bound(py, self.step.value_substrate()).into_any()), None) } } @@ -229,7 +231,7 @@ impl<'py> NullDecoder<'py> { } } -impl<'py> Decoder<'py> for NullDecoder<'py> { +impl<'a, 'py> Decoder<'a, 'py> for NullDecoder<'py> { fn verify_raw(self: &Self) -> PyResult<()> { if self.step.tag().format() != tag::FORMAT_SIMPLE { return Err(self.step.create_error("Invalid NULL value format")) @@ -241,10 +243,10 @@ impl<'py> Decoder<'py> for NullDecoder<'py> { } } - fn decode(self: &Self) -> PyResult<&'py PyAny> { + fn decode(self: &'a Self) -> PyResult> where 'py: 'a { let py = self.step.asn1_spec().py(); - clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(intern![py, ""]), None) + clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(PyString::new_bound(py, "").into_any()), None) } } @@ -259,7 +261,7 @@ impl<'py> ObjectIdentifierDecoder<'py> { } } -impl<'py> Decoder<'py> for ObjectIdentifierDecoder<'py> { +impl<'a, 'py> Decoder<'a, 'py> for ObjectIdentifierDecoder<'py> { fn verify_raw(self: &Self) -> PyResult<()> { match self.step.tag().format() { tag::FORMAT_SIMPLE => Ok(()), @@ -267,14 +269,14 @@ impl<'py> Decoder<'py> for ObjectIdentifierDecoder<'py> { } } - fn decode(self: &Self) -> PyResult<&'py PyAny> { + fn decode(self: &'a Self) -> PyResult> where 'py: 'a { let py = self.step.asn1_spec().py(); match ObjectIdentifier::from_bytes(self.step.value_substrate()) { Ok(oid) => { clone_asn1_schema_obj( self.step.asn1_spec(), - create_value_args(PyTuple::new(py, oid.arcs().collect_vec())), + create_value_args(PyTuple::new_bound(py, oid.arcs().collect_vec()).into_any()), None) } Err(e) => Err(self.step.create_error(&e.to_string())) @@ -294,7 +296,7 @@ impl<'py> CharacterStringDecoder<'py> { } } -impl<'py> Decoder<'py> for CharacterStringDecoder<'py> { +impl<'a, 'py> Decoder<'a, 'py> for CharacterStringDecoder<'py> { fn verify_raw(self: &Self) -> PyResult<()> { match self.step.tag().format() { tag::FORMAT_SIMPLE => Ok(()), @@ -302,10 +304,10 @@ impl<'py> Decoder<'py> for CharacterStringDecoder<'py> { } } - fn decode(self: &Self) -> PyResult<&'py PyAny> { + fn decode(self: &'a Self) -> PyResult> where 'py: 'a { let py = self.step.asn1_spec().py(); - clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(PyBytes::new(py, self.step.value_substrate())), None) + clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(PyBytes::new_bound(py, self.step.value_substrate()).into_any()), None) } } @@ -319,7 +321,7 @@ impl<'py> PrintableStringDecoder<'py> { } } -impl<'py> Decoder<'py> for PrintableStringDecoder<'py> { +impl<'a, 'py> Decoder<'a, 'py> for PrintableStringDecoder<'py> { fn verify_raw(self: &Self) -> PyResult<()> { match self.step.tag().format() { tag::FORMAT_SIMPLE => (), @@ -332,20 +334,20 @@ impl<'py> Decoder<'py> for PrintableStringDecoder<'py> { } } - fn decode(self: &Self) -> PyResult<&'py PyAny> { + fn decode(self: &'a Self) -> PyResult> where 'py: 'a { let py = self.step.asn1_spec().py(); - clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(PyBytes::new(py, self.step.value_substrate())), None) + clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(PyBytes::new_bound(py, self.step.value_substrate()).into_any()), None) } } -fn check_consistency(step: DecodeStep, asn1_value: &PyAny) -> PyResult<()> { +fn check_consistency(step: &DecodeStep, asn1_value: &Bound) -> PyResult<()> { let py = asn1_value.py(); match asn1_value.getattr(intern![py, "isInconsistent"]) { Ok(o) => { - if o.is_true().unwrap() { + if o.is_truthy()? { Err(step.create_error(&o.to_string())) } else { @@ -358,13 +360,17 @@ fn check_consistency(step: DecodeStep, asn1_value: &PyAny) -> PyResult<()> { } -fn get_constructed_set_component_kwargs(m: NativeHelperModule) -> &PyDict { - m.module.getattr(intern![m.module.py(), CONSTRUCTED_SET_COMPONENT_KWARGS]).unwrap().downcast_exact().unwrap() +fn get_constructed_set_component_kwargs<'py>(m: &'py NativeHelperModule) -> Bound<'py, PyDict> { + let kwargs = m.module.getattr(intern![m.module.py(), CONSTRUCTED_SET_COMPONENT_KWARGS]).unwrap(); + + kwargs.downcast_exact().unwrap().clone() } -fn get_choice_set_component_kwargs(m: NativeHelperModule) -> &PyDict { - m.module.getattr(intern![m.module.py(), CHOICE_SET_COMPONENT_KWARGS]).unwrap().downcast_exact().unwrap() +fn get_choice_set_component_kwargs<'py>(m: &'py NativeHelperModule) -> Bound<'py, PyDict> { + let kwargs = m.module.getattr(intern![m.module.py(), CHOICE_SET_COMPONENT_KWARGS]).unwrap(); + + kwargs.downcast_exact().unwrap().clone() } @@ -377,14 +383,14 @@ impl<'py> SequenceDecoder<'py> { Self { step } } - fn get_named_type_at_index(self: &Self, named_types: &'py PyAny, index: usize) -> PyResult<&'py PyAny> { + fn get_named_type_at_index(self: &Self, named_types: &Bound<'py, PyAny>, index: usize) -> PyResult> { match named_types.get_item(index) { Ok(n) => Ok(n), Err(_) => return Err(self.step.create_error("Excessive components detected")) } } - fn get_component_type_for_index(self: &Self, named_types: &'py PyAny, named_type: &'py PyAny, is_optional_or_defaulted: bool, index: usize) -> PyResult<&'py PyAny> { + fn get_component_type_for_index(self: &Self, named_types: Bound<'py, PyAny>, named_type: &Bound<'py, PyAny>, is_optional_or_defaulted: bool, index: usize) -> PyResult> { let py = named_types.py(); if is_optional_or_defaulted { @@ -395,10 +401,10 @@ impl<'py> SequenceDecoder<'py> { } } - fn check_decoded_for_default_value(self: &Self, named_type: &'py PyAny, decoded: &'py PyAny) -> Option { + fn check_decoded_for_default_value(self: &Self, named_type: &Bound, decoded: &Bound<'py, PyAny>) -> Option { let py = named_type.py(); - if named_type.getattr(intern![py, "isDefaulted"]).unwrap().is_true().unwrap() { + if named_type.getattr(intern![py, "isDefaulted"]).unwrap().is_truthy().unwrap() { if decoded.eq(named_type.getattr(intern![py, "asn1Object"]).unwrap()).unwrap() { return Some(self.step.create_error("Explicitly encoded default value")) } @@ -409,7 +415,7 @@ impl<'py> SequenceDecoder<'py> { } -impl<'py> Decoder<'py> for SequenceDecoder<'py> { +impl<'a, 'py> Decoder<'a, 'py> for SequenceDecoder<'py> { fn verify_raw(self: &Self) -> PyResult<()> { match self.step.tag().format() { tag::FORMAT_CONSTRUCTED => Ok(()), @@ -417,29 +423,29 @@ impl<'py> Decoder<'py> for SequenceDecoder<'py> { } } - fn decode(self: &Self) -> PyResult<&'py PyAny> { + fn decode(self: &'a Self) -> PyResult> { let py = self.step.asn1_spec().py(); - let asn1_object = self.step.asn1_spec().call_method(intern![py, "clone"], PyTuple::empty(py), None).unwrap(); - asn1_object.call_method(intern![py, "clear"], PyTuple::empty(py), None)?; + let asn1_object = self.step.asn1_spec().call_method(intern![py, "clone"], PyTuple::empty_bound(py), None)?; + asn1_object.call_method(intern![py, "clear"], PyTuple::empty_bound(py), None)?; let named_types = self.step.asn1_spec().getattr(intern![py, "componentType"])?; let mut index = 0; let mut relative_offset = 0; - let seen_indices = PySet::empty(py)?; + let seen_indices = PySet::empty_bound(py)?; while relative_offset < self.step.value_substrate_len() { let offset_from_parent_tlv = self.step.offset() + self.step.header_len() + relative_offset; - let named_type = match self.get_named_type_at_index(named_types, index) { + let named_type = match self.get_named_type_at_index(&named_types, index) { Ok(n) => n, Err(e) => return Err(e) }; - let is_optional_or_defaulted = named_type.getattr(intern![py, "isOptional"]).unwrap().is_true().unwrap() || named_type.getattr(intern![py, "isDefaulted"]).unwrap().is_true().unwrap(); + let is_optional_or_defaulted = named_type.getattr(intern![py, "isOptional"])?.is_truthy()? || named_type.getattr(intern![py, "isDefaulted"])?.is_truthy()?; - let component_type = match self.get_component_type_for_index(named_types, named_type, is_optional_or_defaulted, index) { + let component_type = match self.get_component_type_for_index(named_types.clone(), &named_type, is_optional_or_defaulted, index) { Ok(c) => c, Err(e) => return Err(e) }; @@ -449,39 +455,39 @@ impl<'py> Decoder<'py> for SequenceDecoder<'py> { Err(e) => return Err(e) }; - let decoded = match decode_der_rec(self.step.module(), tlv, component_type, None, offset_from_parent_tlv) { + let decoded = match decode_der_rec(self.step.module().clone(), tlv, component_type, None, offset_from_parent_tlv) { Ok(d) => d, Err(e) => return Err(e) }; - match self.check_decoded_for_default_value(named_type, decoded) { + match self.check_decoded_for_default_value(&named_type, &decoded) { Some(e) => return Err(e), None => () }; if is_optional_or_defaulted { - index = named_types.call_method(intern![py, "getPositionNearType"], (decoded.getattr(intern![py, "effectiveTagSet"]).unwrap(), index.into_py(py)), None).unwrap().extract().unwrap(); + index = named_types.call_method(intern![py, "getPositionNearType"], (decoded.getattr(intern![py, "effectiveTagSet"])?, index.into_py(py)), None)?.extract()?; } - asn1_object.call_method(intern![py, "setComponentByPosition"], (index, decoded), Some(get_constructed_set_component_kwargs(self.step.module()))).unwrap(); + asn1_object.call_method(intern![py, "setComponentByPosition"], (index, decoded), Some(&get_constructed_set_component_kwargs(&self.step.module())))?; - seen_indices.add(index).unwrap(); + seen_indices.add(index)?; index += 1; relative_offset += tlv.len(); } - let required_components = named_types.getattr(intern![py, "requiredComponents"]).unwrap(); + let required_components = named_types.getattr(intern![py, "requiredComponents"])?; - if required_components.call_method(intern![py, "issubset"], (seen_indices,), None).unwrap().is_true().unwrap() { + if required_components.call_method(intern![py, "issubset"], (seen_indices,), None).unwrap().is_truthy()? { Ok(asn1_object) } else { Err(self.step.create_error("Missing required components")) } } - fn verify_decoded(self: &Self, asn1_value: &PyAny) -> PyResult<()> { - check_consistency(self.step, asn1_value) + fn verify_decoded(self: &Self, asn1_value: &Bound) -> PyResult<()> { + check_consistency(&self.step, asn1_value) } } @@ -495,7 +501,7 @@ impl<'py> SequenceOfDecoder<'py> { } } -impl<'py> Decoder<'py> for SequenceOfDecoder<'py> { +impl<'a, 'py> Decoder<'a, 'py> for SequenceOfDecoder<'py> { fn verify_raw(self: &Self) -> PyResult<()> { match self.step.tag().format() { tag::FORMAT_CONSTRUCTED => Ok(()), @@ -503,16 +509,16 @@ impl<'py> Decoder<'py> for SequenceOfDecoder<'py> { } } - fn decode(self: &Self) -> PyResult<&'py PyAny> { + fn decode(self: &'a Self) -> PyResult> { let py = self.step.asn1_spec().py(); - let asn1_object = self.step.asn1_spec().call_method(intern![py, "clone"], PyTuple::empty(py), None).unwrap(); - asn1_object.call_method(intern![py, "clear"], PyTuple::empty(py), None)?; + let asn1_object = self.step.asn1_spec().call_method(intern![py, "clone"], PyTuple::empty_bound(py), None)?; + asn1_object.call_method(intern![py, "clear"], PyTuple::empty_bound(py), None)?; let mut index = 0; let mut relative_offset = 0; - let component_type = self.step.asn1_spec().getattr(intern![py, "componentType"]).unwrap(); + let component_type = self.step.asn1_spec().getattr(intern![py, "componentType"])?; while relative_offset < self.step.value_substrate_len() { let offset_from_parent_tlv = self.step.offset() + self.step.header_len() + relative_offset; @@ -522,12 +528,12 @@ impl<'py> Decoder<'py> for SequenceOfDecoder<'py> { Err(e) => return Err(e) }; - let decoded = match decode_der_rec(self.step.module(), tlv, component_type, None, offset_from_parent_tlv) { + let decoded = match decode_der_rec(self.step.module().clone(), tlv, component_type.clone(), None, offset_from_parent_tlv) { Ok(d) => d, Err(e) => return Err(e) }; - asn1_object.call_method(intern![py, "setComponentByPosition"], (index, decoded), Some(get_constructed_set_component_kwargs(self.step.module()))).unwrap(); + asn1_object.call_method(intern![py, "setComponentByPosition"], (index, decoded), Some(&get_constructed_set_component_kwargs(&self.step.module()))).unwrap(); index += 1; relative_offset += tlv.len(); @@ -536,8 +542,8 @@ impl<'py> Decoder<'py> for SequenceOfDecoder<'py> { Ok(asn1_object) } - fn verify_decoded(self: &Self, asn1_value: &PyAny) -> PyResult<()> { - check_consistency(self.step, asn1_value) + fn verify_decoded(self: &Self, asn1_value: &Bound) -> PyResult<()> { + check_consistency(&self.step, asn1_value) } } @@ -553,7 +559,7 @@ impl<'py> SetOfDecoder<'py> { } -impl<'py> Decoder<'py> for SetOfDecoder<'py> { +impl<'a, 'py> Decoder<'a, 'py> for SetOfDecoder<'py> { fn verify_raw(self: &Self) -> PyResult<()> { match self.step.tag().format() { tag::FORMAT_CONSTRUCTED => Ok(()), @@ -561,17 +567,17 @@ impl<'py> Decoder<'py> for SetOfDecoder<'py> { } } - fn decode(self: &Self) -> PyResult<&'py PyAny> { + fn decode(self: &'a Self) -> PyResult> { let py = self.step.asn1_spec().py(); - let asn1_object = self.step.asn1_spec().call_method(intern![py, "clone"], PyTuple::empty(py), None).unwrap(); - asn1_object.call_method(intern![py, "clear"], PyTuple::empty(py), None)?; + let asn1_object = self.step.asn1_spec().call_method(intern![py, "clone"], PyTuple::empty_bound(py), None)?; + asn1_object.call_method(intern![py, "clear"], PyTuple::empty_bound(py), None)?; let mut index = 0; let mut relative_offset = 0; let mut last_tlv = None; - let component_type = self.step.asn1_spec().getattr(intern![py, "componentType"]).unwrap(); + let component_type = self.step.asn1_spec().getattr(intern![py, "componentType"])?; while relative_offset < self.step.value_substrate_len() { let offset_from_parent_tlv = self.step.offset() + self.step.header_len() + relative_offset; @@ -592,12 +598,12 @@ impl<'py> Decoder<'py> for SetOfDecoder<'py> { None => last_tlv = Some(tlv) }; - let decoded = match decode_der_rec(self.step.module(), tlv, component_type, None, offset_from_parent_tlv) { + let decoded = match decode_der_rec(self.step.module().clone(), tlv, component_type.clone(), None, offset_from_parent_tlv) { Ok(d) => d, Err(e) => return Err(e) }; - asn1_object.call_method(intern![py, "setComponentByPosition"], (index, decoded), Some(get_constructed_set_component_kwargs(self.step.module()))).unwrap(); + asn1_object.call_method(intern![py, "setComponentByPosition"], (index, decoded), Some(&get_constructed_set_component_kwargs(&self.step.module())))?; index += 1; relative_offset += tlv.len(); @@ -606,8 +612,8 @@ impl<'py> Decoder<'py> for SetOfDecoder<'py> { Ok(asn1_object) } - fn verify_decoded(self: &Self, asn1_value: &PyAny) -> PyResult<()> { - check_consistency(self.step, asn1_value) + fn verify_decoded(self: &Self, asn1_value: &Bound) -> PyResult<()> { + check_consistency(&self.step, asn1_value) } } @@ -621,14 +627,14 @@ impl<'py> AnyDecoder<'py> { } } -impl<'py> Decoder<'py> for AnyDecoder<'py> { - fn decode(self: &Self) -> PyResult<&'py PyAny> { +impl<'a, 'py> Decoder<'a, 'py> for AnyDecoder<'py> { + fn decode(self: &'a Self) -> PyResult> where 'py: 'a { let py = self.step.asn1_spec().py(); - let is_untagged = if self.step.asn1_spec().get_type().is(self.step.module().tagmap_cls) { - !self.step.asn1_spec().contains(self.step.tag_set()).unwrap() + let is_untagged = if self.step.asn1_spec().get_type().is(&self.step.module().tagmap_cls) { + !self.step.asn1_spec().contains(self.step.tag_set())? } else { - self.step.tag_set().ne(self.step.asn1_spec().getattr(intern![py, TAGSET_ATTR]).unwrap()).unwrap() + self.step.tag_set().ne(self.step.asn1_spec().getattr(intern![py, TAGSET_ATTR])?)? }; let substrate = if is_untagged { @@ -638,7 +644,9 @@ impl<'py> Decoder<'py> for AnyDecoder<'py> { self.step.value_substrate() }; - clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(PyBytes::new(py, substrate)), None) + let py_bytes = PyBytes::new_bound(py, substrate); + + clone_asn1_schema_obj(self.step.asn1_spec(), create_value_args(py_bytes.into_any()), None) } } @@ -653,25 +661,25 @@ impl<'py> ChoiceDecoder<'py> { } } -impl<'py> Decoder<'py> for ChoiceDecoder<'py> { - fn decode(self: &Self) -> PyResult<&'py PyAny> { +impl<'a, 'py> Decoder<'a, 'py> for ChoiceDecoder<'py> { + fn decode(self: &'a Self) -> PyResult> { let py = self.step.asn1_spec().py(); - let asn1_object = self.step.asn1_spec().call_method(intern![py, "clone"], (), None).unwrap(); + let asn1_object = self.step.asn1_spec().call_method(intern![py, "clone"], (), None)?; - let component_tag_map = asn1_object.getattr(intern![py, "componentTagMap"]).unwrap(); + let component_tag_map = asn1_object.getattr(intern![py, "componentTagMap"])?; - let decoded_result = if asn1_object.getattr(intern![py, TAGSET_ATTR]).unwrap().eq(self.step.tag_set()).unwrap() { - decode_der_rec(self.step.module(), self.step.value_substrate(), component_tag_map, None, self.step.header_len() + self.step.offset()) + let decoded_result = if asn1_object.getattr(intern![py, TAGSET_ATTR])?.eq(self.step.tag_set())? { + decode_der_rec(self.step.module().clone(), self.step.value_substrate(), component_tag_map, None, self.step.header_len() + self.step.offset()) } else { - let chosen_spec = match get_chosen_spec(self.step.module(), component_tag_map, self.step.tag_set()) { + let chosen_spec = match get_chosen_spec(&self.step.module(), &component_tag_map, self.step.tag_set()) { Err(e) => return Err(e), - Ok(None) => return decode_explicit(self.step), + Ok(None) => return decode_explicit(self.step.clone()), Ok(Some(c)) => c }; - let new_step = DecodeStep::new(self.step.module(), self.step.substrate(), self.step.header(), chosen_spec, self.step.tag_set(), self.step.offset()); + let new_step = DecodeStep::new(self.step.module().clone(), self.step.substrate(), self.step.header(), chosen_spec, self.step.tag_set().clone(), self.step.offset()); decoder::decode_asn1_spec_value(new_step) }; @@ -679,9 +687,9 @@ impl<'py> Decoder<'py> for ChoiceDecoder<'py> { match decoded_result { Err(e) => Err(e), Ok(d) => { - let effective_tag_set = d.getattr(intern![py, "effectiveTagSet"]).unwrap(); + let effective_tag_set = d.getattr(intern![py, "effectiveTagSet"])?; - asn1_object.call_method(intern![py, "setComponentByType"], (effective_tag_set, d), Some(get_choice_set_component_kwargs(self.step.module()))) + asn1_object.call_method(intern![py, "setComponentByType"], (effective_tag_set, d), Some(&get_choice_set_component_kwargs(&self.step.module()))) } } } diff --git a/src/decoder.rs b/src/decoder.rs index 478b414..a84b6e5 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -1,34 +1,34 @@ -use der::{Encode, Header, Reader}; -use pyo3::PyAny; -use pyo3::PyErr; -use pyo3::PyResult; -use pyo3::prelude::{PyModule}; -use pyo3::types::PyDict; -use crate::{HELPER_MODULE_ATTR, NativeHelperModule, Pyasn1FasderError, TYPE_MAP}; use crate::asn1_type::{AnyDecoder, BitStringDecoder, BooleanDecoder, CharacterStringDecoder, ChoiceDecoder, Decoder, IntegerDecoder, NullDecoder, ObjectIdentifierDecoder, OctetStringDecoder, PrintableStringDecoder, SequenceDecoder, SequenceOfDecoder, SetOfDecoder}; use crate::tag::Asn1Tag; - +use crate::{NativeHelperModule, Pyasn1FasderError, HELPER_MODULE_ATTR, TYPE_MAP}; +use der::{Encode, Header, Reader}; +use pyo3::prelude::{PyAnyMethods, PyModule, PyTypeMethods}; +use pyo3::types::PyDict; +use pyo3::types::PyDictMethods; +use pyo3::PyResult; +use pyo3::{Bound, PyAny}; +use pyo3::PyErr; const TYPE_ID_ATTR: &str = "typeId"; -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct DecodeStep<'py> { module: NativeHelperModule<'py>, substrate: &'py [u8], header: Header, - asn1_spec: &'py PyAny, - tag_set: &'py PyAny, + asn1_spec: Bound<'py, PyAny>, + tag_set: Bound<'py, PyAny>, offset: usize } impl<'py> DecodeStep<'py> { - pub fn new(module: NativeHelperModule<'py>, substrate: &'py [u8], header: Header, asn1_spec: &'py PyAny, tag_set: &'py PyAny, offset: usize) -> Self { + pub fn new(module: NativeHelperModule<'py>, substrate: &'py [u8], header: Header, asn1_spec: Bound<'py, PyAny>, tag_set: Bound<'py, PyAny>, offset: usize) -> Self { Self { module, substrate, header, asn1_spec, tag_set, offset } } - pub fn module(&self) -> NativeHelperModule<'py> { - self.module + pub fn module(&self) -> &NativeHelperModule<'py> { + &self.module } pub fn substrate(&self) -> &'py [u8] { @@ -47,12 +47,12 @@ impl<'py> DecodeStep<'py> { Asn1Tag::new(self.substrate[0]) } - pub fn asn1_spec(&self) -> &'py PyAny { - self.asn1_spec + pub fn asn1_spec(&self) -> &Bound<'py, PyAny> { + &self.asn1_spec } - pub fn tag_set(&self) -> &'py PyAny { - self.tag_set + pub fn tag_set(&self) -> &Bound<'py, PyAny> { + &self.tag_set } pub fn value_substrate_len(&self) -> usize { @@ -68,7 +68,8 @@ impl<'py> DecodeStep<'py> { } pub fn create_error(&self, description: &str) -> PyErr { - let asn1_spec_name = self.asn1_spec.get_type().name().unwrap(); + let asn1_spec_type = self.asn1_spec.get_type(); + let asn1_spec_name = asn1_spec_type.name().unwrap(); Pyasn1FasderError::new_err(format!("Error decoding \"{}\" TLV near substrate offset {}: {}", asn1_spec_name, self.offset, description)) } @@ -118,18 +119,20 @@ const DECODER_TYPE_ANY: usize = 98; const DECODER_TYPE_CHOICE: usize = 99; +pub fn decode_asn1_spec_value<'py>(step: DecodeStep<'py>) -> PyResult> { + let type_id = step.asn1_spec().getattr(TYPE_ID_ATTR)?; -pub fn decode_asn1_spec_value(step: DecodeStep) -> PyResult<&PyAny> { - let type_id = step.asn1_spec().getattr(TYPE_ID_ATTR).unwrap(); + let decoder_mappings = &step.module.decoder_mappings; + let type_mapping = PyDictMethods::get_item(decoder_mappings, type_id.clone())?; - match step.module.decoder_mappings.get_item(type_id).unwrap() { + match type_mapping { None => { let type_id_u8 : u8 = type_id.extract()?; Err(step.create_error(&format!("ASN.1 specification with type ID of {} is not supported", type_id_u8))) }, Some(decoder_id) => { - let decoder_id_u8: usize = decoder_id.extract().unwrap(); + let decoder_id_u8: usize = decoder_id.extract()?; let decoder: &dyn Decoder = match decoder_id_u8 { DECODER_TYPE_BOOLEAN => &BooleanDecoder::new(step), @@ -156,6 +159,7 @@ pub fn decode_asn1_spec_value(step: DecodeStep) -> PyResult<&PyAny> { DECODER_TYPE_BMPSTRING => &CharacterStringDecoder::new(step, "BMPSTRING"), DECODER_TYPE_ANY => &AnyDecoder::new(step), DECODER_TYPE_CHOICE => &ChoiceDecoder::new(step), + _ => return Err(Pyasn1FasderError::new_err("ASN.1 type is unsuppported")) }; @@ -169,9 +173,9 @@ pub fn decode_asn1_spec_value(step: DecodeStep) -> PyResult<&PyAny> { match decoded_result { Err(e) => Err(e), Ok(decoded) => { - match decoder.verify_decoded(decoded) { + match decoder.verify_decoded(&decoded) { Err(e) => Err(e), - Ok(()) => Ok(decoded) + Ok(()) => Ok(decoded.clone()) } } } @@ -180,50 +184,51 @@ pub fn decode_asn1_spec_value(step: DecodeStep) -> PyResult<&PyAny> { } -pub fn init_module<'py>(m: &'py PyModule) -> PyResult<()> { +pub fn init_module(m: &Bound) -> PyResult<()> { let py = m.py(); let helper_mod = m.getattr(HELPER_MODULE_ATTR)?; - let type_map : &PyDict = helper_mod.getattr(TYPE_MAP).unwrap().downcast_exact().unwrap(); + let type_map_any = helper_mod.getattr(TYPE_MAP)?; + let type_map : &Bound = type_map_any.downcast_exact()?; - let add_map_entry = |type_mod: &'py PyModule, cls_name: &str, decoder_type: usize| { + let add_map_entry = |type_mod: &Bound, cls_name: &str, decoder_type: usize| { let type_id = type_mod.getattr(cls_name).unwrap().getattr(TYPE_ID_ATTR).unwrap(); type_map.set_item(type_id, decoder_type).unwrap() }; - let univ_mod = py.import("pyasn1.type.univ").unwrap(); - - add_map_entry(univ_mod, "Boolean", DECODER_TYPE_BOOLEAN); - add_map_entry(univ_mod, "Integer", DECODER_TYPE_INTEGER); - add_map_entry(univ_mod, "BitString", DECODER_TYPE_BITSTRING); - add_map_entry(univ_mod, "OctetString", DECODER_TYPE_OCTETSTRING); - add_map_entry(univ_mod, "Null", DECODER_TYPE_NULL); - add_map_entry(univ_mod, "ObjectIdentifier", DECODER_TYPE_OBJECTIDENTIFIER); - add_map_entry(univ_mod, "Enumerated", DECODER_TYPE_ENUMERATED); - add_map_entry(univ_mod, "Sequence", DECODER_TYPE_SEQUENCE); - add_map_entry(univ_mod, "SequenceOf", DECODER_TYPE_SEQUENCEOF); - add_map_entry(univ_mod, "SetOf", DECODER_TYPE_SETOF); - add_map_entry(univ_mod, "Any", DECODER_TYPE_ANY); - add_map_entry(univ_mod, "Choice", DECODER_TYPE_CHOICE); - - let char_mod = py.import("pyasn1.type.char").unwrap(); - - add_map_entry(char_mod, "NumericString", DECODER_TYPE_NUMERICSTRING); - add_map_entry(char_mod, "PrintableString", DECODER_TYPE_PRINTABLESTRING); - add_map_entry(char_mod, "TeletexString", DECODER_TYPE_TELETEXSTRING); - add_map_entry(char_mod, "VideotexString", DECODER_TYPE_VIDEOTEXSTRING); - add_map_entry(char_mod, "IA5String", DECODER_TYPE_IA5STRING); - add_map_entry(char_mod, "GraphicString", DECODER_TYPE_GRAPHICSTRING); - add_map_entry(char_mod, "VisibleString", DECODER_TYPE_VISIBLESTRING); - add_map_entry(char_mod, "UniversalString", DECODER_TYPE_UNIVERSALSTRING); - add_map_entry(char_mod, "BMPString", DECODER_TYPE_BMPSTRING); - add_map_entry(char_mod, "UTF8String", DECODER_TYPE_UTF8STRING); - - let useful_mod = py.import("pyasn1.type.useful")?; - - add_map_entry(useful_mod, "UTCTime", DECODER_TYPE_UTCTIME); - add_map_entry(useful_mod, "GeneralizedTime", DECODER_TYPE_GENERALIZEDTIME); + let univ_mod = py.import_bound("pyasn1.type.univ")?; + + add_map_entry(&univ_mod, "Boolean", DECODER_TYPE_BOOLEAN); + add_map_entry(&univ_mod, "Integer", DECODER_TYPE_INTEGER); + add_map_entry(&univ_mod, "BitString", DECODER_TYPE_BITSTRING); + add_map_entry(&univ_mod, "OctetString", DECODER_TYPE_OCTETSTRING); + add_map_entry(&univ_mod, "Null", DECODER_TYPE_NULL); + add_map_entry(&univ_mod, "ObjectIdentifier", DECODER_TYPE_OBJECTIDENTIFIER); + add_map_entry(&univ_mod, "Enumerated", DECODER_TYPE_ENUMERATED); + add_map_entry(&univ_mod, "Sequence", DECODER_TYPE_SEQUENCE); + add_map_entry(&univ_mod, "SequenceOf", DECODER_TYPE_SEQUENCEOF); + add_map_entry(&univ_mod, "SetOf", DECODER_TYPE_SETOF); + add_map_entry(&univ_mod, "Any", DECODER_TYPE_ANY); + add_map_entry(&univ_mod, "Choice", DECODER_TYPE_CHOICE); + + let char_mod = py.import_bound("pyasn1.type.char")?; + + add_map_entry(&char_mod, "NumericString", DECODER_TYPE_NUMERICSTRING); + add_map_entry(&char_mod, "PrintableString", DECODER_TYPE_PRINTABLESTRING); + add_map_entry(&char_mod, "TeletexString", DECODER_TYPE_TELETEXSTRING); + add_map_entry(&char_mod, "VideotexString", DECODER_TYPE_VIDEOTEXSTRING); + add_map_entry(&char_mod, "IA5String", DECODER_TYPE_IA5STRING); + add_map_entry(&char_mod, "GraphicString", DECODER_TYPE_GRAPHICSTRING); + add_map_entry(&char_mod, "VisibleString", DECODER_TYPE_VISIBLESTRING); + add_map_entry(&char_mod, "UniversalString", DECODER_TYPE_UNIVERSALSTRING); + add_map_entry(&char_mod, "BMPString", DECODER_TYPE_BMPSTRING); + add_map_entry(&char_mod, "UTF8String", DECODER_TYPE_UTF8STRING); + + let useful_mod = py.import_bound("pyasn1.type.useful")?; + + add_map_entry(&useful_mod, "UTCTime", DECODER_TYPE_UTCTIME); + add_map_entry(&useful_mod, "GeneralizedTime", DECODER_TYPE_GENERALIZEDTIME); Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 116387c..d9e87c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ mod tag; mod decoder; mod asn1_type; +use std::clone::Clone; use pyo3::prelude::*; use pyo3::intern; use pyo3::types::{PyAny, PyDict}; @@ -20,48 +21,53 @@ const HELPER_MODULE_ATTR: &str = "_HELPER"; const NESTED_EXPLICIT_TAG_LIMIT: usize = 4; -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct NativeHelperModule<'py> { - module: &'py PyModule, - tag_cls: &'py PyAny, - tagset_cls: &'py PyAny, - tagmap_cls: &'py PyAny, - tag_cache: &'py PyDict, - tagset_cache: &'py PyDict, - decoder_mappings: &'py PyDict, + module: Bound<'py, PyModule>, + tag_cls: Bound<'py, PyAny>, + tagset_cls: Bound<'py, PyAny>, + tagmap_cls: Bound<'py, PyAny>, + tag_cache: Bound<'py, PyDict>, + tagset_cache: Bound<'py, PyDict>, + decoder_mappings: Bound<'py, PyDict>, } impl<'py> NativeHelperModule<'py> { - pub fn new(base_module: &'py PyModule) -> PyResult { + pub fn new(base_module: &Bound<'py, PyModule>) -> PyResult { let py = base_module.py(); - let module : &PyModule = base_module.getattr(intern![py, HELPER_MODULE_ATTR])?.downcast()?; + let module_attr = base_module.getattr(intern![py, HELPER_MODULE_ATTR])?; + let module: Bound = module_attr.downcast_exact()?.clone(); let tag_cls = module.getattr(intern![py, "_TAG_CLS"])?; let tagset_cls = module.getattr(intern![py, "_TAGSET_CLS"])?; let tagmap_cls = module.getattr(intern![py, "_TAGMAP_CLS"])?; - let tag_cache = module.getattr(intern![py, "_TAG_CACHE"])?.downcast_exact()?; - let tagset_cache = module.getattr(intern![py, "_TAGSET_CACHE"])?.downcast_exact()?; + let tag_cache_attr = module.getattr(intern![py, "_TAG_CACHE"])?; + let tag_cache = tag_cache_attr.downcast_exact()?.clone(); - let decoder_mappings = module.getattr(intern![py, TYPE_MAP])?.downcast_exact()?; + let tagset_cache_attr = module.getattr(intern![py, "_TAGSET_CACHE"])?; + let tagset_cache = tagset_cache_attr.downcast_exact()?.clone(); + + let decoder_mappings_attr = module.getattr(intern![py, TYPE_MAP])?; + let decoder_mappings = decoder_mappings_attr.downcast_exact()?.clone(); Ok(Self { module, tag_cls, tagset_cls, tagmap_cls, tag_cache, tagset_cache, decoder_mappings }) } - pub fn create_pyasn1_tag(&self, tag: Asn1Tag) -> PyResult<&'py PyAny> { + pub fn create_pyasn1_tag(&self, tag: Asn1Tag) -> PyResult> { if tag.class() == CLASS_UNIVERSAL { - let cached_tag = self.tag_cache.get_item(u8::from(tag)).unwrap(); + let cached_tag = self.tag_cache.get_item(u8::from(tag))?; if cached_tag.is_some() { return Ok(cached_tag.unwrap()) } } - return self.tag_cls.call((tag.class(), tag.format(), tag.tag_id()), None) + self.tag_cls.call((tag.class(), tag.format(), tag.tag_id()), None) } - pub fn create_pyasn1_tagset(&self, pyasn1_tag: &'py PyAny, tag: Asn1Tag) -> PyResult<&'py PyAny> { + pub fn create_pyasn1_tagset(&self, pyasn1_tag: &Bound, tag: Asn1Tag) -> PyResult> { if tag.class() == CLASS_UNIVERSAL { let cached_tagset = self.tagset_cache.get_item(pyasn1_tag)?; @@ -70,15 +76,14 @@ impl<'py> NativeHelperModule<'py> { } } - return self.tagset_cls.call(((), pyasn1_tag), None) + self.tagset_cls.call(((), pyasn1_tag), None) } } -fn decode_explicit(step: DecodeStep) -> PyResult<&PyAny> { +fn decode_explicit<'call, 'py>(step: DecodeStep<'py>) -> PyResult> where 'py: 'call { // stop recursion if we've already descended multiple times - - if step.tag_set().len().unwrap() >= NESTED_EXPLICIT_TAG_LIMIT { + if step.tag_set().len()? >= NESTED_EXPLICIT_TAG_LIMIT { return Err(step.create_error("Exceeded limit on nested explicit tags")) } @@ -89,7 +94,8 @@ fn decode_explicit(step: DecodeStep) -> PyResult<&PyAny> { if first_tag_fmt.eq(tag::FORMAT_CONSTRUCTED)? && first_tag_class.ne(CLASS_UNIVERSAL)? { let new_offset = step.offset() + usize::try_from(step.header().length).unwrap(); - decode_der_rec(step.module(), step.value_substrate(), step.asn1_spec(), Some(step.tag_set()), new_offset) + decode_der_rec(step.module().clone(), step.value_substrate(), step.asn1_spec().clone(), Some( + step.tag_set().clone()), new_offset) } else { Err(step.create_error("Substrate does not match ASN.1 specification")) @@ -97,17 +103,17 @@ fn decode_explicit(step: DecodeStep) -> PyResult<&PyAny> { } -pub fn get_chosen_spec<'py>(m: NativeHelperModule, asn1_spec: &'py PyAny, substrate_tag_set: &'py PyAny) -> PyResult> { +pub fn get_chosen_spec<'py>(m: &NativeHelperModule, asn1_spec: &pyo3::Bound<'py, PyAny>, substrate_tag_set: &Bound) -> PyResult>> { let py = asn1_spec.py(); - if asn1_spec.get_type().is(m.tagmap_cls) { + if asn1_spec.get_type().is(&m.tagmap_cls) { match asn1_spec.get_item(substrate_tag_set) { Err(_) => Ok(None), Ok(c) => Ok(Some(c)) } } else if substrate_tag_set.eq(asn1_spec.getattr(intern![py, TAGSET_ATTR])?)? || asn1_spec.getattr(intern![py, TAGMAP_ATTR])?.contains(substrate_tag_set)? { - Ok(Some(asn1_spec)) + Ok(Some(asn1_spec.clone())) } else { Ok(None) @@ -115,7 +121,7 @@ pub fn get_chosen_spec<'py>(m: NativeHelperModule, asn1_spec: &'py PyAny, substr } -fn decode_der_rec<'py>(m: NativeHelperModule<'py>, substrate: &'py [u8], asn1_spec: &'py PyAny, tag_set: Option<&'py PyAny>, offset: usize) -> PyResult<&'py PyAny> { +fn decode_der_rec<'py>(m: NativeHelperModule<'py>, substrate: &'py [u8], asn1_spec: Bound<'py, PyAny>, tag_set: Option>, offset: usize) -> PyResult> { if asn1_spec.is_none() { return Err(Pyasn1FasderError::new_err(format!("No ASN.1 specification near substrate offset {}", offset))); } @@ -135,20 +141,20 @@ fn decode_der_rec<'py>(m: NativeHelperModule<'py>, substrate: &'py [u8], asn1_sp let new_tag_set = match tag_set { Some(pyasn1_tagset) => pyasn1_tagset.call_method(intern![m.module.py(), "__radd__"], (substrate_tag,), None)?, - None => m.create_pyasn1_tagset(substrate_tag, Asn1Tag::new(substrate[0]))? + None => m.create_pyasn1_tagset(&substrate_tag, Asn1Tag::new(substrate[0]))?.to_owned() }; // determine ASN.1 spec to use for value decoding - let chosen_spec = match get_chosen_spec(m, asn1_spec, new_tag_set) { - Ok(None) => return decode_explicit(DecodeStep::new(m, substrate, header, asn1_spec, new_tag_set, offset)), + let chosen_spec = match get_chosen_spec(&m, &asn1_spec, &new_tag_set) { + Ok(None) => return decode_explicit(DecodeStep::new(m.clone(), substrate, header, asn1_spec.clone(), new_tag_set, offset)), Ok(Some(c)) => c, Err(e) => return Err(e), }; // create a new step with the chosen ASN.1 spec - let step = DecodeStep::new(m, substrate, header, chosen_spec, new_tag_set, offset); + let step = DecodeStep::new(m.clone(), substrate, header, chosen_spec, new_tag_set, offset); // find decoder for chosen ASN.1 spec and decode substrate value decode_asn1_spec_value(step) @@ -157,15 +163,15 @@ fn decode_der_rec<'py>(m: NativeHelperModule<'py>, substrate: &'py [u8], asn1_sp #[pyfunction] #[pyo3(pass_module)] -fn decode_der<'py>(m: &'py PyModule, substrate: &'py [u8], asn1_spec: &'py PyAny) -> PyResult<&'py PyAny> { +fn decode_der<'py>(m: &Bound<'py, PyModule>, substrate: &'py [u8], asn1_spec: &'py Bound<'py, PyAny>) -> PyResult> { let native_module = NativeHelperModule::new(m)?; - decode_der_rec(native_module, substrate, asn1_spec, None, 0) + decode_der_rec(native_module, substrate, asn1_spec.clone(), None, 0) } -fn initialize_module(m: &PyModule) -> PyResult<()> { - let helper_mod = m.py().import("pyasn1_fasder._native_helper")?; +fn initialize_module(m: &Bound) -> PyResult<()> { + let helper_mod = m.py().import_bound("pyasn1_fasder._native_helper")?; m.setattr(HELPER_MODULE_ATTR, helper_mod)?; @@ -177,7 +183,7 @@ fn initialize_module(m: &PyModule) -> PyResult<()> { #[pymodule] #[pyo3(name="_native")] -fn pyasn1_fasder(_py: Python, m: &PyModule) -> PyResult<()> { +fn pyasn1_fasder(_py: Python, m: &Bound) -> PyResult<()> { m.add_function(wrap_pyfunction!(decode_der, m)?)?; initialize_module(m)?; diff --git a/src/tag.rs b/src/tag.rs index 1d1f743..cc1f46d 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -1,5 +1,6 @@ -use pyo3::PyResult; +use pyo3::prelude::PyAnyMethods; use pyo3::types::PyModule; +use pyo3::{Bound, PyResult}; pub const CLASS_MASK: u8 = 0xC0; pub const CLASS_UNIVERSAL: u8 = 0x00; @@ -52,17 +53,17 @@ impl From for Asn1Tag { } } -pub fn init_module(m: &PyModule) -> PyResult<()> { +pub fn init_module(m: &Bound) -> PyResult<()> { let py = m.py(); - let pyasn1_tag_mod = py.import("pyasn1.type.tag")?; + let pyasn1_tag_mod = py.import_bound("pyasn1.type.tag")?; - m.add(TAG_CLS, pyasn1_tag_mod.getattr("Tag")?)?; - m.add(TAGSET_CLS, pyasn1_tag_mod.getattr("TagSet")?)?; - m.add(TAGMAP_CLS, py.import("pyasn1.type.tagmap")?.getattr("TagMap")?)?; + m.setattr(TAG_CLS, pyasn1_tag_mod.getattr("Tag")?)?; + m.setattr(TAGSET_CLS, pyasn1_tag_mod.getattr("TagSet")?)?; + m.setattr(TAGMAP_CLS, py.import_bound("pyasn1.type.tagmap")?.getattr("TagMap")?)?; - let helper_mod = py.import("pyasn1_fasder._native_helper")?; + let helper_mod = py.import_bound("pyasn1_fasder._native_helper")?; - m.add(TAG_CACHE, helper_mod.getattr(TAG_CACHE)?)?; - m.add(TAGSET_CACHE, helper_mod.getattr(TAGSET_CACHE)?) + m.setattr(TAG_CACHE, helper_mod.getattr(TAG_CACHE)?)?; + m.setattr(TAGSET_CACHE, helper_mod.getattr(TAGSET_CACHE)?) } From 5dd5e0c9747161452160a52bc1798ed53bdf0d17 Mon Sep 17 00:00:00 2001 From: Corey Bonnell Date: Sun, 13 Oct 2024 23:17:26 -0400 Subject: [PATCH 2/6] Remove unneeded clone() --- src/decoder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/decoder.rs b/src/decoder.rs index a84b6e5..b34bf97 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -175,7 +175,7 @@ pub fn decode_asn1_spec_value<'py>(step: DecodeStep<'py>) -> PyResult { match decoder.verify_decoded(&decoded) { Err(e) => Err(e), - Ok(()) => Ok(decoded.clone()) + Ok(()) => Ok(decodede } } } From 6f45ed8e5dfa9519576b67844ed30984c3a08814 Mon Sep 17 00:00:00 2001 From: Corey Bonnell Date: Sun, 13 Oct 2024 23:19:58 -0400 Subject: [PATCH 3/6] Add minimum Python ABI version --- Cargo.toml | 2 +- src/decoder.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a3098cf..705ae8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ name = "pyasn1_fasder" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.22.4", features = ["abi3", "num-bigint"] } +pyo3 = { version = "0.22.4", features = ["abi3", "abi3-py39", "num-bigint"] } der = { version = "0.7.8", features = ["oid"] } num-bigint = "0.4.6" itertools = "0.13.0" diff --git a/src/decoder.rs b/src/decoder.rs index b34bf97..98733d9 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -175,7 +175,7 @@ pub fn decode_asn1_spec_value<'py>(step: DecodeStep<'py>) -> PyResult { match decoder.verify_decoded(&decoded) { Err(e) => Err(e), - Ok(()) => Ok(decodede + Ok(()) => Ok(decoded) } } } From f4df111151682484894d3a25c55215a63d3c91af Mon Sep 17 00:00:00 2001 From: Corey Bonnell Date: Sun, 13 Oct 2024 23:28:07 -0400 Subject: [PATCH 4/6] Update CI --- .github/workflows/CI.yml | Bin 8602 -> 12318 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d49657eafc7175e6c124b83d388b1b02b5bb57b6..8c1ed7b5ae62fd927e72babbbb61ea6395e61b29 100644 GIT binary patch delta 1687 zcmbtU%}Z2q6uqOPGdgOHlSbJ%&zw?==P*hVicw0agl48vtDJ8K=R;=HNm9gZi;(Un zT0}vsAShf0(SJ~oyEeIOrvz=>bnfrXIB!%kh{t>H_j&HQ_uPA5485G){M4_LP79Qv z04-9K(v+bjX_zJOXxNk873@VQi?2p8isL^=OBDR@{iBtiG}QA~hka|iV$yLi2|EWX zO_T0&R|K$G3IRS2K!HoKr}>>N1E3W3@s8con5Hmx!`Ra)i1j!qgn7f+dV3gaV*J)o z6h$_LTN+I$qH}N}h1oLhWMDI%pU1HZ2YIiek$>36*CSvfX9abP?$HoU(kL*dFdwIf zG=u*n)<@|M<^$xV4i$%CDb~Fd+}?hF1#|0;_Ju1n>sN%fjYl; z*?UA;iMk|CF`-s)TWA#HXjVH=-g-5O-K4r1R(Fl0^kFPnu!P$>Mv_lqnx`9xte?7- zuDjL?L#1)s zJ_qM`ug1l*7Ax=8ZC*Ld;V**n&Z*{qs|$W)ee2JGRTk0cfik+Prg`|8rX0S7IF;5N zQj6c5ujfpKw@{?KUD3;*Ypk83m5w*9{1a~jN(u2%)Qn+e5uUH0F2C6f%R1j}7=xD` zHnEGC@ayt3tTl9a)C_n>HED-t*LdC8#uGLTmc86%ztn2Z3ZsHWF%6mt0>)AnzAUUP zA?_ipnfAzst|9s6Q#y%q%NQ*}hi2sCwxiG)bV_dRpZj%uQ~KHB=HC{LpIYoU+WPEK)J@?DF z$@AP4Kff)nBjW0F8m5NTl@XW>^1j>stk%x;)iwR%eiT>>z)a(tH90KpNLM21*fn!g zWl|`TDrs55JIfo6Hdi5qd~_M1&OzdY3ba^|1UKWD3(9DJQrxP{IoaaAD22YD(xzQC Ziq(8q5oRSPn}WcV7316*tx+vi(;o^;XZ`>H delta 212 zcmbQ2Fw1$uKG}4JOokGM42DvMBnAZrT_7xAs050nG88kEZ2Y;KMHM2N22_{FkOGtk z(IELEpvod34Q5X^WRaXaL0oUL04K+0CN>#v; Date: Sun, 13 Oct 2024 23:35:33 -0400 Subject: [PATCH 5/6] Fix Set add method --- src/asn1_type.rs | 4 ++-- tests/test_context_specific.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/asn1_type.rs b/src/asn1_type.rs index c08f78f..fca6cda 100644 --- a/src/asn1_type.rs +++ b/src/asn1_type.rs @@ -2,7 +2,7 @@ use crate::decoder::DecodeStep; use crate::{decode_der_rec, decode_explicit, decoder, get_chosen_spec, tag, NativeHelperModule, TAGSET_ATTR}; use der::asn1::{ObjectIdentifier, PrintableStringRef}; use itertools::Itertools; -use pyo3::prelude::PyAnyMethods; +use pyo3::prelude::{PyAnyMethods, PySetMethods}; use pyo3::types::{IntoPyDict, PyBool, PyBytes, PyDict, PySet, PyString, PyTuple}; use pyo3::{intern, Bound, IntoPy, PyAny, PyErr, PyResult}; @@ -471,7 +471,7 @@ impl<'a, 'py> Decoder<'a, 'py> for SequenceDecoder<'py> { asn1_object.call_method(intern![py, "setComponentByPosition"], (index, decoded), Some(&get_constructed_set_component_kwargs(&self.step.module())))?; - seen_indices.add(index)?; + PySetMethods::add(&seen_indices, index)?; index += 1; relative_offset += tlv.len(); diff --git a/tests/test_context_specific.py b/tests/test_context_specific.py index 5b4e327..70ba098 100644 --- a/tests/test_context_specific.py +++ b/tests/test_context_specific.py @@ -1,7 +1,8 @@ import pytest from pyasn1 import error from pyasn1.type import univ, namedtype, char, tag -from . import MAX, _wrapper + +from . import _wrapper class ImplicitSequence(univ.Sequence): From 949c1874aa1f9b52689123a13ab4f932d7b4874a Mon Sep 17 00:00:00 2001 From: Corey Bonnell Date: Sun, 13 Oct 2024 23:42:52 -0400 Subject: [PATCH 6/6] Remove enscripten --- .github/workflows/CI.yml | Bin 12318 -> 9378 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8c1ed7b5ae62fd927e72babbbb61ea6395e61b29..97b6aa2130abd4c83530712d27e4d80d1fb680e0 100644 GIT binary patch delta 17 ZcmbQ2u*h@6A*s!3YB!iSi)nGN0RTlB22lV2 delta 1200 zcmbtUO-~b16g{T3C85N^(3mz#XOM(8rjSBZ(gZ^!2CESZ0*Navowhd64)z1mNaDt& z3*(L3E?l~*vN3Lq`~uziBi#58Ja=rB7W_!eWahnl-~BlEp8Muiy7i!a7%}oFqlO%+ zC}9V6Dp1>ycC2Yf%l~WT>H+oFC*CiaOY$L4FR6Rdl%!qa7 z%3^PiQ_MDj$9zoMS74?$eHEJH7nYxP z@-b}4bB`(SL-lw+hToFO++lio|NUmX2)<745n7Gym?bp{_eyQCSOP(Z?^RL{rN|^noxR?Hi#29wu+cf5A35VVY`R#dU1F4~ pU3oJYl}d!jjCYdp`cCWEmgU=kA?=}ogTu%d&q@EIgO_7NzVA=z^S=N9