Mark the majority of the remaining Rust types as frozen (#9308)

These types only required mutability for an interior cache. By using `GILOnceCell` we don't require an `&mut` reference for this.
This commit is contained in:
Alex Gaynor 2023-07-29 00:02:30 -04:00 committed by GitHub
parent 7735fffa7b
commit 543cf43179
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 82 deletions

View file

@ -33,11 +33,10 @@ self_cell::self_cell!(
}
);
// TODO: can't be frozen because extensions takes `&mut self`
#[pyo3::prelude::pyclass(module = "cryptography.hazmat.bindings._rust.x509")]
#[pyo3::prelude::pyclass(frozen, module = "cryptography.hazmat.bindings._rust.x509")]
pub(crate) struct Certificate {
pub(crate) raw: OwnedCertificate,
pub(crate) cached_extensions: Option<pyo3::PyObject>,
pub(crate) cached_extensions: pyo3::once_cell::GILOnceCell<pyo3::PyObject>,
}
#[pyo3::prelude::pymethods]
@ -248,11 +247,11 @@ impl Certificate {
}
#[getter]
fn extensions(&mut self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
fn extensions(&self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
let x509_module = py.import(pyo3::intern!(py, "cryptography.x509"))?;
x509::parse_and_cache_extensions(
py,
&mut self.cached_extensions,
&self.cached_extensions,
&self.raw.borrow_dependent().tbs_cert.raw_extensions,
|ext| match ext.extn_id {
oid::PRECERT_POISON_OID => {
@ -386,7 +385,7 @@ fn load_der_x509_certificate(
Ok(Certificate {
raw,
cached_extensions: None,
cached_extensions: pyo3::once_cell::GILOnceCell::new(),
})
}

View file

@ -387,48 +387,46 @@ pub(crate) fn parse_and_cache_extensions<
F: Fn(&Extension<'_>) -> Result<Option<&'p pyo3::PyAny>, CryptographyError>,
>(
py: pyo3::Python<'p>,
cached_extensions: &mut Option<pyo3::PyObject>,
cached_extensions: &pyo3::once_cell::GILOnceCell<pyo3::PyObject>,
raw_extensions: &Option<RawExtensions<'_>>,
parse_ext: F,
) -> pyo3::PyResult<pyo3::PyObject> {
if let Some(cached) = cached_extensions {
return Ok(cached.clone_ref(py));
}
cached_extensions
.get_or_try_init(py, || {
let extensions = match Extensions::from_raw_extensions(raw_extensions.as_ref()) {
Ok(extensions) => extensions,
Err(DuplicateExtensionsError(oid)) => {
let oid_obj = oid_to_py_oid(py, &oid)?;
return Err(exceptions::DuplicateExtension::new_err((
format!("Duplicate {} extension found", &oid),
oid_obj.into_py(py),
)));
}
};
let extensions = match Extensions::from_raw_extensions(raw_extensions.as_ref()) {
Ok(extensions) => extensions,
Err(DuplicateExtensionsError(oid)) => {
let oid_obj = oid_to_py_oid(py, &oid)?;
return Err(exceptions::DuplicateExtension::new_err((
format!("Duplicate {} extension found", &oid),
oid_obj.into_py(py),
)));
}
};
let x509_module = py.import(pyo3::intern!(py, "cryptography.x509"))?;
let exts = pyo3::types::PyList::empty(py);
for raw_ext in extensions.iter() {
let oid_obj = oid_to_py_oid(py, &raw_ext.extn_id)?;
let x509_module = py.import(pyo3::intern!(py, "cryptography.x509"))?;
let exts = pyo3::types::PyList::empty(py);
for raw_ext in extensions.iter() {
let oid_obj = oid_to_py_oid(py, &raw_ext.extn_id)?;
let extn_value = match parse_ext(&raw_ext)? {
Some(e) => e,
None => x509_module.call_method1(
pyo3::intern!(py, "UnrecognizedExtension"),
(oid_obj, raw_ext.extn_value),
)?,
};
let ext_obj = x509_module.call_method1(
pyo3::intern!(py, "Extension"),
(oid_obj, raw_ext.critical, extn_value),
)?;
exts.append(ext_obj)?;
}
let extensions = x509_module
.call_method1(pyo3::intern!(py, "Extensions"), (exts,))?
.to_object(py);
*cached_extensions = Some(extensions.clone_ref(py));
Ok(extensions)
let extn_value = match parse_ext(&raw_ext)? {
Some(e) => e,
None => x509_module.call_method1(
pyo3::intern!(py, "UnrecognizedExtension"),
(oid_obj, raw_ext.extn_value),
)?,
};
let ext_obj = x509_module.call_method1(
pyo3::intern!(py, "Extension"),
(oid_obj, raw_ext.critical, extn_value),
)?;
exts.append(ext_obj)?;
}
Ok(x509_module
.call_method1(pyo3::intern!(py, "Extensions"), (exts,))?
.to_object(py))
})
.map(|p| p.clone_ref(py))
}
pub(crate) fn encode_extensions<

View file

@ -43,7 +43,7 @@ fn load_der_x509_crl(
Ok(CertificateRevocationList {
owned: Arc::new(owned),
revoked_certs: pyo3::once_cell::GILOnceCell::new(),
cached_extensions: None,
cached_extensions: pyo3::once_cell::GILOnceCell::new(),
})
}
@ -71,13 +71,12 @@ self_cell::self_cell!(
}
);
// TODO: can't be frozen because extensions required `&mut self`.
#[pyo3::prelude::pyclass(module = "cryptography.hazmat.bindings._rust.x509")]
#[pyo3::prelude::pyclass(frozen, module = "cryptography.hazmat.bindings._rust.x509")]
struct CertificateRevocationList {
owned: Arc<OwnedCertificateRevocationList>,
revoked_certs: pyo3::once_cell::GILOnceCell<Vec<OwnedRevokedCertificate>>,
cached_extensions: Option<pyo3::PyObject>,
cached_extensions: pyo3::once_cell::GILOnceCell<pyo3::PyObject>,
}
impl CertificateRevocationList {
@ -88,7 +87,7 @@ impl CertificateRevocationList {
fn revoked_cert(&self, py: pyo3::Python<'_>, idx: usize) -> RevokedCertificate {
RevokedCertificate {
owned: self.revoked_certs.get(py).unwrap()[idx].clone(),
cached_extensions: None,
cached_extensions: pyo3::once_cell::GILOnceCell::new(),
}
}
@ -270,13 +269,13 @@ impl CertificateRevocationList {
}
#[getter]
fn extensions(&mut self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
fn extensions(&self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
let tbs_cert_list = &self.owned.borrow_dependent().tbs_cert_list;
let x509_module = py.import(pyo3::intern!(py, "cryptography.x509"))?;
x509::parse_and_cache_extensions(
py,
&mut self.cached_extensions,
&self.cached_extensions,
&tbs_cert_list.raw_crl_extensions,
|ext| match ext.extn_id {
oid::CRL_NUMBER_OID => {
@ -359,7 +358,7 @@ impl CertificateRevocationList {
}
fn get_revoked_certificate_by_serial_number(
&mut self,
&self,
py: pyo3::Python<'_>,
serial: &pyo3::types::PyLong,
) -> pyo3::PyResult<Option<RevokedCertificate>> {
@ -381,7 +380,7 @@ impl CertificateRevocationList {
match owned {
Ok(o) => Ok(Some(RevokedCertificate {
owned: o,
cached_extensions: None,
cached_extensions: pyo3::once_cell::GILOnceCell::new(),
})),
Err(()) => Ok(None),
}
@ -466,7 +465,7 @@ impl CRLIterator {
.ok()?;
Some(RevokedCertificate {
owned: revoked,
cached_extensions: None,
cached_extensions: pyo3::once_cell::GILOnceCell::new(),
})
}
}
@ -491,11 +490,10 @@ impl Clone for OwnedRevokedCertificate {
}
}
// TODO: can't be frozen because extensions required `&mut self`.
#[pyo3::prelude::pyclass(module = "cryptography.hazmat.bindings._rust.x509")]
#[pyo3::prelude::pyclass(frozen, module = "cryptography.hazmat.bindings._rust.x509")]
struct RevokedCertificate {
owned: OwnedRevokedCertificate,
cached_extensions: Option<pyo3::PyObject>,
cached_extensions: pyo3::once_cell::GILOnceCell<pyo3::PyObject>,
}
#[pyo3::prelude::pymethods]
@ -517,10 +515,10 @@ impl RevokedCertificate {
}
#[getter]
fn extensions(&mut self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
fn extensions(&self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
x509::parse_and_cache_extensions(
py,
&mut self.cached_extensions,
&self.cached_extensions,
&self.owned.borrow_dependent().raw_crl_entry_extensions,
|ext| parse_crl_entry_ext(py, ext),
)

View file

@ -22,11 +22,10 @@ self_cell::self_cell!(
}
);
// TODO: can't be frozen extensions take `&mut self`
#[pyo3::prelude::pyclass(module = "cryptography.hazmat.bindings._rust.x509")]
#[pyo3::prelude::pyclass(frozen, module = "cryptography.hazmat.bindings._rust.x509")]
struct CertificateSigningRequest {
raw: OwnedCsr,
cached_extensions: Option<pyo3::PyObject>,
cached_extensions: pyo3::once_cell::GILOnceCell<pyo3::PyObject>,
}
#[pyo3::prelude::pymethods]
@ -179,7 +178,7 @@ impl CertificateSigningRequest {
}
#[getter]
fn attributes<'p>(&mut self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> {
fn attributes<'p>(&self, py: pyo3::Python<'p>) -> pyo3::PyResult<&'p pyo3::PyAny> {
let pyattrs = pyo3::types::PyList::empty(py);
for attribute in self
.raw
@ -212,7 +211,7 @@ impl CertificateSigningRequest {
}
#[getter]
fn extensions(&mut self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
fn extensions(&self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
let raw_exts = self
.raw
.borrow_dependent()
@ -224,7 +223,7 @@ impl CertificateSigningRequest {
)
})?;
x509::parse_and_cache_extensions(py, &mut self.cached_extensions, &raw_exts, |ext| {
x509::parse_and_cache_extensions(py, &self.cached_extensions, &raw_exts, |ext| {
certificate::parse_cert_ext(py, ext)
})
}
@ -283,7 +282,7 @@ fn load_der_x509_csr(
Ok(CertificateSigningRequest {
raw,
cached_extensions: None,
cached_extensions: pyo3::once_cell::GILOnceCell::new(),
})
}

View file

@ -45,16 +45,15 @@ fn load_der_ocsp_request(
Ok(OCSPRequest {
raw,
cached_extensions: None,
cached_extensions: pyo3::once_cell::GILOnceCell::new(),
})
}
// TODO: can't be frozen because extensions takes `&mut self`
#[pyo3::prelude::pyclass(module = "cryptography.hazmat.bindings._rust.ocsp")]
#[pyo3::prelude::pyclass(frozen, module = "cryptography.hazmat.bindings._rust.ocsp")]
struct OCSPRequest {
raw: OwnedOCSPRequest,
cached_extensions: Option<pyo3::PyObject>,
cached_extensions: pyo3::once_cell::GILOnceCell<pyo3::PyObject>,
}
impl OCSPRequest {
@ -112,13 +111,13 @@ impl OCSPRequest {
}
#[getter]
fn extensions(&mut self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
fn extensions(&self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
let tbs_request = &self.raw.borrow_dependent().tbs_request;
let x509_module = py.import(pyo3::intern!(py, "cryptography.x509"))?;
x509::parse_and_cache_extensions(
py,
&mut self.cached_extensions,
&self.cached_extensions,
&tbs_request.raw_request_extensions,
|ext| {
match ext.extn_id {

View file

@ -57,8 +57,8 @@ fn load_der_ocsp_response(
};
Ok(OCSPResponse {
raw: Arc::new(raw),
cached_extensions: None,
cached_single_extensions: None,
cached_extensions: pyo3::once_cell::GILOnceCell::new(),
cached_single_extensions: pyo3::once_cell::GILOnceCell::new(),
})
}
@ -70,13 +70,12 @@ self_cell::self_cell!(
}
);
// TODO: can't be frozen extensions and single_extensions take `&mut self`
#[pyo3::prelude::pyclass(module = "cryptography.hazmat.bindings._rust.ocsp")]
#[pyo3::prelude::pyclass(frozen, module = "cryptography.hazmat.bindings._rust.ocsp")]
struct OCSPResponse {
raw: Arc<OwnedOCSPResponse>,
cached_extensions: Option<pyo3::PyObject>,
cached_single_extensions: Option<pyo3::PyObject>,
cached_extensions: pyo3::once_cell::GILOnceCell<pyo3::PyObject>,
cached_single_extensions: pyo3::once_cell::GILOnceCell<pyo3::PyObject>,
}
impl OCSPResponse {
@ -247,7 +246,7 @@ impl OCSPResponse {
py,
x509::certificate::Certificate {
raw: raw_cert,
cached_extensions: None,
cached_extensions: pyo3::once_cell::GILOnceCell::new(),
},
)?)?;
}
@ -321,7 +320,7 @@ impl OCSPResponse {
}
#[getter]
fn extensions(&mut self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
fn extensions(&self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
self.requires_successful_response()?;
let response_data = &self
@ -337,7 +336,7 @@ impl OCSPResponse {
let x509_module = py.import(pyo3::intern!(py, "cryptography.x509"))?;
x509::parse_and_cache_extensions(
py,
&mut self.cached_extensions,
&self.cached_extensions,
&response_data.raw_response_extensions,
|ext| {
match &ext.extn_id {
@ -360,7 +359,7 @@ impl OCSPResponse {
}
#[getter]
fn single_extensions(&mut self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
fn single_extensions(&self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> {
self.requires_successful_response()?;
let single_resp = single_response(
self.raw
@ -375,7 +374,7 @@ impl OCSPResponse {
let x509_module = py.import(pyo3::intern!(py, "cryptography.x509"))?;
x509::parse_and_cache_extensions(
py,
&mut self.cached_single_extensions,
&self.cached_single_extensions,
&single_resp.raw_single_extensions,
|ext| match &ext.extn_id {
&oid::SIGNED_CERTIFICATE_TIMESTAMPS_OID => {