mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 00:29:09 -05:00
fix(node): use cppgc
for managing X509Certificate (#21999)
Introduces the first cppgc backed Resource into Deno. This fixes the memory leak when using `X509Certificate` **Comparison**: ```js import { X509Certificate } from 'node:crypto'; const r = Deno.readFileSync('cli/tests/node_compat/test/fixtures/keys/agent1-cert.pem'); setInterval(() => { for (let i = 0; i < 10000; i++) { const cert = new X509Certificate(r); } }, 1000); ``` Memory usage after 5 secs `main`: 1692MB `cppgc`: peaks at 400MB
This commit is contained in:
parent
40febd9dd1
commit
28f64171cb
3 changed files with 48 additions and 91 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -1150,9 +1150,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_core"
|
name = "deno_core"
|
||||||
version = "0.247.0"
|
version = "0.248.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ff6e8ee2e08528c1da4f5a48659c67d12012e831c737f6266534d4f550ccc8c3"
|
checksum = "974d075b6647aa6cca14ea75c3833f8996b1c3e487adcde490977f21ac14e27e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bit-set",
|
"bit-set",
|
||||||
|
@ -1600,9 +1600,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_ops"
|
name = "deno_ops"
|
||||||
version = "0.123.0"
|
version = "0.124.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "19f29c5fe78479c3fa437409dca009363feb77036c067d6f3682adff8d06f547"
|
checksum = "a1bc46bc85a26530e196a5f675dab6e06fb86b9104dc6fdc31cfc9ae1832d911"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-rules",
|
"proc-macro-rules",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -5255,9 +5255,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_v8"
|
name = "serde_v8"
|
||||||
version = "0.156.0"
|
version = "0.157.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "48ad52e56e21faee5d310a898ab77f83abdab737fde1e97fa6a8cd6615d139ef"
|
checksum = "8853e607c700ade0acb853aafda7e4cc1f752f4ebb35b0e2ecbf42e784e6d0e0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
|
|
|
@ -41,7 +41,7 @@ repository = "https://github.com/denoland/deno"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
deno_ast = { version = "1.0.1", features = ["transpiling"] }
|
deno_ast = { version = "1.0.1", features = ["transpiling"] }
|
||||||
deno_core = { version = "0.247.0" }
|
deno_core = { version = "0.248.0" }
|
||||||
|
|
||||||
deno_runtime = { version = "0.140.0", path = "./runtime" }
|
deno_runtime = { version = "0.140.0", path = "./runtime" }
|
||||||
napi_sym = { version = "0.62.0", path = "./cli/napi/sym" }
|
napi_sym = { version = "0.62.0", path = "./cli/napi/sym" }
|
||||||
|
|
|
@ -3,10 +3,7 @@
|
||||||
use deno_core::error::bad_resource_id;
|
use deno_core::error::bad_resource_id;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::op2;
|
use deno_core::op2;
|
||||||
use deno_core::OpState;
|
use deno_core::v8;
|
||||||
use deno_core::Resource;
|
|
||||||
|
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
use x509_parser::der_parser::asn1_rs::Any;
|
use x509_parser::der_parser::asn1_rs::Any;
|
||||||
use x509_parser::der_parser::asn1_rs::Tag;
|
use x509_parser::der_parser::asn1_rs::Tag;
|
||||||
|
@ -48,17 +45,11 @@ impl std::ops::Deref for Certificate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resource for Certificate {
|
#[op2]
|
||||||
fn name(&self) -> Cow<str> {
|
pub fn op_node_x509_parse<'s>(
|
||||||
"x509Certificate".into()
|
scope: &'s mut v8::HandleScope,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[op2(fast)]
|
|
||||||
pub fn op_node_x509_parse(
|
|
||||||
state: &mut OpState,
|
|
||||||
#[buffer] buf: &[u8],
|
#[buffer] buf: &[u8],
|
||||||
) -> Result<u32, AnyError> {
|
) -> Result<v8::Local<'s, v8::Object>, AnyError> {
|
||||||
let pem = match pem::parse_x509_pem(buf) {
|
let pem = match pem::parse_x509_pem(buf) {
|
||||||
Ok((_, pem)) => Some(pem),
|
Ok((_, pem)) => Some(pem),
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
|
@ -76,32 +67,25 @@ pub fn op_node_x509_parse(
|
||||||
cert: unsafe { std::mem::transmute(cert) },
|
cert: unsafe { std::mem::transmute(cert) },
|
||||||
pem,
|
pem,
|
||||||
};
|
};
|
||||||
let rid = state.resource_table.add(cert);
|
|
||||||
Ok(rid)
|
let obj = deno_core::cppgc::make_cppgc_object(scope, cert);
|
||||||
|
Ok(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
pub fn op_node_x509_ca(
|
pub fn op_node_x509_ca(rid: v8::Local<v8::Object>) -> Result<bool, AnyError> {
|
||||||
state: &mut OpState,
|
let cert = deno_core::cppgc::unwrap_cppgc_object::<Certificate>(rid)
|
||||||
rid: u32,
|
.ok_or_else(bad_resource_id)?;
|
||||||
) -> Result<bool, AnyError> {
|
|
||||||
let cert = state
|
|
||||||
.resource_table
|
|
||||||
.get::<Certificate>(rid)
|
|
||||||
.map_err(|_| bad_resource_id())?;
|
|
||||||
Ok(cert.is_ca())
|
Ok(cert.is_ca())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
pub fn op_node_x509_check_email(
|
pub fn op_node_x509_check_email(
|
||||||
state: &mut OpState,
|
rid: v8::Local<v8::Object>,
|
||||||
rid: u32,
|
|
||||||
#[string] email: &str,
|
#[string] email: &str,
|
||||||
) -> Result<bool, AnyError> {
|
) -> Result<bool, AnyError> {
|
||||||
let cert = state
|
let cert = deno_core::cppgc::unwrap_cppgc_object::<Certificate>(rid)
|
||||||
.resource_table
|
.ok_or_else(bad_resource_id)?;
|
||||||
.get::<Certificate>(rid)
|
|
||||||
.map_err(|_| bad_resource_id())?;
|
|
||||||
|
|
||||||
let subject = cert.subject();
|
let subject = cert.subject();
|
||||||
if subject
|
if subject
|
||||||
|
@ -137,65 +121,50 @@ pub fn op_node_x509_check_email(
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_fingerprint(
|
pub fn op_node_x509_fingerprint(
|
||||||
state: &mut OpState,
|
rid: v8::Local<v8::Object>,
|
||||||
rid: u32,
|
|
||||||
) -> Result<Option<String>, AnyError> {
|
) -> Result<Option<String>, AnyError> {
|
||||||
let cert = state
|
let cert = deno_core::cppgc::unwrap_cppgc_object::<Certificate>(rid)
|
||||||
.resource_table
|
.ok_or_else(bad_resource_id)?;
|
||||||
.get::<Certificate>(rid)
|
|
||||||
.map_err(|_| bad_resource_id())?;
|
|
||||||
Ok(cert.fingerprint::<sha1::Sha1>())
|
Ok(cert.fingerprint::<sha1::Sha1>())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_fingerprint256(
|
pub fn op_node_x509_fingerprint256(
|
||||||
state: &mut OpState,
|
rid: v8::Local<v8::Object>,
|
||||||
rid: u32,
|
|
||||||
) -> Result<Option<String>, AnyError> {
|
) -> Result<Option<String>, AnyError> {
|
||||||
let cert = state
|
let cert = deno_core::cppgc::unwrap_cppgc_object::<Certificate>(rid)
|
||||||
.resource_table
|
.ok_or_else(bad_resource_id)?;
|
||||||
.get::<Certificate>(rid)
|
|
||||||
.map_err(|_| bad_resource_id())?;
|
|
||||||
Ok(cert.fingerprint::<sha2::Sha256>())
|
Ok(cert.fingerprint::<sha2::Sha256>())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_fingerprint512(
|
pub fn op_node_x509_fingerprint512(
|
||||||
state: &mut OpState,
|
rid: v8::Local<v8::Object>,
|
||||||
rid: u32,
|
|
||||||
) -> Result<Option<String>, AnyError> {
|
) -> Result<Option<String>, AnyError> {
|
||||||
let cert = state
|
let cert = deno_core::cppgc::unwrap_cppgc_object::<Certificate>(rid)
|
||||||
.resource_table
|
.ok_or_else(bad_resource_id)?;
|
||||||
.get::<Certificate>(rid)
|
|
||||||
.map_err(|_| bad_resource_id())?;
|
|
||||||
Ok(cert.fingerprint::<sha2::Sha512>())
|
Ok(cert.fingerprint::<sha2::Sha512>())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_get_issuer(
|
pub fn op_node_x509_get_issuer(
|
||||||
state: &mut OpState,
|
rid: v8::Local<v8::Object>,
|
||||||
rid: u32,
|
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, AnyError> {
|
||||||
let cert = state
|
let cert = deno_core::cppgc::unwrap_cppgc_object::<Certificate>(rid)
|
||||||
.resource_table
|
.ok_or_else(bad_resource_id)?;
|
||||||
.get::<Certificate>(rid)
|
|
||||||
.map_err(|_| bad_resource_id())?;
|
|
||||||
Ok(x509name_to_string(cert.issuer(), oid_registry())?)
|
Ok(x509name_to_string(cert.issuer(), oid_registry())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_get_subject(
|
pub fn op_node_x509_get_subject(
|
||||||
state: &mut OpState,
|
rid: v8::Local<v8::Object>,
|
||||||
rid: u32,
|
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, AnyError> {
|
||||||
let cert = state
|
let cert = deno_core::cppgc::unwrap_cppgc_object::<Certificate>(rid)
|
||||||
.resource_table
|
.ok_or_else(bad_resource_id)?;
|
||||||
.get::<Certificate>(rid)
|
|
||||||
.map_err(|_| bad_resource_id())?;
|
|
||||||
Ok(x509name_to_string(cert.subject(), oid_registry())?)
|
Ok(x509name_to_string(cert.subject(), oid_registry())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,39 +231,30 @@ fn x509name_to_string(
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_get_valid_from(
|
pub fn op_node_x509_get_valid_from(
|
||||||
state: &mut OpState,
|
rid: v8::Local<v8::Object>,
|
||||||
rid: u32,
|
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, AnyError> {
|
||||||
let cert = state
|
let cert = deno_core::cppgc::unwrap_cppgc_object::<Certificate>(rid)
|
||||||
.resource_table
|
.ok_or_else(bad_resource_id)?;
|
||||||
.get::<Certificate>(rid)
|
|
||||||
.map_err(|_| bad_resource_id())?;
|
|
||||||
Ok(cert.validity().not_before.to_string())
|
Ok(cert.validity().not_before.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_get_valid_to(
|
pub fn op_node_x509_get_valid_to(
|
||||||
state: &mut OpState,
|
rid: v8::Local<v8::Object>,
|
||||||
rid: u32,
|
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, AnyError> {
|
||||||
let cert = state
|
let cert = deno_core::cppgc::unwrap_cppgc_object::<Certificate>(rid)
|
||||||
.resource_table
|
.ok_or_else(bad_resource_id)?;
|
||||||
.get::<Certificate>(rid)
|
|
||||||
.map_err(|_| bad_resource_id())?;
|
|
||||||
Ok(cert.validity().not_after.to_string())
|
Ok(cert.validity().not_after.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_get_serial_number(
|
pub fn op_node_x509_get_serial_number(
|
||||||
state: &mut OpState,
|
rid: v8::Local<v8::Object>,
|
||||||
rid: u32,
|
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, AnyError> {
|
||||||
let cert = state
|
let cert = deno_core::cppgc::unwrap_cppgc_object::<Certificate>(rid)
|
||||||
.resource_table
|
.ok_or_else(bad_resource_id)?;
|
||||||
.get::<Certificate>(rid)
|
|
||||||
.map_err(|_| bad_resource_id())?;
|
|
||||||
let mut s = cert.serial.to_str_radix(16);
|
let mut s = cert.serial.to_str_radix(16);
|
||||||
s.make_ascii_uppercase();
|
s.make_ascii_uppercase();
|
||||||
Ok(s)
|
Ok(s)
|
||||||
|
@ -302,13 +262,10 @@ pub fn op_node_x509_get_serial_number(
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
pub fn op_node_x509_key_usage(
|
pub fn op_node_x509_key_usage(
|
||||||
state: &mut OpState,
|
rid: v8::Local<v8::Object>,
|
||||||
rid: u32,
|
|
||||||
) -> Result<u16, AnyError> {
|
) -> Result<u16, AnyError> {
|
||||||
let cert = state
|
let cert = deno_core::cppgc::unwrap_cppgc_object::<Certificate>(rid)
|
||||||
.resource_table
|
.ok_or_else(bad_resource_id)?;
|
||||||
.get::<Certificate>(rid)
|
|
||||||
.map_err(|_| bad_resource_id())?;
|
|
||||||
|
|
||||||
let key_usage = cert
|
let key_usage = cert
|
||||||
.extensions()
|
.extensions()
|
||||||
|
|
Loading…
Reference in a new issue