diff --git a/src/crud_ops.rs b/src/crud_ops.rs index 7e03859..57cd38e 100644 --- a/src/crud_ops.rs +++ b/src/crud_ops.rs @@ -1,4 +1,4 @@ -use crate::{CResult, Config, NotifyGuard, SQ, clients, dyn_connect, static_config, Request}; +use crate::{CResult, Config, NotifyGuard, SQ, clients, dyn_connect, static_config, Request, util::cstr_to_path}; use object_store::{path::Path, ObjectStore}; @@ -174,13 +174,7 @@ pub extern "C" fn get( ) -> CResult { let response = unsafe { ResponseGuard::new(response, handle) }; let path = unsafe { std::ffi::CStr::from_ptr(path) }; - let path: Path = match Path::parse(path.to_str().expect("invalid utf8")) { - Ok(p) => p, - Err(e) => { - response.into_error(e); - return CResult::Error; - } - }; + let path = unsafe{ cstr_to_path(path) }; let slice = unsafe { std::slice::from_raw_parts_mut(buffer, size) }; let config = unsafe { & (*config) }; match SQ.get() { @@ -216,13 +210,7 @@ pub extern "C" fn put( ) -> CResult { let response = unsafe { ResponseGuard::new(response, handle) }; let path = unsafe { std::ffi::CStr::from_ptr(path) }; - let path: Path = match Path::parse(path.to_str().expect("invalid utf8")) { - Ok(p) => p, - Err(e) => { - response.into_error(e); - return CResult::Error; - } - }; + let path = unsafe{ cstr_to_path(path) }; let slice = unsafe { std::slice::from_raw_parts(buffer, size) }; let config = unsafe { & (*config) }; match SQ.get() { @@ -256,13 +244,7 @@ pub extern "C" fn delete( ) -> CResult { let response = unsafe { ResponseGuard::new(response, handle) }; let path = unsafe { std::ffi::CStr::from_ptr(path) }; - let path: Path = match Path::parse(path.to_str().expect("invalid utf8")) { - Ok(p) => p, - Err(e) => { - response.into_error(e); - return CResult::Error; - } - }; + let path = unsafe{ cstr_to_path(path) }; let config = unsafe { & (*config) }; match SQ.get() { Some(sq) => { diff --git a/src/list.rs b/src/list.rs index e503a25..4de74a1 100644 --- a/src/list.rs +++ b/src/list.rs @@ -1,4 +1,4 @@ -use crate::{CResult, Config, NotifyGuard, SQ, RT, clients, dyn_connect, Request}; +use crate::{CResult, Config, NotifyGuard, SQ, RT, clients, dyn_connect, Request, util::cstr_to_path}; use object_store::{path::Path, ObjectStore, ObjectMeta}; @@ -175,13 +175,7 @@ pub extern "C" fn list( ) -> CResult { let response = unsafe { ListResponseGuard::new(response, handle) }; let prefix = unsafe { std::ffi::CStr::from_ptr(prefix) }; - let prefix: Path = match Path::parse(prefix.to_str().expect("invalid utf8")) { - Ok(p) => p, - Err(e) => { - response.into_error(e); - return CResult::Error; - } - }; + let prefix = unsafe{ cstr_to_path(prefix) }; let config = unsafe { & (*config) }; match SQ.get() { Some(sq) => { @@ -283,13 +277,7 @@ pub extern "C" fn list_stream( ) -> CResult { let response = unsafe { ListStreamResponseGuard::new(response, handle) }; let prefix = unsafe { std::ffi::CStr::from_ptr(prefix) }; - let prefix: Path = match Path::parse(prefix.to_str().expect("invalid utf8")) { - Ok(p) => p, - Err(e) => { - response.into_error(e); - return CResult::Error; - } - }; + let prefix = unsafe{ cstr_to_path(prefix) }; let config = unsafe { & (*config) }; match SQ.get() { Some(sq) => { diff --git a/src/stream.rs b/src/stream.rs index 1bf1b47..e6d65f8 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -1,5 +1,5 @@ use crate::{CResult, Config, NotifyGuard, SQ, RT, clients, dyn_connect, static_config, Request}; -use crate::util::{size_to_ranges, Compression, with_decoder, with_encoder}; +use crate::util::{size_to_ranges, Compression, with_decoder, with_encoder, cstr_to_path}; use crate::error::{should_retry_logic, extract_error_info, backoff_duration_for_retry}; use object_store::{path::Path, ObjectStore}; @@ -222,13 +222,7 @@ pub extern "C" fn get_stream( ) -> CResult { let response = unsafe { GetStreamResponseGuard::new(response, handle) }; let path = unsafe { std::ffi::CStr::from_ptr(path) }; - let path: Path = match Path::parse(path.to_str().expect("invalid utf8")) { - Ok(p) => p, - Err(e) => { - response.into_error(e); - return CResult::Error; - } - }; + let path = unsafe{ cstr_to_path(path) }; let decompress = match Compression::try_from(decompress) { Ok(c) => c, Err(e) => { @@ -536,13 +530,7 @@ pub extern "C" fn put_stream( ) -> CResult { let response = unsafe { PutStreamResponseGuard::new(response, handle) }; let path = unsafe { std::ffi::CStr::from_ptr(path) }; - let path: Path = match Path::parse(path.to_str().expect("invalid utf8")) { - Ok(p) => p, - Err(e) => { - response.into_error(e); - return CResult::Error; - } - }; + let path = unsafe{ cstr_to_path(path) }; let compress = match Compression::try_from(compress) { Ok(c) => c, Err(e) => { diff --git a/src/util.rs b/src/util.rs index 3d9d75b..9ec45b5 100644 --- a/src/util.rs +++ b/src/util.rs @@ -98,3 +98,20 @@ pub(crate) fn with_encoder(compression: Compression, writer: impl AsyncWrite + U } } } + +// Safety: This must match the layout of object_store::path::Path +#[allow(dead_code)] +struct RawPath { + raw: String, +} + +// This is a workaround to create an object_store::path::Path from a String while skipping +// validation +pub(crate) unsafe fn cstr_to_path(cstr: &std::ffi::CStr) -> object_store::path::Path { + let raw_path = RawPath { + raw: cstr.to_str().expect("invalid utf8").to_string() + }; + + let path: object_store::path::Path = std::mem::transmute(raw_path); + return path; +}