-
Notifications
You must be signed in to change notification settings - Fork 241
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
Miscompilation of varargs on some targets #246
Comments
@pablosichert Interesting find, we'll definitely fix it!
That would actually be myself (who implemented and tested the feature in rustc) and eddyb who proposed the final design and also reviewed my PR. I'm happy to help with either a C2Rust and rustc fix. The rustc API basically tries to copy whatever clang does as faithfully as possible (modulo the let mut argument: libc::c_int = arguments.as_va_list().arg::<libc::c_int>(); At first glance, this looks wrong to me. |
If I remove the the I'm not sure if you can distinguish between those cases during transpilation? I'll try to come up with an example for that tomorrow. |
Yeah that definitely sounds like a C2Rust bug, you should never have Edit: I think I know what's going on: we add a |
@pablosichert I pushed a fix, could you build C2Rust from commit 9c01882 and try it? |
Tried it and looks good at a first glance, thank you! It still segfaults at a later point (possibly unrelated), so I'll do some more extensive testing today. |
Your commit seems to fix this issue. Do you feel there should still be a follow up on rustc? Regarding the following:
|
That was due to #248. This case seems to be resolved. |
I tried transpiling C using the See the diff pablosichert/rust-varargs-test@ac1db0e and build error here: error[E0599]: no method named `arg` found for type `*mut i8` in the current scope
--> src/variadic.rs:19:51
|
19 | let mut argument: libc::c_int = arguments.arg::<libc::c_int>();
| ^^^ method not found in `*mut i8`
|
= note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref
= note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior
error[E0308]: mismatched types
--> src/variadic.rs:36:12
|
36 | list = args.clone();
| ^^^^^^^^^^^^ expected *-ptr, found struct `std::ffi::VaListImpl`
|
= note: expected raw pointer `*mut i8`
found struct `std::ffi::VaListImpl<'_>` The FAQ state that cross-compiling is not supported at the moment. Does that also include a restriction that transpiling on any architecture other than |
Not explicitly, but we haven't tested any other architecture. The others might be broken in ways we don't know about. Are you still targeting |
Yes targeting I tried transpiling using the If there was some way to control the stage that is responsible for evaluating C builtins, I would also be fine with that. |
I think what's interesting in the diff between 64-bit and 32-bit is that on 64-bit the output is pub type __builtin_va_list = [__va_list_tag; 1];
#[derive(Copy, Clone)]
#[repr(C)]
pub struct __va_list_tag {
pub gp_offset: libc::c_uint,
pub fp_offset: libc::c_uint,
pub overflow_arg_area: *mut libc::c_void,
pub reg_save_area: *mut libc::c_void,
}
pub type va_list = __builtin_va_list; mut arguments: ::std::ffi::VaList vs on 32-bit pub type __builtin_va_list = *mut libc::c_char;
pub type va_list = __builtin_va_list; mut arguments: va_list Therefore a lot of methods are missing for the |
I think that's what could be causing your problems, at least for On the other hand, in your latest error, it seems like the problem is the code is trying to call |
Ah there it is, |
Hi there,
first of all: thanks for this great tool, being able to transpile C to Rust is really valuable!
Unfortunately, the handling around varargs doesn't seem to work for all targets, specifically
wasm32
. To observe the behavior, I provided a C function:https://github.com/pablosichert/rust-varargs-test/blob/e10aead1007cbfa923a006952436d0a324583da2/src/variadic.c#L3-L9
that will be compiled to the following Rust code:
https://github.com/pablosichert/rust-varargs-test/blob/e10aead1007cbfa923a006952436d0a324583da2/src/variadic.rs#L15-L28
and a test case:
https://github.com/pablosichert/rust-varargs-test/blob/e10aead1007cbfa923a006952436d0a324583da2/tests/tests.rs#L16-L37
that succeeds on native, but fails on
wasm32
:https://github.com/pablosichert/rust-varargs-test/runs/543678432.
The problem here is that .as_va_list clones the list on
wasm32
, but is a mutable reference on native, see https://doc.rust-lang.org/src/core/ffi.rs.html#177-201.I asked about this on the Rust #compiler channel on Discord, I'll just paste some of it here:
I haven't opened an issue on https://github.com/rust-lang/rust yet, since I'd like to know if this issue would need to be / could be fixed on the transpilation level.
Code similar to my reproduction case can be found in the wild, e.g. SQLite: https://github.com/sqlite/sqlite/blob/ef7d5187a74fdddee3dabfaddebaf63ca316aac7/src/printf.c#L796.
The text was updated successfully, but these errors were encountered: