rust-lang / rust-lang/rust-clippy

New lint: potentially unwinding caller-supplied operators in `unsafe` code

Open
#9,200 21 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

A-lint
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

What it does

If a non-unsafe generic function containing unsafe block uses an operator that is implemented by the caller (via core::ops::*) the lint warns that the operator may unwind and suggests catch_unwind or calling the method explicitly to signal the programmer thought about it.

Related: #3915
See also: https://github.com/rust-lang/rfcs/pull/3288#discussion_r922871828

Lint Name

suspicious-operators-in-unsafe

Category

suspicious

Advantage
  • Forces the programmer to think about unwinds
  • Signals to the reviewers "yes, I did think about unwinds" (assuming it's also justified in SAFETY comment)
Drawbacks

It's quite possible there will be a bunch of FPs. Maybe it'll have to be off by default.

Example
impl<T> Foo<T> where T: core::ops::Add {
    pub fn foo(&mut self, val: T) {
        unsafe {
            self.break_invariants();
           // oops: if this unwinds `self` ends up in invalid state
            self.a = self.b + val;
            self.restore_invariants();
        }
    }
}

Could be written as:

impl<T> Foo<T> where T: core::ops::Add {
    pub fn foo(&mut self, val: T) {
        unsafe {
            self.break_invariants();
           // prevent the caller from observing invalid state if `+` unwinds
            let result = catch_unwind(|| self.a = self.b + val);
            self.restore_invariants();
            result.unwrap();
        }
    }
}

or:

impl<T> Foo<T> where T: core::ops::Add {
    pub fn foo(&mut self, val: T) {
        unsafe {
            self.doesnt_break_invariants();
           // safe to call add because the invariants are not broken
            self.a = self.b.add(val).
            self.doesnt_affect_invariants();
        }
    }
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the issue's proposed suspicious-operators-in-unsafe behavior and the related discussion in #3915 and RFC 3288. Determine the lint's scope and false-positive policy from the 21-comment thread, then identify the Clippy lint entry point and tests to add. Done means the chosen operator cases are diagnosed consistently with the intended suggestions.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.