Skip to content
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

Dumb bugs are dumb, but still bugs: Huge types generate illegal instructions #55878

Closed
Noxime opened this issue Nov 11, 2018 · 8 comments · Fixed by #63152
Closed

Dumb bugs are dumb, but still bugs: Huge types generate illegal instructions #55878

Noxime opened this issue Nov 11, 2018 · 8 comments · Fixed by #63152
Labels
A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) C-bug Category: This is a bug.

Comments

@Noxime
Copy link

Noxime commented Nov 11, 2018

Having huge data structures (larger than u64::MAX) results in incorrect binaries being built.

I tried this code:

fn main() {
    println!("Size: {}", std::mem::size_of::<[u8; std::u64::MAX as usize]>());
}

I expected this to happen: Output of Size: 18446744073709551616, or a compiler error telling me the structure is too big
Instead, this happened: Binary compiled successfully, but running it results in Illegal instruction (core dumped)

Meta

rustc --version --verbose

rustc 1.32.0-nightly (6e9b84296 2018-11-10)
binary: rustc
commit-hash: 6e9b84296223126a0a59bde63a0f97011bb7b0f5
commit-date: 2018-11-10
host: x86_64-unknown-linux-gnu
release: 1.32.0-nightly
LLVM version: 8.0
@hanna-kruppe
Copy link
Contributor

hanna-kruppe commented Nov 11, 2018

This:

fn main() {
    std::mem::size_of::<[u8; std::u64::MAX as usize]>();
}

gives a graceful error:

the type `[u8; 18446744073709551615]` is too big for the current architecture

Taking a reference, however, reproduces the illegal instruction:

fn main() {
    &std::mem::size_of::<[u8; std::u64::MAX as usize]>();
}

The LLVM IR for the latter function, by the way, is just a call to llvm.trap. So I guess it's because of promotion to static: the size_of call fails in const eval and this causes the llvm.trap call to be emitted. cc @oli-obk @RalfJung

@bluss bluss added C-bug Category: This is a bug. A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) labels Nov 11, 2018
@RalfJung
Copy link
Member

Backtrace for the miri error:

backtrace frames: 72
0: backtrace::backtrace::libunwind::trace::h4333246b1309ea02
	at /home/r/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/backtrace/libunwind.rs:53
0: backtrace::backtrace::trace::h04e30d93063b4479
	at /home/r/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/backtrace/mod.rs:42
1: backtrace::capture::Backtrace::new_unresolved::haf9a7c94d7c84f11
	at /home/r/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/capture.rs:88
2: <rustc::mir::interpret::error::EvalError<'tcx> as core::convert::From<rustc::mir::interpret::error::EvalErrorKind<'tcx, u64>>>::from::hcea04b849bfd8ad1
	at librustc/mir/interpret/error.rs:206
3: <T as core::convert::Into<U>>::into::h6971e8e95ad92abe
	at /home/r/src/rust/rustc.3/src/libcore/convert.rs:456
3: <rustc_mir::interpret::eval_context::EvalContext<'a, 'mir, 'tcx, M> as rustc_target::abi::LayoutOf>::layout_of::{{closure}}::h79fb29344e377e52
	at librustc_mir/interpret/eval_context.rs:169
3: <core::result::Result<T, E>>::map_err::hd0b511dcc0d127aa
	at /home/r/src/rust/rustc.3/src/libcore/result.rs:530
3: <rustc_mir::interpret::eval_context::EvalContext<'a, 'mir, 'tcx, M> as rustc_target::abi::LayoutOf>::layout_of::h977bf27fbf74f806
	at librustc_mir/interpret/eval_context.rs:168
3: rustc_mir::interpret::intrinsics::<impl rustc_mir::interpret::eval_context::EvalContext<'a, 'mir, 'tcx, M>>::emulate_intrinsic::hfb24b0825733ab16
	at librustc_mir/interpret/intrinsics.rs:77
4: <rustc_mir::const_eval::CompileTimeInterpreter<'a, 'mir, 'tcx> as rustc_mir::interpret::machine::Machine<'a, 'mir, 'tcx>>::call_intrinsic::h2e2017486d607b75
	at librustc_mir/const_eval.rs:406
5: rustc_mir::interpret::terminator::<impl rustc_mir::interpret::eval_context::EvalContext<'a, 'mir, 'tcx, M>>::eval_fn_call::h4cc4f67756e1846c
	at librustc_mir/interpret/terminator.rs:252
6: rustc_mir::interpret::terminator::<impl rustc_mir::interpret::eval_context::EvalContext<'a, 'mir, 'tcx, M>>::eval_terminator::hde1131b053413afa
	at librustc_mir/interpret/terminator.rs:105
7: rustc_mir::interpret::step::<impl rustc_mir::interpret::eval_context::EvalContext<'a, 'mir, 'tcx, M>>::terminator::h313c5d2bd41bf6cb
	at librustc_mir/interpret/step.rs:307
