Skip to content

Commit

Permalink
Use libc impl for memcpy and memmove (#29)
Browse files Browse the repository at this point in the history
* use libc impl for memcpy and memmove

* changelog

* fix test
  • Loading branch information
jabuwu authored May 4, 2024
1 parent 50026ba commit 4f68336
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 9 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# 0.8.0 (UNRELEASED)
- Upgrade runtime to Spine 4.2
- Fix `memcpy` crash in Rust 1.78 (when not using `libc` feature)
- Add `Physics` enum
- Add `physics` parameter to `Skeleton::update_world_transform` and `Skeleton::update_world_transform_with`
- Add `physics` parameter to `Controller::update`
Expand Down
209 changes: 200 additions & 9 deletions src/c/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -888,19 +888,210 @@ unsafe extern "C" fn spine_free(ptr: *mut c_void) {
}

#[no_mangle]
unsafe extern "C" fn spine_memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void {
std::ptr::copy_nonoverlapping(src, dest, n as usize);
dest
unsafe extern "C" fn spine_memcpy(
dst0: *mut c_void,
src0: *const c_void,
mut length: size_t,
) -> *mut c_void {
type Word = size_t;
let mut dst: *mut c_char = dst0.cast::<c_char>();
let mut src: *const c_char = src0.cast::<c_char>();
let mut t: size_t;
if !(length == 0 as c_int as c_ulong || dst.cast_const() == src) {
if dst < src.cast_mut() && dst.offset(length as isize) > src.cast_mut()
|| src < dst.cast_const() && src.offset(length as isize) > dst.cast_const()
{
panic!();
}
t = src as c_long as size_t;
if (t | dst as c_long as c_ulong)
& (::core::mem::size_of::<Word>() as c_ulong).wrapping_sub(1 as c_int as c_ulong)
!= 0
{
if (t ^ dst as c_long as c_ulong)
& (::core::mem::size_of::<Word>() as c_ulong).wrapping_sub(1 as c_int as c_ulong)
!= 0
|| length < ::core::mem::size_of::<Word>() as c_ulong
{
t = length;
} else {
t = (::core::mem::size_of::<Word>() as c_ulong).wrapping_sub(
t & (::core::mem::size_of::<Word>() as c_ulong)
.wrapping_sub(1 as c_int as c_ulong),
);
}
length = (length as c_ulong).wrapping_sub(t) as size_t as size_t;
loop {
let fresh0 = src;
src = src.offset(1);
let fresh1 = dst;
dst = dst.offset(1);
*fresh1 = *fresh0;
t = t.wrapping_sub(1);
if t == 0 {
break;
}
}
}
t = length.wrapping_div(::core::mem::size_of::<Word>() as c_ulong);
if t != 0 {
loop {
*dst.cast::<Word>() = *(src as *mut Word);
src = src.offset(::core::mem::size_of::<Word>() as c_ulong as isize);
dst = dst.offset(::core::mem::size_of::<Word>() as c_ulong as isize);
t = t.wrapping_sub(1);
if t == 0 {
break;
}
}
}
t = length
& (::core::mem::size_of::<Word>() as c_ulong).wrapping_sub(1 as c_int as c_ulong);
if t != 0 {
loop {
let fresh2 = src;
src = src.offset(1);
let fresh3 = dst;
dst = dst.offset(1);
*fresh3 = *fresh2;
t = t.wrapping_sub(1);
if t == 0 {
break;
}
}
}
}
dst0
}

#[no_mangle]
unsafe extern "C" fn spine_memmove(
dest: *mut c_void,
src: *const c_void,
n: size_t,
dst0: *mut c_void,
src0: *const c_void,
mut length: size_t,
) -> *mut c_void {
std::ptr::copy(src, dest, n as usize);
dest
type Word = size_t;
let mut dst: *mut c_char = dst0.cast::<c_char>();
let mut src: *const c_char = src0.cast::<c_char>();
let mut t: size_t;
if !(length == 0 as c_int as c_ulong || dst.cast_const() == src) {
if (dst as c_ulong) < src as c_ulong {
t = src as c_long as size_t;
if (t | dst as c_long as c_ulong)
& (::core::mem::size_of::<Word>() as c_ulong).wrapping_sub(1 as c_int as c_ulong)
!= 0
{
if (t ^ dst as c_long as c_ulong)
& (::core::mem::size_of::<Word>() as c_ulong)
.wrapping_sub(1 as c_int as c_ulong)
!= 0
|| length < ::core::mem::size_of::<Word>() as c_ulong
{
t = length;
} else {
t = (::core::mem::size_of::<Word>() as c_ulong).wrapping_sub(
t & (::core::mem::size_of::<Word>() as c_ulong)
.wrapping_sub(1 as c_int as c_ulong),
);
}
length = (length as c_ulong).wrapping_sub(t) as size_t as size_t;
loop {
let fresh0 = src;
src = src.offset(1);
let fresh1 = dst;
dst = dst.offset(1);
*fresh1 = *fresh0;
t = t.wrapping_sub(1);
if t == 0 {
break;
}
}
}
t = length.wrapping_div(::core::mem::size_of::<Word>() as c_ulong);
if t != 0 {
loop {
*dst.cast::<Word>() = *(src as *mut Word);
src = src.offset(::core::mem::size_of::<Word>() as c_ulong as isize);
dst = dst.offset(::core::mem::size_of::<Word>() as c_ulong as isize);
t = t.wrapping_sub(1);
if t == 0 {
break;
}
}
}
t = length
& (::core::mem::size_of::<Word>() as c_ulong).wrapping_sub(1 as c_int as c_ulong);
if t != 0 {
loop {
let fresh2 = src;
src = src.offset(1);
let fresh3 = dst;
dst = dst.offset(1);
*fresh3 = *fresh2;
t = t.wrapping_sub(1);
if t == 0 {
break;
}
}
}
} else {
src = src.offset(length as isize);
dst = dst.offset(length as isize);
t = src as c_long as size_t;
if (t | dst as c_long as c_ulong)
& (::core::mem::size_of::<Word>() as c_ulong).wrapping_sub(1 as c_int as c_ulong)
!= 0
{
if (t ^ dst as c_long as c_ulong)
& (::core::mem::size_of::<Word>() as c_ulong)
.wrapping_sub(1 as c_int as c_ulong)
!= 0
|| length <= ::core::mem::size_of::<Word>() as c_ulong
{
t = length;
} else {
t &= (::core::mem::size_of::<Word>() as c_ulong)
.wrapping_sub(1 as c_int as c_ulong);
}
length = (length as c_ulong).wrapping_sub(t) as size_t as size_t;
loop {
src = src.offset(-1);
dst = dst.offset(-1);
*dst = *src;
t = t.wrapping_sub(1);
if t == 0 {
break;
}
}
}
t = length.wrapping_div(::core::mem::size_of::<Word>() as c_ulong);
if t != 0 {
loop {
src = src.offset(-(::core::mem::size_of::<Word>() as c_ulong as isize));
dst = dst.offset(-(::core::mem::size_of::<Word>() as c_ulong as isize));
*dst.cast::<Word>() = *(src as *mut Word);
t = t.wrapping_sub(1);
if t == 0 {
break;
}
}
}
t = length
& (::core::mem::size_of::<Word>() as c_ulong).wrapping_sub(1 as c_int as c_ulong);
if t != 0 {
loop {
src = src.offset(-1);
dst = dst.offset(-1);
*dst = *src;
t = t.wrapping_sub(1);
if t == 0 {
break;
}
}
}
}
}
dst0
}

#[no_mangle]
Expand Down Expand Up @@ -1144,7 +1335,7 @@ mod tests {
let src = CString::new("1234 hello world").unwrap();
spine_strncpy(dst.as_mut_ptr(), src.as_ptr(), 10);
let string = CStr::from_ptr(dst.as_ptr()).to_string_lossy().to_string();
assert_eq!(string.as_str(), "1234 hello"); //strncpy doesn't add null byte
assert!(string.starts_with("1234 hello")); //strncpy doesn't add null byte

let mut dst: [super::c_char; 10] = [10; 10];
let src = CString::new("1234").unwrap();
Expand Down

0 comments on commit 4f68336

Please sign in to comment.