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

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