Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong Method::invoke implementation #9

Open
nikvoid opened this issue Apr 14, 2024 · 2 comments
Open

Wrong Method::invoke implementation #9

nikvoid opened this issue Apr 14, 2024 · 2 comments

Comments

@nikvoid
Copy link

nikvoid commented Apr 14, 2024

Method::invoke Implementation works fine only with value types like integers. Using Object in method signature breaks it and causing crashes.

wrapped_mono/src/method.rs

Lines 207 to 215 in fac74e2

pub fn invoke(&self, object: Option<Object>, args: Args) -> Result<Option<Object>, Exception> {
//convert object to invoke on to a pointer.
let obj_ptr = object.map_or(core::ptr::null_mut(), |obj| obj.get_ptr());
let mut expect: *mut MonoException = null_mut();
//convert argument types
let mut args = <Args as InteropSend>::get_mono_rep(args);
let mut params = <<Args as InteropSend>::TargetType as TupleToPtrs>::get_ptrs(
std::ptr::addr_of_mut!(args),
);

Actual problem is in get_ptrs method

wrapped_mono/src/method.rs

Lines 213 to 215 in fac74e2

let mut params = <<Args as InteropSend>::TargetType as TupleToPtrs>::get_ptrs(
std::ptr::addr_of_mut!(args),
);

args is the tuple of pointers and values.

But get_ptrs implementations treat all args members like values, creating pointers to each:

impl<A, B, C> TupleToPtrs for (A, B, C) {
type Res = [*mut c_void; 3];
fn get_ptrs(base_ptr: *mut Self) -> Self::Res {
let a = base_ptr as usize;
let b = a + std::mem::size_of::<A>();
let c = b + std::mem::size_of::<B>();
[a as VoidPtr, b as VoidPtr, c as VoidPtr]
}
}

MonoObject* pointers must be stored by value, not by reference to pointer.

I think this is easy to reproduce using any method that takes Object by pointer value:

let object: Object = /*...*/ ; 
let method: Method<(Object, )> = /*...*/ ;
    
// This works fine
let mut params = [object.get_ptr()];
wrapped_mono::binds::mono_runtime_invoke(method.get_ptr(), 0 as _, params.as_mut_ptr() as _, 0 as _);

// This crashes
method.invoke(None, (object, ));
@FractalFir
Copy link
Owner

Thanks for the bug report. I will try to fix this tomorrow, and publish a new version.

@FractalFir
Copy link
Owner

The issue is a bit more complicated, and looking back at the source code, there are some other glaring problems that need fixing(C-style layout of tuples is assumed, when it should not be).

I will try to fix this soon, but I can't guarantee any timelines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants