Skip to content

Commit 19ec7b9

Browse files
committed
First submit
1 parent 8ebe766 commit 19ec7b9

File tree

11 files changed

+274
-1
lines changed

11 files changed

+274
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3581,6 +3581,7 @@ Released 2018-09-13
35813581
[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
35823582
[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
35833583
[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
3584+
[`static_items_large_align`]: https://rust-lang.github.io/rust-clippy/master/index.html#static_items_large_align
35843585
[`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string
35853586
[`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add
35863587
[`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign

clippy_lints/src/lib.register_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ store.register_lints(&[
460460
size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
461461
slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
462462
stable_sort_primitive::STABLE_SORT_PRIMITIVE,
463+
static_items_large_align::STATIC_ITEMS_LARGE_ALIGN,
463464
strings::STRING_ADD,
464465
strings::STRING_ADD_ASSIGN,
465466
strings::STRING_FROM_UTF8_AS_BYTES,

clippy_lints/src/lib.register_pedantic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
8282
LintId::of(ref_option_ref::REF_OPTION_REF),
8383
LintId::of(return_self_not_must_use::RETURN_SELF_NOT_MUST_USE),
8484
LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
85+
LintId::of(static_items_large_align::STATIC_ITEMS_LARGE_ALIGN),
8586
LintId::of(strings::STRING_ADD_ASSIGN),
8687
LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
8788
LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),

clippy_lints/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ mod single_component_path_imports;
360360
mod size_of_in_element_count;
361361
mod slow_vector_initialization;
362362
mod stable_sort_primitive;
363+
mod static_items_large_align;
363364
mod strings;
364365
mod strlen_on_c_strings;
365366
mod suspicious_operation_groupings;
@@ -867,6 +868,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
867868
ignore_publish: cargo_ignore_publish,
868869
})
869870
});
871+
let page_size = conf.page_size;
872+
store.register_late_pass(move || Box::new(static_items_large_align::StaticItemsLargeAlign { page_size }));
870873
// add lints here, do not remove this comment, it's used in `new_lint`
871874
}
872875

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
@@ -310,6 +310,11 @@ define_Conf! {
310310
/// the slice pattern that is suggested. If more elements would be necessary, the lint is suppressed.
311311
/// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
312312
(max_suggested_slice_pattern_length: u64 = 3),
313+
/// Lint: STATIC_ITEMS_LARGE_ALIGN.
314+
///
315+
/// The page size of the target platform. It is useful when we know the exact page size and know that
316+
/// it could be fulfilled (e.g., when we are targeting embedded platforms).
317+
(page_size: u64 = 4096),
313318
}
314319

315320
/// 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+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `avoid-breaking-exported-api`, `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `disallowed-types`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `standard-macro-braces`, `enforced-import-renames`, `allowed-scripts`, `enable-raw-pointer-heuristic-for-send`, `max-suggested-slice-pattern-length`, `third-party` at line 5 column 1
1+
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `avoid-breaking-exported-api`, `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `disallowed-types`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `standard-macro-braces`, `enforced-import-renames`, `allowed-scripts`, `enable-raw-pointer-heuristic-for-send`, `max-suggested-slice-pattern-length`, `page-size`, `third-party` at line 5 column 1
22

33
error: aborting due to previous error
44

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)