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

cg_llvm: Use a type-safe helper to cast &str and &[u8] to *const c_char #132260

Merged
merged 1 commit into from
Oct 29, 2024

Conversation

Zalathar
Copy link
Contributor

In rustc_codegen_llvm there are many uses of .as_ptr().cast() to convert a string or byte-slice to *const c_char, which then gets passed through FFI.

This works, but is fragile, because there's nothing constraining the pointer cast to actually be from u8 to c_char. If the original value changes to something else that has an as_ptr method, or the context changes to expect something other than c_char, the cast will silently do the wrong thing.

By making the cast more explicit via a helper method, we can be sure that it will either perform the intended cast, or fail at compile time.

@rustbot
Copy link
Collaborator

rustbot commented Oct 28, 2024

r? @lcnr

rustbot has assigned @lcnr.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 28, 2024
Copy link
Member

@compiler-errors compiler-errors left a comment

Choose a reason for hiding this comment

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

Yeah, I think it's always best to constrain "dangling generics" sooner than later, so this extension function seems like a nice little improvement.

@compiler-errors
Copy link
Member

r? compiler-errors @bors r+

@bors
Copy link
Contributor

bors commented Oct 28, 2024

📌 Commit 4bd84b2 has been approved by compiler-errors

It is now in the queue for this repository.

@rustbot rustbot assigned compiler-errors and unassigned lcnr Oct 28, 2024
@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 28, 2024
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Oct 28, 2024
…r-errors

cg_llvm: Use a type-safe helper to cast `&str` and `&[u8]` to `*const c_char`

In `rustc_codegen_llvm` there are many uses of `.as_ptr().cast()` to convert a string or byte-slice to `*const c_char`, which then gets passed through FFI.

This works, but is fragile, because there's nothing constraining the pointer cast to actually be from `u8` to `c_char`. If the original value changes to something else that has an `as_ptr` method, or the context changes to expect something other than `c_char`, the cast will silently do the wrong thing.

By making the cast more explicit via a helper method, we can be sure that it will either perform the intended cast, or fail at compile time.
workingjubilee added a commit to workingjubilee/rustc that referenced this pull request Oct 28, 2024
…r-errors

cg_llvm: Use a type-safe helper to cast `&str` and `&[u8]` to `*const c_char`

In `rustc_codegen_llvm` there are many uses of `.as_ptr().cast()` to convert a string or byte-slice to `*const c_char`, which then gets passed through FFI.

This works, but is fragile, because there's nothing constraining the pointer cast to actually be from `u8` to `c_char`. If the original value changes to something else that has an `as_ptr` method, or the context changes to expect something other than `c_char`, the cast will silently do the wrong thing.

By making the cast more explicit via a helper method, we can be sure that it will either perform the intended cast, or fail at compile time.
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 28, 2024
…kingjubilee

Rollup of 9 pull requests

Successful merges:

 - rust-lang#130259 (Lower AST node id only once)
 - rust-lang#131441 (Add a new trait `proc_macro::ToTokens`)
 - rust-lang#132247 (stable_mir: Directly use types from rustc_abi)
 - rust-lang#132249 (compiler: Add rustc_abi dependence to the compiler)
 - rust-lang#132255 (Add `LayoutS::is_uninhabited` and use it)
 - rust-lang#132258 ([rustdoc] Unify variant struct fields margins with struct fields)
 - rust-lang#132260 (cg_llvm: Use a type-safe helper to cast `&str` and `&[u8]` to `*const c_char`)
 - rust-lang#132261 (refactor: cleaner check to return None)
 - rust-lang#132271 (Updating Fuchsia platform-support documentation)

r? `@ghost`
`@rustbot` modify labels: rollup
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Oct 29, 2024
…r-errors

cg_llvm: Use a type-safe helper to cast `&str` and `&[u8]` to `*const c_char`

In `rustc_codegen_llvm` there are many uses of `.as_ptr().cast()` to convert a string or byte-slice to `*const c_char`, which then gets passed through FFI.

This works, but is fragile, because there's nothing constraining the pointer cast to actually be from `u8` to `c_char`. If the original value changes to something else that has an `as_ptr` method, or the context changes to expect something other than `c_char`, the cast will silently do the wrong thing.

By making the cast more explicit via a helper method, we can be sure that it will either perform the intended cast, or fail at compile time.
workingjubilee added a commit to workingjubilee/rustc that referenced this pull request Oct 29, 2024
…r-errors

cg_llvm: Use a type-safe helper to cast `&str` and `&[u8]` to `*const c_char`

In `rustc_codegen_llvm` there are many uses of `.as_ptr().cast()` to convert a string or byte-slice to `*const c_char`, which then gets passed through FFI.

This works, but is fragile, because there's nothing constraining the pointer cast to actually be from `u8` to `c_char`. If the original value changes to something else that has an `as_ptr` method, or the context changes to expect something other than `c_char`, the cast will silently do the wrong thing.

By making the cast more explicit via a helper method, we can be sure that it will either perform the intended cast, or fail at compile time.
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 29, 2024
…iaskrgr

Rollup of 10 pull requests

