]>
git.proxmox.com Git - rustc.git/blob - src/tools/clippy/clippy_lints/src/array_indexing.rs
4 use syntax
::ast
::RangeLimits
;
5 use utils
::{self, higher}
;
6 use consts
::{constant, Constant}
;
8 /// **What it does:** Checks for out of bounds array indexing with a constant
11 /// **Why is this bad?** This will always panic at runtime.
13 /// **Known problems:** Hopefully none.
17 /// let x = [1,2,3,4];
22 declare_clippy_lint
! {
23 pub OUT_OF_BOUNDS_INDEXING
,
25 "out of bounds constant indexing"
28 /// **What it does:** Checks for usage of indexing or slicing.
30 /// **Why is this bad?** Usually, this can be safely allowed. However, in some
31 /// domains such as kernel development, a panic can cause the whole operating
34 /// **Known problems:** Hopefully none.
42 declare_clippy_lint
! {
45 "indexing/slicing usage"
48 #[derive(Copy, Clone)]
49 pub struct ArrayIndexing
;
51 impl LintPass
for ArrayIndexing
{
52 fn get_lints(&self) -> LintArray
{
53 lint_array
!(INDEXING_SLICING
, OUT_OF_BOUNDS_INDEXING
)
57 impl<'a
, 'tcx
> LateLintPass
<'a
, 'tcx
> for ArrayIndexing
{
58 fn check_expr(&mut self, cx
: &LateContext
<'a
, 'tcx
>, e
: &'tcx hir
::Expr
) {
59 if let hir
::ExprIndex(ref array
, ref index
) = e
.node
{
60 // Array with known size can be checked statically
61 let ty
= cx
.tables
.expr_ty(array
);
62 if let ty
::TyArray(_
, size
) = ty
.sty
{
63 let size
= size
.val
.to_raw_bits().unwrap();
65 // Index is a constant uint
66 if let Some((Constant
::Int(const_index
), _
)) = constant(cx
, index
) {
67 if size
<= const_index
{
68 utils
::span_lint(cx
, OUT_OF_BOUNDS_INDEXING
, e
.span
, "const index is out of bounds");
74 // Index is a constant range
75 if let Some(range
) = higher
::range(index
) {
76 let start
= range
.start
.map(|start
| constant(cx
, start
).map(|(c
, _
)| c
));
77 let end
= range
.end
.map(|end
| constant(cx
, end
).map(|(c
, _
)| c
));
79 if let Some((start
, end
)) = to_const_range(&start
, &end
, range
.limits
, size
) {
80 if start
> size
|| end
> size
{
81 utils
::span_lint(cx
, OUT_OF_BOUNDS_INDEXING
, e
.span
, "range is out of bounds");
88 if let Some(range
) = higher
::range(index
) {
89 // Full ranges are always valid
90 if range
.start
.is_none() && range
.end
.is_none() {
94 // Impossible to know if indexing or slicing is correct
95 utils
::span_lint(cx
, INDEXING_SLICING
, e
.span
, "slicing may panic");
97 utils
::span_lint(cx
, INDEXING_SLICING
, e
.span
, "indexing may panic");
103 /// Returns an option containing a tuple with the start and end (exclusive) of
106 start
: &Option
<Option
<Constant
>>,
107 end
: &Option
<Option
<Constant
>>,
110 ) -> Option
<(u128
, u128
)> {
111 let start
= match *start
{
112 Some(Some(Constant
::Int(x
))) => x
,
113 Some(_
) => return None
,
117 let end
= match *end
{
118 Some(Some(Constant
::Int(x
))) => if limits
== RangeLimits
::Closed
{
123 Some(_
) => return None
,