Skip to content

Commit a8fc845

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 87f9dcd commit a8fc845

File tree

8 files changed

+147
-18
lines changed

8 files changed

+147
-18
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+
```ignore (fails only on PE-COFF targets)
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
@@ -545,6 +545,7 @@ E0802: 0802,
545545
E0803: 0803,
546546
E0804: 0804,
547547
E0805: 0805,
548+
E0806: 0806,
548549
);
549550
)
550551
}

compiler/rustc_passes/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,9 @@ passes_remove_fields =
481481
*[other] fields
482482
}
483483
484+
passes_repr_align_greater_than_coff_max =
485+
alignment must not be greater than 8192 bytes for COFF targets
486+
484487
passes_repr_align_greater_than_target_max =
485488
alignment must not be greater than `isize::MAX` bytes
486489
.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
@@ -44,13 +44,18 @@ use rustc_session::lint::builtin::{
4444
use rustc_session::parse::feature_err;
4545
use rustc_span::edition::Edition;
4646
use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, sym};
47+
use rustc_target::spec::BinaryFormat;
4748
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
4849
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
4950
use rustc_trait_selection::traits::ObligationCtxt;
5051
use tracing::debug;
5152

5253
use crate::{errors, fluent_generated as fluent};
5354

55+
// Max alignment supported for PE-COFF binary format.
56+
// See https://learn.microsoft.com/en-us/cpp/cpp/align-cpp?view=msvc-170
57+
const COFF_MAX_ALIGN_BYTES: u64 = 0x2000;
58+
5459
#[derive(LintDiagnostic)]
5560
#[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)]
5661
struct DiagnosticOnUnimplementedOnlyForTraits;
@@ -1805,6 +1810,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
18051810
}
18061811

18071812
fn check_align(&self, align: Align, span: Span) {
1813+
if self.tcx.sess.target.binary_format == BinaryFormat::Coff {
1814+
if align.bytes() > COFF_MAX_ALIGN_BYTES {
1815+
self.dcx().emit_err(errors::InvalidReprAlignForCoff { span });
1816+
}
1817+
}
1818+
18081819
if align.bytes() > 2_u64.pow(29) {
18091820
// for values greater than 2^29, a different error will be emitted, make sure that happens
18101821
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
@@ -478,6 +478,13 @@ pub(crate) struct InvalidReprAlignForTarget {
478478
pub size: u64,
479479
}
480480

481+
#[derive(Diagnostic)]
482+
#[diag(passes_repr_align_greater_than_coff_max, code = E0806)]
483+
pub(crate) struct InvalidReprAlignForCoff {
484+
#[primary_span]
485+
pub span: Span,
486+
}
487+
481488
#[derive(LintDiagnostic)]
482489
#[diag(passes_repr_conflicting, code = E0566)]
483490
pub(crate) struct ReprConflictingLint;

tests/ui/repr/repr-align.stderr renamed to tests/ui/repr/repr-align.notwin.stderr

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,47 @@
11
error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
2-
--> $DIR/repr-align.rs:3:14
2+
--> $DIR/repr-align.rs:14: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:17: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:20: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:27: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:33: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:36: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:39: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:46:14
4545
|
4646
LL | #[repr(align(0))]
4747
| ^

tests/ui/repr/repr-align.rs

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,52 @@
1+
//@ revisions: win notwin
2+
//@ add-minicore
3+
//@ [win] compile-flags: --target x86_64-pc-windows-msvc
4+
//@ [win] needs-llvm-components: x86
5+
//@ [notwin] compile-flags: --target x86_64-unknown-linux-gnu
6+
//@ [notwin] needs-llvm-components: x86
7+
8+
#![feature(no_core, lang_items)]
9+
#![no_core]
110
#![allow(dead_code)]
11+
extern crate minicore;
12+
use minicore::*;
213

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

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

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

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

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

18-
#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
30+
#[repr(align(16384))] //[win]~ ERROR: alignment must not be greater than 8192 bytes for COFF targets
31+
struct S5(i32);
32+
33+
#[repr(align(16.0))] //[notwin,win]~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
1934
enum E0 { A, B }
2035

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

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

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

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

49+
#[repr(align(16384))] //[win]~ ERROR: alignment must not be greater than 8192 bytes for COFF targets
50+
enum E5 { A, B }
51+
3352
fn main() {}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
2+
--> $DIR/repr-align.rs:14: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:17: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:20: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:27: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:33: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:36: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:39: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:46:14
45+
|
46+
LL | #[repr(align(0))]
47+
| ^
48+
49+
error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
50+
--> $DIR/repr-align.rs:23:8
51+
|
52+
LL | #[repr(align(536870912))]
53+
| ^^^^^^^^^^^^^^^^
54+
55+
error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
56+
--> $DIR/repr-align.rs:30:8
57+
|
58+
LL | #[repr(align(16384))]
59+
| ^^^^^^^^^^^^
60+
61+
error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
62+
--> $DIR/repr-align.rs:42:8
63+
|
64+
LL | #[repr(align(536870912))]
65+
| ^^^^^^^^^^^^^^^^
66+
67+
error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
68+
--> $DIR/repr-align.rs:49:8
69+
|
70+
LL | #[repr(align(16384))]
71+
| ^^^^^^^^^^^^
72+
73+
error: aborting due to 12 previous errors
74+
75+
Some errors have detailed explanations: E0589, E0806.
76+
For more information about an error, try `rustc --explain E0589`.

0 commit comments

Comments
 (0)