Skip to content

Commit 0f69824

Browse files
committed
First submit
1 parent 617417e commit 0f69824

File tree

10 files changed

+273
-0
lines changed

10 files changed

+273
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4064,6 +4064,7 @@ Released 2018-09-13
40644064
[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
40654065
[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
40664066
[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
4067+
[`static_items_large_align`]: https://rust-lang.github.io/rust-clippy/master/index.html#static_items_large_align
40674068
[`std_instead_of_alloc`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_alloc
40684069
[`std_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_core
40694070
[`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string

clippy_lints/src/lib.register_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ store.register_lints(&[
515515
single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS,
516516
size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
517517
slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
518+
static_items_large_align::STATIC_ITEMS_LARGE_ALIGN,
518519
std_instead_of_core::ALLOC_INSTEAD_OF_CORE,
519520
std_instead_of_core::STD_INSTEAD_OF_ALLOC,
520521
std_instead_of_core::STD_INSTEAD_OF_CORE,

clippy_lints/src/lib.register_pedantic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
8787
LintId::of(ref_option_ref::REF_OPTION_REF),
8888
LintId::of(return_self_not_must_use::RETURN_SELF_NOT_MUST_USE),
8989
LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
90+
LintId::of(static_items_large_align::STATIC_ITEMS_LARGE_ALIGN),
9091
LintId::of(strings::STRING_ADD_ASSIGN),
9192
LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
9293
LintId::of(types::LINKEDLIST),

clippy_lints/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ mod single_char_lifetime_names;
356356
mod single_component_path_imports;
357357
mod size_of_in_element_count;
358358
mod slow_vector_initialization;
359+
mod static_items_large_align;
359360
mod std_instead_of_core;
360361
mod strings;
361362
mod strlen_on_c_strings;
@@ -902,6 +903,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
902903
store.register_late_pass(|| Box::new(unused_peekable::UnusedPeekable));
903904
store.register_early_pass(|| Box::new(multi_assignments::MultiAssignments));
904905
store.register_late_pass(|| Box::new(bool_to_int_with_if::BoolToIntWithIf));
906+
let page_size = conf.page_size;
907+
store.register_late_pass(move || Box::new(static_items_large_align::StaticItemsLargeAlign { page_size }));
905908
// add lints here, do not remove this comment, it's used in `new_lint`
906909
}
907910

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use clippy_utils::diagnostics::span_lint_and_note;
2+
use rustc_hir::{Item, ItemKind};
3+
use rustc_lint::{LateContext, LateLintPass};
4+
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
5+
use rustc_session::{declare_tool_lint, impl_lint_pass};
6+
use rustc_target::abi::Align;
7+
use rustc_typeck::hir_ty_to_ty;
8+
9+
pub struct StaticItemsLargeAlign {
10+
pub page_size: u64,
11+
}
12+
13+
declare_clippy_lint! {
14+
/// ### What it does
15+
/// Check for usage of static items which have type alignment larger than page size.
16+
///
17+
/// ### Why is this bad?
18+
/// Due to some known unsound issues, the type alignment may not be fulfilled.
19+
/// For more information, see:
20+
/// <https://github.com/rust-lang/rust/issues/70022> and
21+
/// <https://github.com/rust-lang/rust/issues/70143>.
22+
///
23+
/// ### Example
24+
/// ```rust
25+
/// #[repr(align(0x100000))]
26+
/// struct Aligned(u8);
27+
///
28+
/// static X: Aligned = Aligned(0); // Bad
29+
///
30+
/// fn main() {
31+
/// let x = Aligned(0); // Good
32+
/// println!("{:#x}", &x as *const _ as usize);
33+
/// println!("{:#x}", &X as *const _ as usize);
34+
/// let b = Box::new(Aligned(0)); // Good
35+
/// println!("{:#x}", Box::into_raw(b) as usize);
36+
/// }
37+
#[clippy::version = "1.61.0"]
38+
pub STATIC_ITEMS_LARGE_ALIGN,
39+
pedantic,
40+
"static items with large type alignment, which may trigger unsound problems"
41+
}
42+
impl_lint_pass!(StaticItemsLargeAlign => [STATIC_ITEMS_LARGE_ALIGN]);
43+
44+
impl LateLintPass<'_> for StaticItemsLargeAlign {
45+
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
46+
if_chain! {
47+
if let ItemKind::Static(hir_ty, _, _) = item.kind;
48+
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
49+
if let Some(adt_ref) = self.check_ty_alignment(cx.tcx, ty);
50+
let def_span = cx.tcx.def_span(adt_ref.did());
51+
then {
52+
span_lint_and_note(
53+
cx,
54+
STATIC_ITEMS_LARGE_ALIGN,
55+
item.span,
56+
"this static item (itself or its subfield) has large type alignment, which may not be fulfilled,\n\
57+
for more information, see <https://github.com/rust-lang/rust/issues/70022>",
58+
Some(def_span),
59+
format!("this type has an alignment larger than page size ({}KB)", self.page_size/1024).as_str()
60+
);
61+
}
62+
}
63+
}
64+
}
65+
66+
impl StaticItemsLargeAlign {
67+
/// It checks a type with the following steps:
68+
/// 1. picks out this type if its kind is among adt, array, tuple or ref to them;
69+
/// otherwise return None
70+
/// 2. check if its (or its inner fields') alignment are larger than page size
71+
/// 3. return one of them;
72+
/// otherwise return None
73+
fn check_ty_alignment<'tcx>(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<AdtDef<'tcx>> {
74+
match ty.kind() {
75+
ty::Adt(adt_ref, subst_ref) => {
76+
if let Some(align) = adt_ref.repr().align &&
77+
align > Align::from_bytes(self.page_size).unwrap()
78+
{
79+
Some(*adt_ref)
80+
} else {
81+
adt_ref.all_fields()
82+
.map(|field_ref| field_ref.ty(tcx, subst_ref))
83+
.find_map(|ty| self.check_ty_alignment(tcx, ty))
84+
}
85+
},
86+
ty::Array(ty, _) => self.check_ty_alignment(tcx, *ty),
87+
ty::Tuple(ty_list) => ty_list.iter()
88+
.find_map(|ty| self.check_ty_alignment(tcx, ty)),
89+
ty::Ref(region, ty, _) if region.is_static() => self.check_ty_alignment(tcx, *ty),
90+
_ => None,
91+
}
92+
}
93+
}

clippy_lints/src/utils/conf.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,11 @@ define_Conf! {
383383
///
384384
/// The maximum size of the `Err`-variant in a `Result` returned from a function
385385
(large_error_threshold: u64 = 128),
386+
/// Lint: STATIC_ITEMS_LARGE_ALIGN.
387+
///
388+
/// The page size of the target platform. It is useful when we know the exact page size and know that
389+
/// it could be fulfilled (e.g., when we are targeting embedded platforms).
390+
(page_size: u64 = 4096),
386391
}
387392

388393
/// Search for the configuration file.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
page-size = 0x100000
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// The example is adapted from https://github.com/rust-lang/rust/issues/70022
2+
3+
#![warn(clippy::static_items_large_align)]
4+
5+
#[repr(align(0x100000))]
6+
#[derive(Clone, Copy)]
7+
struct Aligned(u8);
8+
9+
struct AlignedWrapper {
10+
f: u8,
11+
g: Aligned,
12+
}
13+
14+
enum AlignedEnum {
15+
A(Aligned),
16+
}
17+
18+
struct AlignedGeneric<T>(T);
19+
20+
static X: Aligned = Aligned(0);
21+
22+
static X_REF: &Aligned = &Aligned(0);
23+
24+
static ARRAY: [Aligned; 10] = [Aligned(0); 10];
25+
26+
static TUPLE: (u8, Aligned) = (0, Aligned(0));
27+
28+
static XW: AlignedWrapper = AlignedWrapper { f: 0, g: Aligned(0) };
29+
30+
static XE: AlignedEnum = AlignedEnum::A(Aligned(0));
31+
32+
static XG: AlignedGeneric<Aligned> = AlignedGeneric(Aligned(0));
33+
34+
fn main() {
35+
let x = Aligned(0);
36+
println!("{:#x}", Box::into_raw(Box::new(Aligned(0))) as usize);
37+
}

tests/ui/static_items_large_align.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// The example is adapted from https://github.com/rust-lang/rust/issues/70022
2+
3+
#![warn(clippy::static_items_large_align)]
4+
5+
#[repr(align(0x100000))]
6+
#[derive(Clone, Copy)]
7+
struct Aligned(u8);
8+
9+
struct AlignedWrapper {
10+
f: u8,
11+
g: Aligned,
12+
}
13+
14+
enum AlignedEnum {
15+
A(Aligned),
16+
}
17+
18+
struct AlignedGeneric<T>(T);
19+
20+
static X: Aligned = Aligned(0);
21+
22+
static X_REF: &Aligned = &Aligned(0);
23+
24+
static ARRAY: [Aligned; 10] = [Aligned(0); 10];
25+
26+
static TUPLE: (u8, Aligned) = (0, Aligned(0));
27+
28+
static XW: AlignedWrapper = AlignedWrapper { f: 0, g: Aligned(0) };
29+
30+
static XE: AlignedEnum = AlignedEnum::A(Aligned(0));
31+
32+
static XG: AlignedGeneric<Aligned> = AlignedGeneric(Aligned(0));
33+
34+
fn main() {
35+
let x = Aligned(0);
36+
println!("{:#x}", Box::into_raw(Box::new(Aligned(0))) as usize);
37+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
error: this static item (itself or its subfield) has large type alignment, which may not be fulfilled,
2+
for more information, see <https://github.com/rust-lang/rust/issues/70022>
3+
--> $DIR/static_items_large_align.rs:20:1
4+
|
5+
LL | static X: Aligned = Aligned(0);
6+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7+
|
8+
= note: `-D clippy::static-items-large-align` implied by `-D warnings`
9+
note: this type has an alignment larger than page size (4KB)
10+
--> $DIR/static_items_large_align.rs:7:1
11+
|
12+
LL | struct Aligned(u8);
13+
| ^^^^^^^^^^^^^^^^^^^
14+
15+
error: this static item (itself or its subfield) has large type alignment, which may not be fulfilled,
16+
for more information, see <https://github.com/rust-lang/rust/issues/70022>
17+
--> $DIR/static_items_large_align.rs:22:1
18+
|
19+
LL | static X_REF: &Aligned = &Aligned(0);
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21+
|
22+
note: this type has an alignment larger than page size (4KB)
23+
--> $DIR/static_items_large_align.rs:7:1
24+
|
25+
LL | struct Aligned(u8);
26+
| ^^^^^^^^^^^^^^^^^^^
27+
28+
error: this static item (itself or its subfield) has large type alignment, which may not be fulfilled,
29+
for more information, see <https://github.com/rust-lang/rust/issues/70022>
30+
--> $DIR/static_items_large_align.rs:24:1
31+
|
32+
LL | static ARRAY: [Aligned; 10] = [Aligned(0); 10];
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34+
|
35+
note: this type has an alignment larger than page size (4KB)
36+
--> $DIR/static_items_large_align.rs:7:1
37+
|
38+
LL | struct Aligned(u8);
39+
| ^^^^^^^^^^^^^^^^^^^
40+
41+
error: this static item (itself or its subfield) has large type alignment, which may not be fulfilled,
42+
for more information, see <https://github.com/rust-lang/rust/issues/70022>
43+
--> $DIR/static_items_large_align.rs:26:1
44+
|
45+
LL | static TUPLE: (u8, Aligned) = (0, Aligned(0));
46+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47+
|
48+
note: this type has an alignment larger than page size (4KB)
49+
--> $DIR/static_items_large_align.rs:7:1
50+
|
51+
LL | struct Aligned(u8);
52+
| ^^^^^^^^^^^^^^^^^^^
53+
54+
error: this static item (itself or its subfield) has large type alignment, which may not be fulfilled,
55+
for more information, see <https://github.com/rust-lang/rust/issues/70022>
56+
--> $DIR/static_items_large_align.rs:28:1
57+
|
58+
LL | static XW: AlignedWrapper = AlignedWrapper { f: 0, g: Aligned(0) };
59+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
60+
|
61+
note: this type has an alignment larger than page size (4KB)
62+
--> $DIR/static_items_large_align.rs:7:1
63+
|
64+
LL | struct Aligned(u8);
65+
| ^^^^^^^^^^^^^^^^^^^
66+
67+
error: this static item (itself or its subfield) has large type alignment, which may not be fulfilled,
68+
for more information, see <https://github.com/rust-lang/rust/issues/70022>
69+
--> $DIR/static_items_large_align.rs:30:1
70+
|
71+
LL | static XE: AlignedEnum = AlignedEnum::A(Aligned(0));
72+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
73+
|
74+
note: this type has an alignment larger than page size (4KB)
75+
--> $DIR/static_items_large_align.rs:7:1
76+
|
77+
LL | struct Aligned(u8);
78+
| ^^^^^^^^^^^^^^^^^^^
79+
80+
error: this static item (itself or its subfield) has large type alignment, which may not be fulfilled,
81+
for more information, see <https://github.com/rust-lang/rust/issues/70022>
82+
--> $DIR/static_items_large_align.rs:32:1
83+
|
84+
LL | static XG: AlignedGeneric<Aligned> = AlignedGeneric(Aligned(0));
85+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
86+
|
87+
note: this type has an alignment larger than page size (4KB)
88+
--> $DIR/static_items_large_align.rs:7:1
89+
|
90+
LL | struct Aligned(u8);
91+
| ^^^^^^^^^^^^^^^^^^^
92+
93+
error: aborting due to 7 previous errors
94+

0 commit comments

Comments
 (0)