Successful merges:

 - rust-lang#130259 (Lower AST node id only once)
 - rust-lang#131441 (Add a new trait `proc_macro::ToTokens`)
 - rust-lang#132247 (stable_mir: Directly use types from rustc_abi)
 - rust-lang#132249 (compiler: Add rustc_abi dependence to the compiler)
 - rust-lang#132255 (Add `LayoutData::is_uninhabited` and use it)
 - rust-lang#132258 ([rustdoc] Unify variant struct fields margins with struct fields)
 - rust-lang#132260 (cg_llvm: Use a type-safe helper to cast `&str` and `&[u8]` to `*const c_char`)
 - rust-lang#132261 (refactor: cleaner check to return None)
 - rust-lang#132271 (Updating Fuchsia platform-support documentation)
 - rust-lang#132295 (fixed wast version was released, remove randomization exemption)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 29, 2024
…kingjubilee

Rollup of 9 pull requests

Successful merges:

 - rust-lang#130259 (Lower AST node id only once)
 - rust-lang#131441 (Add a new trait `proc_macro::ToTokens`)
 - rust-lang#132247 (stable_mir: Directly use types from rustc_abi)
 - rust-lang#132249 (compiler: Add rustc_abi dependence to the compiler)
 - rust-lang#132255 (Add `LayoutData::is_uninhabited` and use it)
 - rust-lang#132258 ([rustdoc] Unify variant struct fields margins with struct fields)
 - rust-lang#132260 (cg_llvm: Use a type-safe helper to cast `&str` and `&[u8]` to `*const c_char`)
 - rust-lang#132261 (refactor: cleaner check to return None)
 - rust-lang#132271 (Updating Fuchsia platform-support documentation)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit bd43f8e into rust-lang:master Oct 29, 2024
6 checks passed
@rustbot rustbot added this to the 1.84.0 milestone Oct 29, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Oct 29, 2024
Rollup merge of rust-lang#132260 - Zalathar:type-safe-cast, r=compiler-errors

cg_llvm: Use a type-safe helper to cast `&str` and `&[u8]` to `*const c_char`

In `rustc_codegen_llvm` there are many uses of `.as_ptr().cast()` to convert a string or byte-slice to `*const c_char`, which then gets passed through FFI.

This works, but is fragile, because there's nothing constraining the pointer cast to actually be from `u8` to `c_char`. If the original value changes to something else that has an `as_ptr` method, or the context changes to expect something other than `c_char`, the cast will silently do the wrong thing.

By making the cast more explicit via a helper method, we can be sure that it will either perform the intended cast, or fail at compile time.
@Zalathar Zalathar deleted the type-safe-cast branch October 29, 2024 10:05
Comment on lines +402 to +406
impl AsCCharPtr for str {
fn as_c_char_ptr(&self) -> *const c_char {
self.as_ptr().cast()
}
}
Copy link
Contributor

@klensy klensy Oct 29, 2024

Choose a reason for hiding this comment

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

Isn't this wrong? &str can contain null bytes and casting it to c_char will lead to funny results in that case. It works for now because all used strings are well behaved and do not contain nulls.

Same with [u8].

Copy link
Contributor

Choose a reason for hiding this comment

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

in #132319 it broken further: c literals (for which it's ok to take *c_char), you changed to &str, which don't have guarantees of cstr.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A pointer to c_char doesn't have to be nul-terminated. We have plenty of code that passes strings over FFI as pointer/length pairs.

As long as it gets reassembled with StringRef(Ptr, Len) on the C++ side, it's fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And in #132319, all of the relevant FFI functions have been adjusted to take pointer/length pairs instead of nul-terminated strings, so there's no longer any need for those strings to be c"" literals.

Copy link
Contributor

@klensy klensy Oct 29, 2024

Choose a reason for hiding this comment

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

Yes, but fragile. Can't find if it ok for StringRef to have nulls inside, if it later pass them as c strings, things will blow.

Comment on lines 1045 to +1046
let section = bitcode_section_name(cgcx);
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
llvm::LLVMSetSection(llglobal, section.as_c_char_ptr());
Copy link
Contributor

Choose a reason for hiding this comment

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

LLVMSetSection accepts const char* without length, where section is &str.

Ahh, bitcode_section_name have fixme, so it can actually return cstr literals.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, and all of the calls to llvm::LLVMSetSection should really be calling the safe wrapper llvm::set_section (which takes &CStr), which would enforce type-safety.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

workingjubilee added a commit to workingjubilee/rustc that referenced this pull request Oct 30, 2024
…rrors

cg_llvm: Consistently use safe wrapper function `set_section`

Follow-up to rust-lang#131962 and rust-lang#132260 (comment).

To avoid too much scope creep, I've deliberately kept the changes to `LLVMRustGetSliceFromObjectDataByName` as minimal as possible.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Oct 30, 2024
…rrors

cg_llvm: Consistently use safe wrapper function `set_section`

Follow-up to rust-lang#131962 and rust-lang#132260 (comment).

To avoid too much scope creep, I've deliberately kept the changes to `LLVMRustGetSliceFromObjectDataByName` as minimal as possible.
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Oct 30, 2024
Rollup merge of rust-lang#132340 - Zalathar:set-section, r=compiler-errors

cg_llvm: Consistently use safe wrapper function `set_section`

Follow-up to rust-lang#131962 and rust-lang#132260 (comment).

To avoid too much scope creep, I've deliberately kept the changes to `LLVMRustGetSliceFromObjectDataByName` as minimal as possible.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants