Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions crates/rpl_meta/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ pub fn collect_default_patterns() -> Vec<(PathBuf, String)> {
}

default_patterns!(
// When you add a pattern to the list below,
// ensure that its order matches the file system's order.
// (To ensure consistency of output information during testing)
// Clippy lints
"clippy/cast-slice-different-sizes.rpl",
"clippy/cast-slice-from-raw-parts.rpl",
Expand All @@ -45,6 +48,7 @@ pub fn collect_default_patterns() -> Vec<(PathBuf, String)> {
"clippy/mem-replace-with-uninit.rpl",
"clippy/mut-from-ref.rpl",
"clippy/not-unsafe-ptr-arg-deref.rpl",
"clippy/ptr-offset-with-cast.rpl",
"clippy/size-of-in-element-count.rpl",
"clippy/swap-ptr-to-ref.rpl",
"clippy/transmute-int-to-non-zero.rpl",
Expand Down
35 changes: 35 additions & 0 deletions docs/patterns-pest/clippy/ptr-offset-with-cast.rpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
pattern ptr-offset-with-cast

patt {
#[diag = "ptr-offset-with-cast"]
p_offset[
$PTR: type where is_ptr(self),
] = fn _ (..) -> _ {
let $ptr: $PTR = _;
let $offset_usize: usize = _;
let $offset_isize: isize = copy $offset_usize as isize (IntToInt);
'ptr_offset_call:
_ = std::intrinsics::arith_offset::<u8>(copy $ptr, copy $offset_isize);
Comment thread
stuuupidcat marked this conversation as resolved.
}

#[diag = "ptr-offset-with-cast"]
p_wrapping_offset[
$PTR: type where is_ptr(self),
] = fn _ (..) -> _ {
let $ptr: $PTR = _;
let $offset_usize: usize = _;
let $offset_isize: isize = copy $offset_usize as isize (IntToInt);
'ptr_offset_call:
_ = Offset(copy $ptr, copy $offset_isize);
}

}

diag {
ptr-offset-with-cast = {
primary(ptr_offset_call) = "usage of the `offset` pointer method with a usize casted to an isize.",
Comment thread
stuuupidcat marked this conversation as resolved.
help = "if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.",
Comment thread
stuuupidcat marked this conversation as resolved.
name = "ptr_offset_with_cast",
level = "warn",
}
}
45 changes: 45 additions & 0 deletions tests/ui/clippy/ptr_offset_with_cast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//@compile-flags: -Z mir-opt-level=0
fn main() {
let vec = vec![b'a', b'b', b'c'];
let ptr = vec.as_ptr();

let offset_u8 = 1_u8;
let offset_usize = 1_usize;
let offset_isize = 1_isize;

unsafe {
let _ = ptr.offset(offset_usize as isize);
//~^ ptr_offset_with_cast
//~|ERROR: it is an undefined behavior to offset a pointer using an unchecked integer
let _ = ptr.offset(offset_isize as isize);
//~^ERROR: it is an undefined behavior to offset a pointer using an unchecked integer
let _ = ptr.offset(offset_u8 as isize);
//~^ERROR: it is an undefined behavior to offset a pointer using an unchecked integer

let _ = ptr.wrapping_offset(offset_usize as isize);
//~^ ptr_offset_with_cast
let _ = ptr.wrapping_offset(offset_isize as isize);
let _ = ptr.wrapping_offset(offset_u8 as isize);

let _ = S.offset(offset_usize as isize);
let _ = S.wrapping_offset(offset_usize as isize);

let _ = (&ptr).offset(offset_usize as isize);
//~^ ptr_offset_with_cast
//~|ERROR: it is an undefined behavior to offset a pointer using an unchecked integer
let _ = (&ptr).wrapping_offset(offset_usize as isize);
//~^ ptr_offset_with_cast
}
}

#[derive(Clone, Copy)]
struct S;

impl S {
fn offset(self, _: isize) -> Self {
self
}
fn wrapping_offset(self, _: isize) -> Self {
self
}
}
82 changes: 82 additions & 0 deletions tests/ui/clippy/ptr_offset_with_cast.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/clippy/ptr_offset_with_cast.rs:19:21
|
LL | let _ = ptr.wrapping_offset(offset_usize as isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.
= note: `-D rpl::ptr-offset-with-cast` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(rpl::ptr_offset_with_cast)]`

error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/clippy/ptr_offset_with_cast.rs:30:24
|
LL | let _ = (&ptr).wrapping_offset(offset_usize as isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.

error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/clippy/ptr_offset_with_cast.rs:11:21
|
LL | let _ = ptr.offset(offset_usize as isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.

error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/clippy/ptr_offset_with_cast.rs:27:24
|
LL | let _ = (&ptr).offset(offset_usize as isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.

error: it is an undefined behavior to offset a pointer using an unchecked integer
--> tests/ui/clippy/ptr_offset_with_cast.rs:11:21
|
LL | let _ = ptr.offset(offset_usize as isize);
| --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ offset here
| |
| pointer used here
|
= help: check whether it's in bound before offsetting
= note: See the safety section in https://doc.rust-lang.org/std/primitive.pointer.html#method.offset
= note: `-D rpl::unchecked-pointer-offset` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(rpl::unchecked_pointer_offset)]`

error: it is an undefined behavior to offset a pointer using an unchecked integer
--> tests/ui/clippy/ptr_offset_with_cast.rs:14:21
|
LL | let _ = ptr.offset(offset_isize as isize);
| --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ offset here
| |
| pointer used here
|
= help: check whether it's in bound before offsetting
= note: See the safety section in https://doc.rust-lang.org/std/primitive.pointer.html#method.offset

error: it is an undefined behavior to offset a pointer using an unchecked integer
--> tests/ui/clippy/ptr_offset_with_cast.rs:16:21
|
LL | let _ = ptr.offset(offset_u8 as isize);
| --- ^^^^^^^^^^^^^^^^^^^^^^^^^^ offset here
| |
| pointer used here
|
= help: check whether it's in bound before offsetting
= note: See the safety section in https://doc.rust-lang.org/std/primitive.pointer.html#method.offset

error: it is an undefined behavior to offset a pointer using an unchecked integer
--> tests/ui/clippy/ptr_offset_with_cast.rs:27:24
|
LL | let _ = (&ptr).offset(offset_usize as isize);
| ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ offset here
| |
| pointer used here
|
= help: check whether it's in bound before offsetting
= note: See the safety section in https://doc.rust-lang.org/std/primitive.pointer.html#method.offset

error: aborting due to 8 previous errors

1 change: 1 addition & 0 deletions tests/ui/clippy/size_of_in_element_count/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ fn main() {

unsafe { y.as_ptr().offset(size_of::<u16>() as isize) };
//~^ size_of_in_element_count
//~| ptr_offset_with_cast

y.as_mut_ptr().wrapping_offset(size_of::<u16>() as isize);
//~^ size_of_in_element_count
Expand Down
14 changes: 12 additions & 2 deletions tests/ui/clippy/size_of_in_element_count/functions.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/clippy/size_of_in_element_count/functions.rs:74:25
|
LL | unsafe { y.as_ptr().offset(size_of::<u16>() as isize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.
= note: `-D rpl::ptr-offset-with-cast` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(rpl::ptr_offset_with_cast)]`

error: found a count of bytes instead of a count of elements of `u16`
--> tests/ui/clippy/size_of_in_element_count/functions.rs:20:62
|
Expand Down Expand Up @@ -104,7 +114,7 @@ LL | y.as_mut_ptr().wrapping_add(size_of::<u16>());
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type

error: found a count of bytes instead of a count of elements of `u16`
--> tests/ui/clippy/size_of_in_element_count/functions.rs:77:36
--> tests/ui/clippy/size_of_in_element_count/functions.rs:78:36
|
LL | y.as_mut_ptr().wrapping_offset(size_of::<u16>() as isize);
| ^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -151,5 +161,5 @@ LL | unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<
|
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type

error: aborting due to 19 previous errors
error: aborting due to 20 previous errors

13 changes: 11 additions & 2 deletions tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ impl<T> Drop for Slab<T> {
for x in 0..self.len {
unsafe {
let elem_ptr = self.mem.offset(x as isize);
//~^ ptr_offset_with_cast
//~| HELP: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.
//~| HELP: to override `-D warnings` add `#[allow(rpl::ptr_offset_with_cast)]`
ptr::drop_in_place(elem_ptr);
std::hint::black_box(elem_ptr);
}
Expand All @@ -27,8 +30,10 @@ impl<T> Index<usize> for Slab<T> {
fn index(&self, index: usize) -> &Self::Output {
unsafe { &(*(self.mem.offset(index as isize))) }
//~^ERROR: it is an undefined behavior to offset a pointer using an unchecked integer
//~|HELP: check whether it's in bound before offsetting
//~|HELP: to override `-D warnings` add `#[allow(rpl::unchecked_pointer_offset)]`
//~| HELP: check whether it's in bound before offsetting
//~| HELP: to override `-D warnings` add `#[allow(rpl::unchecked_pointer_offset)]`
//~| ptr_offset_with_cast
//~| HELP: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.
}
}

Expand All @@ -49,9 +54,13 @@ impl<T> Slab<T> {
elem_ptr = self.mem.offset(offset as isize);
//~^ ERROR: it is an undefined behavior to offset a pointer using an unchecked integer
//~| HELP: check whether it's in bound before offsetting
//~| ptr_offset_with_cast
//~| HELP: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.
last_elem_ptr = self.mem.offset(self.len as isize);
//~^ HELP: this is because `self.len` exceeds the container's length by one
//~| HELP: did you mean this
//~| ptr_offset_with_cast
//~| HELP: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.

elem = ptr::read(elem_ptr);
last_elem = ptr::read(last_elem_ptr);
Expand Down
46 changes: 40 additions & 6 deletions tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:16:41
|
LL | let elem_ptr = self.mem.offset(x as isize);
| ^^^^^^^^^^^^^^^^^^
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.
= note: `-D rpl::ptr-offset-with-cast` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(rpl::ptr_offset_with_cast)]`

error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:31:31
|
LL | unsafe { &(*(self.mem.offset(index as isize))) }
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.

error: it is an undefined behavior to offset a pointer using an unchecked integer
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:28:31
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:31:31
|
LL | unsafe { &(*(self.mem.offset(index as isize))) }
| -------- ^^^^^^^^^^^^^^^^^^^^^^ offset here
Expand All @@ -11,8 +29,24 @@ LL | unsafe { &(*(self.mem.offset(index as isize))) }
= note: `-D rpl::unchecked-pointer-offset` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(rpl::unchecked_pointer_offset)]`

error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:54:33
|
LL | elem_ptr = self.mem.offset(offset as isize);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.

error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:59:38
|
LL | last_elem_ptr = self.mem.offset(self.len as isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.

error: it is an undefined behavior to offset a pointer using an unchecked integer
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:49:33
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:54:33
|
LL | elem_ptr = self.mem.offset(offset as isize);
| -------- ^^^^^^^^^^^^^^^^^^^^^^^ offset here
Expand All @@ -23,7 +57,7 @@ LL | elem_ptr = self.mem.offset(offset as isize);
= note: See the safety section in https://doc.rust-lang.org/std/primitive.pointer.html#method.offset

error: pointer out of bound
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:57:25
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:66:25
|
LL | last_elem_ptr = self.mem.offset(self.len as isize);
| -------------------------
Expand All @@ -35,14 +69,14 @@ LL | last_elem = ptr::read(last_elem_ptr);
| ^^^^^^^^^^^^^^^^^^^^^^^^ pointer read here
|
help: this is because `self.len` exceeds the container's length by one
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:52:45
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:59:45
|
LL | last_elem_ptr = self.mem.offset(self.len as isize);
| ^^^^^^^^
= note: `#[deny(rpl::offset_by_one)]` on by default

error: it usually isn't necessary to apply #[inline] to generic functions
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:37:5
--> tests/ui/cve/cve_2020_35892_3/cve_2020_35892_3.rs:42:5
|
LL | #[inline]
| --------- `#[inline]` here
Expand All @@ -57,5 +91,5 @@ LL | | }
= note: `-D rpl::generic-function-marked-inline` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(rpl::generic_function_marked_inline)]`

error: aborting due to 4 previous errors
error: aborting due to 8 previous errors

52 changes: 52 additions & 0 deletions tests/ui/cve/cve_2021_25905/minimal.inline.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/cve/cve_2021_25905/minimal.rs:19:38
|
LL | buf.as_mut_ptr().offset(b as isize),
| ^^^^^^^^^^^^^^^^^^
...
LL | cases!(Vec::new());
| ------------------ in this macro invocation
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.
= note: `-D rpl::ptr-offset-with-cast` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(rpl::ptr_offset_with_cast)]`
= note: this error originates in the macro `cases` (in Nightly builds, run with -Z macro-backtrace for more info)

error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/cve/cve_2021_25905/minimal.rs:19:38
|
LL | buf.as_mut_ptr().offset(b as isize),
| ^^^^^^^^^^^^^^^^^^
...
LL | cases!(vec![1, 2, 3]);
| --------------------- in this macro invocation
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.
= note: this error originates in the macro `cases` (in Nightly builds, run with -Z macro-backtrace for more info)

error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/cve/cve_2021_25905/minimal.rs:19:38
|
LL | buf.as_mut_ptr().offset(b as isize),
| ^^^^^^^^^^^^^^^^^^
...
LL | cases!(Vec::with_capacity(0));
| ----------------------------- in this macro invocation
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.
= note: this error originates in the macro `cases` (in Nightly builds, run with -Z macro-backtrace for more info)

error: usage of the `offset` pointer method with a usize casted to an isize.
--> tests/ui/cve/cve_2021_25905/minimal.rs:19:38
|
LL | buf.as_mut_ptr().offset(b as isize),
| ^^^^^^^^^^^^^^^^^^
...
LL | cases!(Vec::with_capacity(1));
| ----------------------------- in this macro invocation
|
= help: if you’re always increasing the pointer address, you can avoid the numeric cast by using the `add` method instead.
= note: this error originates in the macro `cases` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 4 previous errors

Loading