rust-lang / rust-lang/rust-clippy

Lint on Using `as_ptr()` or `as_ptr_mut()` on a MutexGuard if the Guard is Dropped After the Call

Open
#9,936 0 comments 0 reactions 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

This lint warns you if you unlock a mutex after getting access to a pointer to the object inside, as in:

let my_pointer = mutex.lock().unwrap().as_ptr();

or even more suspiciously:
let mut my_pointer = mutex.lock().unwrap().as_mut_ptr();

My suggestion is that doing this is a clear enough sign that you are planning to use that pointer soon in a way unguarded by the mutex that it warrants a lint.

Lint Name

Obtained Pointer to Contents of Unlocked Mutex?

Category

suspicious

Advantage

This bit me with this code:

pub fn get_frame(&self, frame:&mut [u8]) {
   let source = self.front_buffer.lock().unwrap().as_ptr();
   unsafe {
      let destination = frame.as_mut_ptr();
      ptr::copy_nonoverlapping(source, destination, frame.len());
   }
}

If it had been a Clippy lint, I would have avoided this problem because I'm using real-time Clippy analysis through the CLion IDE.

Drawbacks

Calling as_ptr() or as_ptr_mut() is perfectly safe in isolation, so it might produce false positives in code that wants to do something that only involves the pointer addresses rather that the things they are pointing at.

It could also encourage in such cases for people to work around the lint by locking the mutex longer than necessary:

let my_pointer = mutex.lock().unwrap().as_ptr();`
// perfectly safe code

to:

let guard = mutex.lock().unwrap();`
let my_pointer = guard.as_ptr();
// perfectly safe code, but mutex is still locked and doesn't need to be
Example
pub fn get_frame(&self, frame:&mut [u8]) {
   let source = self.front_buffer.lock().unwrap().as_ptr();
   unsafe {
      let destination = frame.as_mut_ptr();
      ptr::copy_nonoverlapping(source, destination, frame.len());
   }
}

Could be written as:

pub fn get_frame(&self, frame:&mut [u8]) {
   let source = self.front_buffer.lock().unwrap();
   unsafe {
      let destination = frame.as_mut_ptr();
      ptr::copy_nonoverlapping(source.as_ptr(), destination, frame.len());
   }
}

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

The issue names no implementation files or tests. Start by locating Clippy's lint entry points and existing mutex-related lint tests, then define the cases the lint should diagnose and the cases it should avoid. Done means the behavior is implemented with coverage for the shown pointer patterns and false-positive concerns.

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
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.