Skip to content

Warn when casting double indirection pointer to single indirection (e.g. *const *const i8 to *const i8) #9877

Open
@tgross35

Description

@tgross35

What it does

I just spent about an hour debugging an issue like the following:

let attr_ptrs: *const *const i8 = ...;

// Actually wrote this line
let buf_ptr: *const u8 = attr_ptrs.add(1).cast();
// Should have written this line
let buf_ptr: *const u8 = *attr_ptrs.add(1).cast();

let buf = slice::from_raw_parts(buf_ptr, len);
str::from_utf8(buf)

At first glance it seems reasonable enough - cast a *const i8 (c_char) to a *const u8 so it can be used as a string. However it's easy to miss that the first buf_ptr line is actually casting a *const *const i8 directly to a *const u8 without dereferencing.

This lint would catch casting any double pointer to any single pointer, which is currently very easy to miss. (Would likely also work for ***type to **type/*type)

Lint Name

double_indirection_cast

Category

suspicious

Advantage

  • Prevent UB that is very difficult to trace back
  • Aid users coming from C who easily miss that replicating something like double_ptr[1] requires a deref *double_ptr.add(1)

Drawbacks

This use may occasionally be intentional (e.g. casting to/from *const c_void). In my experience, these cases are less common than pointer array access.

Example

let attr_ptrs: *const *const i8 = ...;
let buf_ptr: *const u8 = attr_ptrs.add(1).cast();

Could be written as:

let attr_ptrs: *const *const i8 = ...;
let buf_ptr: *const u8 = *attr_ptrs.add(1).cast();

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintArea: New lints

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions