Skip to content

Commit 687d94e

Browse files
authored
Merge pull request #3 from vinipsmaker/fix-utf8-alloc2
fix/helper: Fix dealloc_c_utf8_alloced_from_rust
2 parents 91f72ea + 2bd8160 commit 687d94e

File tree

4 files changed

+46
-25
lines changed

4 files changed

+46
-25
lines changed

Diff for: src/ffi/directory_details.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use nfs::metadata::directory_metadata::DirectoryMetadata as NfsDirectoryMetadata
2929
use std::ptr;
3030
use std::sync::{Arc, Mutex};
3131
use super::helper;
32+
use ffi::low_level_api::misc::misc_u8_ptr_free;
3233

3334
/// Details about a directory and its content.
3435
#[derive(Debug)]
@@ -94,8 +95,10 @@ impl Drop for DirectoryDetails {
9495
pub struct DirectoryMetadata {
9596
pub name: *mut u8,
9697
pub name_len: usize,
98+
pub name_cap: usize,
9799
pub user_metadata: *mut u8,
98100
pub user_metadata_len: usize,
101+
pub user_metadata_cap: usize,
99102
pub is_private: bool,
100103
pub is_versioned: bool,
101104
pub creation_time_sec: i64,
@@ -112,16 +115,19 @@ impl DirectoryMetadata {
112115
let created_time = dir_metadata.get_created_time().to_timespec();
113116
let modified_time = dir_metadata.get_modified_time().to_timespec();
114117

115-
let (name, name_len) = helper::string_to_c_utf8(dir_metadata.get_name()
118+
let (name, name_len, name_cap) = helper::string_to_c_utf8(dir_metadata.get_name()
116119
.to_string());
117120
let user_metadata = dir_metadata.get_user_metadata().to_base64(config::get_base64_config());
118-
let (user_metadata, user_metadata_len) = helper::string_to_c_utf8(user_metadata);
121+
let (user_metadata, user_metadata_len, user_metadata_cap) =
122+
helper::string_to_c_utf8(user_metadata);
119123

120124
Ok(DirectoryMetadata {
121125
name: name,
122126
name_len: name_len,
127+
name_cap: name_cap,
123128
user_metadata: user_metadata,
124129
user_metadata_len: user_metadata_len,
130+
user_metadata_cap: user_metadata_cap,
125131
is_private: *dir_key.get_access_level() == ::nfs::AccessLevel::Private,
126132
is_versioned: dir_key.is_versioned(),
127133
creation_time_sec: created_time.sec,
@@ -135,9 +141,10 @@ impl DirectoryMetadata {
135141
// a proper impl Drop.
136142
fn deallocate(&mut self) {
137143
unsafe {
138-
let _ = helper::dealloc_c_utf8_alloced_from_rust(self.name, self.name_len);
139-
let _ = helper::dealloc_c_utf8_alloced_from_rust(self.user_metadata,
140-
self.user_metadata_len);
144+
let _ = misc_u8_ptr_free(self.name, self.name_len, self.name_cap);
145+
let _ = misc_u8_ptr_free(self.user_metadata,
146+
self.user_metadata_len,
147+
self.user_metadata_cap);
141148
}
142149
}
143150
}

Diff for: src/ffi/file_details.rs

+18-6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use core::client::Client;
2222
use ffi::config;
2323
use ffi::errors::FfiError;
24+
use ffi::low_level_api::misc::misc_u8_ptr_free;
2425
use nfs::file::File;
2526
use nfs::helper::file_helper::FileHelper;
2627
use nfs::metadata::file_metadata::FileMetadata as NfsFileMetadata;
@@ -37,6 +38,8 @@ pub struct FileDetails {
3738
pub content: *mut u8,
3839
/// Size of `content`
3940
pub content_len: usize,
41+
/// Capacity of `content`. Only used by the allocator's `dealloc` algorithm.
42+
pub content_cap: usize,
4043
/// Metadata of the file.
4144
pub metadata: *mut FileMetadata,
4245
}
@@ -59,7 +62,7 @@ impl FileDetails {
5962

6063
let content = try!(reader.read(start_position, size));
6164
let content = content.to_base64(config::get_base64_config());
62-
let (content, content_len) = helper::string_to_c_utf8(content);
65+
let (content, content_len, content_cap) = helper::string_to_c_utf8(content);
6366

6467
let file_metadata_ptr = if include_metadata {
6568
Box::into_raw(Box::new(try!(FileMetadata::new(file.get_metadata()))))
@@ -70,6 +73,7 @@ impl FileDetails {
7073
Ok(FileDetails {
7174
content: content,
7275
content_len: content_len,
76+
content_cap: content_cap,
7377
metadata: file_metadata_ptr,
7478
})
7579
}
@@ -78,7 +82,7 @@ impl FileDetails {
7882
// a proper impl Drop.
7983
fn deallocate(self) {
8084
unsafe {
81-
helper::dealloc_c_utf8_alloced_from_rust(self.content, self.content_len);
85+
misc_u8_ptr_free(self.content, self.content_len, self.content_cap);
8286
}
8387

8488
if !self.metadata.is_null() {
@@ -94,8 +98,10 @@ impl FileDetails {
9498
pub struct FileMetadata {
9599
pub name: *mut u8,
96100
pub name_len: usize,
101+
pub name_cap: usize,
97102
pub user_metadata: *mut u8,
98103
pub user_metadata_len: usize,
104+
pub user_metadata_cap: usize,
99105
pub size: i64,
100106
pub creation_time_sec: i64,
101107
pub creation_time_nsec: i64,
@@ -111,18 +117,22 @@ impl FileMetadata {
111117
let created_time = file_metadata.get_created_time().to_timespec();
112118
let modified_time = file_metadata.get_modified_time().to_timespec();
113119

114-
let (name, name_len) = helper::string_to_c_utf8(file_metadata.get_name().to_string());
120+
let (name, name_len, name_cap) = helper::string_to_c_utf8(file_metadata.get_name()
121+
.to_string());
115122

116123
let user_metadata = file_metadata.get_user_metadata()
117124
.to_base64(config::get_base64_config());
118-
let (user_metadata, user_metadata_len) = helper::string_to_c_utf8(user_metadata);
125+
let (user_metadata, user_metadata_len, user_metadata_cap) =
126+
helper::string_to_c_utf8(user_metadata);
119127

120128
Ok(FileMetadata {
121129
name: name,
122130
name_len: name_len,
131+
name_cap: name_cap,
123132
size: file_metadata.get_size() as i64,
124133
user_metadata: user_metadata,
125134
user_metadata_len: user_metadata_len,
135+
user_metadata_cap: user_metadata_cap,
126136
creation_time_sec: created_time.sec,
127137
creation_time_nsec: created_time.nsec as i64,
128138
modification_time_sec: modified_time.sec,
@@ -135,8 +145,10 @@ impl FileMetadata {
135145
// a proper impl Drop.
136146
pub fn deallocate(&mut self) {
137147
unsafe {
138-
helper::dealloc_c_utf8_alloced_from_rust(self.name, self.name_len);
139-
helper::dealloc_c_utf8_alloced_from_rust(self.user_metadata, self.user_metadata_len);
148+
misc_u8_ptr_free(self.name, self.name_len, self.name_cap);
149+
misc_u8_ptr_free(self.user_metadata,
150+
self.user_metadata_len,
151+
self.user_metadata_cap);
140152
}
141153
}
142154
}

Diff for: src/ffi/helper.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,17 @@ pub unsafe fn c_utf8_to_opt_string(ptr: *const u8, len: usize) -> Result<Option<
5353
}
5454
}
5555

56-
pub fn string_to_c_utf8(s: String) -> (*mut u8, usize) {
56+
/// Returns a heap-allocated raw string, usable by C/FFI-boundary.
57+
/// The tuple means (pointer, length_in_bytes, capacity).
58+
/// Use `dealloc_c_utf8_alloced_from_rust` to free the memory.
59+
pub fn string_to_c_utf8(s: String) -> (*mut u8, usize, usize) {
5760
let mut v = s.into_bytes();
5861
v.shrink_to_fit();
5962
let p = v.as_mut_ptr();
6063
let len = v.len();
64+
let cap = v.capacity();
6165
mem::forget(v);
62-
(p, len)
63-
}
64-
65-
pub unsafe fn dealloc_c_utf8_alloced_from_rust(p: *mut u8, len: usize) {
66-
let _ = Vec::from_raw_parts(p, len, len);
66+
(p, len, cap)
6767
}
6868

6969
// TODO: add c_char_ptr_to_str and c_char_ptr_to_opt_str (return &str instead of String)

Diff for: src/ffi/low_level_api/misc.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ pub extern "C" fn misc_sign_key_free(handle: SignKeyHandle) -> i32 {
5252
#[no_mangle]
5353
pub unsafe extern "C" fn misc_serailise_data_id(data_id_h: DataIdHandle,
5454
o_data: *mut *mut u8,
55-
o_size: *mut u64,
56-
o_capacity: *mut u64)
55+
o_size: *mut usize,
56+
o_capacity: *mut usize)
5757
-> i32 {
5858
helper::catch_unwind_i32(|| {
5959
let mut ser_data_id = ffi_try!(serialise(ffi_try!(unwrap!(object_cache().lock())
@@ -63,8 +63,8 @@ pub unsafe extern "C" fn misc_serailise_data_id(data_id_h: DataIdHandle,
6363
.map_err(FfiError::from));
6464

6565
*o_data = ser_data_id.as_mut_ptr();
66-
ptr::write(o_size, ser_data_id.len() as u64);
67-
ptr::write(o_capacity, ser_data_id.capacity() as u64);
66+
ptr::write(o_size, ser_data_id.len());
67+
ptr::write(o_capacity, ser_data_id.capacity());
6868
mem::forget(ser_data_id);
6969

7070
0
@@ -74,11 +74,11 @@ pub unsafe extern "C" fn misc_serailise_data_id(data_id_h: DataIdHandle,
7474
/// Deserialise DataIdentifier
7575
#[no_mangle]
7676
pub unsafe extern "C" fn misc_deserailise_data_id(data: *const u8,
77-
size: u64,
77+
size: usize,
7878
o_handle: *mut DataIdHandle)
7979
-> i32 {
8080
helper::catch_unwind_i32(|| {
81-
let ser_data_id = slice::from_raw_parts(data, size as usize);
81+
let ser_data_id = slice::from_raw_parts(data, size);
8282
let data_id = ffi_try!(deserialise(ser_data_id).map_err(FfiError::from));
8383

8484
let mut object_cache = unwrap!(object_cache().lock());
@@ -94,8 +94,10 @@ pub unsafe extern "C" fn misc_deserailise_data_id(data: *const u8,
9494

9595
/// Deallocate pointer obtained via FFI and allocated by safe_core
9696
#[no_mangle]
97-
pub unsafe extern "C" fn misc_u8_ptr_free(ptr: *mut u8, size: u64, capacity: u64) {
98-
let _ = Vec::from_raw_parts(ptr, size as usize, capacity as usize);
97+
pub unsafe extern "C" fn misc_u8_ptr_free(ptr: *mut u8, size: usize, capacity: usize) {
98+
// TODO: refactor implementation to remove the need for `cap`. Related issue:
99+
// <https://github.com/rust-lang/rust/issues/36284>.
100+
let _ = Vec::from_raw_parts(ptr, size, capacity);
99101
}
100102

101103
#[cfg(test)]

0 commit comments

Comments
 (0)