Skip to content

error out when repr(align) exceeds COFF limit #142638

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0806.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
The value of `N` that was specified for `repr(align(N))` was greater than the
PE-COFF limit (8192 bytes).

Erroneous code example:

```ignore (fails only on PE-COFF targets)
#[repr(align(16384))] // error: alignment must not be greater than 8192 bytes
// for COFF targets
enum Foo {
Bar(u64),
}
```
1 change: 1 addition & 0 deletions compiler/rustc_error_codes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ E0802: 0802,
E0803: 0803,
E0804: 0804,
E0805: 0805,
E0806: 0806,
);
)
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,9 @@ passes_remove_fields =
*[other] fields
}
passes_repr_align_greater_than_coff_max =
alignment must not be greater than 8192 bytes for COFF targets
passes_repr_align_greater_than_target_max =
alignment must not be greater than `isize::MAX` bytes
.note = `isize::MAX` is {$size} for the current target
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,18 @@ use rustc_session::lint::builtin::{
};
use rustc_session::parse::feature_err;
use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, kw, sym};
use rustc_target::spec::BinaryFormat;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
use rustc_trait_selection::traits::ObligationCtxt;
use tracing::debug;

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

// Max alignment supported for PE-COFF binary format.
// See https://learn.microsoft.com/en-us/cpp/cpp/align-cpp?view=msvc-170
const COFF_MAX_ALIGN_BYTES: u64 = 0x2000;

#[derive(LintDiagnostic)]
#[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)]
struct DiagnosticOnUnimplementedOnlyForTraits;
Expand Down Expand Up @@ -2171,6 +2176,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}

fn check_align_value(&self, align: Align, span: Span) {
if self.tcx.sess.target.binary_format == BinaryFormat::Coff {
if align.bytes() > COFF_MAX_ALIGN_BYTES {
self.dcx().emit_err(errors::InvalidReprAlignForCoff { span });
}
}

if align.bytes() > 2_u64.pow(29) {
// for values greater than 2^29, a different error will be emitted, make sure that happens
self.dcx().span_delayed_bug(
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,13 @@ pub(crate) struct InvalidReprAlignForTarget {
pub size: u64,
}

#[derive(Diagnostic)]
#[diag(passes_repr_align_greater_than_coff_max, code = E0806)]
pub(crate) struct InvalidReprAlignForCoff {
#[primary_span]
pub span: Span,
}

#[derive(LintDiagnostic)]
#[diag(passes_repr_conflicting, code = E0566)]
pub(crate) struct ReprConflictingLint;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,75 @@
error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
--> $DIR/repr-align.rs:3:14
--> $DIR/repr-align.rs:8:14
|
LL | #[repr(align(16.0))]
| ^^^^

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

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

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

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

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

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

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

error: aborting due to 8 previous errors
error[E0589]: invalid alignment value: not an unsuffixed integer
--> $DIR/repr-align.rs:46:9
|
LL | #[align(16.0)]
| ^^^^

error[E0589]: invalid alignment value: not a power of two
--> $DIR/repr-align.rs:49:9
|
LL | #[align(15)]
| ^^

error[E0589]: invalid alignment value: larger than 2^29
--> $DIR/repr-align.rs:52:9
|
LL | #[align(4294967296)]
| ^^^^^^^^^^

error[E0589]: invalid alignment value: not a power of two
--> $DIR/repr-align.rs:59:9
|
LL | #[align(0)]
| ^

error: aborting due to 12 previous errors

For more information about this error, try `rustc --explain E0589`.
52 changes: 42 additions & 10 deletions tests/ui/repr/repr-align.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,65 @@
//@ revisions: win notwin
//@[win] only-windows
//@[notwin] ignore-windows

#![feature(fn_align)]
#![allow(dead_code)]

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

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

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

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

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

#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
#[repr(align(16384))] //[win]~ ERROR: alignment must not be greater than 8192 bytes for COFF targets
struct S5(i32);

#[repr(align(16.0))] //[notwin,win]~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer
enum E0 { A, B }

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

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

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

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

#[repr(align(16384))] //[win]~ ERROR: alignment must not be greater than 8192 bytes for COFF targets
enum E5 { A, B }

#[align(16.0)] //[notwin,win]~ ERROR: invalid alignment value: not an unsuffixed integer
fn f0() {}

#[align(15)] //[notwin,win]~ ERROR: invalid alignment value: not a power of two
fn f1() {}

#[align(4294967296)] //[notwin,win]~ ERROR: alignment value: larger than 2^29
fn f2() {}

#[align(536870912)] //[win]~ ERROR: alignment must not be greater than 8192 bytes for COFF targets
// notwin: this is the largest accepted alignment
fn f3() {}

#[align(0)] //[notwin,win]~ ERROR: alignment value: not a power of two
fn f4() {}

#[align(16384)] //[win]~ ERROR: alignment must not be greater than 8192 bytes for COFF targets
fn f5() {}

fn main() {}
112 changes: 112 additions & 0 deletions tests/ui/repr/repr-align.win.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
--> $DIR/repr-align.rs:8:14
|
LL | #[repr(align(16.0))]
| ^^^^

error[E0589]: invalid `repr(align)` attribute: not a power of two
--> $DIR/repr-align.rs:11:14
|
LL | #[repr(align(15))]
| ^^

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

error[E0589]: invalid `repr(align)` attribute: not a power of two
--> $DIR/repr-align.rs:21:14
|
LL | #[repr(align(0))]
| ^

error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
--> $DIR/repr-align.rs:27:14
|
LL | #[repr(align(16.0))]
| ^^^^

error[E0589]: invalid `repr(align)` attribute: not a power of two
--> $DIR/repr-align.rs:30:14
|
LL | #[repr(align(15))]
| ^^

error[E0589]: invalid `repr(align)` attribute: larger than 2^29
--> $DIR/repr-align.rs:33:14
|
LL | #[repr(align(4294967296))]
| ^^^^^^^^^^

error[E0589]: invalid `repr(align)` attribute: not a power of two
--> $DIR/repr-align.rs:40:14
|
LL | #[repr(align(0))]
| ^

error[E0589]: invalid alignment value: not an unsuffixed integer
--> $DIR/repr-align.rs:46:9
|
LL | #[align(16.0)]
| ^^^^

error[E0589]: invalid alignment value: not a power of two
--> $DIR/repr-align.rs:49:9
|
LL | #[align(15)]
| ^^

error[E0589]: invalid alignment value: larger than 2^29
--> $DIR/repr-align.rs:52:9
|
LL | #[align(4294967296)]
| ^^^^^^^^^^

error[E0589]: invalid alignment value: not a power of two
--> $DIR/repr-align.rs:59:9
|
LL | #[align(0)]
| ^

error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
--> $DIR/repr-align.rs:17:8
|
LL | #[repr(align(536870912))]
| ^^^^^^^^^^^^^^^^

error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
--> $DIR/repr-align.rs:24:8
|
LL | #[repr(align(16384))]
| ^^^^^^^^^^^^

error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
--> $DIR/repr-align.rs:36:8
|
LL | #[repr(align(536870912))]
| ^^^^^^^^^^^^^^^^

error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
--> $DIR/repr-align.rs:43:8
|
LL | #[repr(align(16384))]
| ^^^^^^^^^^^^

error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
--> $DIR/repr-align.rs:55:1
|
LL | #[align(536870912)]
| ^^^^^^^^^^^^^^^^^^^

error[E0806]: alignment must not be greater than 8192 bytes for COFF targets
--> $DIR/repr-align.rs:62:1
|
LL | #[align(16384)]
| ^^^^^^^^^^^^^^^

error: aborting due to 18 previous errors

Some errors have detailed explanations: E0589, E0806.
For more information about an error, try `rustc --explain E0589`.
Loading