From 4f68336869edccbdeaecd2a9830c8261882fdac8 Mon Sep 17 00:00:00 2001 From: jabu <46233424+jabuwu@users.noreply.github.com> Date: Sat, 4 May 2024 12:49:30 -0500 Subject: [PATCH] Use libc impl for `memcpy` and `memmove` (#29) * use libc impl for memcpy and memmove * changelog * fix test --- changelog.md | 1 + src/c/wasm.rs | 209 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 201 insertions(+), 9 deletions(-) diff --git a/changelog.md b/changelog.md index f486f1d..e4d758e 100644 --- a/changelog.md +++ b/changelog.md @@ -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` diff --git a/src/c/wasm.rs b/src/c/wasm.rs index f5c67d6..49256b3 100644 --- a/src/c/wasm.rs +++ b/src/c/wasm.rs @@ -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::(); + let mut src: *const c_char = src0.cast::(); + 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::() 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::() as c_ulong).wrapping_sub(1 as c_int as c_ulong) + != 0 + || length < ::core::mem::size_of::() as c_ulong + { + t = length; + } else { + t = (::core::mem::size_of::() as c_ulong).wrapping_sub( + t & (::core::mem::size_of::() 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::() as c_ulong); + if t != 0 { + loop { + *dst.cast::() = *(src as *mut Word); + src = src.offset(::core::mem::size_of::() as c_ulong as isize); + dst = dst.offset(::core::mem::size_of::() as c_ulong as isize); + t = t.wrapping_sub(1); + if t == 0 { + break; + } + } + } + t = length + & (::core::mem::size_of::() 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::(); + let mut src: *const c_char = src0.cast::(); + 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::() 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::() as c_ulong) + .wrapping_sub(1 as c_int as c_ulong) + != 0 + || length < ::core::mem::size_of::() as c_ulong + { + t = length; + } else { + t = (::core::mem::size_of::() as c_ulong).wrapping_sub( + t & (::core::mem::size_of::() 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::() as c_ulong); + if t != 0 { + loop { + *dst.cast::() = *(src as *mut Word); + src = src.offset(::core::mem::size_of::() as c_ulong as isize); + dst = dst.offset(::core::mem::size_of::() as c_ulong as isize); + t = t.wrapping_sub(1); + if t == 0 { + break; + } + } + } + t = length + & (::core::mem::size_of::() 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::() 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::() as c_ulong) + .wrapping_sub(1 as c_int as c_ulong) + != 0 + || length <= ::core::mem::size_of::() as c_ulong + { + t = length; + } else { + t &= (::core::mem::size_of::() 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::() as c_ulong); + if t != 0 { + loop { + src = src.offset(-(::core::mem::size_of::() as c_ulong as isize)); + dst = dst.offset(-(::core::mem::size_of::() as c_ulong as isize)); + *dst.cast::() = *(src as *mut Word); + t = t.wrapping_sub(1); + if t == 0 { + break; + } + } + } + t = length + & (::core::mem::size_of::() 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] @@ -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();