Blame SOURCES/0007-Ticket-51175-resolve-plugin-name-leaking.patch

91ce38
From 279bdb5148eb0b67ddab40c4dd9d08e9e1672f13 Mon Sep 17 00:00:00 2001
91ce38
From: William Brown <william@blackhats.net.au>
91ce38
Date: Fri, 26 Jun 2020 10:27:56 +1000
91ce38
Subject: [PATCH 07/12] Ticket 51175 - resolve plugin name leaking
91ce38
91ce38
Bug Description: Previously pblock.c assumed that all plugin
91ce38
names were static c strings. Rust can't create static C
91ce38
strings, so these were intentionally leaked.
91ce38
91ce38
Fix Description: Rather than leak these, we do a dup/free
91ce38
through the slapiplugin struct instead, meaning we can use
91ce38
ephemeral, and properly managed strings in rust. This does not
91ce38
affect any other existing code which will still handle the
91ce38
static strings correctly.
91ce38
91ce38
https://pagure.io/389-ds-base/issue/51175
91ce38
91ce38
Author: William Brown <william@blackhats.net.au>
91ce38
91ce38
Review by: mreynolds, tbordaz (Thanks!)
91ce38
---
91ce38
 Makefile.am                             |  1 +
91ce38
 configure.ac                            |  2 +-
91ce38
 ldap/servers/slapd/pagedresults.c       |  6 +--
91ce38
 ldap/servers/slapd/pblock.c             |  9 ++--
91ce38
 ldap/servers/slapd/plugin.c             |  7 +++
91ce38
 ldap/servers/slapd/pw_verify.c          |  1 +
91ce38
 ldap/servers/slapd/tools/pwenc.c        |  2 +-
91ce38
 src/slapi_r_plugin/README.md            |  6 +--
91ce38
 src/slapi_r_plugin/src/charray.rs       | 32 ++++++++++++++
91ce38
 src/slapi_r_plugin/src/lib.rs           |  8 ++--
91ce38
 src/slapi_r_plugin/src/macros.rs        | 17 +++++---
91ce38
 src/slapi_r_plugin/src/syntax_plugin.rs | 57 +++++++------------------
91ce38
 12 files changed, 85 insertions(+), 63 deletions(-)
91ce38
 create mode 100644 src/slapi_r_plugin/src/charray.rs
91ce38
91ce38
diff --git a/Makefile.am b/Makefile.am
91ce38
index 627953850..36434cf17 100644
91ce38
--- a/Makefile.am
91ce38
+++ b/Makefile.am
91ce38
@@ -1312,6 +1312,7 @@ rust-nsslapd-private.h: @abs_top_builddir@/rs/@rust_target_dir@/librnsslapd.a
91ce38
 libslapi_r_plugin_SOURCES = \
91ce38
 	src/slapi_r_plugin/src/backend.rs \
91ce38
 	src/slapi_r_plugin/src/ber.rs \
91ce38
+	src/slapi_r_plugin/src/charray.rs \
91ce38
 	src/slapi_r_plugin/src/constants.rs \
91ce38
 	src/slapi_r_plugin/src/dn.rs \
91ce38
 	src/slapi_r_plugin/src/entry.rs \
91ce38
diff --git a/configure.ac b/configure.ac
91ce38
index b3cf77d08..61bf35e4a 100644
91ce38
--- a/configure.ac
91ce38
+++ b/configure.ac
91ce38
@@ -122,7 +122,7 @@ if test "$enable_debug" = yes ; then
91ce38
   debug_defs="-DDEBUG -DMCC_DEBUG"
91ce38
   debug_cflags="-g3 -O0 -rdynamic"
91ce38
   debug_cxxflags="-g3 -O0 -rdynamic"
91ce38
-  debug_rust_defs="-C debuginfo=2"
91ce38
+  debug_rust_defs="-C debuginfo=2 -Z macro-backtrace"
91ce38
   cargo_defs=""
91ce38
   rust_target_dir="debug"
91ce38
 else
91ce38
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
91ce38
index d8b8798b6..e3444e944 100644
91ce38
--- a/ldap/servers/slapd/pagedresults.c
91ce38
+++ b/ldap/servers/slapd/pagedresults.c
91ce38
@@ -738,10 +738,10 @@ pagedresults_cleanup(Connection *conn, int needlock)
91ce38
     int i;
