Lint str-ptr-in-c-abi discourage str pointers in C ABI fns#17401
Lint str-ptr-in-c-abi discourage str pointers in C ABI fns#17401fpdotmonkey wants to merge 1 commit into
Conversation
|
Thanks for the pull request, and welcome!You should hear from one of our reviewers after this PR is reviewed by at least 2 reviewers from the community Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (
|
db505ce to
0d5dddd
Compare
|
I'm not really sure what the failure on Lintcheck is. The error messages sounds like failures in external crates, but that's almost certainly not the case. |
|
You are currently using |
|
Reminder, once the PR becomes ready for a review, use |
0d5dddd to
5f74d2d
Compare
|
Lintcheck changes for 9669223
This comment will be updated if you push new changes |
Fixed @rustbot ready |
This comment has been minimized.
This comment has been minimized.
This discourages using a pointer to a `str` instead of to a CString for `extern "C"` functions.
5f74d2d to
9669223
Compare
|
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
| let ExprKind::Call(callee, args) = expr.kind else { | ||
| return; | ||
| }; | ||
| // where the signature of the callee shows it is | ||
| // extern "C" | ||
| if is_extern_c_fn(cx, callee) { | ||
| // and takes a raw pointer as an argument | ||
| let arg_idxs = raw_pointer_arg_idxs(cx, callee); | ||
| if arg_idxs.is_empty() { | ||
| return; | ||
| } | ||
| let relevant_args = arg_idxs | ||
| .into_iter() | ||
| .filter_map(|idx| args.get(idx)) | ||
| .map(Clone::clone) | ||
| .collect::<Vec<_>>(); | ||
| let problem_args = args_str_ptr_cast(cx, &relevant_args); | ||
| if problem_args.is_empty() { | ||
| return; | ||
| } | ||
| let span: rustc_errors::MultiSpan = problem_args | ||
| .into_iter() | ||
| .map(|arg| arg.span) | ||
| .collect::<Vec<rustc_span::Span>>() | ||
| .into(); |
There was a problem hiding this comment.
You can combine these checks into an if let chain and use an iterator that only collect at the end. (See review below). then you can pass the spans directly to span_lint_and_help (if they are not empty).
| /// Returns elements from `args` which have a Rust `str` as a raw pointer cast to a raw pointer. | ||
| fn args_str_ptr_cast<'tcx>(cx: &LateContext<'tcx>, args: &[Expr<'tcx>]) -> Vec<Expr<'tcx>> { | ||
| args.iter() | ||
| .filter(|arg| { | ||
| // just a simple check for | ||
| // `let s: &str; libc::strlen(s.as_ptr() as *const _);` | ||
| // or similarly with `as_mut_ptr`/`*mut` | ||
| if let ExprKind::Cast(expr, ty) = arg.kind | ||
| && matches!(ty.kind, TyKind::Ptr(_)) | ||
| && let ExprKind::MethodCall(method, this, _args, _span) = expr.kind | ||
| && ["as_ptr", "as_mut_ptr"].contains(&method.ident.name.as_str()) | ||
| && is_ref_str(cx.typeck_results().expr_ty(this)) | ||
| { | ||
| true | ||
| } else { | ||
| false | ||
| } | ||
| }) | ||
| .map(Clone::clone) | ||
| .collect() | ||
| } | ||
|
|
||
| /// is `ty` either `&str` or `&mut str`? | ||
| fn is_ref_str(ty: Ty<'_>) -> bool { | ||
| if let rustc_middle::ty::Ref(_, reffed_ty, _) = ty.kind() { | ||
| return reffed_ty.is_str(); | ||
| } | ||
| false | ||
| } |
There was a problem hiding this comment.
You can replace this with a single function that checks one argument and returns a bool if it's cast to a raw pointer (for example a is_str_ptr_cast that you can use in the above filter closure in the iterator), you can use expr_ty_adjusted to catch String, etc... instead of being limited to str.
Also you can use sym from clippy_utils instead of comparing strings directly, like this:
....
matches!(method.ident.name, sym::as_ptr | sym::as_mut_ptr)
Please write a short comment explaining your change (or "none" for internal only changes)
changelog:
str-ptr-in-c-abi: This discourages using a pointer to astrinstead of to a CString forextern "C"functions.This addresses #1236