Skip to content

Incorrect handling of come invalid inline assembly constraints #54130

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

Closed
alois31 opened this issue Sep 11, 2018 · 3 comments
Closed

Incorrect handling of come invalid inline assembly constraints #54130

alois31 opened this issue Sep 11, 2018 · 3 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-inline-assembly Area: Inline assembly (`asm!(…)`) C-bug Category: This is a bug.

Comments

@alois31
Copy link

alois31 commented Sep 11, 2018

Short summary: When an inline assembly constraint lacks its closing curly brace, the compiler segfaults when optimizing, and accepts the code when not optimizing.

Steps to reproduce:

  • Write the following (invalid) code to some file (e.g. main.rs):
#![feature(asm)]
fn main() {
    let rax: u64;
    unsafe {asm!("", :"={rax"(rax))};
    println!("Accumulator is: {}", rax);
}

(note the missing closing brace in the constraint)

  • Compile it with optimization (i.e. rustc -O main.rs, on nightly because we use a feature flag)
  • Compile it without optimization (i.e. rustc main.rs)

Expected result

Error message that the constraint is not well-formed

Actual result

  • With optimization: The compiler terminates with SIGSEGV (note: this happens with any optimization flag enabled)
  • Without optimization: The code is silently accepted

Meta

  • rustc --version --verbose:
rustc 1.30.0-nightly (0198a1ea4 2018-09-08)
binary: rustc
commit-hash: 0198a1ea45e29af00d92423aa6d2ac876410c3f9
commit-date: 2018-09-08
host: x86_64-unknown-linux-gnu
release: 1.30.0-nightly
LLVM version: 8.0
  • Backtrace: not applicable (compiler does not panic)
@estebank estebank added A-diagnostics Area: Messages for errors, warnings, and lints A-inline-assembly Area: Inline assembly (`asm!(…)`) C-bug Category: This is a bug. labels Sep 11, 2018
@levex
Copy link
Contributor

levex commented Sep 17, 2018

I am unable to reproduce this issue:

$ rustc +nightly-2018-09-09 -vV                                                                                                                                 
rustc 1.30.0-nightly (0198a1ea4 2018-09-08)                                                                                                                                                                                                   
binary: rustc
commit-hash: 0198a1ea45e29af00d92423aa6d2ac876410c3f9
commit-date: 2018-09-08
host: x86_64-unknown-linux-gnu
release: 1.30.0-nightly                                                                                                                                                                                                                       
LLVM version: 8.0

$ rustc +nightly-2018-09-09 54130.rs                                                                                                                            
error[E0660]: malformed inline assembly                                                                                                                                                                                                       
 --> 54130.rs:4:13
  |
4 |     unsafe {asm!("", :"={rax"(rax))};
  |             ^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

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

$ rustc +nightly-2018-09-09 -O 54130.rs                                                                                                                         
error[E0660]: malformed inline assembly                                                                                                                                                                                                       
 --> 54130.rs:4:13
  |
4 |     unsafe {asm!("", :"={rax"(rax))};
  |             ^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

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

Later versions, including the master branch, seem to exhibit the same behavior that nightly-2018-09-09 did.

Is there something that I'm missing?

@alois31
Copy link
Author

alois31 commented Sep 19, 2018

Sorry, an extra comma sneaked in while trying to get the code formatting on Github. The reproducing code is:

#![feature(asm)]
fn main() {
    let rax: u64;
    unsafe {asm!("" :"={rax"(rax))};
    println!("Accumulator is: {}", rax);
}

@levex
Copy link
Contributor

levex commented Sep 23, 2018

Thanks, I can now reproduce it. Backtrace of the segfault:

#0  0x00007fffef80b596 in llvm::LiveVariables::HandleVirtRegUse(unsigned int, llvm::MachineBasicBlock*, llvm::MachineInstr&) ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#1  0x00007fffef80d73e in llvm::LiveVariables::runOnInstr(llvm::MachineInstr&, llvm::SmallVectorImpl<unsigned int>&) ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#2  0x00007fffef80db2f in llvm::LiveVariables::runOnBlock(llvm::MachineBasicBlock*, unsigned int) ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#3  0x00007fffef80e443 in llvm::LiveVariables::runOnMachineFunction(llvm::MachineFunction&) ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#4  0x00007fffef86369a in llvm::MachineFunctionPass::runOnFunction(llvm::Function&) ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#5  0x00007ffff030962e in llvm::FPPassManager::runOnFunction(llvm::Function&) ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#6  0x00007ffff03099d3 in llvm::FPPassManager::runOnModule(llvm::Module&) ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#7  0x00007ffff030a0f4 in llvm::legacy::PassManagerImpl::run(llvm::Module&) ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#8  0x00007fffee3c149c in LLVMRustWriteOutputFile ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#9  0x00007fffee22064a in rustc_codegen_llvm::back::write::write_output_file ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#10 0x00007fffee1f5b15 in rustc_codegen_llvm::back::write::codegen::{{closure}} ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#11 0x00007fffee1ed168 in rustc::util::common::time_ext ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#12 0x00007fffee222b9a in rustc_codegen_llvm::back::write::codegen ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#13 0x00007fffee228fcd in rustc_codegen_llvm::back::write::execute_work_item ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#14 0x00007fffee2026ed in std::sys_common::backtrace::__rust_begin_short_backtrace ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#15 0x00007fffee219bc6 in std::panicking::try::do_call ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#16 0x00007ffff78c57da in __rust_maybe_catch_panic () at libpanic_unwind/lib.rs:103
#17 0x00007fffee20b371 in <F as alloc::boxed::FnBox<A>>::call_box ()
   from /home/lkurusa/.rustup/toolchains/nightly-2018-09-09-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
#18 0x00007ffff78b33eb in _$LT$alloc..boxed..Box$LT$$LP$dyn$u20$alloc..boxed..FnBox$LT$A$C$$u20$Output$u3d$R$GT$$u20$$u2b$$u20$$u27$a$RP$$GT$$u20$as$u20$core..ops..function..FnOnce$LT$A$GT$$GT$::call_once::hf8f28b18ff71f43a () at /checkout/src/liballoc/boxed.rs:656
#19 std::sys_common::thread::start_thread () at libstd/sys_common/thread.rs:24
#20 0x00007ffff7886e86 in std::sys::unix::thread::Thread::new::thread_start () at libstd/sys/unix/thread.rs:90
#21 0x00007ffff207ba9d in start_thread () from /usr/lib/libpthread.so.0
#22 0x00007ffff7743a43 in clone () from /usr/lib/libc.so.6

bors added a commit that referenced this issue Sep 28, 2018
codegen_llvm: check inline assembly constraints with LLVM

---%<---
Hey all,

As issue #54130 highlights, constraints are not checked and passing bad constraints to LLVM can crash it since a `Verify()` call is placed inside an assertion (see: `src/llvm/lib/IR/InlineAsm.cpp:39`).

As this is my first PR to the Rust compiler (woot! 🎉), there might be better ways of achieving this result. In particular, I am not too happy about generating an error in codegen; it would be much nicer if we did it earlier. However, @rkruppe [noted on IRC](https://botbot.me/mozilla/rustc/2018-09-25/?msg=104791581&page=1) that this should be fine for an unstable feature and a much better solution than the _status quo_, which is an ICE.

Thanks!
--->%---

LLVM provides a way of checking whether the constraints and the actual
inline assembly make sense. This commit introduces a check before
emitting code for the inline assembly. If LLVM rejects the inline
assembly (or its constraints), then the compiler emits an error E0668
("malformed inline assembly").

Fixes: #54130
Signed-off-by: Levente Kurusa \<[email protected]\>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-inline-assembly Area: Inline assembly (`asm!(…)`) C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

3 participants