91ce38
     PagedResults *prp = NULL;
91ce38
 
91ce38
-    slapi_log_err(SLAPI_LOG_TRACE, "pagedresults_cleanup", "=>\n");
91ce38
+    /* slapi_log_err(SLAPI_LOG_TRACE, "pagedresults_cleanup", "=>\n"); */
91ce38
 
91ce38
     if (NULL == conn) {
91ce38
-        slapi_log_err(SLAPI_LOG_TRACE, "pagedresults_cleanup", "<= Connection is NULL\n");
91ce38
+        /* slapi_log_err(SLAPI_LOG_TRACE, "pagedresults_cleanup", "<= Connection is NULL\n"); */
91ce38
         return 0;
91ce38
     }
91ce38
 
91ce38
@@ -767,7 +767,7 @@ pagedresults_cleanup(Connection *conn, int needlock)
91ce38
     if (needlock) {
91ce38
         pthread_mutex_unlock(&(conn->c_mutex));
91ce38
     }
91ce38
-    slapi_log_err(SLAPI_LOG_TRACE, "pagedresults_cleanup", "<= %d\n", rc);
91ce38
+    /* slapi_log_err(SLAPI_LOG_TRACE, "pagedresults_cleanup", "<= %d\n", rc); */
91ce38
     return rc;
91ce38
 }
91ce38
 
91ce38
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
91ce38
index 1ad9d0399..f7d1f8885 100644
91ce38
--- a/ldap/servers/slapd/pblock.c
91ce38
+++ b/ldap/servers/slapd/pblock.c
91ce38
@@ -3351,13 +3351,15 @@ slapi_pblock_set(Slapi_PBlock *pblock, int arg, void *value)
91ce38
         if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_SYNTAX) {
91ce38
             return (-1);
91ce38
         }
91ce38
-        pblock->pb_plugin->plg_syntax_names = (char **)value;
91ce38
+        PR_ASSERT(pblock->pb_plugin->plg_syntax_names == NULL);
91ce38
+        pblock->pb_plugin->plg_syntax_names = slapi_ch_array_dup((char **)value);
91ce38
         break;
91ce38
     case SLAPI_PLUGIN_SYNTAX_OID:
91ce38
         if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_SYNTAX) {
91ce38
             return (-1);
91ce38
         }
91ce38
-        pblock->pb_plugin->plg_syntax_oid = (char *)value;
91ce38
+        PR_ASSERT(pblock->pb_plugin->plg_syntax_oid == NULL);
91ce38
+        pblock->pb_plugin->plg_syntax_oid = slapi_ch_strdup((char *)value);
91ce38
         break;
91ce38
     case SLAPI_PLUGIN_SYNTAX_FLAGS:
91ce38
         if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_SYNTAX) {
91ce38
@@ -3806,7 +3808,8 @@ slapi_pblock_set(Slapi_PBlock *pblock, int arg, void *value)
91ce38
         if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_MATCHINGRULE) {
91ce38
             return (-1);
91ce38
         }
91ce38
-        pblock->pb_plugin->plg_mr_names = (char **)value;
91ce38
+        PR_ASSERT(pblock->pb_plugin->plg_mr_names == NULL);
91ce38
+        pblock->pb_plugin->plg_mr_names = slapi_ch_array_dup((char **)value);
91ce38
         break;
91ce38
     case SLAPI_PLUGIN_MR_COMPARE:
