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

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