Skip to content

Commit

Permalink
Fix possible bug when allocator in FFI is not malloc when requesting …
Browse files Browse the repository at this point in the history
…packages
  • Loading branch information
danpashin committed Jun 14, 2024
1 parent 7e0bd2d commit ab6f23f
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 4 deletions.
2 changes: 1 addition & 1 deletion twackup-gui/Twackup/Sources/FFI Models/Dpkg.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ actor Dpkg {
let count = tw_get_packages(innerDpkg, onlyLeaves, TW_PACKAGES_SORT_NAME.clampedToU8, &packagesPtr)

let buffer = UnsafeBufferPointer(start: packagesPtr, count: Int(count))
defer { buffer.deallocate() }
defer { tw_free_packages(packagesPtr, count) }

return buffer.compactMap { package in
let model = FFIPackage(package)
Expand Down
4 changes: 2 additions & 2 deletions twackup/src/ffi/c_dpkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ impl TwDpkg {
let packages: Option<Vec<_>> = tokio_rt.block_on(async {
if sort == TwPackagesSort::Unsorted {
let packages = dpkg.unsorted_packages(leaves_only).await.ok()?;
Some(packages.into_iter().map(TwPackage::from).collect())
Some(packages.into_iter().map(Into::into).collect())
} else {
let packages = dpkg.packages(leaves_only, sort.into()).await.ok()?;
Some(packages.into_values().map(TwPackage::from).collect())
Some(packages.into_values().map(Into::into).collect())
}
});

Expand Down
19 changes: 18 additions & 1 deletion twackup/src/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use crate::{
Dpkg,
};
use safer_ffi::{boxed, derive_ReprC, ffi_export, prelude::c_slice, prelude::char_p};
use std::{mem, mem::ManuallyDrop, ptr::NonNull};
use std::{mem, mem::ManuallyDrop, ptr::NonNull, slice};

#[derive_ReprC]
#[repr(i8)]
Expand Down Expand Up @@ -82,6 +82,15 @@ fn tw_get_packages(
if let Some(packages) = dpkg.get_packages(leaves_only, sort) {
let packages = ManuallyDrop::new(packages);

// Since memory allocators for Rust and outer FFI callee can be different
// we must release slice by ourselves
//
// To do that, slice must have valid length and layout
// Releasing func will decrement counter on ARC, so we need to increase it here
for package in packages.as_slice() {
package.inner.retain();
}

let packages_ptr = packages.as_ptr().cast_mut();
unsafe { output.write(NonNull::new_unchecked(packages_ptr)) };

Expand All @@ -91,6 +100,14 @@ fn tw_get_packages(
}
}

#[ffi_export]
fn tw_free_packages(mut start: NonNull<TwPackage>, length: i64) {
unsafe {
let packages = slice::from_raw_parts_mut(start.as_mut(), length as usize);
drop(Box::from_raw(packages))
}
}

/// Returns package section description
///
/// \param[in] package package instance
Expand Down

0 comments on commit ab6f23f

Please sign in to comment.