91ce38
         if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_MATCHINGRULE) {
91ce38
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
91ce38
index 282b98738..e6b48de60 100644
91ce38
--- a/ldap/servers/slapd/plugin.c
91ce38
+++ b/ldap/servers/slapd/plugin.c
91ce38
@@ -2694,6 +2694,13 @@ plugin_free(struct slapdplugin *plugin)
91ce38
     if (plugin->plg_type == SLAPI_PLUGIN_PWD_STORAGE_SCHEME || plugin->plg_type == SLAPI_PLUGIN_REVER_PWD_STORAGE_SCHEME) {
91ce38
         slapi_ch_free_string(&plugin->plg_pwdstorageschemename);
91ce38
     }
91ce38
+    if (plugin->plg_type == SLAPI_PLUGIN_SYNTAX) {
91ce38
+        slapi_ch_free_string(&plugin->plg_syntax_oid);
91ce38
+        slapi_ch_array_free(plugin->plg_syntax_names);
91ce38
+    }
91ce38
+    if (plugin->plg_type == SLAPI_PLUGIN_MATCHINGRULE) {
91ce38
+        slapi_ch_array_free(plugin->plg_mr_names);
91ce38
+    }
91ce38
     release_componentid(plugin->plg_identity);
91ce38
     slapi_counter_destroy(&plugin->plg_op_counter);
91ce38
     if (!plugin->plg_group) {
91ce38
diff --git a/ldap/servers/slapd/pw_verify.c b/ldap/servers/slapd/pw_verify.c
91ce38
index 4f0944b73..4ff1fa2fd 100644
91ce38
--- a/ldap/servers/slapd/pw_verify.c
91ce38
+++ b/ldap/servers/slapd/pw_verify.c
91ce38
@@ -111,6 +111,7 @@ pw_verify_token_dn(Slapi_PBlock *pb) {
91ce38
     if (fernet_verify_token(dn, cred->bv_val, key, tok_ttl) != 0) {
91ce38
         rc = SLAPI_BIND_SUCCESS;
91ce38
     }
91ce38
+    slapi_ch_free_string(&key);
91ce38
 #endif
91ce38
     return rc;
91ce38
 }
91ce38
diff --git a/ldap/servers/slapd/tools/pwenc.c b/ldap/servers/slapd/tools/pwenc.c
91ce38
index 1629c06cd..d89225e34 100644
91ce38
--- a/ldap/servers/slapd/tools/pwenc.c
91ce38
+++ b/ldap/servers/slapd/tools/pwenc.c
91ce38
@@ -34,7 +34,7 @@
91ce38
 
91ce38
 int ldap_syslog;
91ce38
 int ldap_syslog_level;
91ce38
-int slapd_ldap_debug = LDAP_DEBUG_ANY;
91ce38
+/* int slapd_ldap_debug = LDAP_DEBUG_ANY; */
91ce38
 int detached;
91ce38
 FILE *error_logfp;
91ce38
 FILE *access_logfp;
91ce38
diff --git a/src/slapi_r_plugin/README.md b/src/slapi_r_plugin/README.md
91ce38
index af9743ec9..1c9bcbf17 100644
91ce38
--- a/src/slapi_r_plugin/README.md
91ce38
+++ b/src/slapi_r_plugin/README.md
91ce38
@@ -15,7 +15,7 @@ the [Rust Nomicon](https://doc.rust-lang.org/nomicon/index.html)
91ce38
 > warning about danger.
91ce38
 
91ce38
 This document will not detail the specifics of unsafe or the invariants you must adhere to for rust
91ce38
-to work with C.
91ce38
+to work with C. Failure to uphold these invariants will lead to less than optimal consequences.
91ce38
 
91ce38
 If you still want to see more about the plugin bindings, go on ...
91ce38
 
91ce38
@@ -135,7 +135,7 @@ associated functions.
91ce38
 Now, you may notice that not all members of the trait are implemented. This is due to a feature
91ce38
 of rust known as default trait impls. This allows the trait origin (src/plugin.rs) to provide
91ce38
 template versions of these functions. If you "overwrite" them, your implementation is used. Unlike
91ce38
-OO, you may not inherit or call the default function. 
91ce38
+OO, you may not inherit or call the default function.
91ce38
 
91ce38
 If a default is not provided you *must* implement that function to be considered valid. Today (20200422)
91ce38
 this only applies to `start` and `close`.
91ce38
@@ -183,7 +183,7 @@ It's important to understand how Rust manages memory both on the stack and the h
91ce38
 As a result, this means that we must express in code, assertions about the proper ownership of memory
91ce38
 and who is responsible for it (unlike C, where it can be hard to determine who or what is responsible
91ce38
 for freeing some value.) Failure to handle this correctly, can and will lead to crashes, leaks or
91ce38
-*hand waving* magical failures that are eXtReMeLy FuN to debug.
91ce38
+*hand waving* magical failures that are `eXtReMeLy FuN` to debug.
91ce38
 
91ce38
 ### Reference Types
91ce38
 
91ce38
diff --git a/src/slapi_r_plugin/src/charray.rs b/src/slapi_r_plugin/src/charray.rs
91ce38
new file mode 100644
91ce38
index 000000000..d2e44693c
91ce38
--- /dev/null
91ce38
+++ b/src/slapi_r_plugin/src/charray.rs
91ce38
@@ -0,0 +1,32 @@
91ce38
+use std::ffi::CString;
91ce38
+use std::iter::once;
91ce38
+use std::os::raw::c_char;
91ce38
+use std::ptr;
91ce38
+
91ce38
+pub struct Charray {
91ce38
+    pin: Vec<CString>,
91ce38
+    charray: Vec<*const c_char>,
91ce38
+}
91ce38
+
91ce38
+impl Charray {
91ce38
+    pub fn new(input: &[&str]) -> Result<Self, ()> {
91ce38
+        let pin: Result<Vec<_>, ()> = input
91ce38
+            .iter()
91ce38
+            .map(|s| CString::new(*s).map_err(|_e| ()))
91ce38
+            .collect();
91ce38
+
91ce38
+        let pin = pin?;
91ce38
+
91ce38
+        let charray: Vec<_> = pin
91ce38
+            .iter()
91ce38
+            .map(|s| s.as_ptr())
91ce38
+            .chain(once(ptr::null()))
91ce38
+            .collect();
91ce38
+
91ce38
+        Ok(Charray { pin, charray })
91ce38
+    }
91ce38
+
91ce38
+    pub fn as_ptr(&self) -> *const *const c_char {
91ce38
+        self.charray.as_ptr()
91ce38
+    }
91ce38
+}
91ce38
diff --git a/src/slapi_r_plugin/src/lib.rs b/src/slapi_r_plugin/src/lib.rs
91ce38
index 076907bae..be28cac95 100644
91ce38
--- a/src/slapi_r_plugin/src/lib.rs
91ce38
+++ b/src/slapi_r_plugin/src/lib.rs
91ce38
@@ -1,9 +1,11 @@
91ce38
-// extern crate lazy_static;
91ce38
+#[macro_use]
91ce38
+extern crate lazy_static;
91ce38
 
91ce38
 #[macro_use]
91ce38
 pub mod macros;
91ce38
 pub mod backend;
91ce38
 pub mod ber;
91ce38
+pub mod charray;
91ce38
 mod constants;
91ce38
 pub mod dn;
91ce38
 pub mod entry;
91ce38
@@ -20,6 +22,7 @@ pub mod value;
91ce38
 pub mod prelude {
91ce38
     pub use crate::backend::{BackendRef, BackendRefTxn};
91ce38
     pub use crate::ber::BerValRef;
91ce38
+    pub use crate::charray::Charray;
91ce38
     pub use crate::constants::{FilterType, PluginFnType, PluginType, PluginVersion, LDAP_SUCCESS};
91ce38
     pub use crate::dn::{Sdn, SdnRef};
91ce38
     pub use crate::entry::EntryRef;
91ce38
@@ -30,8 +33,7 @@ pub mod prelude {
91ce38
     pub use crate::plugin::{register_plugin_ext, PluginIdRef, SlapiPlugin3};
91ce38
     pub use crate::search::{Search, SearchScope};
91ce38
     pub use crate::syntax_plugin::{
91ce38
-        matchingrule_register, name_to_leaking_char, names_to_leaking_char_array, SlapiOrdMr,
91ce38
-        SlapiSubMr, SlapiSyntaxPlugin1,
91ce38
+        matchingrule_register, SlapiOrdMr, SlapiSubMr, SlapiSyntaxPlugin1,
91ce38
     };
91ce38
     pub use crate::task::{task_register_handler_fn, task_unregister_handler_fn, Task, TaskRef};
91ce38
     pub use crate::value::{Value, ValueArray, ValueArrayRef, ValueRef};
91ce38
diff --git a/src/slapi_r_plugin/src/macros.rs b/src/slapi_r_plugin/src/macros.rs
91ce38
index bc8dfa60f..97fc5d7ef 100644
91ce38
--- a/src/slapi_r_plugin/src/macros.rs
91ce38
+++ b/src/slapi_r_plugin/src/macros.rs
91ce38
@@ -249,6 +249,7 @@ macro_rules! slapi_r_syntax_plugin_hooks {
91ce38
         paste::item! {
91ce38
             use libc;
91ce38
             use std::convert::TryFrom;
91ce38
+            use std::ffi::CString;
91ce38
 
91ce38
             #[no_mangle]
91ce38
             pub extern "C" fn [<$mod_ident _plugin_init>](raw_pb: *const libc::c_void) -> i32 {
91ce38
@@ -261,15 +262,15 @@ macro_rules! slapi_r_syntax_plugin_hooks {
91ce38
                 };
91ce38
 
91ce38
                 // Setup the names/oids that this plugin provides syntaxes for.
91ce38
-
91ce38
-                let name_ptr = unsafe { names_to_leaking_char_array(&$hooks_ident::attr_supported_names()) };
91ce38
-                match pb.register_syntax_names(name_ptr) {
91ce38
+                // DS will clone these, so they can be ephemeral to this function.
91ce38
+                let name_vec = Charray::new($hooks_ident::attr_supported_names().as_slice()).expect("invalid supported names");
91ce38
+                match pb.register_syntax_names(name_vec.as_ptr()) {
91ce38
                     0 => {},
91ce38
                     e => return e,
91ce38
                 };
91ce38
 
91ce38
-                let name_ptr = unsafe { name_to_leaking_char($hooks_ident::attr_oid()) };
91ce38
-                match pb.register_syntax_oid(name_ptr) {
91ce38
+                let attr_oid = CString::new($hooks_ident::attr_oid()).expect("invalid attr oid");
91ce38
+                match pb.register_syntax_oid(attr_oid.as_ptr()) {
91ce38
                     0 => {},
91ce38
                     e => return e,
91ce38
                 };
91ce38
@@ -430,7 +431,8 @@ macro_rules! slapi_r_syntax_plugin_hooks {
91ce38
                     e => return e,
91ce38
                 };
91ce38
 
91ce38
-                let name_ptr = unsafe { names_to_leaking_char_array(&$hooks_ident::eq_mr_supported_names()) };
91ce38
+                let name_vec = Charray::new($hooks_ident::eq_mr_supported_names().as_slice()).expect("invalid mr supported names");
91ce38
+                let name_ptr = name_vec.as_ptr();
91ce38
                 // SLAPI_PLUGIN_MR_NAMES
91ce38
                 match pb.register_mr_names(name_ptr) {
91ce38
                     0 => {},
91ce38
@@ -672,7 +674,8 @@ macro_rules! slapi_r_syntax_plugin_hooks {
91ce38
                     e => return e,
91ce38
                 };
91ce38
 
91ce38
-                let name_ptr = unsafe { names_to_leaking_char_array(&$hooks_ident::ord_mr_supported_names()) };
91ce38
+                let name_vec = Charray::new($hooks_ident::ord_mr_supported_names().as_slice()).expect("invalid ord supported names");
91ce38
+                let name_ptr = name_vec.as_ptr();
91ce38
                 // SLAPI_PLUGIN_MR_NAMES
91ce38
                 match pb.register_mr_names(name_ptr) {
91ce38
                     0 => {},
91ce38
diff --git a/src/slapi_r_plugin/src/syntax_plugin.rs b/src/slapi_r_plugin/src/syntax_plugin.rs
91ce38
index e7d5c01bd..86f84bdd8 100644
91ce38
--- a/src/slapi_r_plugin/src/syntax_plugin.rs
91ce38
+++ b/src/slapi_r_plugin/src/syntax_plugin.rs
91ce38
@@ -1,11 +1,11 @@
91ce38
 use crate::ber::BerValRef;
91ce38
 // use crate::constants::FilterType;
91ce38
+use crate::charray::Charray;
91ce38
 use crate::error::PluginError;
91ce38
 use crate::pblock::PblockRef;
91ce38
 use crate::value::{ValueArray, ValueArrayRef};
91ce38
 use std::cmp::Ordering;
91ce38
 use std::ffi::CString;
91ce38
-use std::iter::once;
91ce38
 use std::os::raw::c_char;
91ce38
 use std::ptr;
91ce38
 
91ce38
@@ -26,37 +26,6 @@ struct slapi_matchingRuleEntry {
91ce38
     mr_compat_syntax: *const *const c_char,
91ce38
 }
91ce38
 
91ce38
-pub unsafe fn name_to_leaking_char(name: &str) -> *const c_char {
91ce38
-    let n = CString::new(name)
91ce38
-        .expect("An invalid string has been hardcoded!")
91ce38
-        .into_boxed_c_str();
91ce38
-    let n_ptr = n.as_ptr();
91ce38
-    // Now we intentionally leak the name here, and the pointer will remain valid.
91ce38
-    Box::leak(n);
91ce38
-    n_ptr
91ce38
-}
91ce38
-
91ce38
-pub unsafe fn names_to_leaking_char_array(names: &[&str]) -> *const *const c_char {
91ce38
-    let n_arr: Vec<CString> = names
91ce38
-        .iter()
91ce38
-        .map(|s| CString::new(*s).expect("An invalid string has been hardcoded!"))
91ce38
-        .collect();
91ce38
-    let n_arr = n_arr.into_boxed_slice();
91ce38
-    let n_ptr_arr: Vec<*const c_char> = n_arr
91ce38
-        .iter()
91ce38
-        .map(|v| v.as_ptr())
91ce38
-        .chain(once(ptr::null()))
91ce38
-        .collect();
91ce38
-    let n_ptr_arr = n_ptr_arr.into_boxed_slice();
91ce38
-
91ce38
-    // Now we intentionally leak these names here,
91ce38
-    let _r_n_arr = Box::leak(n_arr);
91ce38
-    let r_n_ptr_arr = Box::leak(n_ptr_arr);
91ce38
-
91ce38
-    let name_ptr = r_n_ptr_arr as *const _ as *const *const c_char;
91ce38
-    name_ptr
91ce38
-}
91ce38
-
91ce38
 // oid - the oid of the matching rule
91ce38
 // name - the name of the mr
91ce38
 // desc - description
91ce38
@@ -69,20 +38,24 @@ pub unsafe fn matchingrule_register(
91ce38
     syntax: &str,
91ce38
     compat_syntax: &[&str],
91ce38
 ) -> i32 {
91ce38
-    let oid_ptr = name_to_leaking_char(oid);
91ce38
-    let name_ptr = name_to_leaking_char(name);
91ce38
-    let desc_ptr = name_to_leaking_char(desc);
91ce38
-    let syntax_ptr = name_to_leaking_char(syntax);
91ce38
-    let compat_syntax_ptr = names_to_leaking_char_array(compat_syntax);
91ce38
+    // Make everything CStrings that live long enough.
91ce38
+
91ce38
+    let oid_cs = CString::new(oid).expect("invalid oid");
91ce38
+    let name_cs = CString::new(name).expect("invalid name");
91ce38
+    let desc_cs = CString::new(desc).expect("invalid desc");
91ce38
+    let syntax_cs = CString::new(syntax).expect("invalid syntax");
91ce38
+
91ce38
+    // We have to do this so the cstrings live long enough.
91ce38
+    let compat_syntax_ca = Charray::new(compat_syntax).expect("invalid compat_syntax");
91ce38
 
91ce38
     let new_mr = slapi_matchingRuleEntry {
91ce38
-        mr_oid: oid_ptr,
91ce38
+        mr_oid: oid_cs.as_ptr(),
91ce38
         _mr_oidalias: ptr::null(),
91ce38
-        mr_name: name_ptr,
91ce38
-        mr_desc: desc_ptr,
91ce38
-        mr_syntax: syntax_ptr,
91ce38
+        mr_name: name_cs.as_ptr(),
91ce38
+        mr_desc: desc_cs.as_ptr(),
91ce38
+        mr_syntax: syntax_cs.as_ptr(),
91ce38
         _mr_obsolete: 0,
91ce38
-        mr_compat_syntax: compat_syntax_ptr,
91ce38
+        mr_compat_syntax: compat_syntax_ca.as_ptr(),
91ce38
     };
91ce38
 
91ce38
     let new_mr_ptr = &new_mr as *const _;
91ce38
-- 
91ce38
2.26.3
91ce38