Skip to content

Lint for large on-stack temporary values #15809

@bczhc

Description

@bczhc

What it does

This lint warns unintentional large temporary values which may cause an overflowed stack.

Taking this function definition:

const LENGTH: usize = 1048576;

fn foo(buf: &[u8; LENGTH]) {
    let _a = buf;
}

On the signature, a thin ref &[u8; LENGTH] ensures the argument passed in should have exactly this size. Out of the function, array.try_into().unwrap() can be used as an assertion to the array size. However,

fn main() {
    let buf = vec![0_u8; LENGTH];
    // No! equivalent to: foo(&<[u8; LENGTH]>::try_from(buf).unwrap())
    foo(&buf.try_into().unwrap());
}

One may carelessly write a function call like above (I searched and found many occurrences like this on GitHub). Note, it will create a [u8; LENGTH] temporary value that is then referenced and passed to the function. This temporary value may cause an overflowed stack.

In this case above, due to different stack size limit on the two platforms, it runs smoothly on Linux but Stack overflow encounters on Windows. This may be tricky somehow.

Advantage

  • Avoid unneeded stack temporary values and potential stack overflow errors.

Drawbacks

No response

Example

let buf: Vec<T> = ...
foo(&buf.try_into().unwrap());

Could be written as:

let buf: Vec<T> = ...
foo(<&[T; LENGTH]>::try_from(&buf[..]).unwrap());

Or,

let buf: Vec<T> = ...
foo((&buf[..]).try_into().unwrap());

Comparison with existing lints

We have large_stack_arrays lint but this is unable to detect such cases.

Additional Context

No response

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