Skip to content

Enum support and ASAN/MSAN C roundtrip tests#58

Merged
fredszaq merged 17 commits intomainfrom
enum-support
Apr 13, 2026
Merged

Enum support and ASAN/MSAN C roundtrip tests#58
fredszaq merged 17 commits intomainfrom
enum-support

Conversation

@fredszaq
Copy link
Copy Markdown
Collaborator

This adds support for unit enums. Fixes #57

I also expanded the roundtrip test we have; this will now generate a C header and compile C \o/

@fredszaq fredszaq mentioned this pull request Apr 11, 2026
@fredszaq
Copy link
Copy Markdown
Collaborator Author

@anthonyray @Deluvi 👋 care for a review ?

@fredszaq fredszaq changed the title Enum support Enum support and MSAN C roundtrip tests Apr 11, 2026
Copy link
Copy Markdown
Contributor

@Deluvi Deluvi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unit enum support looks great ! 👍

The rest is a bit of nitpicks and such for the ASan / MSan tests, but it's good to have that covered ! (though through a very parkoury interpretation of a Rust test)

Feel free to dig into it. If that's irrelevant, ship it :shipit:

I don't know how much is relevant here, but maybe mind that cross-language ASan and MSan might require extra caution because there might two conflicting ASan/MSan Clang runtimes, see: https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#working-with-other-languages

Comment thread ffi-convert-tests/test_round_trip.c Outdated
printf("Triggering ASan canary (should crash):\n");
test_asan_canary();
printf("ERROR: ASan did not catch use-after-free!\n");
return 1;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you run the ASan canary, you expect the binary to return a non-zero status:

assert!(
    !canary.status.success(),
    "Sanitizer canary ({}) should have crashed but didn't",
    canary_flag
);

That's because ASan will make exit the program with a non-zero status.

By doing return 1; here, you won't actually signal to the test program that ASan did not catch the use-after-free.

I think you should be doing a return 0; here

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did that ! I also made sure the test won't actually segfault when doing the violation so we can actually get there if asan/msan is not enabled

Comment thread ffi-convert-tests/test_round_trip.c Outdated
printf("Triggering MSan canary (should crash):\n");
test_msan_canary();
printf("ERROR: MSan did not catch uninitialized read!\n");
return 1;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, I think you should return 0; here

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread ffi-convert-tests/src/lib.rs Outdated

/// Helper: set the env vars that the cc crate expects outside of build.rs.
fn setup_cc_env(host_target: &str) {
std::env::set_var("TARGET", host_target);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: std::env::set_var is not thread-safe:

This function is safe to call in a single-threaded program.
...
In multi-threaded programs on other operating systems, the only safe option is to not use set_var or remove_var at all.

cargo test will make several tests run in parallel in the same process but in different threads

Thankfully, for now, your tests are mutually exclusives because of #[cfg(feature = "msan")], but that's something to note

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got rid of that, there are actually proper functions to configure CC

Comment thread ffi-convert-tests/src/lib.rs Outdated
compile_c_test(
tmp_dir.path(),
&target_dir,
"-fsanitize=address",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We build the C binary with ASan, but we don't build the Rust cdylib with ASan

Is there a reason why not?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oversight, fixed, we now have the normal C round trip test that won't do asan/msan and will run on stable rust. We also have 2 nightly runs of the tests, enabling asan/msan on the rust code (at two levels, once for the full rust tests, and once when building the test cdylib

let tmp_dir = tempfile::tempdir().expect("Failed to create temp dir");

// Are we calling cargo from inside the test binary to make sure the cdylib is built ?
// yes, watch me.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that feels wrong, that's probably something that should be done outside of a cargo test, especially because tinkering with the build flags will probably render the cache of the cargo test invalid when running cargo build with such things as -Zsanitizer=memory, making the iteration loop a bit cumbersome

But hey, at least the CI and the developer will run them with a simple cargo test, so I guess it's not that so wrong 😂 (until it becomes annoying for the developer I guess)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made sure to change the cargo target dir when we do that now. This is actually quite fast once you have built it once (and first build is ok) this will prevent having weird things with the cargo lock on the build dir, this did work previously but was not really solid

Comment thread ffi-convert-tests/src/lib.rs Outdated
let stderr = String::from_utf8_lossy(&canary.stderr);
assert!(
stderr.contains(expected_stderr),
"Canary ({}) crashed but not from expected sanitizer: {}",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, you check for AddressSanitizer / MemorySanitizer in the logs. I don't know how much checking for such log is reliable and will not result in false positives

Maybe checking for return 0; is less finicky ?

Copy link
Copy Markdown
Collaborator Author

@fredszaq fredszaq Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configured asan/msan to return 42 on violation and checking that, should be more robust

@fredszaq fredszaq changed the title Enum support and MSAN C roundtrip tests Enum support and ASAN/MSAN C roundtrip tests Apr 12, 2026
pub flattened_range: Range<i64>,
pub field_with_specific_rust_name: String,
pub pancake_data: Option<Vec<u8>>,
pub extra_ice_cream_flavor: Flavor,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's getting yummier and yummier

@fredszaq fredszaq merged commit 4f3ae6b into main Apr 13, 2026
1 check passed
@fredszaq fredszaq deleted the enum-support branch April 13, 2026 17:48
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

Successfully merging this pull request may close these issues.

feat: enum support

3 participants