Skip to content

Commit 7aca56f

Browse files
committed
Error out when repr(align) exceeds COFF limit
The PE-COFF binary format limits section alignment to 8192 bytes. Emit error when alignment exceeds this limit to avoid crash in llvm.
1 parent df4ad9e commit 7aca56f

File tree

8 files changed

+221
-19
lines changed

8 files changed

+221
-19
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
The value of `N` that was specified for `repr(align(N))` was greater than the
2+
PE-COFF limit (8192 bytes).
3+
4+
Erroneous code example:
5+
6+
```compile_fail,E0806
7+
#[repr(align(16384))] // error: alignment must not be greater than 8192 bytes
8+
// for COFF targets
9+
enum Foo {
10+
Bar(u64),
11+
}
12+
```

compiler/rustc_error_codes/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,7 @@ E0802: 0802,
548548
E0803: 0803,
549549
E0804: 0804,
550550
E0805: 0805,
551+
E0806: 0806,
551552
);
552553
)
553554
}

compiler/rustc_passes/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,9 @@ passes_remove_fields =
583583
*[other] fields
584584
}
585585
586+
passes_repr_align_greater_than_coff_max =
587+
alignment must not be greater than 8192 bytes for COFF targets
588+
586589
passes_repr_align_greater_than_target_max =
587590
alignment must not be greater than `isize::MAX` bytes
588591
.note = `isize::MAX` is {$size} for the current target

compiler/rustc_passes/src/check_attr.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,18 @@ use rustc_session::lint::builtin::{
3636
};
3737
use rustc_session::parse::feature_err;
3838
use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, kw, sym};
39+
use rustc_target::spec::BinaryFormat;
3940
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
4041
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
4142
use rustc_trait_selection::traits::ObligationCtxt;
4243
use tracing::debug;
4344

4445
use crate::{errors, fluent_generated as fluent};
4546

47+
// Max alignment supported for PE-COFF binary format.
48+
// See https://learn.microsoft.com/en-us/cpp/cpp/align-cpp?view=msvc-170
49+
const COFF_MAX_ALIGN_BYTES: u64 = 0x2000;
50+
4651
#[derive(LintDiagnostic)]
4752
#[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)]
4853
struct DiagnosticOnUnimplementedOnlyForTraits;
@@ -2171,6 +2176,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
21712176
}
21722177

21732178
fn check_align_value(&self, align: Align, span: Span) {
2179+
if self.tcx.sess.target.binary_format == BinaryFormat::Coff {
2180+
if align.bytes() > COFF_MAX_ALIGN_BYTES {
2181+
self.dcx().emit_err(errors::InvalidReprAlignForCoff { span });
2182+
}
2183+
}
2184+
21742185
if align.bytes() > 2_u64.pow(29) {
21752186
// for values greater than 2^29, a different error will be emitted, make sure that happens
21762187
self.dcx().span_delayed_bug(

compiler/rustc_passes/src/errors.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,13 @@ pub(crate) struct InvalidReprAlignForTarget {
597597
pub size: u64,
598598
}
599599

600+
#[derive(Diagnostic)]
601+
#[diag(passes_repr_align_greater_than_coff_max, code = E0806)]
602+
pub(crate) struct InvalidReprAlignForCoff {
603+
#[primary_span]
604+
pub span: Span,
605+
}
606+
600607
#[derive(LintDiagnostic)]
601608
#[diag(passes_repr_conflicting, code = E0566)]
602609
pub(crate) struct ReprConflictingLint;
Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,75 @@
11
error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
2-
--> $DIR/repr-align.rs:3:14
2+
--> $DIR/repr-align.rs:8:14
33
|
44
LL | #[repr(align(16.0))]
55
| ^^^^
66

77
error[E0589]: invalid `repr(align)` attribute: not a power of two
8-
--> $DIR/repr-align.rs:6:14
8+
--> $DIR/repr-align.rs:11:14
99
|
1010
LL | #[repr(align(15))]
1111
| ^^
1212

1313
error[E0589]: invalid `repr(align)` attribute: larger than 2^29
14-
--> $DIR/repr-align.rs:9:14
14+
--> $DIR/repr-align.rs:14:14
1515
|
1616
LL | #[repr(align(4294967296))]
1717
| ^^^^^^^^^^
1818

1919
error[E0589]: invalid `repr(align)` attribute: not a power of two
20-
--> $DIR/repr-align.rs:15:14
20+
--> $DIR/repr-align.rs:21:14
2121
|
2222
LL | #[repr(align(0))]
2323
| ^
2424

2525
error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
26-
--> $DIR/repr-align.rs:18:14
26+
--> $DIR/repr-align.rs:27:14
2727
|
2828
LL | #[repr(align(16.0))]
2929
| ^^^^
3030

3131
error[E0589]: invalid `repr(align)` attribute: not a power of two
32-
--> $DIR/repr-align.rs:21:14
32+
--> $DIR/repr-align.rs:30:14
3333
|
3434
LL | #[repr(align(15))]
3535
| ^^
3636

3737
error[E0589]: invalid `repr(align)` attribute: larger than 2^29
38-
--> $DIR/repr-align.rs:24:14
38+
--> $DIR/repr-align.rs:33:14
3939
|
4040
LL | #[repr(align(4294967296))]
4141
| ^^^^^^^^^^
4242

4343
error[E0589]: invalid `repr(align)` attribute: not a power of two
44-
--> $DIR/repr-align.rs:30:14
44+
--> $DIR/repr-align.rs:40:14
4545
|
4646
LL | #[repr(align(0))]
4747
| ^
4848

49-
error: aborting due to 8 previous errors
49+
error[E0589]: invalid alignment value: not an unsuffixed integer
50+
--> $DIR/repr-align.rs:46:9
51+
|
52+
LL | #[align(16.0)]
53+
| ^^^^
54+
55+
error[E0589]: invalid alignment value: not a power of two
56+
--> $DIR/repr-align.rs:49:9
57+
|
58+
LL | #[align(15)]
59+
| ^^
60+
61+
error[E0589]: invalid alignment value: larger than 2^29
62+
--> $DIR/repr-align.rs:52:9
63+
|
64+
LL | #[align(4294967296)]
65+
| ^^^^^^^^^^
66+
67+
error[E0589]: invalid alignment value: not a power of two
68+
--> $DIR/repr-align.rs:59:9
69+
|
70+
LL | #[align(0)]
71+
| ^
72+
73+
error: aborting due to 12 previous errors
5074

5175
For more information about this error, try `rustc --explain E0589`.

tests/ui/repr/repr-align.rs

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,65 @@
1+
//@ revisions: win notwin
2+
//@[win] only-windows
3+
//@[notwin] ignore-windows
4+
5+
#![feature(fn_align)]
16
#![allow(dead_code)]
27

3-
#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
8+
#[repr(align(16.0))] //[notwin,win]~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
49
struct S0(i32);
510

6-
#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
11+
#[repr(align(15))] //[notwin,win]~ ERROR: invalid `repr(align)` attribute: not a power of two
712
struct S1(i32);
813

9-
#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29
14+
#[repr(align(4294967296))] //[notwin,win]~ ERROR: invalid `repr(align)` attribute: larger than 2^29
1015
struct S2(i32);
1116

12-
#[repr(align(536870912))] // ok: this is the largest accepted alignment
17+
#[repr(align(536870912))] //[win]~ ERROR: alignment must not be greater than 8192 bytes for COFF targets
18+
// notwin: this is the largest accepted alignment
1319
struct S3(i32);
1420

15-
#[repr(align(0))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
21+
#[repr(align(0))] //[notwin,win]~ ERROR: invalid `repr(align)` attribute: not a power of two
1622
struct S4(i32);
1723

18-
#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
24+
#[repr(align(16384))] //[win]~ ERROR: alignment must not be greater than 8192 bytes for COFF targets
25+
struct S5(i32);
26+
27+
#[repr(align(16.0))] //[notwin,win]~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
1928
enum E0 { A, B }
2029

21-
#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
30+
#[repr(align(15))] //[notwin,win]~ ERROR: invalid `repr(align)` attribute: not a power of two
2231
enum E1 { A, B }
2332

24-
#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29
33+
#[repr(align(4294967296))] //[notwin,win]~ ERROR: invalid `repr(align)` attribute: larger than 2^29
2534
enum E2 { A, B }
2635

27-
#[repr(align(536870912))] // ok: this is the largest accepted alignment
36+
#[repr(align(536870912))] //[win]~ ERROR: alignment must not be greater than 8192 bytes for COFF targets
37+
// notwin: this is the largest accepted alignment
2838
enum E3 { A, B }
2939

30-
#[repr(align(0))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
40+
#[repr(align(0))] //[notwin,win]~ ERROR: invalid `repr(align)` attribute: not a power of two
3141
enum E4 { A, B }
3242

43+
#[repr(align(16384))] //[win]~ ERROR: alignment must not be greater than 8192 bytes for COFF targets
44+
enum E5 { A, B }
45+
46+
#[align(16.0)] //[notwin,win]~ ERROR: invalid alignment value: not an unsuffixed integer
47+
fn f0() {}
48+
49+
#[align(15)] //[notwin,win]~ ERROR: invalid alignment value: not a power of two
50+
fn f1() {}
51+
52+
#[align(4294967296)] //[notwin,win]~ ERROR: alignment value: larger than 2^29
53+
fn f2() {}
54+
55+
#[align(536870912)] //[win]~ ERROR: alignment must not be greater than 8192 bytes for COFF targets
56+
// notwin: this is the largest accepted alignment
57+
fn f3() {}
58+
59+
#[align(0)] //[notwin,win]~ ERROR: alignment value: not a power of two
60+
fn f4() {}
61+
62+
#[align(16384)] //[win]~ ERROR: alignment must not be greater than 8192 bytes for COFF targets
63+
fn f5() {}
64+
3365
fn main() {}

tests/ui/repr/repr-align.win.stderr

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
2+
--> $DIR/repr-align.rs:8:14
3+
|
4+
LL | #[repr(align(16.0))]
5+
| ^^^^
6+
7+
error[E0589]: invalid `repr(align)` attribute: not a power of two
8+
--> $DIR/repr-align.rs:11:14
9+
|
10+
LL | #[repr(align(15))]
11+
| ^^
12+
13+
error[E0589]: invalid `repr(align)` attribute: larger than 2^29
14+
--> $DIR/repr-align.rs:14:14
15+
|
16+
LL | #[repr(align(4294967296))]
17+
| ^^^^^^^^^^
18+
19+
error[E0589]: invalid `repr(align)` attribute: not a power of two
20+
--> $DIR/repr-align.rs:21:14
21+
|
22+
LL | #[repr(align(0))]
23+
| ^
24+
25+
error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
26+
--> $DIR/repr-align.rs:27:14
27+
|
28+
LL | #[repr(align(16.0))]
29+
| ^^^^
30+
31+
error[E0589]: invalid `repr(align)` attribute: not a power of two
32+
--> $DIR/repr-align.rs:30:14
33+
|
34+
LL | #[repr(align(15))]
35+
| ^^
36+
37+
error[E0589]: invalid `repr(align)` attribute: larger than 2^29
38+
--> $DIR/repr-align.rs:33:14
39+
|
40+
LL | #[repr(align(4294967296))]
41+
| ^^^^^^^^^^
42+
43+
error[E0589]: invalid `repr(align)` attribute: not a power of two
44+
--> $DIR/repr-align.rs:40:14
45+
|
46+
LL | #[repr(align(0))]
47+
| ^
48+
49+
error[E0589]: invalid alignment value: not an unsuffixed integer
50+
--> $DIR/repr-align.rs:46:9
51+
|
52+
LL | #[align(16.0)]
53+
| ^^^^
54+
55+
error[E0589]: invalid alignment value: not a power of two
56+
--> $DIR/repr-align.rs:49:9
57+
|
58+
LL | #[align(15)]
59+
| ^^
60+
61+
error[E0589]: invalid alignment value: larger than 2^29
62+
--> $DIR/repr-align.rs:52:9
63+
|
64+
LL | #[align(4294967296)]
65+
| ^^^^^^^^^^
66+
67+
error[E0589]: invalid alignment value: not a power of two
68+
--> $DIR/repr-align.rs:59:9
69+
|
70+
LL | #[align(0)]
71+
| ^
72+
73+
error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
74+
--> $DIR/repr-align.rs:17:8
75+
|
76+
LL | #[repr(align(536870912))]
77+
| ^^^^^^^^^^^^^^^^
78+
79+
error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
80+
--> $DIR/repr-align.rs:24:8
81+
|
82+
LL | #[repr(align(16384))]
83+
| ^^^^^^^^^^^^
84+
85+
error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
86+
--> $DIR/repr-align.rs:36:8
87+
|
88+
LL | #[repr(align(536870912))]
89+
| ^^^^^^^^^^^^^^^^
90+
91+
error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
92+
--> $DIR/repr-align.rs:43:8
93+
|
94+
LL | #[repr(align(16384))]
95+
| ^^^^^^^^^^^^
96+
97+
error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
98+
--> $DIR/repr-align.rs:55:1
99+
|
100+
LL | #[align(536870912)]
101+
| ^^^^^^^^^^^^^^^^^^^
102+
103+
error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
104+
--> $DIR/repr-align.rs:62:1
105+
|
106+
LL | #[align(16384)]
107+
| ^^^^^^^^^^^^^^^
108+
109+
error: aborting due to 18 previous errors
110+
111+
Some errors have detailed explanations: E0589, E0806.
112+
For more information about an error, try `rustc --explain E0589`.

0 commit comments

Comments
 (0)