7: rustc_mir::interpret::step::<impl rustc_mir::interpret::eval_context::EvalContext<'a, 'mir, 'tcx, M>>::step::hed0450c3d705762a
	at librustc_mir/interpret/step.rs:79
7: rustc_mir::interpret::step::<impl rustc_mir::interpret::eval_context::EvalContext<'a, 'mir, 'tcx, M>>::run::hb00fb5f6b0079b0e
	at librustc_mir/interpret/step.rs:50
8: rustc_mir::const_eval::eval_body_using_ecx::he486bdd5ad00e3d1
	at librustc_mir/const_eval.rs:204
9: rustc_mir::const_eval::eval_body_and_ecx::h295b12b32be5cca7
	at librustc_mir/const_eval.rs:167
9: rustc_mir::const_eval::const_eval_raw_provider::h3e776eaa15edbc8f
	at librustc_mir/const_eval.rs:658
10: rustc::ty::query::<impl rustc::ty::query::config::QueryAccessors<'tcx> for rustc::ty::query::queries::const_eval_raw<'tcx>>::compute::{{closure}}::ha5592ff73bea82f6
	at librustc/ty/query/plumbing.rs:834
10: rustc::ty::query::__query_compute::const_eval_raw::h2542e1d85c704c97
	at librustc/ty/query/plumbing.rs:796
11: rustc::ty::query::<impl rustc::ty::query::config::QueryAccessors<'tcx> for rustc::ty::query::queries::const_eval_raw<'tcx>>::compute::h3b525a50b8883ade
	at librustc/ty/query/plumbing.rs:826

Looks like layout_of fails and we do not handle that very gracefully?

@oli-obk
Copy link
Contributor

oli-obk commented Nov 12, 2018

The problem is the reporting in

err.report_as_lint(
which makes
EvalErrorKind::Layout(LayoutError::Unknown(_)) |
EvalErrorKind::TooGeneric => return Err(ErrorHandled::TooGeneric),
EvalErrorKind::Layout(LayoutError::SizeOverflow(_)) |
EvalErrorKind::TypeckError => return Err(ErrorHandled::Reported),
assume that the error has already been reported.

We should keep reporting these as a hard error if we are in a RevealAll param env. At least that's how statics are doing it: https://github.com/rust-lang/rust/blob/master/src/librustc_mir/const_eval.rs#L661 You can probably ICE the compiler by putting such structures in static initializers.

@Centril Centril added the I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness label Nov 30, 2018
@estebank
Copy link
Contributor

@oli-obk would it make sense to use delay_span_bug here to avoid the miscompilation?

@oli-obk
Copy link
Contributor

oli-obk commented Jul 30, 2019

I think we should add a ParamEnv argument to

fn struct_generic(
and in case it's RevealAll, we emit the error again?

But yea, as an intermediate step, add delay_span_bug or check the error counter and directly ICE if no errors have been reported yet (like statics do)

@estebank
Copy link
Contributor

@oli-obk reveal is UserFacing for the repro case above and having an unconditional delay_span_bug in struct_generic caused it to be emitted in a significant amount of tests.

Removing the early return only for EvalErrorKind::Layout(LayoutError::SizeOverflow(_)) gets rid of the bug. We can gate it behind delay_span_bug if we're afraid we'll have duplicated errors, but that's not what I'm seeing in this repro case:

error: reaching this expression at runtime will panic or abort
   --> rust/src/libcore/mem/mod.rs:243:5
    |
243 |     intrinsics::size_of::<T>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ rustc layout computation failed: SizeOverflow([u8; 18446744073709551615])
    |
   ::: file7.rs:2:26
    |
2   |     println!("Size: {}", std::mem::size_of::<[u8; std::u64::MAX as usize]>());
    |                          ---------------------------------------------------
    |
    = note: `#[deny(const_err)]` on by default

error: aborting due to previous error

@RalfJung
Copy link
Member

RalfJung commented Aug 3, 2019

@Centril AFAIK this generates a trap, no UB. Why is this a soundness issue?

@Centril
Copy link
Contributor

Centril commented Aug 3, 2019

@RalfJung Well I didn't know that then. ;) I typically add I-unsound when I hear "illegal instruction", "segfault", or similar things and then someone can remove the label if they think otherwise + explanation.

@Centril Centril removed the I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness label Aug 3, 2019
Centril added a commit to Centril/rust that referenced this issue Aug 5, 2019
Always error on `SizeOverflow` during mir evaluation

Fix rust-lang#55878, fix rust-lang#25116.

r? @oli-obk
Centril added a commit to Centril/rust that referenced this issue Aug 6, 2019
Always error on `SizeOverflow` during mir evaluation

Fix rust-lang#55878, fix rust-lang#25116.

r? @oli-obk
bors added a commit that referenced this issue Aug 6, 2019
Always error on `SizeOverflow` during mir evaluation

Fix #55878, fix #25116.

r? @oli-obk
bors added a commit that referenced this issue Aug 7, 2019
Always error on `SizeOverflow` during mir evaluation

Fix #55878, fix #25116.

r? @oli-obk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants